Documentation |
Check a mathematical property of an expression
This functionality does not run in MATLAB.
is(cond) is(ex, set)
is(cond) checks whether the condition cond holds for all possible values.
is(ex, set) checks whether the expression ex lies in the set set.
The property mechanism helps to simplify expressions involving expressions that carry "mathematical properties". The function assume allows to assume "assumptions" such as `x is a real number' or `x is an odd integer' to an identifier x, say. Arithmetical expressions involving x may inherit such properties. E.g., `1 + x^2 is positive' if `x is a real number'. The function is is the basic tool for querying mathematical properties.
is queries the assumptions of all involved identifiers and checks whether the condition cond holds for all possible values. If this is the case, then is returns TRUE. If is derives that cond is not satisfied by any possible value it returns FALSE. Otherwise, is returns UNKNOWN.
If a relation is given to is, and the operands are complex numbers or identifiers with this property, is returns FALSE, because a relations holds only with real objects. Cf. Example 4.
It may happen that is returns UNKNOWN, although the queried property holds mathematically. Cf. Example 5.
In MuPAD^{®}, there also exists the function bool to check a relation y rel z. However, there are two main differences between bool and is:
bool produces an error if it cannot decide whether the relation holds or not; is(y rel z) returns UNKNOWN in this case.
bool does not take properties into account.
Cf. Example 3.
If bool(y rel z) returns TRUE, then so does is(y rel z). However, is is more powerful than bool, even when no properties are involved. Cf. Example 3. On the other hand, is is usually much slower than bool.
Note: Be careful when using is in a condition of an if statement or a for, while, or repeat loop: these constructs cannot handle the value UNKNOWN. Use either is(...) = TRUE or a case statement. Cf. Example 6. |
If is needs to check whether a constant symbolic expression is zero, then it may employ a heuristic numerical zero test based on floating-point evaluation. Despite internal numerical stabilization, this zero test may return the wrong answer in exceptional pathological cases; in such a case, is may return a wrong result as well.
The identifier x is assumed to be an integer:
assume(x, Type::Integer): is(x, Type::Integer), is(x > 0), is(x^2 >= 0)
The identifier x is assumed to be a positive real number:
assume(x > 0): is(x > 1), is(x >= 0), is(x < 0)
unassume(x):
is can derive certain facts even when no properties were assumed explicitly:
is(x > x + 1), is(abs(x) >= 0)
is(Re(exp(x)), Type::Real)
For relations between numbers, is yields the same answers as bool:
bool(1 > 0), is(1 > 0)
is resolves more constant symbolic expressions than bool:
is(sqrt(14) <= sqrt(2)*sqrt(7)), is(sin(10^20) > 0), is(sqrt(2) > 1.41)
bool(sqrt(14) <= sqrt(2)*sqrt(7))
Error: Cannot evaluate to Boolean. [_leequal]
bool(sin(10^20) > 0)
Error: Cannot evaluate to Boolean. [_less]
is(exp(5), Type::Real), is(PI, Type::PosInt)
In the next example a relation with complex objects is given, the returned value is FALSE:
is(0 < I), is(I + 1 > I), is(1 + 2*I <= 2 + 3*I)
The identifier in the next example is assumed to be complex, but it could be real too:
assume(x, Type::Complex): is(x > 0)
The next relation is false, either the identifier x is real, then the relation is false, or the identifiers is not real, then the comparison is illegal:
unassume(x): is(x + 1 < x)
unassume(x):
Here are some examples where the queried property can be derived mathematically. However, the current implementation of is is not yet strong enough to derive the property:
assume(x in Z_ and y in Z_ and x^2 + y^2 = 2); is(x > 1)
unassume(x):
Care must be taken when using is in if statements or for, repeat, while loops:
myabs := proc(x) begin if is(x >= 0) then x elif is(x < 0) then -x else procname(x) end_if end_proc:
assume(x < 0): myabs(1), myabs(-2), myabs(x)
When the call of is returns UNKNOWN, an error occurs because if expects TRUE or FALSE:
unassume(x): myabs(x)
Error: Cannot evaluate to Boolean. [if] Evaluating: myabs
The easiest way to achieve the desired functionality is a comparison of the result of is with TRUE:
myabs := proc(x) begin if is(x >= 0) = TRUE then x elif is(x < 0) = TRUE then -x else procname(x) end_if end_proc:
myabs(x)
delete myabs:
is can handle sets returned by solve. These include intervals of type Dom::Interval and R_ = solvelib::BasicSet(Dom::Real):
assume(x >= 0 and x <= 1): is(x in Dom::Interval([0, 1])), is(x in R_)
The following solve command returns the solution as an infinite parameterized set of type Dom::ImageSet:
unassume(x): solutionset := solve(sin(x) = 0, x)
domtype(solutionset)
is can be used to check whether an expression is contained in this set:
is(20*PI in solutionset), is(PI/2 in solutionset)
delete solutionset:
cond |
A condition |
ex | |
set |
A property representing a set of numbers (e.g., Type::PosInt) or a set returned by solve; such a set can be an element of Dom::Interval, Dom::ImageSet, piecewise, or one of C_, R_, Q_, Z_. |