Skip to content

Commit

Permalink
Merge branch 'new-pyros-preprocessor-and-subproblems' of github.com:s…
Browse files Browse the repository at this point in the history
…hermanjasonaf/pyomo into new-pyros-preprocessor-and-subproblems
  • Loading branch information
shermanjasonaf committed Aug 12, 2024
2 parents c1689fe + fb6f05a commit 44fe269
Show file tree
Hide file tree
Showing 41 changed files with 1,049 additions and 793 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_branches.yml
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ jobs:
$BARON_DIR = "${env:TPL_DIR}/baron"
echo "$BARON_DIR" | `
Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
$URL = "https://www.minlp.com/downloads/xecs/baron/current/"
$URL = "https://minlp.com/downloads/xecs/baron/current/"
if ( "${{matrix.TARGET}}" -eq "win" ) {
$INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe"
$URL += "baron-win64.exe"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_pr_and_main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ jobs:
$BARON_DIR = "${env:TPL_DIR}/baron"
echo "$BARON_DIR" | `
Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
$URL = "https://www.minlp.com/downloads/xecs/baron/current/"
$URL = "https://minlp.com/downloads/xecs/baron/current/"
if ( "${{matrix.TARGET}}" -eq "win" ) {
$INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe"
$URL += "baron-win64.exe"
Expand Down
6 changes: 3 additions & 3 deletions doc/OnlineDocs/contributed_packages/gdpopt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ An example that includes the modeling approach may be found below.
Variables:
x : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : -1.2 : 0.0 : 2 : False : False : Reals
None : -1.2 : 0 : 2 : False : False : Reals
y : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : -10 : 1.0 : 10 : False : False : Reals
None : -10 : 1 : 10 : False : False : Reals
<BLANKLINE>
Objectives:
objective : Size=1, Index=None, Active=True
Expand All @@ -106,7 +106,7 @@ An example that includes the modeling approach may be found below.
Constraints:
c : Size=1
Key : Lower : Body : Upper
None : 1.0 : 1.0 : 1.0
None : 1.0 : 1 : 1.0

.. note::

Expand Down
35 changes: 4 additions & 31 deletions pyomo/contrib/appsi/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ def add_constraints(self, cons: List[ConstraintData]):
raise ValueError(
'constraint {name} has already been added'.format(name=con.name)
)
self._active_constraints[con] = (con.lower, con.body, con.upper)
self._active_constraints[con] = con.expr
if self.use_extensions and cmodel_available:
tmp = cmodel.prep_for_repn(con.body, self._expr_types)
else:
Expand Down Expand Up @@ -1363,40 +1363,13 @@ def update(self, timer: HierarchicalTimer = None):
cons_to_remove_and_add = dict()
need_to_set_objective = False
if config.update_constraints:
cons_to_update = list()
sos_to_update = list()
for c in current_cons_dict.keys():
if c not in new_cons_set:
cons_to_update.append(c)
if c not in new_cons_set and c.expr is not self._active_constraints[c]:
cons_to_remove_and_add[c] = None
sos_to_update = []
for c in current_sos_dict.keys():
if c not in new_sos_set:
sos_to_update.append(c)
for c in cons_to_update:
lower, body, upper = self._active_constraints[c]
new_lower, new_body, new_upper = c.lower, c.body, c.upper
if new_body is not body:
cons_to_remove_and_add[c] = None
continue
if new_lower is not lower:
if (
type(new_lower) is NumericConstant
and type(lower) is NumericConstant
and new_lower.value == lower.value
):
pass
else:
cons_to_remove_and_add[c] = None
continue
if new_upper is not upper:
if (
type(new_upper) is NumericConstant
and type(upper) is NumericConstant
and new_upper.value == upper.value
):
pass
else:
cons_to_remove_and_add[c] = None
continue
self.remove_sos_constraints(sos_to_update)
self.add_sos_constraints(sos_to_update)
timer.stop('cons')
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/appsi/cmodel/src/fbbt_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ void process_fbbt_constraints(FBBTModel *model, PyomoExprTypes &expr_types,
py::handle con_body;

for (py::handle c : cons) {
lower_body_upper = active_constraints[c];
lower_body_upper = c.attr("to_bounded_expression")();
con_lb = lower_body_upper[0];
con_body = lower_body_upper[1];
con_ub = lower_body_upper[2];
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/appsi/cmodel/src/lp_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ void process_lp_constraints(py::list cons, py::object writer) {
py::object nonlinear_expr;
PyomoExprTypes expr_types = PyomoExprTypes();
for (py::handle c : cons) {
lower_body_upper = active_constraints[c];
lower_body_upper = c.attr("to_bounded_expression")();
cname = getSymbol(c, labeler);
repn = generate_standard_repn(
lower_body_upper[1], "compute_values"_a = false, "quadratic"_a = true);
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/appsi/cmodel/src/nl_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ void process_nl_constraints(NLWriter *nl_writer, PyomoExprTypes &expr_types,
py::handle repn_nonlinear_expr;

for (py::handle c : cons) {
lower_body_upper = active_constraints[c];
lower_body_upper = c.attr("to_bounded_expression")();
repn = generate_standard_repn(
lower_body_upper[1], "compute_values"_a = false, "quadratic"_a = false);
_const = appsi_expr_from_pyomo_expr(repn.attr("constant"), var_map,
Expand Down
40 changes: 11 additions & 29 deletions pyomo/contrib/appsi/solvers/maingo.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,33 +57,13 @@
from pyomo.repn.util import valid_expr_ctypes_minlp


def _import_SolverModel():
try:
from . import maingo_solvermodel
except ImportError:
raise
return maingo_solvermodel


maingo_solvermodel, solvermodel_available = attempt_import(
"maingo_solvermodel", importer=_import_SolverModel
)

MaingoVar = namedtuple("MaingoVar", "type name lb ub init")

logger = logging.getLogger(__name__)


def _import_maingopy():
try:
import maingopy
except ImportError:
MAiNGO._available = MAiNGO.Availability.NotFound
raise
return maingopy


maingopy, maingopy_available = attempt_import("maingopy", importer=_import_maingopy)
MaingoVar = namedtuple("MaingoVar", "type name lb ub init")
maingopy, maingopy_available = attempt_import("maingopy")
# Note that importing maingo_solvermodel will trigger the import of
# maingopy, so we defer that import using attempt_import (which will
# always succeed, even if maingopy is not available)
maingo_solvermodel = attempt_import("pyomo.contrib.appsi.solvers.maingo_solvermodel")[0]


class MAiNGOConfig(MIPSolverConfig):
Expand Down Expand Up @@ -185,9 +165,11 @@ def __init__(self, only_child_vars=False):
self._last_results_object: Optional[MAiNGOResults] = None

def available(self):
if not maingopy_available:
return self.Availability.NotFound
self._available = True
if self._available is None:
if maingopy_available:
MAiNGO._available = True
else:
MAiNGO._available = MAiNGO.Availability.NotFound
return self._available

def version(self):
Expand Down
12 changes: 2 additions & 10 deletions pyomo/contrib/appsi/solvers/maingo_solvermodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,7 @@
from pyomo.repn.util import valid_expr_ctypes_minlp


def _import_maingopy():
try:
import maingopy
except ImportError:
raise
return maingopy


maingopy, maingopy_available = attempt_import("maingopy", importer=_import_maingopy)
maingopy, maingopy_available = attempt_import("maingopy")

_plusMinusOne = {1, -1}

Expand Down Expand Up @@ -219,7 +211,7 @@ def _linear_to_maingo(self, node):
return sum(values)


class SolverModel(maingopy.MAiNGOmodel):
class SolverModel(maingopy.MAiNGOmodel if maingopy_available else object):
def __init__(self, var_list, objective, con_list, idmap, logger):
maingopy.MAiNGOmodel.__init__(self)
self._var_list = var_list
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/community_detection/community_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def generate_model_graph(
# Create a list of the variable numbers that occur in the given constraint equation
numbered_variables_in_constraint_equation = [
component_number_map[constraint_variable]
for constraint_variable in identify_variables(model_constraint.body)
for constraint_variable in identify_variables(model_constraint.expr)
]

# Update constraint_variable_map
Expand Down
37 changes: 35 additions & 2 deletions pyomo/contrib/cp/tests/test_logical_to_disjunctive.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,41 @@ def test_equivalence(self):

assertExpressionsEqual(self, m.cons[10].expr, m.z[5] >= 1)

def test_equivalent_to_True(self):
m = self.make_model()
e = m.a.equivalent_to(True)

visitor = LogicalToDisjunctiveVisitor()
m.cons = visitor.constraints
m.z = visitor.z_vars

visitor.walk_expression(e)

self.assertIs(m.a.get_associated_binary(), m.z[1])
self.assertEqual(len(m.z), 4)
self.assertEqual(len(m.cons), 10)

# z[2] == !a v True
assertExpressionsEqual(
self, m.cons[1].expr, (1 - m.z[2]) + (1 - m.z[1]) + 1 >= 1
)
assertExpressionsEqual(self, m.cons[2].expr, 1 - (1 - m.z[1]) + m.z[2] >= 1)
assertExpressionsEqual(self, m.cons[3].expr, m.z[2] + (1 - 1) >= 1)

# z[3] == a v ! c
assertExpressionsEqual(self, m.cons[4].expr, (1 - m.z[3]) + m.z[1] >= 1)
assertExpressionsEqual(self, m.cons[5].expr, m.z[3] + (1 - m.z[1]) >= 1)
assertExpressionsEqual(self, m.cons[6].expr, m.z[3] + 1 >= 1)

# z[4] == z[2] ^ z[3]
assertExpressionsEqual(self, m.cons[7].expr, m.z[4] <= m.z[2])
assertExpressionsEqual(self, m.cons[8].expr, m.z[4] <= m.z[3])
assertExpressionsEqual(
self, m.cons[9].expr, 1 - m.z[4] <= 2 - (m.z[2] + m.z[3])
)

assertExpressionsEqual(self, m.cons[10].expr, m.z[4] >= 1)

def test_xor(self):
m = self.make_model()
e = m.a.xor(m.b)
Expand Down Expand Up @@ -263,8 +298,6 @@ def test_at_most(self):
# z3 = a ^ b
assertExpressionsEqual(self, m.cons[1].expr, m.z[3] <= a)
assertExpressionsEqual(self, m.cons[2].expr, m.z[3] <= b)
m.cons.pprint()
print(m.cons[3].expr)
assertExpressionsEqual(self, m.cons[3].expr, 1 - m.z[3] <= 2 - sum([a, b]))

# atmost in disjunctive form
Expand Down
15 changes: 7 additions & 8 deletions pyomo/contrib/cp/transform/logical_to_disjunctive_walker.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,7 @@ def _dispatch_var(visitor, node):


def _dispatch_param(visitor, node):
if int(value(node)) == value(node):
return False, node
else:
raise ValueError(
"Found non-integer valued Param '%s' in a logical "
"expression. This cannot be written to a disjunctive "
"form." % node.name
)
return False, node


def _dispatch_expression(visitor, node):
Expand Down Expand Up @@ -244,6 +237,12 @@ def initializeWalker(self, expr):

def beforeChild(self, node, child, child_idx):
if child.__class__ in EXPR.native_types:
if child.__class__ is bool:
# If we encounter a bool, we are going to need to treat it as
# binary explicitly because we are finally pedantic enough in the
# expression system to not allow some of the mixing we will need
# (like summing a LinearExpression with a bool)
return False, int(child)
return False, child

if child.is_numeric_type():
Expand Down
6 changes: 3 additions & 3 deletions pyomo/contrib/fbbt/expression_bounds_walker.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,15 @@ def _handle_unknowable_bounds(visitor, node, arg):


def _handle_equality(visitor, node, arg1, arg2):
return eq(*arg1, *arg2)
return eq(*arg1, *arg2, feasibility_tol=visitor.feasibility_tol)


def _handle_inequality(visitor, node, arg1, arg2):
return ineq(*arg1, *arg2)
return ineq(*arg1, *arg2, feasibility_tol=visitor.feasibility_tol)


def _handle_ranged(visitor, node, arg1, arg2, arg3):
return ranged(*arg1, *arg2, *arg3)
return ranged(*arg1, *arg2, *arg3, feasibility_tol=visitor.feasibility_tol)


def _handle_expr_if(visitor, node, arg1, arg2, arg3):
Expand Down
Loading

0 comments on commit 44fe269

Please sign in to comment.