Skip to content

Commit

Permalink
Merge pull request #1 from jsiirola/conservative-rule
Browse files Browse the repository at this point in the history
Remove Port.Conservative, be more selective for evar bounds
  • Loading branch information
ReinboldV authored Jan 30, 2020
2 parents a108b21 + edb99d5 commit 3cea644
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 140 deletions.
110 changes: 27 additions & 83 deletions pyomo/network/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
IPyomoScriptModifyInstance, TransformationFactory
from pyomo.core.kernel.component_map import ComponentMap

from pyomo.network.util import replicate_var
from pyomo.network.util import create_var, tighten_var_domain

logger = logging.getLogger('pyomo.network')

Expand Down Expand Up @@ -205,10 +205,6 @@ def is_extensive(self, name):
"""Return True if the rule for this port member is Port.Extensive"""
return self.rule_for(name) is Port.Extensive

def is_conservative(self, name):
"""Return True if the rule for this port member is Port.Conservative"""
return self.rule_for(name) is Port.Conservative

def fix(self):
"""
Fix all variables in the port at their current values.
Expand Down Expand Up @@ -385,13 +381,23 @@ def _add_from_container(self, port, items):
if type(items) is dict:
for key, val in iteritems(items):
if type(val) is tuple:
port.add(val[0], key, val[1])
if len(val) == 2:
obj, rule = val
port.add(obj, key, rule)
else:
obj, rule, kwds = val
port.add(obj, key, rule, **kwds)
else:
port.add(val, key)
else:
for val in self._initialize:
if type(val) is tuple:
port.add(val[0], rule=val[1])
if len(val) == 2:
obj, rule = val
port.add(obj, rule=rule)
else:
obj, rule, kwds = val
port.add(obj, rule=rule, **kwds)
else:
port.add(val)

Expand Down Expand Up @@ -452,7 +458,7 @@ def Equality(port, name, index_set):
Port._add_equality_constraint(arc, name, index_set)

@staticmethod
def Extensive(port, name, index_set, include_splitfrac=False,
def Extensive(port, name, index_set, include_splitfrac=None,
write_var_sum=True):
"""
Arc Expansion procedure for extensive variable properties
Expand Down Expand Up @@ -501,23 +507,6 @@ def Extensive(port, name, index_set, include_splitfrac=False,
include_splitfrac=include_splitfrac, write_var_sum=write_var_sum)
in_vars = Port._Combine(port, name, index_set)

@staticmethod
def Conservative(port, name, index_set):
"""
Arc Expansion procedure for conservative variable properties.
This procedure is the rule to use when variable quantities should
be conserved without fixing a split for inlets or fixing combinations
for outlet.
It acts like Extensive but does not introduces a split variable
nor a split constraint.
"""

port_parent = port.parent_block()
out_vars = Port._Split_Conservative(port, name, index_set)
in_vars = Port._Combine(port, name, index_set)

@staticmethod
def _Combine(port, name, index_set):
port_parent = port.parent_block()
Expand All @@ -541,6 +530,9 @@ def _Combine(port, name, index_set):
evar = Port._create_evar(port.vars[name], name, eblock, index_set)
in_vars.append(evar)

if len(sources) == 1:
tighten_var_domain(port.vars[name], in_vars[0], index_set)

# Create constraint: var == sum of evars
# Same logic as Port._Split
cname = unique_component_name(port_parent, "%s_%s_insum" %
Expand All @@ -556,12 +548,11 @@ def rule(m, *args):
return in_vars

@staticmethod
def _Split(port, name, index_set, include_splitfrac=False,
def _Split(port, name, index_set, include_splitfrac=None,
write_var_sum=True):
port_parent = port.parent_block()
var = port.vars[name]
out_vars = []
no_splitfrac = False
dests = port.dests(active=True)

if not len(dests):
Expand All @@ -577,7 +568,8 @@ def _Split(port, name, index_set, include_splitfrac=False,
"Cannot fix splitfrac not at 1 for port '%s' with a "
"single dest '%s'" % (port.name, dests[0].name))

no_splitfrac = True
if include_splitfrac is not True:
include_splitfrac = False

if len(dests[0].destination.sources(active=True)) == 1:
# This is a 1-to-1 connection, no need for evar, just equality.
Expand All @@ -592,7 +584,7 @@ def _Split(port, name, index_set, include_splitfrac=False,
evar = Port._create_evar(port.vars[name], name, eblock, index_set)
out_vars.append(evar)

if no_splitfrac:
if include_splitfrac is False:
continue

# Create and potentially initialize split fraction variables.
Expand Down Expand Up @@ -627,7 +619,7 @@ def _Split(port, name, index_set, include_splitfrac=False,
"splitfracs, please pass the "
" include_splitfrac=True argument." %
(port.name, arc.name))
no_splitfrac = True
include_splitfrac = False
continue

eblock.splitfrac = Var()
Expand All @@ -647,6 +639,9 @@ def rule(m, *args):
con = Constraint(index_set, rule=rule)
eblock.add_component(cname, con)

if len(dests) == 1:
tighten_var_domain(port.vars[name], out_vars[0], index_set)

if write_var_sum:
# Create var total sum constraint: var == sum of evars
# Need to alphanum port name in case it is indexed.
Expand All @@ -661,7 +656,7 @@ def rule(m, *args):
port_parent.add_component(cname, con)
else:
# OR create constraint on splitfrac vars: sum == 1
if no_splitfrac:
if include_splitfrac is False:
raise ValueError(
"Cannot choose to write split fraction sum constraint for "
"ports with a single destination or a single Extensive "
Expand All @@ -676,56 +671,6 @@ def rule(m, *args):

return out_vars

@staticmethod
def _Split_Conservative(port, name, index_set):
port_parent = port.parent_block()
var = port.vars[name]
out_vars = []
no_splitfrac = False
dests = port.dests(active=True)

if not len(dests):
return out_vars

if len(dests) == 1:
# No need for splitting on one outlet.
# Make sure they do not try to fix splitfrac not at 1.
splitfracspec = port.get_split_fraction(dests[0])
if splitfracspec is not None:
if splitfracspec[0] != 1 and splitfracspec[1] is True:
raise ValueError(
"Cannot fix splitfrac not at 1 for port '%s' with a "
"single dest '%s'" % (port.name, dests[0].name))

if len(dests[0].destination.sources(active=True)) == 1:
# This is a 1-to-1 connection, no need for evar, just equality.
arc = dests[0]
Port._add_equality_constraint(arc, name, index_set)
return out_vars

for arc in dests:
eblock = arc.expanded_block

# Make and record new variables for every arc with this member.
evar = Port._create_evar(port.vars[name], name, eblock, index_set)
out_vars.append(evar)

# Create var total sum constraint: var == sum of evars
# Need to alphanum port name in case it is indexed.
cname = unique_component_name(port_parent, "%s_%s_outsum" %
(alphanum_label_from_name(port.local_name), name))

def rule(m, *args):
if len(args):
return sum(evar[args] for evar in out_vars) == var[args]
else:
return sum(evar for evar in out_vars) == var

con = Constraint(index_set, rule=rule)
port_parent.add_component(cname, con)

return out_vars

@staticmethod
def _add_equality_constraint(arc, name, index_set):
# This function will add the equality constraint if it doesn't exist.
Expand All @@ -751,10 +696,9 @@ def _create_evar(member, name, eblock, index_set):
# before making a new one.
evar = eblock.component(name)
if evar is None:
evar = replicate_var(member, name, eblock, index_set)
evar = create_var(member, name, eblock, index_set)
return evar


class SimplePort(Port, _PortData):

def __init__(self, *args, **kwd):
Expand Down
70 changes: 35 additions & 35 deletions pyomo/network/tests/test_arc.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,14 +984,14 @@ def test_inactive(self):
1 Declarations: v_equality
""")

def test_conservative_single_var(self):
def test_extensive_no_splitfrac_single_var(self):
m = ConcreteModel()
m.x = Var()
m.y = Var()
m.z = Var()
m.p1 = Port(initialize={'v': (m.x, Port.Conservative)})
m.p2 = Port(initialize={'v': (m.y, Port.Conservative)})
m.p3 = Port(initialize={'v': (m.z, Port.Conservative)})
m.p1 = Port(initialize={'v': (m.x, Port.Extensive, {'include_splitfrac':False})})
m.p2 = Port(initialize={'v': (m.y, Port.Extensive, {'include_splitfrac':False})})
m.p3 = Port(initialize={'v': (m.z, Port.Extensive, {'include_splitfrac':False})})
m.a1 = Arc(source=m.p1, destination=m.p2)
m.a2 = Arc(source=m.p1, destination=m.p3)

Expand Down Expand Up @@ -1136,7 +1136,7 @@ def test_extensive_single_var(self):
13 Declarations: x y z p1 p2 p3 a1 a2 a1_expanded a2_expanded p1_v_outsum p2_v_insum p3_v_insum
""")

def test_conservative_expansion(self):
def test_extensive_no_splitfrac_expansion(self):
m = ConcreteModel()
m.time = Set(initialize=[1, 2, 3])

Expand All @@ -1147,12 +1147,12 @@ def test_conservative_expansion(self):
def source_block(b):
b.t = Set(initialize=[1, 2, 3])
b.p_out = Var(b.t)
b.outlet = Port(initialize={'p': (b.p_out, Port.Conservative)})
b.outlet = Port(initialize={'p': (b.p_out, Port.Extensive, {'include_splitfrac':False})})

def load_block(b):
b.t = Set(initialize=[1, 2, 3])
b.p_in = Var(b.t)
b.inlet = Port(initialize={'p': (b.p_in, Port.Conservative)})
b.inlet = Port(initialize={'p': (b.p_in, Port.Extensive, {'include_splitfrac':False})})

source_block(m.source)
load_block(m.load1)
Expand Down Expand Up @@ -1530,9 +1530,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : None : None : None : False : True : Reals
b : None : None : None : False : True : Reals
c : None : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand All @@ -1558,9 +1558,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : None : None : None : False : True : Reals
b : None : None : None : False : True : Reals
c : None : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand All @@ -1586,9 +1586,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : None : None : None : False : True : Reals
b : None : None : None : False : True : Reals
c : None : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand All @@ -1614,9 +1614,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : 0 : None : None : False : True : Reals
b : 0 : None : None : False : True : Reals
c : 0 : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand Down Expand Up @@ -1657,9 +1657,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : None : None : None : False : True : Reals
b : None : None : None : False : True : Reals
c : None : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand All @@ -1685,9 +1685,9 @@ def test_extensive_expansion(self):
2 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : 0 : None : None : False : True : Reals
b : 0 : None : None : False : True : Reals
c : 0 : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand All @@ -1702,9 +1702,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : None : None : None : False : True : Reals
b : None : None : None : False : True : Reals
c : None : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand All @@ -1730,9 +1730,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : None : None : None : False : True : Reals
b : None : None : None : False : True : Reals
c : None : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand All @@ -1758,9 +1758,9 @@ def test_extensive_expansion(self):
3 Var Declarations
flow : Size=3, Index=comp
Key : Lower : Value : Upper : Fixed : Stale : Domain
a : 0 : None : None : False : True : NonNegativeReals
b : 0 : None : None : False : True : NonNegativeReals
c : 0 : None : None : False : True : NonNegativeReals
a : None : None : None : False : True : Reals
b : None : None : None : False : True : Reals
c : None : None : None : False : True : Reals
mass : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : None : None : None : False : True : Reals
Expand Down Expand Up @@ -1873,4 +1873,4 @@ def test_extensive_expansion(self):


if __name__ == "__main__":
unittest.main()
unittest.main()
Loading

0 comments on commit 3cea644

Please sign in to comment.