Skip to content

Commit

Permalink
Generalizing the VarData list domain, fixing the error for multiple a…
Browse files Browse the repository at this point in the history
…ctive objectives
  • Loading branch information
emma58 committed Nov 10, 2024
1 parent 7a296c8 commit 669e6d5
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 44 deletions.
4 changes: 2 additions & 2 deletions pyomo/contrib/fme/fourier_motzkin_elimination.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from pyomo.repn.standard_repn import generate_standard_repn
from pyomo.common.collections import ComponentMap, ComponentSet
from pyomo.opt import TerminationCondition
from pyomo.util.var_list_domain import var_component_set
from pyomo.util.config_domains import ComponentDataList

import logging

Expand Down Expand Up @@ -95,7 +95,7 @@ class Fourier_Motzkin_Elimination_Transformation(Transformation):
'vars_to_eliminate',
ConfigValue(
default=None,
domain=var_component_set,
domain=ComponentDataList(Var),
description="Continuous variable or list of continuous variables to "
"project out of the model",
doc="""
Expand Down
8 changes: 4 additions & 4 deletions pyomo/core/plugins/transform/lp_dual.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
)
from pyomo.opt import WriterFactory
from pyomo.repn.standard_repn import isclose_const
from pyomo.util.var_list_domain import var_component_set
from pyomo.util.config_domains import ComponentDataList


class _LPDualData(AutoSlots.Mixin):
Expand All @@ -54,7 +54,7 @@ class LinearProgrammingDual(object):
'parameterize_wrt',
ConfigValue(
default=None,
domain=var_component_set,
domain=ComponentDataList(Var),
description="Vars to treat as data for the purposes of taking the dual",
doc="""
Optional list of Vars to be treated as data while taking the LP dual.
Expand Down Expand Up @@ -108,8 +108,8 @@ def create_using(self, model, ostream=None, **kwds):
def _take_dual(self, model, std_form):
if len(std_form.objectives) != 1:
raise ValueError(
"Model '%s' has no objective or multiple active objectives. Cannot "
"take dual with more than one objective!" % model.name
"Model '%s' has no objective or multiple active objectives. Can "
"only take dual with exactly one active objective!" % model.name
)
primal_sense = std_form.objectives[0].sense

Expand Down
4 changes: 2 additions & 2 deletions pyomo/core/tests/unit/test_lp_dual.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def test_multiple_obj_error(self):
with self.assertRaisesRegex(
ValueError,
"Model 'primal' has no objective or multiple active objectives. "
"Cannot take dual with more than one objective!",
"Can only take dual with exactly one active objective!",
):
dual = lp_dual.create_using(m, parameterize_wrt=[m.outer1, m.outer])

Expand All @@ -341,7 +341,7 @@ def test_multiple_obj_error(self):
with self.assertRaisesRegex(
ValueError,
"Model 'primal' has no objective or multiple active objectives. "
"Cannot take dual with more than one objective!",
"Can only take dual with exactly one active objective!",
):
dual = lp_dual.create_using(m, parameterize_wrt=[m.outer1, m.outer])

Expand Down
9 changes: 7 additions & 2 deletions pyomo/repn/plugins/parameterized_standard_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from pyomo.common.dependencies import numpy as np
from pyomo.common.gc_manager import PauseGC
from pyomo.common.numeric_types import native_numeric_types
from pyomo.core import Var

from pyomo.opt import WriterFactory
from pyomo.repn.parameterized_linear import ParameterizedLinearRepnVisitor
Expand All @@ -21,7 +22,7 @@
LinearStandardFormCompiler,
_LinearStandardFormCompiler_impl,
)
from pyomo.util.var_list_domain import var_component_set
from pyomo.util.config_domains import ComponentDataList


@WriterFactory.register(
Expand All @@ -36,7 +37,7 @@ class ParameterizedLinearStandardFormCompiler(LinearStandardFormCompiler):
'wrt',
ConfigValue(
default=None,
domain=var_component_set,
domain=ComponentDataList(Var),
description="Vars to treat as data for the purposes of compiling"
"the standard form",
doc="""
Expand Down Expand Up @@ -191,6 +192,10 @@ def todense(self):
def sum_duplicates(self):
"""Implements the algorithm from scipy's csr_sum_duplicates function
in sparsetools.
Note that this only removes duplicates that are adjacent, so it will remove
all duplicates if the incoming CSC matrix has sorted indices. (In particular
this will be true if it was just convered from CSR).
"""
ncols = self.shape[1]
row_index = self.indices
Expand Down
53 changes: 53 additions & 0 deletions pyomo/util/config_domains.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# ___________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright (c) 2008-2024
# National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________

from pyomo.common.collections import ComponentSet


class ComponentDataList():
"""ComponentDataList(ctype)
Domain validation class that accepts singleton or iterable arguments and
compiles them into a ComponentSet, verifying that they are all ComponentDatas
of type 'ctype.'
Parameters
----------
ctype: The component type of the list
Raises
------
ValueError if all of the arguments are not of type 'ctype'
"""
def __init__(self, ctype):
self._ctype = ctype

def __call__(self, x):
if hasattr(x, 'ctype') and x.ctype is self._ctype:
if not x.is_indexed():
return ComponentSet([x])
ans = ComponentSet()
for j in x.index_set():
ans.add(x[j])
return ans
elif hasattr(x, '__iter__'):
ans = ComponentSet()
for i in x:
ans.update(self(i))
return ans
else:
_ctype_name = str(self._ctype)
raise ValueError(
f"Expected {_ctype_name} or iterable of "
f"{_ctype_name}s.\n\tReceived {type(x)}")

def domain_name(self):
_ctype_name = str(self._ctype)
return f'ComponentDataList({_ctype_name})'
34 changes: 0 additions & 34 deletions pyomo/util/var_list_domain.py

This file was deleted.

0 comments on commit 669e6d5

Please sign in to comment.