is_lower.cpp
1 #include <symengine/basic.h>
2 #include <symengine/assumptions.h>
3 #include <symengine/visitor.h>
4 #include <symengine/test_visitors.h>
5 
6 namespace SymEngine
7 {
8 
9 class MatrixLowerVisitor : public BaseVisitor<MatrixLowerVisitor>
10 {
11 private:
12  tribool is_lower_;
13  const Assumptions *assumptions_;
14 
15 public:
16  MatrixLowerVisitor(const Assumptions *assumptions)
17  : assumptions_(assumptions)
18  {
19  }
20 
21  void bvisit(const Basic &x){};
22  void bvisit(const MatrixExpr &x)
23  {
24  is_lower_ = tribool::indeterminate;
25  }
26 
27  void bvisit(const IdentityMatrix &x)
28  {
29  is_lower_ = tribool::tritrue;
30  }
31 
32  void bvisit(const ZeroMatrix &x)
33  {
34  is_lower_ = is_square(x, assumptions_);
35  }
36 
37  void bvisit(const DiagonalMatrix &x)
38  {
39  is_lower_ = tribool::tritrue;
40  }
41 
42  void bvisit(const ImmutableDenseMatrix &x)
43  {
44  size_t nrows = x.nrows();
45  size_t ncols = x.ncols();
46  if (nrows != ncols) {
47  is_lower_ = tribool::trifalse;
48  return;
49  }
50  ZeroVisitor visitor(assumptions_);
51  is_lower_ = tribool::tritrue;
52  for (size_t i = 0; i < nrows; i++) {
53  for (size_t j = i + 1; j < nrows; j++) {
54  is_lower_ = and_tribool(is_lower_, visitor.apply(*x.get(i, j)));
55  if (is_false(is_lower_)) {
56  return;
57  }
58  }
59  }
60  }
61 
62  void bvisit(const MatrixAdd &x)
63  {
64  bool found_nonlower = false;
65  for (auto &elt : x.get_terms()) {
66  elt->accept(*this);
67  if (is_indeterminate(is_lower_)) {
68  return;
69  } else if (is_false(is_lower_)) {
70  if (found_nonlower) {
71  return;
72  } else {
73  found_nonlower = true;
74  }
75  }
76  }
77  if (found_nonlower) {
78  is_lower_ = tribool::trifalse;
79  } else {
80  is_lower_ = tribool::tritrue;
81  }
82  }
83 
84  void bvisit(const HadamardProduct &x)
85  {
86  // lower x (lower | nolower | indeterminate) x ... = lower
87  // (indet | nolower) x (indet | nocwlower) x ... = indeterminate
88  for (auto &elt : x.get_factors()) {
89  elt->accept(*this);
90  if (is_true(is_lower_)) {
91  return;
92  }
93  }
94  is_lower_ = tribool::indeterminate;
95  }
96 
97  tribool apply(const MatrixExpr &s)
98  {
99  s.accept(*this);
100  return is_lower_;
101  }
102 };
103 
104 tribool is_lower(const MatrixExpr &m, const Assumptions *assumptions)
105 {
106  MatrixLowerVisitor visitor(assumptions);
107  return visitor.apply(m);
108 }
109 
110 } // namespace SymEngine
The base class for SymEngine.
The lowest unit of symbolic representation.
Definition: basic.h:97
Main namespace for SymEngine package.
Definition: add.cpp:19