0

If I have a constraint reading like this:

For all a in A there exists a b in B so that for all c in C it holds 
that a variable x(a, b + c) is equal to a parameter m(a, c)

short:

forall a in A, exists b in B, forall c in C: x(a,b+c)=m(a,c)

I tried to create the constraint as follows:

constr = lambda model, a: any(all(model.x[a, b + c] <= model.m[a, c] for c in model.C[a]) for b in model.B if b + max(model.C[a]) <= max(model.B))
model.Constr = pyo.Constraint(model.A, rule = constr))

The variables and parameters follow How to define in pyomo parameters representing differently sized vectors and sets? :

  • model.m[a, c] are constructed as shown in for m.data but with binary values
  • model.A correspond to m.nodes with keys as integers (the keys of some_vector)
  • model.B is pyo.Set(initialize=list(range(1000)))
  • model.C corresponds to m.elements
  • model.x is pyo.Var(model.A, model.B, domain = pyo.Binary)

currently I receive the following errors:

ERROR: evaluating object as numeric value: x[0,0]
        (object: <class 'pyomo.core.base.var._GeneralVarData'>)
    No value for uninitialized NumericValue object x[0,0]
ERROR: Rule failed when generating expression for constraint Constr2 with
    index 0: ValueError: No value for uninitialized NumericValue object x[0,0]
ERROR: Constructing component 'Constr2' from data=None failed: ValueError: No
    value for uninitialized NumericValue object x[0,0]
Traceback (most recent call last):
  File "gadget_chain.py", line 134, in <module>
    op.satisfiability_check(mgcm)
  File "optimise_payload.py", line 70, in satisfiability_check
    model.Constr2 = pyo.Constraint(model.Nodes, rule = constr2)
  File "/usr/lib/python3.10/site-packages/pyomo/core/base/block.py", line 544, in __setattr__
    self.add_component(name, val)
  File "/usr/lib/python3.10/site-packages/pyomo/core/base/block.py", line 1089, in add_component
    val.construct(data)
  File "/usr/lib/python3.10/site-packages/pyomo/core/base/constraint.py", line 836, in construct
    index, self.rule(block, index)
  File "/usr/lib/python3.10/site-packages/pyomo/core/base/util.py", line 304, in __call__
    return self._fcn(parent, idx)
  File "optimise_payload.py", line 69, in <lambda>
    any(all(model.x[node, addr + reg] == model.NodeRegisterUsage[node, reg] for reg in model.RegisterIndices[node]) for addr in model.Payload if addr + max(model.RegisterIndices[node]) <= max(model.Payload))
  File "optimise_payload.py", line 69, in <genexpr>
    any(all(model.x[node, addr + reg] == model.NodeRegisterUsage[node, reg] for reg in model.RegisterIndices[node]) for addr in model.Payload if addr + max(model.RegisterIndices[node]) <= max(model.Payload))
  File "pyomo/core/expr/logical_expr.pyx", line 304, in pyomo.core.expr.logical_expr.EqualityExpression.__nonzero__
  File "pyomo/core/expr/numeric_expr.pyx", line 218, in pyomo.core.expr.numeric_expr.ExpressionBase.__call__
  File "/usr/lib/python3.10/site-packages/pyomo/core/expr/visitor.py", line 1054, in evaluate_expression
    return visitor.dfs_postorder_stack(exp)
  File "/usr/lib/python3.10/site-packages/pyomo/core/expr/visitor.py", line 584, in dfs_postorder_stack
    flag, value = self.visiting_potential_leaf(_sub)
  File "/usr/lib/python3.10/site-packages/pyomo/core/expr/visitor.py", line 962, in visiting_potential_leaf
    return True, value(node)
  File "pyomo/core/expr/numvalue.pyx", line 246, in pyomo.core.expr.numvalue.value
  File "pyomo/core/expr/numvalue.pyx", line 233, in pyomo.core.expr.numvalue.value
ValueError: No value for uninitialized NumericValue object x[0,0]

The parameter are named differently here. I checked the constraints independent of one another and the error stays the same whether I comment the others or not. Therefore, the error has to be corresponding with this constraint.

In general feel free to also propose more efficient ways of creating constraints in Pyomo. I am a total beginner with this software.

baxbear
  • 860
  • 3
  • 9
  • 27
  • It's not real clear what you are trying to do in this case, but sadly `max()`, `any()`, and `all()` are nonlinear constructs that are illegal in `pyomo` ... meaning they do not produce recognizable expressions that `pyomo` is trying to build to hand to the solver. You'll have to re-formulate whatever it is you have packed into that constraint. ;) – AirSquid Jun 22 '22 at 14:32
  • @AirSquid you are completely right and I just didn't notice that exists in this contexts means that only a subset of the constraints have to be true - currently I slightly question whether this constraint can be somehow reformulated. Tried to explain it as well as I can here: https://or.stackexchange.com/questions/8588/reformulating-a-constraint-that-is-non-linear because I just don't see how. General geometric knapsack problems seem to be solvable with ILPs ( Optimal Solutions for a Geometric Knapsack Problem using Integer Programming - Paper). My problem should be a lot simpler. – baxbear Jun 22 '22 at 16:33

1 Answers1

1
 forall a in A, exists b in B, forall c in C: x(a,b+c)=m(a,c)

We miss a lot of details, and I am a bit confused by your non-standard description, but my guess is that you mean :

    x[a,1+c] = m[a,c] or x[a,2+c] = m[a,c] or ...   ∀a,c

For the last c this has no meaning. So not sure what you want to do then.

These or conditions can be handled with disjunctions in Pyomo or using binary or SOS1 variables.

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39