Evaluate constraint expression as boolean - pyomo

I want to evaluate if a constraint is respected or not in Pyomo when the values of the variables contained in constraint expression are known.
Use case: We know that one particular constraint sometimes makes the problem infeasible, depending on the value of the variable. Instead of sending the problem to the solver to test if the problem is feasible, converting the constraint expression to a boolean type would be enough to determine if the constraint is the culprit.
For the sake of providing a feasible example, here would be the code:
from pyomo.environ import ConcreteModel, Var, Constraint
model = ConcreteModel()
model.X = Var()
def constraint_rule(model):
return model.X <= 1
model.a_constraint = Constraint(rule=constraint_rule)
Now, let's try to work with the expression to evaluate:
# Let's define the expression in this way:
expression = constraint_rule(model)
# Let's show that the expression is what we expected:
print(str(expression))
The previous statement should print X <= 1.0.
Now, the tricky part is how to evaluate the expression.
if expression == True:
print("feasible")
else:
print("infeasible")
creates an TypeError Exception (TypeError: Cannot create an EqualityExpression where one of the sub-expressions is a relational expression: X <= 1.0).
The last example doesn't work because constraint_rule doesn't return a boolean but a Pyomo expression.
Finally, I know that something like
def evaluate_constraint_a_expression(model):
return value(model.X) <= 1
would work, but I can't assume that I will always know the content of my constraint expression, so I need a robust way of evaluating it.
Is there a clever way of achieving this? Like, evaluating the expression as a boolean and evaluating the left hand side and right hand side of the expression at the same time?

The solution is to use value function. Even if it says that it evaluates an expression to a numeric value, it also converts the expression to a boolean value if it is an equality/inequality expression, like the rule of a constraint.
Let's suppose that the model is defined the way it is in the question, then the rest of the code should be:
from pyomo.environ import value
if value(expression) == True:
print("feasible")
else:
print("infeasible")
where expression is defined as written in the question.
However, be advised that numeric precision in Python using this method can be different than the one provided by the solver. Therefore, it is possible that this method will show that a constraint is infeasible while it is just a matter of numeric imprecision of under 1e-10. So, while it is useful in finding if most constraints are feasible, it also generates some false positives.

Related

Sympy Typeerror: cannot determine truth value of Relational (How to make sure x > 0)

I want to check if 6**x1 is bigger than 0 for every positive value of x1. I am using sympy.
I've done the following:
x1 = sm.symbols('x_1',nonnegative=True)
u = 6**x1
def checker(func):
if u > 0:
return True
else:
return False
However, I get the error:
TypeError: cannot determine truth value of Relational
I think this is because the function does not know that x1 is positive. But how do I make sure it knows this? Apparently, its not enough with the sm.symbols definition.
Zebraboard
SymPy only let's you compare things that can be computed to a number with literal > (and similar). If you want to make a query on a symbolic expression use expr.is_positive or (expr.is_extended_positive if you want oo to be considered, too).
>>> u.is_positive
True
This can be None or False, too. None is returned when a definitive determination cannot be made, e.g. symbols('x').is_positive is None -> True.

How to use a mutable Param pyomo?

I'm trying to make Param mutable with initializer zero but when I tried to read the Param in the constraint its doesn't understand what is reading, the only way that I found to read is using .value but when the problem finishes declaring the whole constraint. the solver found the first solution but when I defined the new param value, it doesn't change the value of the param. I know if I am doing bad the declared or I haven't found the correct white to do that.
As a solver im using CPLEX
This is the way i defined the Param:
model.s_value = pe.Param(mutable=True, initialize=0)
But if I use the Param as a normal Param is a constraint promo sent this message:
ValueError: Constraint 'def_constraint[0]' encountered a strict inequality expression ('>' or '<'). All constraints must be formulated using using '<=', '>=', or '=='.
I think is because when pyomo tired to read the param that sends an object like this:
pyomo.core.base.param.IndexedParam object at 0x1939C6A0
After declaring all the variable I put the solver inside a for and there I redefine the value of the Param:
model.s_value.value= new_value
Please. Someone can explain to me who can I use correctly the mutable Param and how can I iterate the model.
This is a simple example of changing the value of a mutable parameter. You didn't post a full set of executable code above, so it is difficult to figure out what is going on. If this below doesn't answer your question, request you update (edit) your post above with a minimal reproducible example.
import pyomo.environ as pyo
m = pyo.ConcreteModel()
m.x = pyo.Var(domain=pyo.NonNegativeReals)
m.p = pyo.Param(mutable=True, initialize = 10)
# the problem
m.OBJ = pyo.Objective(expr=m.x)
m.c1 = pyo.Constraint(expr=m.x >= m.p)
solver = pyo.SolverFactory('glpk')
# solve it...
results = solver.solve(m)
m.display() # x=10
# change the mutable parameter
m.p = 5
# re-solve it
results = solver.solve(m)
m.display() # x=5

How to get a value from multiple functions in Pyomo

Let's suppose that the objective function is
max z(x,y) = f1(x) - f2(y)
where f1 is function of variables x and f2 is functions of variables y.
This could be written in Pyomo as
def z(model):
return f1(model) - f2(model)
def f1(model):
return [some summation of x variables with some coefficients]
def f2(model):
return [some summation of y variables with some coefficients]
model.objective = Objective(rule=z)
I know it is possible to get the numeric value of z(x,y) easily by calling (since it is the objective function) :
print(model.objective())
but is there a way to get the numeric value of any of these sub-functions separetedly after the optimization, even if they are not explicitly defined as objectives?
I'll answer your question in terms of a ConcreteModel, since rules in Pyomo, for the most part, are nothing more than a mechanism to delay building a ConcereteModel. For now, they are also required to define indexed objects, but that will likely change soon.
First, there is nothing stopping you from defining those "rules" as standard functions that take in some argument and return a value. E.g.,
def z(x, y):
return f1(x) - f2(y)
def f1(x):
return x + 1
def f2(x):
return y**2
Now if you call any of these functions with a built-in type (e.g., f(1,5)), you will get a number back. However, if you call them with Pyomo variables (or Pyomo expressions) you will get a Pyomo expression back, which you can assign to an objective or constraint. This works because Pyomo modeling components, such as variables, overload the standard algebraic operators like +, -, *, etc. Here is an example of how you can build an objective with these functions:
import pyomo.environ as aml
m = aml.ConcreteModel()
m.x = aml.Var()
m.y = aml.Var()
m.o = aml.Objective(expr= z(m.x, m.y))
Now if m.x and m.y have a value loaded into them (i.e., the .value attribute is something other than None), then you can call one of the sub-functions with them and evaluate the returned expression (slower)
aml.value(f1(m.x))
aml.value(f2(m.y))
or you can extract the value from them and pass that to the sub-functions (faster)
f1(m.x.value)
f2(m.y.value)
You can also use the Expression object to store sub-expressions that you want to evaluate on the fly or share inside multiple other expression on a model (all of which you can update by changing what expression is stored under the Expression object).

how to check if sympy expression contains instance of Integral or NonElementaryIntegral?

How to check if an expression returned from sympy integrate command still contain an instance of integrals.Integral or ? NonElementaryIntegral
I am trying to check the antiderivative from sympy to see if it was successful or not, by checking if it remains unevaluated or not
For example:
from sympy import *
x=symbols('x')
isinstance(Integral(x**2, x),integrals.Integral)
Works and returns True. But if the expression has one instance Integral inside other expressions, how to check?
I need a way to look at the expression tree and see if at least one instance of integrals.Integral exist in it, and return True. I am not sure how to iterate over it and do this at this time.
I tried the following (I am very much a newbie in Python and sympy).
from sympy import *
x=symbols('x')
expr=integrate((-x**2+2)*exp(x/(x**2+2))/(x**3+2*x),x)
which gives
-Integral(-2*exp(x/(x**2 + 2))/(x**3 + 2*x), x) -
Integral(x**2*exp(x/(x**2 + 2))/(x**3 + 2*x), x)
expr.args #which is tuple
(-Integral(-2*exp(x/(x**2 + 2))/(x**3 + 2*x), x), -
Integral(x**2*exp(x/(x**2 + 2))/(x**3 + 2*x), x))
any(isinstance(m, integrals.Integral) for m in expr.args)
But this gave False, why?
I also tried
for m in expr.args:
isinstance(m, integrals.Integral)
And this gaves
False
False
I was expecting both to be True.
How to check if an expression contains at least one instance of integrals.Integral any where in it?
Update
Ok, found something. The integrals above are actually NonElementaryIntegral
and not Integral. Looking at the expression tree of expr
srepr(expr)
"Add(Mul(Integer(-1), NonElementaryIntegral(Mul(Integer(-1), Integer(2),
Pow(Add(Pow(Symbol('x'), Integer(3)), Mul(Integer(2), Symbol('x'))),
Integer(-1)), exp(Mul(Symbol('x'), Pow(Add(Pow(Symbol('x'), Integer(2)),
Integer(2)), Integer(-1))))), Tuple(Symbol('x')))), Mul(Integer(-1),
NonElementaryIntegral(Mul(Pow(Symbol('x'), Integer(2)),
Pow(Add(Pow(Symbol('x'), Integer(3)), Mul(Integer(2), Symbol('x'))),
Integer(-1)), exp(Mul(Symbol('x'), Pow(Add(Pow(Symbol('x'), Integer(2)),
Integer(2)), Integer(-1))))), Tuple(Symbol('x')))))"
So I need to look for both Integral and NonElementaryIntegral. But so far, I do not know how to check for NonElementaryIntegral since I do not know in which class it is supposed to be. It is not integral.NonElementaryIntegral and need to find where this lives.
any(isinstance(mx, integrals.NonElementaryIntegral) for mx in anti.args)
gives
error: module 'sympy.integrals.integrals' has no attribute
'NonElementaryIntegral'
The page http://docs.sympy.org/latest/modules/integrals/integrals.html only says
If the indefinite Integral returned by this function is an instance of
NonElementaryIntegral, that means that the Risch algorithm has proven that
integral to be non-elementary.
Ok, but how to check for it?
expr.has(Integral)
does this. The class NonElementaryIntegral inherits from Integral, so according to inheritance rules it suffices to check for Integral.
A self-contained example would be
from sympy import *
x = symbols('x')
expr = integrate(exp(x**4)/(x**2+1), x)
print(expr.has(Integral))
You can find detailed information about the class names by using
print([type(a) for a in preorder_traversal(expr)])

Boolean Assert in ABAP Unit

How do I write a simple ABAP Unit Assert statement to check if any call, expression or other statement evaluates to true?
I can't see any basic assert() or assert_true() methods in CL_AUNIT_ASSERT while I'd expect those to be very common. I can approximate such an assert as follows, but is there no cleaner way?
cl_aunit_assert=>assert_equals(
act = boolc( lv_value > 100 OR lv_value < 2 )
exp = abap_true ).
cl_aunit_assert=>assert_equals(
act = mo_model->is_active )
exp = abap_true ).
Depending on your SAP NetWeaver stack you can (or should) use the updated ABAP Unit Class CL_ABAP_UNIT_ASSERT. This class is available at a Basis-Release >= 7.02. SAP declared this class as 'FINAL' so it´s impossible to inherit from it, but on the other side they added some ASSERT-Methods like the ASSERT_TRUE Method!
Here is a possible usage of this method:
cl_abap_unit_assert=>assert_true(
exporting
act = m_ref_foo->is_bar( l_some_var )
msg = 'is_bar Method fails with Input { l_some_var }'
).
For the releases I have access to, there's probably no shorter way than the one you outlined. You can create a subclass of CL_AUNIT_ASSERT and add your own static ASSERT_TRUE method. It's not a bad idea to do so and at the same time make your local ABAP Unit test class a subclass of that ZCL_AUNIT_ASSERT - this way, you can omit the cl_aunit_assert=> prefix which will save some keystrokes.
You cannot see such methods because there is no boolean type in ABAP.
While in Java, C++ or C, you are able to assign a result of a condition to a variable, like this
int i = 5;
boolean result = i > 3;
You cannot do the same thing in ABAP as there is no boolean type. Therefore what in other languages is a one liner, in ABAP it will always be more prolix.
DATA: i TYPE i VALUE 5.
DATA: result TYPE abap_bool.
IF i > 3.
result = abap_true.
ELSE.
result = abap_false.
ENDIF.
The thing you used seems to be a new feature, that has been recently added to the language and most of the customers will not be using for a long time. Also the CL_AUNIT_ASSERT class was created way before the new elements came to the language.
So right now, there is a possibility to write the above thing as one liner. However there is still no boolean type in the language.
DATA: i TYPE i VALUE 5.
DATA: result TYPE abap_bool.
result = boolc( i > 3 ).
On the other hand, there is no boolean type, but you could simply use ASSERT_INITIAL or ASSERT_NOT_INITIAL in this case, as boolean is emulated by either X (true) or space (false). The latter is an initial value in ABAP.
The cleanest way is to just fail:
if value > limit.
cl_abap_unit_assert=>fail( ).
endif.
Or a more informative:
cl_abap_unit=>fail( msg = 'Limit exceeded' ).