Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pyomo/core/base/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
'active_components', 'components', 'active_components_data',
'components_data']

import re
import copy
import sys
import weakref
Expand All @@ -38,6 +39,7 @@

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

valid_component_name = re.compile("[_a-zA-Z][_a-zA-Z0-9]*")

# Monkey-patch for deepcopying weakrefs
# Only required on Python <= 2.6
Expand Down Expand Up @@ -818,6 +820,9 @@ def add_component(self, name, val):
#
# Error checks
#
if valid_component_name.fullmatch(name) is None:
raise AttributeError(
"'%s' is not a valid component name. Cannot add '%s' as a component to a block with t" % (name, str(type(val))))
if not val.valid_model_component():
raise RuntimeError(
"Cannot add '%s' as a component to a block" % str(type(val)))
Expand Down
7 changes: 3 additions & 4 deletions pyomo/core/plugins/transform/add_slack_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def _apply_to(self, instance, **kwds):
xblockname = unique_component_name(instance, "_core_add_slack_variables")
instance.add_component(xblockname, Block())
xblock = instance.component(xblockname)
xblock.slacks = Var(Any, within=NonNegativeReals, dense=False)

obj_expr = 0
for cons in constraintDatas:
Expand All @@ -72,8 +73,7 @@ def _apply_to(self, instance, **kwds):
# we add positive slack variable to body:
# declare positive slack
varName = "_slack_plus_" + cons.name
posSlack = Var(within=NonNegativeReals)
xblock.add_component(varName, posSlack)
posSlack = xblock.slacks.add(varName)
# add positive slack to body expression
cons._body += posSlack
# penalize slack in objective
Expand All @@ -82,8 +82,7 @@ def _apply_to(self, instance, **kwds):
# we subtract a positive slack variable from the body:
# declare slack
varName = "_slack_minus_" + cons.name
negSlack = Var(within=NonNegativeReals)
xblock.add_component(varName, negSlack)
negSlack = xblock.slacks.add(varName)
# add negative slack to body expression
cons._body -= negSlack
# add slack to objective
Expand Down
6 changes: 3 additions & 3 deletions pyomo/core/plugins/transform/expand_connectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def _apply_to(self, instance, **kwds):
for constraint, conn_set in constraint_list:
cList = ConstraintList()
constraint.parent_block().add_component(
'%s.expanded' % ( constraint.local_name, ), cList )
'%s_expanded' % ( constraint.local_name, ), cList )
connId = next(iterkeys(conn_set))
ref = known_conn_sets[id(matched_connectors[connId])]
for k,v in sorted(iteritems(ref)):
Expand Down Expand Up @@ -123,7 +123,7 @@ def _apply_to(self, instance, **kwds):
for var, aggregator in iteritems(conn.aggregators):
c = Constraint(expr=aggregator(block, conn.vars[var]))
block.add_component(
'%s.%s.aggregate' % (conn.local_name, var), c )
'%s_%s_aggregate' % (conn.local_name, var), c )


def _validate_and_expand_connector_set(self, connectors):
Expand Down Expand Up @@ -227,7 +227,7 @@ def _validate_and_expand_connector_set(self, connectors):
except AttributeError:
pass
new_var = Var( *idx, **var_args )
block.add_component('%s.auto.%s' % ( c.local_name, k ), new_var)
block.add_component('%s_auto_%s' % ( c.local_name, k ), new_var)
if idx:
for i in idx[0]:
new_var[i].domain = v[0][i].domain
Expand Down
84 changes: 38 additions & 46 deletions pyomo/core/tests/transform/test_add_slacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,15 @@ def test_slack_vars_added(self):
xblock = m.component("_core_add_slack_variables")

# should have new variables on new block
self.assertIsInstance(xblock.component("_slack_minus_rule1"), Var)
self.assertFalse(hasattr(xblock, "_slack_plus_rule1"))
self.assertIsInstance(xblock.component("_slack_minus_rule2"), Var)
self.assertIsInstance(xblock.component("_slack_plus_rule2"), Var)
self.assertFalse(hasattr(xblock, "_slack_minus_rule3"))
self.assertIsInstance(xblock.component("_slack_plus_rule3"), Var)
self.assertTrue("_slack_minus_rule1" in xblock.slacks)
self.assertTrue("_slack_minus_rule2" in xblock.slacks)
self.assertTrue("_slack_plus_rule2" in xblock.slacks)
self.assertTrue("_slack_plus_rule3" in xblock.slacks)
# all new variables in non-negative reals
self.assertEqual(xblock._slack_minus_rule1.bounds, (0, None))
self.assertEqual(xblock._slack_minus_rule2.bounds, (0, None))
self.assertEqual(xblock._slack_plus_rule2.bounds, (0, None))
self.assertEqual(xblock._slack_plus_rule3.bounds, (0, None))
self.assertEqual(xblock.slacks['_slack_minus_rule1'].bounds, (0, None))
self.assertEqual(xblock.slacks['_slack_minus_rule2'].bounds, (0, None))
self.assertEqual(xblock.slacks['_slack_plus_rule2'].bounds, (0, None))
self.assertEqual(xblock.slacks['_slack_plus_rule3'].bounds, (0, None))

# wrapping this as a method because I use it again later when I test
# targets
Expand All @@ -81,7 +79,7 @@ def checkRule1(self, m):
self.assertIs(cons.body.arg(0), m.x)
self.assertIs(cons.body.arg(1).__class__, EXPR.MonomialTermExpression)
self.assertEqual(cons.body.arg(1).arg(0), -1)
self.assertIs(cons.body.arg(1).arg(1), transBlock._slack_minus_rule1)
self.assertIs(cons.body.arg(1).arg(1), transBlock.slacks['_slack_minus_rule1'])

def checkRule3(self, m):
# check all original variables still there:
Expand All @@ -94,7 +92,7 @@ def checkRule3(self, m):
self.assertEqual(cons.body.nargs(), 2)

self.assertIs(cons.body.arg(0), m.x)
self.assertIs(cons.body.arg(1), transBlock._slack_plus_rule3)
self.assertIs(cons.body.arg(1), transBlock.slacks['_slack_plus_rule3'])

def test_ub_constraint_modified(self):
m = self.makeModel()
Expand All @@ -120,10 +118,10 @@ def test_both_bounds_constraint_modified(self):
self.assertEqual(cons.body.nargs(), 3)

self.assertIs(cons.body.arg(0), m.y)
self.assertIs(cons.body.arg(1), transBlock._slack_plus_rule2)
self.assertIs(cons.body.arg(1), transBlock.slacks['_slack_plus_rule2'])
self.assertIs(cons.body.arg(2).__class__, EXPR.MonomialTermExpression)
self.assertEqual(cons.body.arg(2).arg(0), -1)
self.assertIs(cons.body.arg(2).arg(1), transBlock._slack_minus_rule2)
self.assertIs(cons.body.arg(2).arg(1), transBlock.slacks['_slack_minus_rule2'])

def test_obj_deactivated(self):
m = self.makeModel()
Expand All @@ -145,10 +143,10 @@ def test_new_obj_created(self):

self.assertEqual(obj.expr.nargs(), 4)

self.assertIs(obj.expr.arg(0), transBlock._slack_minus_rule1)
self.assertIs(obj.expr.arg(1), transBlock._slack_plus_rule2)
self.assertIs(obj.expr.arg(2), transBlock._slack_minus_rule2)
self.assertIs(obj.expr.arg(3), transBlock._slack_plus_rule3)
self.assertIs(obj.expr.arg(0), transBlock.slacks['_slack_minus_rule1'])
self.assertIs(obj.expr.arg(1), transBlock.slacks['_slack_plus_rule2'])
self.assertIs(obj.expr.arg(2), transBlock.slacks['_slack_minus_rule2'])
self.assertIs(obj.expr.arg(3), transBlock.slacks['_slack_plus_rule3'])

def test_badModel_err(self):
model = ConcreteModel()
Expand All @@ -173,12 +171,10 @@ def test_leave_deactivated_constraints(self):
self.assertIs(cons.body, m.y)

def checkTargetSlackVars(self, transBlock):
self.assertIsInstance(transBlock.component("_slack_minus_rule1"), Var)
self.assertFalse(hasattr(transBlock, "_slack_plus_rule1"))
self.assertIsNone(transBlock.component("_slack_minus_rule2"))
self.assertIsNone(transBlock.component("_slack_plus_rule2"))
self.assertFalse(hasattr(transBlock, "_slack_minus_rule3"))
self.assertIsInstance(transBlock.component("_slack_plus_rule3"), Var)
self.assertTrue("_slack_minus_rule1" in transBlock.slacks)
self.assertFalse("_slack_minus_rule2" in transBlock.slacks)
self.assertFalse("_slack_plus_rule2" in transBlock.slacks)
self.assertTrue("_slack_plus_rule3" in transBlock.slacks)

def test_only_targets_have_slack_vars(self):
m = self.makeModel()
Expand Down Expand Up @@ -245,8 +241,8 @@ def checkTargetsObj(self, m):
transBlock = m._core_add_slack_variables
obj = transBlock.component("_slack_objective")
self.assertEqual(obj.expr.nargs(), 2)
self.assertIs(obj.expr.arg(0), transBlock._slack_minus_rule1)
self.assertIs(obj.expr.arg(1), transBlock._slack_plus_rule3)
self.assertIs(obj.expr.arg(0), transBlock.slacks['_slack_minus_rule1'])
self.assertIs(obj.expr.arg(1), transBlock.slacks['_slack_plus_rule3'])

def test_target_objective(self):
m = self.makeModel()
Expand Down Expand Up @@ -294,10 +290,10 @@ def test_transformed_constraints_sumexpression_body(self):
self.assertIs(c.body.arg(0), m.x)
self.assertIs(c.body.arg(1).arg(0), -2)
self.assertIs(c.body.arg(1).arg(1), m.y)
self.assertIs(c.body.arg(2), transBlock._slack_plus_rule4)
self.assertIs(c.body.arg(2), transBlock.slacks['_slack_plus_rule4'])
self.assertIs(c.body.arg(3).__class__, EXPR.MonomialTermExpression)
self.assertEqual(c.body.arg(3).arg(0), -1)
self.assertIs(c.body.arg(3).arg(1), transBlock._slack_minus_rule4)
self.assertIs(c.body.arg(3).arg(1), transBlock.slacks['_slack_minus_rule4'])

def test_transformed_constraint_scalar_body(self):
m = self.makeModel()
Expand All @@ -315,7 +311,7 @@ def test_transformed_constraint_scalar_body(self):
self.assertEqual(c.body.arg(0), 6)
self.assertIs(c.body.arg(1).__class__, EXPR.MonomialTermExpression)
self.assertEqual(c.body.arg(1).arg(0), -1)
self.assertIs(c.body.arg(1).arg(1), transBlock._slack_minus_rule4)
self.assertIs(c.body.arg(1).arg(1), transBlock.slacks['_slack_minus_rule4'])


class TestAddSlacks_IndexedConstraints(unittest.TestCase):
Expand All @@ -334,10 +330,10 @@ def rule1_rule(m, s):
return m

def checkSlackVars_indexedtarget(self, transBlock):
self.assertIsInstance(transBlock.component("_slack_plus_rule1[1]"), Var)
self.assertIsInstance(transBlock.component("_slack_plus_rule1[2]"), Var)
self.assertIsInstance(transBlock.component("_slack_plus_rule1[3]"), Var)
self.assertIsNone(transBlock.component("_slack_minus_rule2"))
self.assertTrue("_slack_plus_rule1[1]" in transBlock.slacks)
self.assertTrue("_slack_plus_rule1[2]" in transBlock.slacks)
self.assertTrue("_slack_plus_rule1[3]" in transBlock.slacks)
self.assertFalse("_slack_minus_rule2" in transBlock.slacks)

def test_indexedtarget_only_create_slackvars_for_targets(self):
m = self.makeModel()
Expand Down Expand Up @@ -387,12 +383,9 @@ def checkTargetObj(self, m):
obj = transBlock.component("_slack_objective")
self.assertIsInstance(obj, Objective)
self.assertEqual(obj.expr.nargs(), 3)
self.assertIs(obj.expr.arg(0),
transBlock.component("_slack_plus_rule1[1]"))
self.assertIs(obj.expr.arg(1),
transBlock.component("_slack_plus_rule1[2]"))
self.assertIs(obj.expr.arg(2),
transBlock.component("_slack_plus_rule1[3]"))
self.assertIs(obj.expr.arg(0), transBlock.slacks["_slack_plus_rule1[1]"])
self.assertIs(obj.expr.arg(1), transBlock.slacks["_slack_plus_rule1[2]"])
self.assertIs(obj.expr.arg(2), transBlock.slacks["_slack_plus_rule1[3]"])

def test_indexedtarget_objective(self):
m = self.makeModel()
Expand Down Expand Up @@ -422,8 +415,7 @@ def checkTransformedRule1(self, m, i):
self.assertIs(c.body.arg(0).arg(1), m.x[i])
self.assertIs(
c.body.arg(1),
m._core_add_slack_variables.component(
"_slack_plus_rule1[%s]" % i))
m._core_add_slack_variables.slacks["_slack_plus_rule1[%s]" % i])

def test_indexedtarget_targets_transformed(self):
m = self.makeModel()
Expand All @@ -444,10 +436,10 @@ def test_indexedtarget_targets_transformed_create_using(self):
self.checkTransformedRule1(m2, i)

def checkSlackVars_constraintDataTarget(self, transBlock):
self.assertIsInstance(transBlock.component("_slack_plus_rule1[2]"), Var)
self.assertIsNone(transBlock.component("_slack_plus_rule1[1]"))
self.assertIsNone(transBlock.component("_slack_plus_rule1[3]"))
self.assertIsNone(transBlock.component("_slack_minus_rule2"))
self.assertTrue("_slack_plus_rule1[2]" in transBlock.slacks)
self.assertFalse("_slack_plus_rule1[1]" in transBlock.slacks)
self.assertFalse("_slack_plus_rule1[3]" in transBlock.slacks)
self.assertFalse("_slack_minus_rule2" in transBlock.slacks)

def test_ConstraintDatatarget_only_add_slackvars_for_targets(self):
m = self.makeModel()
Expand Down Expand Up @@ -514,7 +506,7 @@ def checkConstraintDataObj(self, m):
transBlock = m._core_add_slack_variables
obj = transBlock.component("_slack_objective")
self.assertIsInstance(obj, Objective)
self.assertIs(obj.expr, transBlock.component("_slack_plus_rule1[2]"))
self.assertIs(obj.expr, transBlock.slacks["_slack_plus_rule1[2]"])

def test_ConstraintDatatarget_objective(self):
m = self.makeModel()
Expand Down
22 changes: 11 additions & 11 deletions pyomo/core/tests/unit/test_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,9 @@ def test_generate_cuid_names(self):
model.V = Var([('a','b'),(1,'2'),(3,4)])
model.b = Block(concrete=True)
model.b.z = Var([1,'2'])
setattr(model.b, '.H', Var(['a',2]))
setattr(model.b, '_H', Var(['a',2]))
model.B = Block(['a',2], concrete=True)
setattr(model.B['a'],'.k', Var())
setattr(model.B['a'],'_k', Var())
model.B[2].b = Block()
model.B[2].b.x = Var()

Expand All @@ -385,14 +385,14 @@ def test_generate_cuid_names(self):
model.b.z_index,
model.b.z[1],
model.b.z['2'],
getattr(model.b, '.H'),
getattr(model.b, '.H_index'),
getattr(model.b, '.H')['a'],
getattr(model.b, '.H')[2],
getattr(model.b, '_H'),
getattr(model.b, '_H_index'),
getattr(model.b, '_H')['a'],
getattr(model.b, '_H')[2],
model.B,
model.B_index,
model.B['a'],
getattr(model.B['a'],'.k'),
getattr(model.B['a'],'_k'),
model.B[2],
model.B[2].b,
model.B[2].b.x]:
Expand Down Expand Up @@ -437,12 +437,12 @@ def test_generate_cuid_names(self):
model.b.z,
model.b.z[1],
model.b.z['2'],
getattr(model.b, '.H'),
getattr(model.b, '.H')['a'],
getattr(model.b, '.H')[2],
getattr(model.b, '_H'),
getattr(model.b, '_H')['a'],
getattr(model.b, '_H')[2],
model.B,
model.B['a'],
getattr(model.B['a'],'.k'),
getattr(model.B['a'],'_k'),
model.B[2],
model.B[2].b,
model.B[2].b.x]:
Expand Down
Loading