예제 #1
0
파일: collect.py 프로젝트: jlgearh/pao
def create_linear_dual_from(block, fixed=None, unfixed=None):
    """
    Construct a block that represents the dual of the given block.

    The resulting block contains variables and constraints whose names are
    the dual names of the primal block.  Note that this involves a many
    string operations.  A quicker operations could be executed, but it
    would generate a dual representation that is difficult to interpret.

    Note that the dualization of a maximization problem is performed by
    negating objective and right-hand side coefficients after dualizing
    the corresponding minimization problem.  This suggestion is made
    by Dimitri Bertsimas and John Tsitsiklis in section 4.2 page 143 of
    "Introduction to Linear Optimization"

    Arguments:
        block: A Pyomo block or model
        unfixed: An iterable object with VarData values that are not fixed
                variables.  All other variables are assumed to be fixed.
        fixed: An iterable object with VarData values that are fixed.  All
                other variables are assumed not fixed.

    Returns:
        If the block is a model object, then this returns a ConcreteModel.
        Otherwise, it returns a Block.
    """
    #
    # Collect linear terms from the block
    #
    # NOTE: We are ignoring the vnames and cnames data
    #
    A, b_coef, c_rhs, c_sense, d_sense, v_domain = \
        collect_dual_representation(block, fixed, unfixed)
    #
    # Construct the block
    #
    if isinstance(block, Model):
        dual = ConcreteModel()
    else:
        dual = Block()
    dual.construct()
    _vars = {}

    # Return variable object from name and index (if applicable)
    def getvar(name, ndx=None):
        v = _vars.get((name, ndx), None)
        if v is None:
            v = Var()
            if ndx is None:
                v_name = name
            elif isinstance(ndx, tuple):
                v_name = "%s[%s]" % (name, ','.join(map(str, ndx)))
            else:
                v_name = "%s[%s]" % (name, str(ndx))
            setattr(dual, v_name, v)
            _vars[name, ndx] = v
        return v

    #
    # Construct the objective
    # The dualization of a maximization problem is handled by simply negating the
    # objective and left-hand side coefficients while keeping the dual sense.
    #
    if d_sense == minimize:
        dual.o = Objective(expr=sum(-b_coef[name, ndx] * getvar(name, ndx)
                                    for name, ndx in b_coef),
                           sense=d_sense)
        rhs_multiplier = -1
    else:
        dual.o = Objective(expr=sum(b_coef[name, ndx] * getvar(name, ndx)
                                    for name, ndx in b_coef),
                           sense=d_sense)
        rhs_multiplier = 1
    #
    # Construct the constraints from dual A matrix
    #
    for cname in A:
        for ndx, terms in A[cname].items():

            # Build left-hand side of constraint
            expr = 0
            for term in terms:
                expr += term.coef * getvar(term.var, term.ndx)

            #
            # Assign right-hand side coefficient
            # Note that rhs_multiplier is 1 if the dual is a maximization problem and -1 otherwise
            #
            rhsval = rhs_multiplier * c_rhs.get((cname, ndx), 0.0)

            # Using the correct inequality or equality
            if c_sense[cname, ndx] == 'e':
                e = expr - rhsval == 0
            elif c_sense[cname, ndx] == 'l':
                e = expr - rhsval <= 0
            else:
                e = expr - rhsval >= 0
            c = Constraint(expr=e)

            # Build constraint name
            if ndx is None:
                c_name = cname
            elif isinstance(ndx, tuple):
                c_name = "%s[%s]" % (cname, ','.join(map(str, ndx)))
            else:
                c_name = "%s[%s]" % (cname, str(ndx))

            # Add new constraint along with its name to the dual
            setattr(dual, c_name, c)

        # Set variable domains
        for (name, ndx), domain in v_domain.items():
            v = getvar(name, ndx)
            #flag = type(ndx) is tuple and (ndx[-1] == 'lb' or ndx[-1] == 'ub')
            if domain == 1:
                v.domain = NonNegativeReals
            elif domain == -1:
                v.domain = NonPositiveReals
            else:
                # This is possible when the variable's corresponding constraint is an equality
                v.domain = Reals

    return dual
예제 #2
0
    def _generate_model(self):
        self.model = ConcreteModel()
        model = self.model
        model._name = self.description

        model.s = RangeSet(1, 12)
        model.x = Var(model.s)
        model.x[1].setlb(-1)
        model.x[1].setub(1)
        model.x[2].setlb(-1)
        model.x[2].setub(1)
        model.obj = Objective(expr=sum(model.x[i] * ((-1)**(i + 1))
                                       for i in model.x.index_set()))
        model.c = ConstraintList()
        # to make the variable used in the constraint match the name
        model.c.add(Constraint.Skip)
        model.c.add(Constraint.Skip)
        model.c.add(model.x[3] >= -1.)
        model.c.add(model.x[4] <= 1.)
        model.c.add(model.x[5] == -1.)
        model.c.add(model.x[6] == -1.)
        model.c.add(model.x[7] == 1.)
        model.c.add(model.x[8] == 1.)
        model.c.add((-1., model.x[9], -1.))
        model.c.add((-1., model.x[10], -1.))
        model.c.add((1., model.x[11], 1.))
        model.c.add((1., model.x[12], 1.))
        cdata = model.c.add((0, 1, 3))
        assert cdata.lower == 0
        assert cdata.upper == 3
        assert cdata.body() == 1
        assert not cdata.equality
        cdata = model.c.add((0, 2, 3))
        assert cdata.lower == 0
        assert cdata.upper == 3
        assert cdata.body() == 2
        assert not cdata.equality
        cdata = model.c.add((0, 1, None))
        assert cdata.lower is None
        assert cdata.upper == 1
        assert cdata.body() == 0
        assert not cdata.equality
        cdata = model.c.add((None, 0, 1))
        assert cdata.lower is None
        assert cdata.upper == 1
        assert cdata.body() == 0
        assert not cdata.equality
        cdata = model.c.add((1, 1))
        assert cdata.lower == 1
        assert cdata.upper == 1
        assert cdata.body() == 1
        assert cdata.equality

        model.fixed_var = Var()
        model.fixed_var.fix(1.0)
        cdata = model.c.add((0, 1 + model.fixed_var, 3))
        cdata = model.c.add((0, 2 + model.fixed_var, 3))
        cdata = model.c.add((0, model.fixed_var, None))
        cdata = model.c.add((None, model.fixed_var, 1))
        cdata = model.c.add((model.fixed_var, 1))

        model.c_inactive = ConstraintList()
        # to make the variable used in the constraint match the name
        model.c_inactive.add(Constraint.Skip)
        model.c_inactive.add(Constraint.Skip)
        model.c_inactive.add(model.x[3] >= -2.)
        model.c_inactive.add(model.x[4] <= 2.)

        compile_block_linear_constraints(model, 'Amatrix')
예제 #3
0
    def test_numerical_instability_early_elimination(self):
        # A more subtle numerical problem is that, in infinite precision, a
        # variable might be eliminated early. However, if this goes wrong, the
        # result can be unexpected (including getting no constraints when some
        # are expected.)
        m = ConcreteModel()
        m.x = Var()
        m.x0 = Var()
        m.y = Var()

        # we'll pretend that the 1.123e-9 is noise from previous calculations
        m.cons1 = Constraint(
            expr=0 <= (4.27 + 1.123e-9) * m.x + 13 * m.y - m.x0)
        m.cons2 = Constraint(expr=m.x0 >= 12 * m.y + 4.27 * m.x)

        fme = TransformationFactory('contrib.fourier_motzkin_elimination')

        # doing my own clones because I want assertIs tests
        first = m.clone()
        second = m.clone()
        third = m.clone()

        fme.apply_to(first, vars_to_eliminate=[first.x0], zero_tolerance=1e-10)
        constraints = first._pyomo_contrib_fme_transformation.\
                      projected_constraints
        cons = constraints[1]
        self.assertEqual(cons.lower, 0)
        repn = generate_standard_repn(cons.body)
        self.assertTrue(repn.is_linear())
        self.assertEqual(repn.constant, 0)
        self.assertEqual(len(repn.linear_coefs), 2)  # x is still around
        self.assertIs(repn.linear_vars[0], first.x)
        self.assertAlmostEqual(repn.linear_coefs[0], 1.123e-9)
        self.assertIs(repn.linear_vars[1], first.y)
        self.assertEqual(repn.linear_coefs[1], 1)
        self.assertIsNone(cons.upper)

        # so just to drive home the point, this results in no constraints:
        # (Though also note that that only happens if x0 is the first to be
        # projected out)
        fme.apply_to(second,
                     vars_to_eliminate=[second.x0, second.x],
                     zero_tolerance=1e-10)
        self.assertEqual(len(second._pyomo_contrib_fme_transformation.\
                             projected_constraints), 0)

        # but in this version, we assume that x is already gone...
        fme.apply_to(third,
                     vars_to_eliminate=[third.x0],
                     verbose=True,
                     zero_tolerance=1e-8)
        constraints = third._pyomo_contrib_fme_transformation.\
                      projected_constraints
        cons = constraints[1]
        self.assertEqual(cons.lower, 0)
        self.assertIs(cons.body, third.y)
        self.assertIsNone(cons.upper)

        # and this is exactly the same as the above:
        fme.apply_to(m,
                     vars_to_eliminate=[m.x0, m.x],
                     verbose=True,
                     zero_tolerance=1e-8)
        constraints = m._pyomo_contrib_fme_transformation.projected_constraints
        cons = constraints[1]
        self.assertEqual(cons.lower, 0)
        self.assertIs(cons.body, m.y)
        self.assertIsNone(cons.upper)
예제 #4
0
    def _generate_model(self):
        self.model = None
        self.model = ConcreteModel()
        model = self.model
        model._name = self.description

        model.s = Set(initialize=[1, 2])

        model.x_unused = Var()
        model.x_unused.stale = False

        model.x_unused_initialy_stale = Var()
        model.x_unused_initialy_stale.stale = True

        model.X_unused = Var(model.s)
        model.X_unused_initialy_stale = Var(model.s)
        for i in model.s:
            model.X_unused[i].stale = False
            model.X_unused_initialy_stale[i].stale = True

        model.x = Var()
        model.x.stale = False

        model.x_initialy_stale = Var()
        model.x_initialy_stale.stale = True

        model.X = Var(model.s)
        model.X_initialy_stale = Var(model.s)
        for i in model.s:
            model.X[i].stale = False
            model.X_initialy_stale[i].stale = True

        model.obj = Objective(expr= model.x + \
                                    model.x_initialy_stale + \
                                    summation(model.X) + \
                                    summation(model.X_initialy_stale))

        model.c = ConstraintList()
        model.c.add(model.x >= 1)
        model.c.add(model.x_initialy_stale >= 1)
        model.c.add(model.X[1] >= 0)
        model.c.add(model.X[2] >= 1)
        model.c.add(model.X_initialy_stale[1] >= 0)
        model.c.add(model.X_initialy_stale[2] >= 1)

        # Test that stale flags do not get updated
        # on inactive blocks (where "inactive blocks" mean blocks
        # that do NOT follow a path of all active parent blocks
        # up to the top-level model)
        flat_model = model.clone()
        model.b = Block()
        model.B = Block(model.s)
        model.b.b = flat_model.clone()
        model.B[1].b = flat_model.clone()
        model.B[2].b = flat_model.clone()

        model.b.deactivate()
        model.B.deactivate()
        model.b.b.activate()
        model.B[1].b.activate()
        model.B[2].b.deactivate()
        assert model.b.active is False
        assert model.B[1].active is False
        assert model.B[1].active is False
        assert model.b.b.active is True
        assert model.B[1].b.active is True
        assert model.B[2].b.active is False
    def test_project_disaggregated_vars(self):
        """This is a little bit more of an integration test with GDP, 
        but also an example of why FME is 'useful.' We will give a GDP, 
        take chull relaxation, and then project out the disaggregated 
        variables."""

        m = ConcreteModel()
        m.p = Var([1, 2], bounds=(0, 10))
        m.time1 = Disjunction(expr=[m.p[1] >= 1, m.p[1] == 0])

        m.on = Disjunct()
        m.on.above_min = Constraint(expr=m.p[2] >= 1)
        m.on.ramping = Constraint(expr=m.p[2] - m.p[1] <= 3)
        m.on.on_before = Constraint(expr=m.p[1] >= 1)

        m.startup = Disjunct()
        m.startup.startup_limit = Constraint(expr=(1, m.p[2], 2))
        m.startup.off_before = Constraint(expr=m.p[1] == 0)

        m.off = Disjunct()
        m.off.off = Constraint(expr=m.p[2] == 0)
        m.time2 = Disjunction(expr=[m.on, m.startup, m.off])

        TransformationFactory('gdp.chull').apply_to(m)
        relaxationBlocks = m._pyomo_gdp_chull_relaxation.relaxedDisjuncts
        disaggregatedVars = ComponentSet([
            relaxationBlocks[0].component("p[1]"),
            relaxationBlocks[1].component("p[1]"),
            relaxationBlocks[2].component("p[1]"),
            relaxationBlocks[2].component("p[2]"),
            relaxationBlocks[3].component("p[1]"),
            relaxationBlocks[3].component("p[2]"),
            relaxationBlocks[4].component("p[1]"),
            relaxationBlocks[4].component("p[2]")
        ])
        TransformationFactory('contrib.fourier_motzkin_elimination').apply_to(
            m, vars_to_eliminate=disaggregatedVars)

        constraints = m._pyomo_contrib_fme_transformation.projected_constraints
        # we of course get tremendous amounts of garbage, but we make sure that
        # what should be here is:

        # p[1] >= on.ind_var
        cons = constraints[22]
        self.assertEqual(cons.lower, 0)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 2)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.p[1])
        self.assertEqual(body.linear_coefs[0], 1)
        self.assertIs(body.linear_vars[1], m.on.indicator_var)
        self.assertEqual(body.linear_coefs[1], -1)

        # p[1] <= 10*on.ind_var + 10*off.ind_var
        cons = constraints[20]
        self.assertEqual(cons.lower, 0)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 3)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.on.indicator_var)
        self.assertEqual(body.linear_coefs[0], 10)
        self.assertIs(body.linear_vars[1], m.off.indicator_var)
        self.assertEqual(body.linear_coefs[1], 10)
        self.assertIs(body.linear_vars[2], m.p[1])
        self.assertEqual(body.linear_coefs[2], -1)

        # p[1] >= time1_disjuncts[0].ind_var
        cons = constraints[58]
        self.assertEqual(cons.lower, 0)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 2)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[1], m.time1_disjuncts[0].indicator_var)
        self.assertEqual(body.linear_coefs[1], -1)
        self.assertIs(body.linear_vars[0], m.p[1])
        self.assertEqual(body.linear_coefs[0], 1)

        # p[1] <= 10*time1_disjuncts[0].ind_var
        cons = constraints[61]
        self.assertEqual(cons.lower, 0)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 2)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.time1_disjuncts[0].indicator_var)
        self.assertEqual(body.linear_coefs[0], 10)
        self.assertIs(body.linear_vars[1], m.p[1])
        self.assertEqual(body.linear_coefs[1], -1)

        # p[2] - p[1] <= 3*on.ind_var + 2*startup.ind_var
        cons = constraints[56]
        self.assertEqual(value(cons.lower), 0)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 4)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[3], m.p[2])
        self.assertEqual(body.linear_coefs[3], -1)
        self.assertIs(body.linear_vars[0], m.p[1])
        self.assertEqual(body.linear_coefs[0], 1)
        self.assertIs(body.linear_vars[1], m.on.indicator_var)
        self.assertEqual(body.linear_coefs[1], 3)
        self.assertIs(body.linear_vars[2], m.startup.indicator_var)
        self.assertEqual(body.linear_coefs[2], 2)

        # p[2] >= on.ind_var + startup.ind_var
        cons = constraints[38]
        self.assertEqual(cons.lower, 0)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 3)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.p[2])
        self.assertEqual(body.linear_coefs[0], 1)
        self.assertIs(body.linear_vars[1], m.startup.indicator_var)
        self.assertEqual(body.linear_coefs[1], -1)
        self.assertIs(body.linear_vars[2], m.on.indicator_var)
        self.assertEqual(body.linear_coefs[2], -1)

        # p[2] <= 10*on.ind_var + 2*startup.ind_var
        cons = constraints[32]
        self.assertEqual(cons.lower, 0)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 3)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.on.indicator_var)
        self.assertEqual(body.linear_coefs[0], 10)
        self.assertIs(body.linear_vars[1], m.startup.indicator_var)
        self.assertEqual(body.linear_coefs[1], 2)
        self.assertIs(body.linear_vars[2], m.p[2])
        self.assertEqual(body.linear_coefs[2], -1)

        # 1 <= time1_disjuncts[0].ind_var + time_1.disjuncts[1].ind_var
        cons = constraints[1]
        self.assertEqual(cons.lower, 1)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 2)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.time1_disjuncts[0].indicator_var)
        self.assertEqual(body.linear_coefs[0], 1)
        self.assertIs(body.linear_vars[1], m.time1_disjuncts[1].indicator_var)
        self.assertEqual(body.linear_coefs[1], 1)

        # 1 >= time1_disjuncts[0].ind_var + time_1.disjuncts[1].ind_var
        cons = constraints[2]
        self.assertEqual(cons.lower, -1)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 2)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.time1_disjuncts[0].indicator_var)
        self.assertEqual(body.linear_coefs[0], -1)
        self.assertIs(body.linear_vars[1], m.time1_disjuncts[1].indicator_var)
        self.assertEqual(body.linear_coefs[1], -1)

        # 1 <= on.ind_var + startup.ind_var + off.ind_var
        cons = constraints[3]
        self.assertEqual(cons.lower, 1)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 3)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.on.indicator_var)
        self.assertEqual(body.linear_coefs[0], 1)
        self.assertIs(body.linear_vars[1], m.startup.indicator_var)
        self.assertEqual(body.linear_coefs[1], 1)
        self.assertIs(body.linear_vars[2], m.off.indicator_var)
        self.assertEqual(body.linear_coefs[2], 1)

        # 1 >= on.ind_var + startup.ind_var + off.ind_var
        cons = constraints[4]
        self.assertEqual(cons.lower, -1)
        self.assertIsNone(cons.upper)
        body = generate_standard_repn(cons.body)
        self.assertEqual(body.constant, 0)
        self.assertEqual(len(body.linear_vars), 3)
        self.assertTrue(body.is_linear())
        self.assertIs(body.linear_vars[0], m.on.indicator_var)
        self.assertEqual(body.linear_coefs[0], -1)
        self.assertIs(body.linear_vars[1], m.startup.indicator_var)
        self.assertEqual(body.linear_coefs[1], -1)
        self.assertIs(body.linear_vars[2], m.off.indicator_var)
        self.assertEqual(body.linear_coefs[2], -1)
예제 #6
0
파일: duality.py 프로젝트: tsaycal/romodel
def create_linear_dual_from(block, fixed=None, unfixed=None):
    """
    Construct a block that represents the dual of the given block.

    The resulting block contains variables and constraints whose names are
    the dual names of the primal block.  Note that this involves a many
    string operations.  A quicker operations could be executed, but it
    would generate a dual representation that is difficult to interpret.

    Note that the dualization of a maximization problem is performed by
    negating objective and right-hand side coefficients after dualizing
    the corresponding minimization problem.  This suggestion is made
    by Dimitri Bertsimas and John Tsitsiklis in section 4.2 page 143 of
    "Introduction to Linear Optimization"

    Arguments:
        block: A Pyomo block or model
        unfixed: An iterable object with Variable and VarData values that are 
                not fixed variables.  All other variables are assumed to be fixed.
        fixed: An iterable object with Variable and VarData values that are fixed.  
                All other variables are assumed not fixed.

    Returns:
        If the block is a model object, then this returns a ConcreteModel.
        Otherwise, it returns a Block.
    """
    #
    # Collect vardata that needs to be fixed
    #
    fixed_modelvars = {}
    if fixed or unfixed:
        #
        # Collect model variables
        #
        modelvars = {}
        #
        # vardata in objectives
        #
        for obj in block.component_objects(Objective, active=True):
            for ndx in obj:
                #odata = generate_standard_repn(obj[ndx].expr, compute_values=False)
                for vdata in identify_variables(obj[ndx].expr,
                                                include_fixed=False):
                    id_ = id(vdata)
                    if not id_ in modelvars:
                        modelvars[id_] = vdata
        #
        # vardata in constraints
        #
        for con in block.component_objects(Constraint, active=True):
            for ndx in con:
                #cdata = generate_standard_repn(con[ndx].body, compute_values=False)
                for vdata in identify_variables(con[ndx].body,
                                                include_fixed=False):
                    id_ = id(vdata)
                    if not id_ in modelvars:
                        modelvars[id_] = vdata
        #
        # Fix everything that isn't specified as unfixed
        #
        if unfixed:
            unfixed_vars = set()
            for v in unfixed:
                if v.is_indexed():
                    for vardata in v.values():
                        unfixed_vars.add(id(vardata))
                else:
                    unfixed_vars.add(id(v))
            for id_, vdata in modelvars.items():
                if id_ not in unfixed_vars:
                    fixed_modelvars[id_] = vdata
        #
        # ... or fix everything that is specified as fixed
        #
        elif fixed:
            fixed_vars = set()
            for v in fixed:
                if v.is_indexed():
                    for vardata in v.values():
                        fixed_vars.add(id(vardata))
                else:
                    fixed_vars.add(id(v))
            for id_ in fixed_vars:
                if id_ in modelvars:
                    fixed_modelvars[id_] = modelvars[id_]

    A, b_coef, obj_constant, c_rhs, c_sense, d_sense, v_domain =\
                    collect_dual_representation(block, fixed_modelvars)

    #
    # Construct the block
    #
    if isinstance(block, Model):
        dual = ConcreteModel()
    else:
        dual = Block()
    dual.construct()
    _vars = {}

    # Return variable object from name and index (if applicable)
    def getvar(name, ndx=None):
        v = _vars.get((name, ndx), None)
        if v is None:
            v = Var()
            if ndx is None:
                v_name = name
            elif isinstance(ndx, tuple):
                v_name = "%s[%s]" % (name, ','.join(map(str, ndx)))
            else:
                v_name = "%s[%s]" % (name, str(ndx))
            setattr(dual, v_name, v)
            _vars[name, ndx] = v
        return v

    #
    # Construct the objective
    # The dualization of a maximization problem is handled by simply negating the
    # objective and left-hand side coefficients while keeping the dual sense.
    #
    if d_sense == minimize:
        dual.o = Objective(expr=obj_constant +
                           sum(-b_coef[name, ndx] * getvar(name, ndx)
                               for name, ndx in b_coef),
                           sense=d_sense)
        rhs_multiplier = -1
    else:
        dual.o = Objective(expr=obj_constant +
                           sum(b_coef[name, ndx] * getvar(name, ndx)
                               for name, ndx in b_coef),
                           sense=d_sense)
        rhs_multiplier = 1
    #
    # Construct the constraints from dual A matrix
    #
    for cname in A:
        for ndx, terms in A[cname].items():

            # Build left-hand side of constraint
            expr = 0
            for term in terms:
                expr += term.coef * getvar(term.var, term.ndx)

            #
            # Assign right-hand side coefficient
            # Note that rhs_multiplier is 1 if the dual is a maximization problem and -1 otherwise
            #
            rhsval = rhs_multiplier * c_rhs.get((cname, ndx), 0.0)

            # Using the correct inequality or equality
            if c_sense[cname, ndx] == 'e':
                e = expr - rhsval == 0
            elif c_sense[cname, ndx] == 'l':
                e = expr - rhsval <= 0
            else:
                e = expr - rhsval >= 0
            c = Constraint(expr=e)

            # Build constraint name
            if ndx is None:
                c_name = cname
            elif isinstance(ndx, tuple):
                c_name = "%s[%s]" % (cname, ','.join(map(str, ndx)))
            else:
                c_name = "%s[%s]" % (cname, str(ndx))

            # Add new constraint along with its name to the dual
            setattr(dual, c_name, c)

        # Set variable domains
        for (name, ndx), domain in v_domain.items():
            v = getvar(name, ndx)
            #flag = type(ndx) is tuple and (ndx[-1] == 'lb' or ndx[-1] == 'ub')
            if domain == 1:
                v.domain = NonNegativeReals
            elif domain == -1:
                v.domain = NonPositiveReals
            else:
                # This is possible when the variable's corresponding constraint is an equality
                v.domain = Reals

    return dual
예제 #7
0
 def test_abs(self):
     m = ConcreteModel()
     m.x = Var(bounds=(-1, 1), initialize=0)
     mc_expr = mc(abs((m.x)))
     self.assertEqual(mc_expr.lower(), 0)
     self.assertEqual(mc_expr.upper(), 1)
예제 #8
0
    def criticalityCheck(self, x, y, z, rom_params, worstcase=False, M=[0.0]):

        model = self.model

        self.setVarValue(x=x,y=y,z=z)
        self.setBound(x, y, z, 1e10)
        self.deactiveExtraConObj()
        self.activateRomCons(x, rom_params)

        optGJH = SolverFactory('contrib.gjh')
        optGJH.solve(model, tee=False, symbolic_solver_labels=True)
        g, J, varlist, conlist = model._gjh_info

        l = ConcreteModel()
        l.v = Var(varlist, domain=Reals)
        for i in varlist:
            #dummy = model.find_component(i)
            l.v[i] = 0.0
            l.v[i].setlb(-1.0)
            l.v[i].setub(1.0)
        if worstcase:
            if M.all() == 0.0:
                print('WARNING: worstcase criticality was requested but Jacobian error bound is zero')
            l.t = Var(range(0, self.ly), domain=Reals)
            for i in range(0, self.ly):
                l.t[i].setlb(-M[i])
                l.t[i].setub(M[i])

        def linConMaker(l, i):
            # i should be range(len(conlist) - 1)
            # because last element of conlist is the objective
            con_i = model.find_component(conlist[i])

            isEquality = con_i.equality

            isROM = False

            if conlist[i][:7] == '.' + self.TRF.name + '.rom':
                isROM = True
                romIndex = int(filter(str.isdigit, conlist[i]))

            # This is very inefficient
            # Fix this later if these problems get big
            # This is the ith row of J times v
            Jv = sum(x[2] * l.v[varlist[x[1]]] for x in J if x[0] == i)

            if isEquality:
                if worstcase and isROM:
                    return Jv + l.t[romIndex] == 0
                else:
                    return Jv == 0
            else:
                lo = con_i.lower
                up = con_i.upper
                if lo is not None:
                    level = lo.value - con_i.lslack()
                    if up is not None:
                        return (lo.value <= level + Jv <= up.value)
                    else:
                        return (lo.value <= level + Jv)
                elif up is not None:
                    level = up.value - con_i.uslack()
                    return (level + Jv <= up.value)
                else:
                    raise Exception(
                        "This constraint seems to be neither equality or inequality: " + conlist(i))


        l.lincons = Constraint(range(len(conlist)-1), rule=linConMaker)

        l.obj = Objective(expr=sum(x[1] * l.v[varlist[x[0]]] for x in g))

        # Calculate gradient norm for scaling purposes
        gfnorm = sqrt(sum(x[1]**2 for x in g))


        opt = SolverFactory(self.solver, solver_io=self.solver_io)
        opt.options['halt_on_ampl_error'] = 'yes'
        opt.options['max_iter'] = 5000
        results = opt.solve(
            l, keepfiles=self.keepfiles, tee=self.stream_solver)

        if ((results.solver.status == SolverStatus.ok)
                and (results.solver.termination_condition == TerminationCondition.optimal)):
            l.solutions.load_from(results)
            if gfnorm > 1:
                return True, abs(l.obj())/gfnorm
            else:
                return True, abs(l.obj())
        else:
            print("Waring: Crticality check fails with solver Status: " + str(results.solver.status))
            print("And Termination Conditions: " + str(results.solver.termination_condition))
            return False, infinity
예제 #9
0
    def _construct_bundle_dual_master_model(self, ph):

        self._master_model = ConcreteModel()
        for scenario in ph._scenario_tree._scenarios:
            for tree_node in scenario._node_list[:-1]:
                new_w_variable_name = "WVAR_" + str(
                    tree_node._name) + "_" + str(scenario._name)
                new_w_k_parameter_name = "WDATA_" + str(
                    tree_node._name) + "_" + str(scenario._name) + "_K"
                setattr(self._master_model, new_w_variable_name,
                        Var(tree_node._standard_variable_ids, within=Reals))
                setattr(
                    self._master_model, new_w_k_parameter_name,
                    Param(tree_node._standard_variable_ids,
                          within=Reals,
                          default=0.0,
                          mutable=True))
                setattr(self._master_model, "V_" + str(scenario._name),
                        Var(within=Reals))
                # HERE - NEED TO MAKE CK VARAIBLE-DEPENDENT - PLUS WE NEED A SANE INITIAL VALUE (AND SUBSEQUENT VALUE)
        # DLW SAYS NO - THIS SHOULD BE VARIABLE-SPECIFIC
        setattr(self._master_model, "CK", Param(default=1.0, mutable=True))

        def obj_rule(m):
            expr = 0.0
            for scenario in ph._scenario_tree._scenarios:
                for tree_node in scenario._node_list[:-1]:
                    new_w_variable_name = "WVAR_" + str(
                        tree_node._name) + "_" + str(scenario._name)
                    new_w_k_parameter_name = "WDATA_" + str(
                        tree_node._name) + "_" + str(scenario._name) + "_K"
                    w_variable = m.find_component(new_w_variable_name)
                    w_k_parameter = m.find_component(new_w_k_parameter_name)
                    expr += 1.0 / (2.0 * m.CK) * sum(
                        w_variable[i]**2 -
                        2.0 * w_variable[i] * w_k_parameter[i]
                        for i in w_variable)
                expr -= getattr(m, "V_" + str(scenario._name))
            return expr

        self._master_model.TheObjective = Objective(sense=minimize,
                                                    rule=obj_rule)

        self._master_model.W_Balance = ConstraintList()

        for stage in ph._scenario_tree._stages[:-1]:

            for tree_node in stage._tree_nodes:

                # GABE SHOULD HAVE A SERVICE FOR THIS???
                for idx in tree_node._standard_variable_ids:

                    expr = 0.0
                    for scenario in tree_node._scenarios:
                        scenario_probability = scenario._probability
                        new_w_variable_name = "WVAR_" + str(
                            tree_node._name) + "_" + str(scenario._name)
                        w_variable = self._master_model.find_component(
                            new_w_variable_name)
                        expr += scenario_probability * w_variable[idx]

                    self._master_model.W_Balance.add(expr == 0.0)

        # we can't populate until we see data from PH....
        self._master_model.V_Bound = ConstraintList()
예제 #10
0
def device_scheduler(  # noqa C901
    device_constraints: List[pd.DataFrame],
    ems_constraints: pd.DataFrame,
    commitment_quantities: List[pd.Series],
    commitment_downwards_deviation_price: Union[List[pd.Series], List[float]],
    commitment_upwards_deviation_price: Union[List[pd.Series], List[float]],
) -> Tuple[List[pd.Series], float, SolverResults]:
    """This generic device scheduler is able to handle an EMS with multiple devices,
    with various types of constraints on the EMS level and on the device level,
    and with multiple market commitments on the EMS level.
    A typical example is a house with many devices.
    The commitments are assumed to be with regard to the flow of energy to the device (positive for consumption,
    negative for production). The solver minimises the costs of deviating from the commitments.

    Device constraints are on a device level. Handled constraints (listed by column name):
        max: maximum stock assuming an initial stock of zero (e.g. in MWh or boxes)
        min: minimum stock assuming an initial stock of zero
        equal: exact amount of stock (we do this by clamping min and max)
        derivative max: maximum flow (e.g. in MW or boxes/h)
        derivative min: minimum flow
        derivative equals: exact amount of flow (we do this by clamping derivative min and derivative max)
        derivative down efficiency: ratio of downwards flows (flow into EMS : flow out of device)
        derivative up efficiency: ratio of upwards flows (flow into device : flow out of EMS)
    EMS constraints are on an EMS level. Handled constraints (listed by column name):
        derivative max: maximum flow
        derivative min: minimum flow
    Commitments are on an EMS level. Parameter explanations:
        commitment_quantities: amounts of flow specified in commitments (both previously ordered and newly requested)
            - e.g. in MW or boxes/h
        commitment_downwards_deviation_price: penalty for downwards deviations of the flow
            - e.g. in EUR/MW or EUR/(boxes/h)
            - either a single value (same value for each flow value) or a Series (different value for each flow value)
        commitment_upwards_deviation_price: penalty for upwards deviations of the flow

    All Series and DataFrames should have the same resolution.

    For now, we pass in the various constraints and prices as separate variables, from which we make a MultiIndex
    DataFrame. Later we could pass in a MultiIndex DataFrame directly.
    """

    # If the EMS has no devices, don't bother
    if len(device_constraints) == 0:
        return [], 0, SolverResults()

    # Check if commitments have the same time window and resolution as the constraints
    start = device_constraints[0].index.to_pydatetime()[0]
    resolution = pd.to_timedelta(device_constraints[0].index.freq)
    end = device_constraints[0].index.to_pydatetime()[-1] + resolution
    if len(commitment_quantities) != 0:
        start_c = commitment_quantities[0].index.to_pydatetime()[0]
        resolution_c = pd.to_timedelta(commitment_quantities[0].index.freq)
        end_c = commitment_quantities[0].index.to_pydatetime()[-1] + resolution
        if not (start_c == start and end_c == end):
            raise Exception(
                "Not implemented for different time windows.\n(%s,%s)\n(%s,%s)"
                % (start, end, start_c, end_c))
        if resolution_c != resolution:
            raise Exception(
                "Not implemented for different resolutions.\n%s\n%s" %
                (resolution, resolution_c))

    # Turn prices per commitment into prices per commitment flow
    if len(commitment_downwards_deviation_price) != 0:
        if all(
                isinstance(price, float)
                for price in commitment_downwards_deviation_price):
            commitment_downwards_deviation_price = [
                initialize_series(price, start, end, resolution)
                for price in commitment_downwards_deviation_price
            ]
    if len(commitment_upwards_deviation_price) != 0:
        if all(
                isinstance(price, float)
                for price in commitment_upwards_deviation_price):
            commitment_upwards_deviation_price = [
                initialize_series(price, start, end, resolution)
                for price in commitment_upwards_deviation_price
            ]

    model = ConcreteModel()

    # Add indices for devices (d), datetimes (j) and commitments (c)
    model.d = RangeSet(0, len(device_constraints) - 1, doc="Set of devices")
    model.j = RangeSet(0,
                       len(device_constraints[0].index.to_pydatetime()) - 1,
                       doc="Set of datetimes")
    model.c = RangeSet(0,
                       len(commitment_quantities) - 1,
                       doc="Set of commitments")

    # Add parameters
    def price_down_select(m, c, j):
        return commitment_downwards_deviation_price[c].iloc[j]

    def price_up_select(m, c, j):
        return commitment_upwards_deviation_price[c].iloc[j]

    def commitment_quantity_select(m, c, j):
        return commitment_quantities[c].iloc[j]

    def device_max_select(m, d, j):
        max_v = device_constraints[d]["max"].iloc[j]
        equal_v = device_constraints[d]["equals"].iloc[j]
        if np.isnan(max_v) and np.isnan(equal_v):
            return infinity
        else:
            return np.nanmin([max_v, equal_v])

    def device_min_select(m, d, j):
        min_v = device_constraints[d]["min"].iloc[j]
        equal_v = device_constraints[d]["equals"].iloc[j]
        if np.isnan(min_v) and np.isnan(equal_v):
            return -infinity
        else:
            return np.nanmax([min_v, equal_v])

    def device_derivative_max_select(m, d, j):
        max_v = device_constraints[d]["derivative max"].iloc[j]
        equal_v = device_constraints[d]["derivative equals"].iloc[j]
        if np.isnan(max_v) and np.isnan(equal_v):
            return infinity
        else:
            return np.nanmin([max_v, equal_v])

    def device_derivative_min_select(m, d, j):
        min_v = device_constraints[d]["derivative min"].iloc[j]
        equal_v = device_constraints[d]["derivative equals"].iloc[j]
        if np.isnan(min_v) and np.isnan(equal_v):
            return -infinity
        else:
            return np.nanmax([min_v, equal_v])

    def ems_derivative_max_select(m, j):
        v = ems_constraints["derivative max"].iloc[j]
        if np.isnan(v):
            return infinity
        else:
            return v

    def ems_derivative_min_select(m, j):
        v = ems_constraints["derivative min"].iloc[j]
        if np.isnan(v):
            return -infinity
        else:
            return v

    def device_derivative_down_efficiency(m, d, j):
        try:
            return device_constraints[d]["derivative down efficiency"].iloc[j]
        except KeyError:
            return 1

    def device_derivative_up_efficiency(m, d, j):
        try:
            return device_constraints[d]["derivative up efficiency"].iloc[j]
        except KeyError:
            return 1

    model.up_price = Param(model.c, model.j, initialize=price_up_select)
    model.down_price = Param(model.c, model.j, initialize=price_down_select)
    model.commitment_quantity = Param(model.c,
                                      model.j,
                                      initialize=commitment_quantity_select)
    model.device_max = Param(model.d, model.j, initialize=device_max_select)
    model.device_min = Param(model.d, model.j, initialize=device_min_select)
    model.device_derivative_max = Param(
        model.d, model.j, initialize=device_derivative_max_select)
    model.device_derivative_min = Param(
        model.d, model.j, initialize=device_derivative_min_select)
    model.ems_derivative_max = Param(model.j,
                                     initialize=ems_derivative_max_select)
    model.ems_derivative_min = Param(model.j,
                                     initialize=ems_derivative_min_select)
    model.device_derivative_down_efficiency = Param(
        model.d, model.j, initialize=device_derivative_down_efficiency)
    model.device_derivative_up_efficiency = Param(
        model.d, model.j, initialize=device_derivative_up_efficiency)

    # Add variables
    model.ems_power = Var(model.d, model.j, domain=Reals, initialize=0)
    model.device_power_down = Var(model.d,
                                  model.j,
                                  domain=NonPositiveReals,
                                  initialize=0)
    model.device_power_up = Var(model.d,
                                model.j,
                                domain=NonNegativeReals,
                                initialize=0)
    model.commitment_downwards_deviation = Var(model.c,
                                               model.j,
                                               domain=NonPositiveReals,
                                               initialize=0)
    model.commitment_upwards_deviation = Var(model.c,
                                             model.j,
                                             domain=NonNegativeReals,
                                             initialize=0)

    # Add constraints as a tuple of (lower bound, value, upper bound)
    def device_bounds(m, d, j):
        return (
            m.device_min[d, j],
            sum(m.device_power_down[d, k] + m.device_power_up[d, k]
                for k in range(0, j + 1)),
            m.device_max[d, j],
        )

    def device_derivative_bounds(m, d, j):
        return (
            m.device_derivative_min[d, j],
            m.device_power_down[d, j] + m.device_power_up[d, j],
            m.device_derivative_max[d, j],
        )

    def device_down_derivative_bounds(m, d, j):
        return (
            m.device_derivative_min[d, j],
            m.device_power_down[d, j],
            0,
        )

    def device_up_derivative_bounds(m, d, j):
        return (
            0,
            m.device_power_up[d, j],
            m.device_derivative_max[d, j],
        )

    def ems_derivative_bounds(m, j):
        return m.ems_derivative_min[j], sum(
            m.ems_power[:, j]), m.ems_derivative_max[j]

    def ems_flow_commitment_equalities(m, j):
        """Couple EMS flows (sum over devices) to commitments."""
        return (
            0,
            sum(m.commitment_quantity[:, j]) +
            sum(m.commitment_downwards_deviation[:, j]) +
            sum(m.commitment_upwards_deviation[:, j]) - sum(m.ems_power[:, j]),
            0,
        )

    def device_derivative_equalities(m, d, j):
        """Couple device flows to EMS flows per device, applying efficiencies."""
        return (
            0,
            m.device_power_up[d, j] / m.device_derivative_up_efficiency[d, j] +
            m.device_power_down[d, j] *
            m.device_derivative_down_efficiency[d, j] - m.ems_power[d, j],
            0,
        )

    model.device_energy_bounds = Constraint(model.d,
                                            model.j,
                                            rule=device_bounds)
    model.device_power_bounds = Constraint(model.d,
                                           model.j,
                                           rule=device_derivative_bounds)
    model.device_power_down_bounds = Constraint(
        model.d, model.j, rule=device_down_derivative_bounds)
    model.device_power_up_bounds = Constraint(model.d,
                                              model.j,
                                              rule=device_up_derivative_bounds)
    model.ems_power_bounds = Constraint(model.j, rule=ems_derivative_bounds)
    model.ems_power_commitment_equalities = Constraint(
        model.j, rule=ems_flow_commitment_equalities)
    model.device_power_equalities = Constraint(
        model.d, model.j, rule=device_derivative_equalities)

    # Add objective
    def cost_function(m):
        costs = 0
        for c in m.c:
            for j in m.j:
                costs += m.commitment_downwards_deviation[c,
                                                          j] * m.down_price[c,
                                                                            j]
                costs += m.commitment_upwards_deviation[c, j] * m.up_price[c,
                                                                           j]
        return costs

    model.costs = Objective(rule=cost_function, sense=minimize)

    # Solve
    results = SolverFactory(
        current_app.config.get("FLEXMEASURES_LP_SOLVER")).solve(model)

    planned_costs = value(model.costs)
    planned_power_per_device = []
    for d in model.d:
        planned_device_power = [
            model.device_power_down[d, j].value +
            model.device_power_up[d, j].value for j in model.j
        ]
        planned_power_per_device.append(
            pd.Series(
                index=pd.date_range(start=start,
                                    end=end,
                                    freq=to_offset(resolution),
                                    closed="left"),
                data=planned_device_power,
            ))

    # model.pprint()
    # print(results.solver.termination_condition)
    # print(planned_costs)
    # model.display()
    return planned_power_per_device, planned_costs, results
예제 #11
0
파일: test_mcpp.py 프로젝트: CanLi1/pyomo-1
 def test_outofbounds(self):
     m = ConcreteModel()
     m.x = Var(bounds=(-1, 5), initialize=2)
     with self.assertRaisesRegexp(MCPP_Error,
                                  '.*Log with negative values in range'):
         mc(log(m.x))
예제 #12
0
    def test_cast_to_binary(self):
        m = ConcreteModel()
        m.iv = AutoLinkedBooleanVar()
        m.biv = AutoLinkedBinaryVar(m.iv)
        m.iv.associate_binary_var(m.biv)

        m.biv = 1

        deprecation_msg = (
            "Implicit conversion of the Boolean indicator_var 'iv'")

        out = StringIO()
        with LoggingIntercept(out):
            self.assertEqual(m.iv.lb, 0)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertEqual(m.iv.ub, 1)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertEqual(m.iv.bounds, (0, 1))
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            with self.assertRaisesRegex(
                    AttributeError, "Assignment not allowed. Use the setlb"):
                m.iv.lb = 1
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            with self.assertRaisesRegex(
                    AttributeError, "Assignment not allowed. Use the setub"):
                m.iv.ub = 1
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            with self.assertRaisesRegex(
                    AttributeError, "Assignment not allowed. Use the "
                    "setub and setlb"):
                m.iv.bounds = (1, 1)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            m.iv.setlb(1)
            self.assertEqual(m.biv.lb, 1)
            m.biv.setlb(0)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            m.iv.setub(0)
            self.assertEqual(m.biv.ub, 0)
            m.biv.setub(1)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs(abs(m.iv).args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs(bool(m.iv), True)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            with self.assertRaisesRegex(
                    TypeError, "Implicit conversion of Pyomo NumericValue "
                    "type `biv' to a float"):
                float(m.iv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            with self.assertRaisesRegex(
                    TypeError, "Implicit conversion of Pyomo NumericValue "
                    "type `biv' to an integer"):
                int(m.iv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((-m.iv).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs(+m.iv, m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertTrue(m.iv.has_lb())
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertTrue(m.iv.has_ub())
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertTrue(m.iv.is_binary())
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertFalse(m.iv.is_continuous())
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertTrue(m.iv.is_integer())
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertEqual(m.iv.polynomial_degree(), 1)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv == 0).args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv <= 0).args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv >= 0).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv < 0).args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv > 0).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv + 1).args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv - 1).args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv * 2).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv / 2).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((m.iv**2).args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((1 + m.iv).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((1 - m.iv).args[1].args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((2 * m.iv).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((2 / m.iv).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            self.assertIs((2**m.iv).args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            a = m.iv
            a += 1
            self.assertIs(a.args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            a = m.iv
            a -= 1
            self.assertIs(a.args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            a = m.iv
            a *= 2
            self.assertIs(a.args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            a = m.iv
            a /= 2
            self.assertIs(a.args[1], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())

        out = StringIO()
        with LoggingIntercept(out):
            a = m.iv
            a **= 2
            self.assertIs(a.args[0], m.biv)
        self.assertIn(deprecation_msg, out.getvalue())
예제 #13
0
    def test_synchronize_value(self):
        m = ConcreteModel()
        m.iv = AutoLinkedBooleanVar()
        m.biv = AutoLinkedBinaryVar(m.iv)
        m.iv.associate_binary_var(m.biv)

        self.assertIsNone(m.iv.value)
        self.assertIsNone(m.biv.value)

        # Note: test the following twice to exercise the "no update"
        # situation, and to ensure no infinite loops

        m.iv = True
        self.assertEqual(m.iv.value, True)
        self.assertEqual(m.biv.value, 1)
        m.iv = True
        self.assertEqual(m.iv.value, True)
        self.assertEqual(m.biv.value, 1)

        m.iv = False
        self.assertEqual(m.iv.value, False)
        self.assertEqual(m.biv.value, 0)
        m.iv = False
        self.assertEqual(m.iv.value, False)
        self.assertEqual(m.biv.value, 0)

        m.iv = None
        self.assertEqual(m.iv.value, None)
        self.assertEqual(m.biv.value, None)
        m.iv = None
        self.assertEqual(m.iv.value, None)
        self.assertEqual(m.biv.value, None)

        m.biv = 1
        self.assertEqual(m.iv.value, True)
        self.assertEqual(m.biv.value, 1)
        m.biv = 1
        self.assertEqual(m.iv.value, True)
        self.assertEqual(m.biv.value, 1)

        eps = AutoLinkedBinaryVar.INTEGER_TOLERANCE / 10

        m.biv = None
        self.assertEqual(m.iv.value, None)
        self.assertEqual(m.biv.value, None)
        m.biv = None
        self.assertEqual(m.iv.value, None)
        self.assertEqual(m.biv.value, None)

        m.biv.value = 1 - eps
        self.assertEqual(m.iv.value, True)
        self.assertEqual(m.biv.value, 1 - eps)
        m.biv.value = 1 - eps
        self.assertEqual(m.iv.value, True)
        self.assertEqual(m.biv.value, 1 - eps)

        m.biv.value = eps
        self.assertEqual(m.iv.value, False)
        self.assertEqual(m.biv.value, eps)
        m.biv.value = eps
        self.assertEqual(m.iv.value, False)
        self.assertEqual(m.biv.value, eps)

        m.biv.value = 0.5
        self.assertEqual(m.iv.value, None)
        self.assertEqual(m.biv.value, 0.5)
        m.biv.value = 0.5
        self.assertEqual(m.iv.value, None)
        self.assertEqual(m.biv.value, 0.5)
예제 #14
0
    def test_deactivate(self):
        m = ConcreteModel()
        m.x = Var()
        m.d1 = Disjunct()
        m.d1.constraint = Constraint(expr=m.x <= 0)
        m.d = Disjunction(expr=[m.d1, m.x >= 1, m.x >= 5])
        d2 = m.d.disjuncts[1].parent_component()
        self.assertEqual(len(m.component_map(Disjunction)), 1)
        self.assertEqual(len(m.component_map(Disjunct)), 2)
        self.assertIsNot(m.d1, d2)

        self.assertTrue(m.d1.active)
        self.assertTrue(d2.active)
        self.assertTrue(m.d.disjuncts[0].active)
        self.assertTrue(m.d.disjuncts[1].active)
        self.assertTrue(m.d.disjuncts[2].active)
        self.assertFalse(m.d.disjuncts[0].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[1].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[2].indicator_var.is_fixed())

        m.d.disjuncts[0].deactivate()
        self.assertFalse(m.d1.active)
        self.assertTrue(d2.active)
        self.assertFalse(m.d.disjuncts[0].active)
        self.assertTrue(m.d.disjuncts[1].active)
        self.assertTrue(m.d.disjuncts[2].active)
        self.assertTrue(m.d.disjuncts[0].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[1].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[2].indicator_var.is_fixed())

        m.d.disjuncts[1].deactivate()
        self.assertFalse(m.d1.active)
        self.assertTrue(d2.active)
        self.assertFalse(m.d.disjuncts[0].active)
        self.assertFalse(m.d.disjuncts[1].active)
        self.assertTrue(m.d.disjuncts[2].active)
        self.assertTrue(m.d.disjuncts[0].indicator_var.is_fixed())
        self.assertTrue(m.d.disjuncts[1].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[2].indicator_var.is_fixed())

        d2.deactivate()
        self.assertFalse(m.d1.active)
        self.assertFalse(d2.active)
        self.assertFalse(m.d.disjuncts[0].active)
        self.assertFalse(m.d.disjuncts[1].active)
        self.assertFalse(m.d.disjuncts[2].active)
        self.assertTrue(m.d.disjuncts[0].indicator_var.is_fixed())
        self.assertTrue(m.d.disjuncts[1].indicator_var.is_fixed())
        self.assertTrue(m.d.disjuncts[2].indicator_var.is_fixed())

        m.d.disjuncts[2].activate()
        self.assertFalse(m.d1.active)
        self.assertTrue(d2.active)
        self.assertFalse(m.d.disjuncts[0].active)
        self.assertFalse(m.d.disjuncts[1].active)
        self.assertTrue(m.d.disjuncts[2].active)
        self.assertTrue(m.d.disjuncts[0].indicator_var.is_fixed())
        self.assertTrue(m.d.disjuncts[1].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[2].indicator_var.is_fixed())

        d2.activate()
        self.assertFalse(m.d1.active)
        self.assertTrue(d2.active)
        self.assertFalse(m.d.disjuncts[0].active)
        self.assertTrue(m.d.disjuncts[1].active)
        self.assertTrue(m.d.disjuncts[2].active)
        self.assertTrue(m.d.disjuncts[0].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[1].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[2].indicator_var.is_fixed())

        m.d1.activate()
        self.assertTrue(m.d1.active)
        self.assertTrue(d2.active)
        self.assertTrue(m.d.disjuncts[0].active)
        self.assertTrue(m.d.disjuncts[1].active)
        self.assertTrue(m.d.disjuncts[2].active)
        self.assertFalse(m.d.disjuncts[0].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[1].indicator_var.is_fixed())
        self.assertFalse(m.d.disjuncts[2].indicator_var.is_fixed())
예제 #15
0
    def generate_structured_model(self):
        """
        Using the community map and the original model used to create this community map, we will create
        structured_model, which will be based on the original model but will place variables, constraints, and
        objectives into or outside of various blocks (communities) based on the community map.

        Returns
        -------
        structured_model: Block
            a Pyomo model that reflects the nature of the community map
        """

        # Initialize a new model (structured_model) which will contain variables and constraints in blocks based on
        # their respective communities within the CommunityMap
        structured_model = ConcreteModel()

        # Create N blocks (where N is the number of communities found within the model)
        structured_model.b = Block([0, len(self.community_map) - 1, 1])  # values given for (start, stop, step)

        # Initialize a ComponentMap that will map a variable from the model (for example, old_model.x1) used to
        # create the CommunityMap to a list of variables in various blocks that were created based on this
        # variable (for example, [structured_model.b[0].x1, structured_model.b[3].x1])
        blocked_variable_map = ComponentMap()
        # Example key-value pair -> {original_model.x1 : [structured_model.b[0].x1, structured_model.b[3].x1]}

        # TODO - Consider changing structure of the next two for loops to be more efficient (maybe loop through
        #  constraints and add variables as you go) (but note that disconnected variables would be
        #  missed with this strategy)

        # First loop through community_map to add all the variables to structured_model before we add constraints
        # that use those variables
        for community_key, community in self.community_map.items():
            _, variables_in_community = community

            # Loop through all of the variables (from the original model) in the given community
            for stored_variable in variables_in_community:
                # Construct a new_variable whose attributes are determined by querying the variable from the
                # original model
                new_variable = Var(domain=stored_variable.domain, bounds=stored_variable.bounds)

                # Add this new_variable to its block/community and name it using the string of the variable from the
                # original model
                structured_model.b[community_key].add_component(str(stored_variable), new_variable)

                # Since there could be multiple variables 'x1' (such as
                # structured_model.b[0].x1, structured_model.b[3].x1, etc), we need to create equality constraints
                # for all of the variables 'x1' within structured_model (this is the purpose of blocked_variable_map)

                # Here we update blocked_variable_map to keep track of what equality constraints need to be made
                variable_in_new_model = structured_model.find_component(new_variable)
                blocked_variable_map[stored_variable] = blocked_variable_map.get(stored_variable,
                                                                                 []) + [variable_in_new_model]

        # Now that we have all of our variables within the model, we will initialize a dictionary that used to
        # replace variables within constraints to other variables (in our case, this will convert variables from the
        # original model into variables from the new model (structured_model))
        replace_variables_in_expression_map = dict()

        # Loop through community_map again, this time to add constraints (with replaced variables)
        for community_key, community in self.community_map.items():
            constraints_in_community, _ = community

            # Loop through all of the constraints (from the original model) in the given community
            for stored_constraint in constraints_in_community:

                # Now, loop through all of the variables within the given constraint expression
                for variable_in_stored_constraint in identify_variables(stored_constraint.expr):

                    # Loop through each of the "blocked" variables that a variable is mapped to and update
                    # replace_variables_in_expression_map if a variable has a "blocked" form in the given community

                    # What this means is that if we are looping through constraints in community 0, then it would be
                    # best to change a variable x1 into b[0].x1 as opposed to b[2].x1 or b[5].x1 (assuming all of these
                    # blocked versions of the variable x1 exist (which depends on the community map))

                    variable_in_current_block = False
                    for blocked_variable in blocked_variable_map[variable_in_stored_constraint]:
                        if 'b[%d]' % community_key in str(blocked_variable):
                            # Update replace_variables_in_expression_map accordingly
                            replace_variables_in_expression_map[id(variable_in_stored_constraint)] = blocked_variable
                            variable_in_current_block = True

                    if not variable_in_current_block:
                        # Create a version of the given variable outside of blocks then add it to
                        # replace_variables_in_expression_map

                        new_variable = Var(domain=variable_in_stored_constraint.domain,
                                           bounds=variable_in_stored_constraint.bounds)

                        # Add the new variable just as we did above (but now it is not in any blocks)
                        structured_model.add_component(str(variable_in_stored_constraint), new_variable)

                        # Update blocked_variable_map to keep track of what equality constraints need to be made
                        variable_in_new_model = structured_model.find_component(new_variable)
                        blocked_variable_map[variable_in_stored_constraint] = blocked_variable_map.get(
                            variable_in_stored_constraint, []) + [variable_in_new_model]

                        # Update replace_variables_in_expression_map accordingly
                        replace_variables_in_expression_map[id(variable_in_stored_constraint)] = variable_in_new_model

                # TODO - Is there a better way to check whether something is actually an objective? (as done below)
                # Check to see whether 'stored_constraint' is actually an objective (since constraints and objectives
                # grouped together)
                if self.with_objective and isinstance(stored_constraint, (_GeneralObjectiveData, Objective)):
                    # If the constraint is actually an objective, we add it to the block as an objective
                    new_objective = Objective(
                        expr=replace_expressions(stored_constraint.expr, replace_variables_in_expression_map))
                    structured_model.b[community_key].add_component(str(stored_constraint), new_objective)

                else:
                    # Construct a constraint based on the expression within stored_constraint and the dict we have
                    # created for the purpose of replacing the variables within the constraint expression
                    new_constraint = Constraint(
                        expr=replace_expressions(stored_constraint.expr, replace_variables_in_expression_map))

                    # Add this new constraint to the corresponding community/block with its name as the string of the
                    # constraint from the original model
                    structured_model.b[community_key].add_component(str(stored_constraint), new_constraint)

        # If with_objective was set to False, that means we might have missed an objective function within the
        # original model
        if not self.with_objective:
            # Construct a new dictionary for replacing the variables (replace_variables_in_objective_map) which will
            # be specific to the variables in the objective function, since there is the possibility that the
            # objective contains variables we have not yet seen (and thus not yet added to our new model)
            for objective_function in self.model.component_data_objects(ctype=Objective,
                                                                        active=self.use_only_active_components,
                                                                        descend_into=True):

                for variable_in_objective in identify_variables(objective_function):
                    # Add all of the variables in the objective function (not within any blocks)

                    # Check to make sure a form of the variable has not already been made outside of the blocks
                    if structured_model.find_component(str(variable_in_objective)) is None:

                        new_variable = Var(domain=variable_in_objective.domain, bounds=variable_in_objective.bounds)
                        structured_model.add_component(str(variable_in_objective), new_variable)

                        # Again we update blocked_variable_map to keep track of what
                        # equality constraints need to be made
                        variable_in_new_model = structured_model.find_component(new_variable)
                        blocked_variable_map[variable_in_objective] = blocked_variable_map.get(
                            variable_in_objective, []) + [variable_in_new_model]

                        # Update the dictionary that we will use to replace the variables
                        replace_variables_in_expression_map[id(variable_in_objective)] = variable_in_new_model

                    else:
                        for version_of_variable in blocked_variable_map[variable_in_objective]:
                            if 'b[' not in str(version_of_variable):
                                replace_variables_in_expression_map[id(variable_in_objective)] = version_of_variable

                # Now we will construct a new objective function based on the one from the original model and then
                # add it to the new model just as we have done before
                new_objective = Objective(
                    expr=replace_expressions(objective_function.expr, replace_variables_in_expression_map))
                structured_model.add_component(str(objective_function), new_objective)

        # Now, we need to create equality constraints for all of the different "versions" of a variable (such
        # as x1, b[0].x1, b[2].x2, etc.)

        # Create a constraint list for the equality constraints
        structured_model.equality_constraint_list = ConstraintList(doc="Equality Constraints for the different "
                                                                       "forms of a given variable")

        # Loop through blocked_variable_map and create constraints accordingly
        for variable, duplicate_variables in blocked_variable_map.items():
            # variable -> variable from the original model
            # duplicate_variables -> list of variables in the new model

            # Create a list of all the possible equality constraints that need to be made
            equalities_to_make = combinations(duplicate_variables, 2)

            # Loop through the list of two-variable tuples and create an equality constraint for those two variables
            for variable_1, variable_2 in equalities_to_make:
                structured_model.equality_constraint_list.add(expr=variable_1 == variable_2)

        # Return 'structured_model', which is essentially identical to the original model but now has all of the
        # variables, constraints, and objectives placed into blocks based on the nature of the CommunityMap

        return structured_model
예제 #16
0
def run_pyomo(options=Options(), parser=None):
    data = Options(options=options)

    if options.model.filename == '':
        parser.print_help()
        return Container()

    try:
        pyomo.scripting.util.setup_environment(data)

        pyomo.scripting.util.apply_preprocessing(data, parser=parser)
    except:
        # TBD: I should be able to call this function in the case of
        #      an exception to perform cleanup. However, as it stands
        #      calling finalize with its default keyword value for
        #      model(=None) results in an a different error related to
        #      task port values.  Not sure how to interpret that.
        pyomo.scripting.util.finalize(data,
                                      model=ConcreteModel(),
                                      instance=None,
                                      results=None)
        raise
    else:
        if data.error:
            # TBD: I should be able to call this function in the case of
            #      an exception to perform cleanup. However, as it stands
            #      calling finalize with its default keyword value for
            #      model(=None) results in an a different error related to
            #      task port values.  Not sure how to interpret that.
            pyomo.scripting.util.finalize(data,
                                          model=ConcretModel(),
                                          instance=None,
                                          results=None)
            return Container()  #pragma:nocover

    try:
        model_data = pyomo.scripting.util.create_model(data)
    except:
        # TBD: I should be able to call this function in the case of
        #      an exception to perform cleanup. However, as it stands
        #      calling finalize with its default keyword value for
        #      model(=None) results in an a different error related to
        #      task port values.  Not sure how to interpret that.
        pyomo.scripting.util.finalize(data,
                                      model=ConcreteModel(),
                                      instance=None,
                                      results=None)
        raise
    else:
        if (((not options.runtime.logging == 'debug') and \
             options.model.save_file) or \
            options.runtime.only_instance):
            pyomo.scripting.util.finalize(data,
                                          model=model_data.model,
                                          instance=model_data.instance,
                                          results=None)
            return Container(instance=model_data.instance)

    try:
        opt_data = pyomo.scripting.util.apply_optimizer(
            data, instance=model_data.instance)

        pyomo.scripting.util.process_results(data,
                                             instance=model_data.instance,
                                             results=opt_data.results,
                                             opt=opt_data.opt)

        pyomo.scripting.util.apply_postprocessing(data,
                                                  instance=model_data.instance,
                                                  results=opt_data.results)
    except:
        # TBD: I should be able to call this function in the case of
        #      an exception to perform cleanup. However, as it stands
        #      calling finalize with its default keyword value for
        #      model(=None) results in an a different error related to
        #      task port values.  Not sure how to interpret that.
        pyomo.scripting.util.finalize(data,
                                      model=ConcreteModel(),
                                      instance=None,
                                      results=None)
        raise
    else:
        pyomo.scripting.util.finalize(data,
                                      model=model_data.model,
                                      instance=model_data.instance,
                                      results=opt_data.results)

        return Container(options=options,
                         instance=model_data.instance,
                         results=opt_data.results,
                         local=opt_data.local)
예제 #17
0
def define_model(**kwds):

    model = ConcreteModel()

    model.x1 = Var(bounds=(-5, 4))  # domain variable
    model.x2 = Var(bounds=(-5, 4))  # domain variable
    model.x3 = Var(bounds=(-5, 4))  # domain variable
    model.x4 = Var(bounds=(-5, 4))  # domain variable
    model.x5 = Var(bounds=(-5, 4))  # domain variable
    model.x6 = Var(bounds=(-5, 4))  # domain variable
    model.x7 = Var(bounds=(-5, 4))  # domain variable

    model.Fx1 = Var()  # range variable
    model.Fx2 = Var()  # range variable
    model.Fx3 = Var()  # range variable
    model.Fx4 = Var()  # range variable
    model.Fx5 = Var()  # range variable
    model.Fx6 = Var()  # range variable
    model.Fx7 = Var()  # range variable

    model.obj = Objective(expr=model.Fx1 + model.Fx2 + model.Fx3 + model.Fx4 +
                          model.Fx5 + model.Fx6 + model.Fx7,
                          sense=kwds.pop('sense', maximize))

    model.piecewise1 = Piecewise(model.Fx1,
                                 model.x1,
                                 pw_pts=DOMAIN_PTS,
                                 f_rule=F,
                                 **kwds)
    model.piecewise2 = Piecewise(model.Fx2,
                                 model.x2,
                                 pw_pts=DOMAIN_PTS,
                                 f_rule=F,
                                 **kwds)
    model.piecewise3 = Piecewise(model.Fx3,
                                 model.x3,
                                 pw_pts=DOMAIN_PTS,
                                 f_rule=F,
                                 **kwds)
    model.piecewise4 = Piecewise(model.Fx4,
                                 model.x4,
                                 pw_pts=DOMAIN_PTS,
                                 f_rule=F,
                                 **kwds)
    model.piecewise5 = Piecewise(model.Fx5,
                                 model.x5,
                                 pw_pts=DOMAIN_PTS,
                                 f_rule=F,
                                 **kwds)
    model.piecewise6 = Piecewise(model.Fx6,
                                 model.x6,
                                 pw_pts=DOMAIN_PTS,
                                 f_rule=F,
                                 **kwds)
    model.piecewise7 = Piecewise(model.Fx7,
                                 model.x7,
                                 pw_pts=DOMAIN_PTS,
                                 f_rule=F,
                                 **kwds)

    #Fix the answer for testing purposes
    model.set_answer_constraint1 = Constraint(expr=model.x1 == -5.0)
    model.set_answer_constraint2 = Constraint(expr=model.x2 == -3.0)
    model.set_answer_constraint3 = Constraint(expr=model.x3 == -2.5)
    model.set_answer_constraint4 = Constraint(expr=model.x4 == -1.5)
    model.set_answer_constraint5 = Constraint(expr=model.x5 == 2.0)
    model.set_answer_constraint6 = Constraint(expr=model.x6 == 3.5)
    model.set_answer_constraint7 = Constraint(expr=model.x7 == 4.0)

    return model
예제 #18
0
 def get_mock_model(self):
     model = ConcreteModel()
     model.x = Var(within=Binary)
     model.con = Constraint(expr=model.x >= 1)
     model.obj = Objective(expr=model.x)
     return model
예제 #19
0
def create_ef_instance(scenario_tree,
                       ef_instance_name="MASTER",
                       verbose_output=False,
                       generate_weighted_cvar=False,
                       cvar_weight=None,
                       risk_alpha=None,
                       cc_indicator_var_name=None,
                       cc_alpha=0.0):

    #
    # create the new and empty binding instance.
    #

    # scenario tree must be "linked" with a set of instances
    # to used this function
    scenario_instances = {}
    for scenario in scenario_tree.scenarios:
        if scenario._instance is None:
            raise ValueError("Cannot construct extensive form instance. "
                             "The scenario tree does not appear to be linked "
                             "to any Pyomo models. Missing model for scenario "
                             "with name: %s" % (scenario.name))
        scenario_instances[scenario.name] = scenario._instance

    binding_instance = ConcreteModel(name=ef_instance_name)
    root_node = scenario_tree.findRootNode()

    opt_sense = minimize \
                if (scenario_tree._scenarios[0]._instance_objective.is_minimizing()) \
                   else maximize

    #
    # validate cvar options, if specified.
    #
    cvar_excess_vardatas = []
    if generate_weighted_cvar:
        if (cvar_weight is None) or (cvar_weight < 0.0):
            raise RuntimeError(
                "Weight of CVaR term must be >= 0.0 - value supplied=" +
                str(cvar_weight))
        if (risk_alpha is None) or (risk_alpha <= 0.0) or (risk_alpha >= 1.0):
            raise RuntimeError(
                "CVaR risk alpha must be between 0 and 1, exclusive - value supplied="
                + str(risk_alpha))

        if verbose_output:
            print("Writing CVaR weighted objective")
            print("CVaR term weight=" + str(cvar_weight))
            print("CVaR alpha=" + str(risk_alpha))
            print("")

        # create the eta and excess variable on a per-scenario basis,
        # in addition to the constraint relating to the two.

        cvar_eta_variable_name = "CVAR_ETA_" + str(root_node._name)
        cvar_eta_variable = Var()
        binding_instance.add_component(cvar_eta_variable_name,
                                       cvar_eta_variable)

        excess_var_domain = NonNegativeReals if (opt_sense == minimize) else \
                            NonPositiveReals

        compute_excess_constraint = \
            binding_instance.COMPUTE_SCENARIO_EXCESS = \
                ConstraintList()

        for scenario in scenario_tree._scenarios:

            cvar_excess_variable_name = "CVAR_EXCESS_" + scenario._name
            cvar_excess_variable = Var(domain=excess_var_domain)
            binding_instance.add_component(cvar_excess_variable_name,
                                           cvar_excess_variable)

            compute_excess_expression = cvar_excess_variable
            compute_excess_expression -= scenario._instance_cost_expression
            compute_excess_expression += cvar_eta_variable
            if opt_sense == maximize:
                compute_excess_expression *= -1

            compute_excess_constraint.add(
                (0.0, compute_excess_expression, None))

            cvar_excess_vardatas.append(
                (cvar_excess_variable, scenario._probability))

    # the individual scenario instances are sub-blocks of the binding instance.
    for scenario in scenario_tree._scenarios:
        scenario_instance = scenario_instances[scenario._name]
        binding_instance.add_component(str(scenario._name), scenario_instance)
        # Now deactivate the scenario instance Objective since we are creating
        # a new master objective
        scenario._instance_objective.deactivate()

    # walk the scenario tree - create variables representing the
    # common values for all scenarios associated with that node, along
    # with equality constraints to enforce non-anticipativity.  also
    # create expected cost variables for each node, to be computed via
    # constraints/objectives defined in a subsequent pass. master
    # variables are created for all nodes but those in the last
    # stage. expected cost variables are, for no particularly good
    # reason other than easy coding, created for nodes in all stages.
    if verbose_output:
        print("Creating variables for master binding instance")

    _cmap = binding_instance.MASTER_CONSTRAINT_MAP = ComponentMap()
    for stage in scenario_tree._stages[:-1]:  # skip the leaf stage

        for tree_node in stage._tree_nodes:

            # create the master blending variable and constraints for this node
            master_blend_variable_name = \
                "MASTER_BLEND_VAR_"+str(tree_node._name)
            master_blend_constraint_name = \
                "MASTER_BLEND_CONSTRAINT_"+str(tree_node._name)

            # don't create master variables for derived
            # stage variables as they will not be used in
            # the problem, and their values would likely
            # never be consistent with what is stored on the
            # scenario variables
            master_variable_index = Set(
                initialize=sorted(tree_node._standard_variable_ids),
                ordered=True,
                name=master_blend_variable_name + "_index")

            binding_instance.add_component(
                master_blend_variable_name + "_index", master_variable_index)

            master_variable = Var(master_variable_index,
                                  name=master_blend_variable_name)

            binding_instance.add_component(master_blend_variable_name,
                                           master_variable)

            master_constraint = ConstraintList(
                name=master_blend_constraint_name)

            binding_instance.add_component(master_blend_constraint_name,
                                           master_constraint)

            tree_node_variable_datas = tree_node._variable_datas
            for variable_id in sorted(tree_node._standard_variable_ids):
                master_vardata = master_variable[variable_id]
                vardatas = tree_node_variable_datas[variable_id]
                # Don't blend fixed variables
                if not tree_node.is_variable_fixed(variable_id):
                    for scenario_vardata, scenario_probability in vardatas:
                        _cmap[scenario_vardata] = master_constraint.add(
                            (master_vardata - scenario_vardata, 0.0))

    if generate_weighted_cvar:

        cvar_cost_expression_name = "CVAR_COST_" + str(root_node._name)
        cvar_cost_expression = Expression(name=cvar_cost_expression_name)
        binding_instance.add_component(cvar_cost_expression_name,
                                       cvar_cost_expression)

    # create an expression to represent the expected cost at the root node
    binding_instance.EF_EXPECTED_COST = \
        Expression(initialize=sum(scenario._probability * \
                                  scenario._instance_cost_expression
                                  for scenario in scenario_tree._scenarios))

    opt_expression = \
        binding_instance.MASTER_OBJECTIVE_EXPRESSION = \
            Expression(initialize=binding_instance.EF_EXPECTED_COST)

    if generate_weighted_cvar:
        cvar_cost_expression_name = "CVAR_COST_" + str(root_node._name)
        cvar_cost_expression = \
            binding_instance.find_component(cvar_cost_expression_name)
        if cvar_weight == 0.0:
            # if the cvar weight is 0, then we're only
            # doing cvar - no mean.
            opt_expression.set_value(cvar_cost_expression)
        else:
            opt_expression.expr += cvar_weight * cvar_cost_expression

    binding_instance.MASTER = Objective(sense=opt_sense, expr=opt_expression)

    # CVaR requires the addition of a variable per scenario to
    # represent the cost excess, and a constraint to compute the cost
    # excess relative to eta.
    if generate_weighted_cvar:

        # add the constraint to compute the master CVaR variable value. iterate
        # over scenario instances to create the expected excess component first.
        cvar_cost_expression_name = "CVAR_COST_" + str(root_node._name)
        cvar_cost_expression = binding_instance.find_component(
            cvar_cost_expression_name)
        cvar_eta_variable_name = "CVAR_ETA_" + str(root_node._name)
        cvar_eta_variable = binding_instance.find_component(
            cvar_eta_variable_name)

        cost_expr = 1.0
        for scenario_excess_vardata, scenario_probability in cvar_excess_vardatas:
            cost_expr += (scenario_probability * scenario_excess_vardata)
        cost_expr /= (1.0 - risk_alpha)
        cost_expr += cvar_eta_variable

        cvar_cost_expression.set_value(cost_expr)

    if cc_indicator_var_name is not None:
        if verbose_output is True:
            print("Creating chance constraint for indicator variable= " +
                  cc_indicator_var_name)
            print("with alpha= " + str(cc_alpha))
        if not isVariableNameIndexed(cc_indicator_var_name):
            cc_expression = 0  #??????
            for scenario in scenario_tree._scenarios:
                scenario_instance = scenario_instances[scenario._name]
                scenario_probability = scenario._probability
                cc_var = scenario_instance.find_component(
                    cc_indicator_var_name)

                cc_expression += scenario_probability * cc_var

            def makeCCRule(expression):
                def CCrule(model):
                    return (1.0 - cc_alpha, cc_expression, None)

                return CCrule

            cc_constraint_name = "cc_" + cc_indicator_var_name
            cc_constraint = Constraint(name=cc_constraint_name,
                                       rule=makeCCRule(cc_expression))
            binding_instance.add_component(cc_constraint_name, cc_constraint)
        else:
            print("multiple cc not yet supported.")
            variable_name, index_template = extractVariableNameAndIndex(
                cc_indicator_var_name)

            # verify that the root variable exists and grab it.
            # NOTE: we are using whatever scenario happens to laying around... it might be better to use the reference
            variable = scenario_instance.find_component(variable_name)
            if variable is None:
                raise RuntimeError("Unknown variable=" + variable_name +
                                   " referenced as the CC indicator variable.")

            # extract all "real", i.e., fully specified, indices matching the index template.
            match_indices = extractComponentIndices(variable, index_template)

            # there is a possibility that no indices match the input template.
            # if so, let the user know about it.
            if len(match_indices) == 0:
                raise RuntimeError("No indices match template=" +
                                   str(index_template) + " for variable=" +
                                   variable_name)

            # add the suffix to all variable values identified.
            for index in match_indices:
                variable_value = variable[index]

                cc_expression = 0  #??????
                for scenario in scenario_tree._scenarios:
                    scenario_instance = scenario_instances[scenario._name]
                    scenario_probability = scenario._probability
                    cc_var = scenario_instance.find_component(
                        variable_name)[index]

                    cc_expression += scenario_probability * cc_var

                def makeCCRule(expression):
                    def CCrule(model):
                        return (1.0 - cc_alpha, cc_expression, None)

                    return CCrule

                indexasname = ''
                for c in str(index):
                    if c not in ' ,':
                        indexasname += c
                cc_constraint_name = "cc_" + variable_name + "_" + indexasname

                cc_constraint = Constraint(name=cc_constraint_name,
                                           rule=makeCCRule(cc_expression))
                binding_instance.add_component(cc_constraint_name,
                                               cc_constraint)

    return binding_instance
    def test_model_with_unrelated_nonlinear_expressions(self):
        m = ConcreteModel()
        m.x = Var([1, 2, 3], bounds=(0, 3))
        m.y = Var()
        m.z = Var()

        @m.Constraint([1, 2])
        def cons(m, i):
            return m.x[i] <= m.y**i

        m.cons2 = Constraint(expr=m.x[1] >= m.y)
        m.cons3 = Constraint(expr=m.x[2] >= m.z - 3)
        # This is vacuous, but I just want something that's not quadratic
        m.cons4 = Constraint(expr=m.x[3] <= log(m.y + 1))

        TransformationFactory('contrib.fourier_motzkin_elimination').\
            apply_to(m, vars_to_eliminate=m.x)
        constraints = m._pyomo_contrib_fme_transformation.projected_constraints

        # 0 <= y <= 3
        cons = constraints[6]
        self.assertEqual(cons.lower, 0)
        self.assertIs(cons.body, m.y)
        cons = constraints[5]
        self.assertEqual(cons.lower, -3)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_linear())
        self.assertEqual(len(body.linear_vars), 1)
        self.assertIs(body.linear_vars[0], m.y)
        self.assertEqual(body.linear_coefs[0], -1)

        # z <= y**2 + 3
        cons = constraints[4]
        self.assertEqual(cons.lower, -3)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_quadratic())
        self.assertEqual(len(body.linear_vars), 1)
        self.assertIs(body.linear_vars[0], m.z)
        self.assertEqual(body.linear_coefs[0], -1)
        self.assertEqual(len(body.quadratic_vars), 1)
        self.assertEqual(body.quadratic_coefs[0], 1)
        self.assertIs(body.quadratic_vars[0][0], m.y)
        self.assertIs(body.quadratic_vars[0][1], m.y)

        # z <= 6
        cons = constraints[2]
        self.assertEqual(cons.lower, -6)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_linear())
        self.assertEqual(len(body.linear_vars), 1)
        self.assertEqual(body.linear_coefs[0], -1)
        self.assertIs(body.linear_vars[0], m.z)

        # 0 <= ln(y+ 1)
        cons = constraints[1]
        self.assertEqual(cons.lower, 0)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_nonlinear())
        self.assertFalse(body.is_quadratic())
        self.assertEqual(len(body.linear_vars), 0)
        self.assertEqual(body.nonlinear_expr.name, 'log')
        self.assertEqual(len(body.nonlinear_expr.args[0].args), 2)
        self.assertIs(body.nonlinear_expr.args[0].args[0], m.y)
        self.assertEqual(body.nonlinear_expr.args[0].args[1], 1)

        # 0 <= y**2
        cons = constraints[3]
        self.assertEqual(cons.lower, 0)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_quadratic())
        self.assertEqual(len(body.quadratic_vars), 1)
        self.assertEqual(body.quadratic_coefs[0], 1)
        self.assertIs(body.quadratic_vars[0][0], m.y)
        self.assertIs(body.quadratic_vars[0][1], m.y)

        # check constraints valid for a selection of points (this is nonconvex,
        # but anyway...)
        pts = [  #(sqrt(3), 6), Not numerically stable enough for this test
            (1, 4), (3, 6), (3, 0), (0, 0), (2, 6)
        ]
        for pt in pts:
            m.y.fix(pt[0])
            m.z.fix(pt[1])
            for i in constraints:
                self.assertLessEqual(value(constraints[i].lower),
                                     value(constraints[i].body))
예제 #21
0
    def test_construct_implicit_disjuncts(self):
        m = ConcreteModel()
        m.x = Var()
        m.y = Var()
        m.d = Disjunction(expr=[m.x <= 0, m.y >= 1])
        self.assertEqual(len(m.component_map(Disjunction)), 1)
        self.assertEqual(len(m.component_map(Disjunct)), 1)

        implicit_disjuncts = list(iterkeys(m.component_map(Disjunct)))
        self.assertEqual(implicit_disjuncts[0][:2], "d_")
        disjuncts = m.d.disjuncts
        self.assertEqual(len(disjuncts), 2)
        self.assertIs(disjuncts[0].parent_block(), m)
        self.assertIs(disjuncts[0].constraint[1].body, m.x)
        self.assertIs(disjuncts[1].parent_block(), m)
        self.assertIs(disjuncts[1].constraint[1].body, m.y)

        # Test that the implicit disjuncts get a unique name
        m.add_component('e_disjuncts', Var())
        m.e = Disjunction(expr=[m.y <= 0, m.x >= 1])
        self.assertEqual(len(m.component_map(Disjunction)), 2)
        self.assertEqual(len(m.component_map(Disjunct)), 2)
        implicit_disjuncts = list(iterkeys(m.component_map(Disjunct)))
        self.assertEqual(implicit_disjuncts[1][:12], "e_disjuncts_")
        disjuncts = m.e.disjuncts
        self.assertEqual(len(disjuncts), 2)
        self.assertIs(disjuncts[0].parent_block(), m)
        self.assertIs(disjuncts[0].constraint[1].body, m.y)
        self.assertIs(disjuncts[1].parent_block(), m)
        self.assertIs(disjuncts[1].constraint[1].body, m.x)
        self.assertEqual(len(disjuncts[0].parent_component().name), 13)
        self.assertEqual(disjuncts[0].name[:12], "e_disjuncts_")

        # Test that the implicit disjuncts can be lists/tuples/generators
        def _gen():
            yield m.y <= 4
            yield m.x >= 5

        m.f = Disjunction(expr=[[m.y <= 0, m.x >= 1], (
            m.y <= 2,
            m.x >= 3), _gen()])
        self.assertEqual(len(m.component_map(Disjunction)), 3)
        self.assertEqual(len(m.component_map(Disjunct)), 3)
        implicit_disjuncts = list(iterkeys(m.component_map(Disjunct)))
        self.assertEqual(implicit_disjuncts[2][:12], "f_disjuncts")
        disjuncts = m.f.disjuncts
        self.assertEqual(len(disjuncts), 3)
        self.assertIs(disjuncts[0].parent_block(), m)
        self.assertIs(disjuncts[0].constraint[1].body, m.y)
        self.assertEqual(disjuncts[0].constraint[1].upper, 0)
        self.assertIs(disjuncts[0].constraint[2].body, m.x)
        self.assertEqual(disjuncts[0].constraint[2].lower, 1)

        self.assertIs(disjuncts[1].parent_block(), m)
        self.assertIs(disjuncts[1].constraint[1].body, m.y)
        self.assertEqual(disjuncts[1].constraint[1].upper, 2)
        self.assertIs(disjuncts[1].constraint[2].body, m.x)
        self.assertEqual(disjuncts[1].constraint[2].lower, 3)

        self.assertIs(disjuncts[2].parent_block(), m)
        self.assertIs(disjuncts[2].constraint[1].body, m.y)
        self.assertEqual(disjuncts[2].constraint[1].upper, 4)
        self.assertIs(disjuncts[2].constraint[2].body, m.x)
        self.assertEqual(disjuncts[2].constraint[2].lower, 5)

        self.assertEqual(len(disjuncts[0].parent_component().name), 11)
        self.assertEqual(disjuncts[0].name, "f_disjuncts[0]")
예제 #22
0
    def test_model_with_unrelated_nonlinear_expressions(self):
        m = ConcreteModel()
        m.x = Var([1, 2, 3], bounds=(0, 3))
        m.y = Var()
        m.z = Var()

        @m.Constraint([1, 2])
        def cons(m, i):
            return m.x[i] <= m.y**i

        m.cons2 = Constraint(expr=m.x[1] >= m.y)
        m.cons3 = Constraint(expr=m.x[2] >= m.z - 3)
        # This is vacuous, but I just want something that's not quadratic
        m.cons4 = Constraint(expr=m.x[3] <= log(m.y + 1))

        fme = TransformationFactory('contrib.fourier_motzkin_elimination')
        fme.apply_to(m,
                     vars_to_eliminate=m.x,
                     projected_constraints_name='projected_constraints',
                     constraint_filtering_callback=None)
        constraints = m.projected_constraints

        # 0 <= y <= 3
        cons = constraints[5]
        self.assertEqual(value(cons.lower), 0)
        self.assertIs(cons.body, m.y)
        cons = constraints[6]
        self.assertEqual(value(cons.lower), -3)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_linear())
        self.assertEqual(len(body.linear_vars), 1)
        self.assertIs(body.linear_vars[0], m.y)
        self.assertEqual(body.linear_coefs[0], -1)

        # z <= y**2 + 3
        cons = constraints[2]
        self.assertEqual(value(cons.lower), -3)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_quadratic())
        self.assertEqual(len(body.linear_vars), 1)
        self.assertIs(body.linear_vars[0], m.z)
        self.assertEqual(body.linear_coefs[0], -1)
        self.assertEqual(len(body.quadratic_vars), 1)
        self.assertEqual(body.quadratic_coefs[0], 1)
        self.assertIs(body.quadratic_vars[0][0], m.y)
        self.assertIs(body.quadratic_vars[0][1], m.y)

        # z <= 6
        cons = constraints[4]
        self.assertEqual(cons.lower, -6)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_linear())
        self.assertEqual(len(body.linear_vars), 1)
        self.assertEqual(body.linear_coefs[0], -1)
        self.assertIs(body.linear_vars[0], m.z)

        # 0 <= ln(y+ 1)
        cons = constraints[1]
        self.assertEqual(value(cons.lower), 0)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_nonlinear())
        self.assertFalse(body.is_quadratic())
        self.assertEqual(len(body.linear_vars), 0)
        self.assertEqual(body.nonlinear_expr.name, 'log')
        self.assertEqual(len(body.nonlinear_expr.args[0].args), 2)
        self.assertIs(body.nonlinear_expr.args[0].args[0], m.y)
        self.assertEqual(body.nonlinear_expr.args[0].args[1], 1)

        # 0 <= y**2
        cons = constraints[3]
        self.assertEqual(value(cons.lower), 0)
        body = generate_standard_repn(cons.body)
        self.assertTrue(body.is_quadratic())
        self.assertEqual(len(body.quadratic_vars), 1)
        self.assertEqual(body.quadratic_coefs[0], 1)
        self.assertIs(body.quadratic_vars[0][0], m.y)
        self.assertIs(body.quadratic_vars[0][1], m.y)

        # check constraints valid for a selection of points (this is nonconvex,
        # but anyway...)
        pts = [  #(sqrt(3), 6), Not numerically stable enough for this test
            (1, 4), (3, 6), (3, 0), (0, 0), (2, 6)
        ]
        for pt in pts:
            m.y.fix(pt[0])
            m.z.fix(pt[1])
            for i in constraints:
                self.assertLessEqual(value(constraints[i].lower),
                                     value(constraints[i].body))
        m.y.fixed = False
        m.z.fixed = False

        # check post process these are non-convex, so I don't want to deal with
        # it... (and this is a good test that I *don't* deal with it.)
        constraints[2].deactivate()
        constraints[3].deactivate()
        constraints[1].deactivate()
        # NOTE also that some of the suproblems in this test are unbounded: We
        # need to keep those constraints.
        fme.post_process_fme_constraints(
            m,
            SolverFactory('glpk'),
            projected_constraints=m.projected_constraints)
        # we needed all the constraints, so we kept them all
        self.assertEqual(len(constraints), 6)

        # last check that if someone activates something on the model in
        # between, we just use it. (I struggle to imagine why you would do this
        # because why withold the information *during* FME, but if there's some
        # reason, we may as well use all the information we've got.)
        m.some_new_cons = Constraint(expr=m.y <= 2)
        fme.post_process_fme_constraints(
            m,
            SolverFactory('glpk'),
            projected_constraints=m.projected_constraints)
        # now we should have lost one constraint
        self.assertEqual(len(constraints), 5)
        # and it should be the y <= 3 one...
        self.assertIsNone(dict(constraints).get(6))
예제 #23
0
파일: test_misc.py 프로젝트: jialuw96/pyomo
 def test_getname(self):
     m = ConcreteModel()
     m.b = Block()
     m.b.v = Var()
     self.assertEqual(m.b.v.getname(fully_qualified=True, relative_to=m.b), 'v')
예제 #24
0
#  ___________________________________________________________________________
#
#  Pyomo: Python Optimization Modeling Objects
#  Copyright 2017 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.core import ConcreteModel, Var, Objective, Constraint, maximize

model = ConcreteModel()

model.x = Var(bounds=(1, None))
model.y = Var(bounds=(1, None))

model.o = Objective(expr=-model.x - model.y, sense=maximize)

model.c = Constraint(expr=model.x + model.y <= 0)
예제 #25
0
파일: test_misc.py 프로젝트: jialuw96/pyomo
 def test_getname_error(self):
     m = ConcreteModel()
     m.b = Block()
     m.b.v = Var()
     m.c = Block()
     self.assertRaises(RuntimeError, m.b.v.getname, fully_qualified=True, relative_to=m.c)
예제 #26
0
def build_model(use_mccormick=False):
    """Build the GDP model."""
    m = ConcreteModel()
    m.F = Var(bounds=(0, 8), doc="Flow into reactor")
    m.X = Var(bounds=(0, 1), doc="Reactor conversion")
    m.d = Param(initialize=2, doc="Max product demand")
    m.c = Param(
        [1, 2, 'I', 'II'],
        doc="Costs",
        initialize={
            1: 2,  # Value of product
            2: 0.2,  # Cost of raw material
            'I': 2.5,  # Cost of reactor I
            'II': 1.5  # Cost of reactor II
        })
    m.alpha = Param(['I', 'II'],
                    doc="Reactor coefficient",
                    initialize={
                        'I': -8,
                        'II': -10
                    })
    m.beta = Param(['I', 'II'],
                   doc="Reactor coefficient",
                   initialize={
                       'I': 9,
                       'II': 15
                   })
    m.X_LB = Param(['I', 'II'],
                   doc="Reactor conversion lower bound",
                   initialize={
                       'I': 0.2,
                       'II': 0.7
                   })
    m.X_UB = Param(['I', 'II'],
                   doc="Reactor conversion upper bound",
                   initialize={
                       'I': 0.95,
                       'II': 0.99
                   })
    m.C_rxn = Var(bounds=(1.5, 2.5), doc="Cost of reactor")
    m.reactor_choice = Disjunction(
        expr=[
            # Disjunct 1: Choose reactor I
            [
                m.F == m.alpha['I'] * m.X + m.beta['I'], m.X_LB['I'] <= m.X,
                m.X <= m.X_UB['I'], m.C_rxn == m.c['I']
            ],
            # Disjunct 2: Choose reactor II
            [
                m.F == m.alpha['II'] * m.X + m.beta['II'], m.X_LB['II'] <= m.X,
                m.X <= m.X_UB['II'], m.C_rxn == m.c['II']
            ]
        ],
        xor=True)
    if use_mccormick:
        m.P = Var(bounds=(0, 8), doc="McCormick approximation of F*X")
        m.mccormick_1 = Constraint(
            expr=m.P <= m.F.lb * m.X + m.F * m.X.ub - m.F.lb * m.X.ub,
            doc="McCormick overestimator")
        m.mccormick_2 = Constraint(
            expr=m.P <= m.F.ub * m.X + m.F * m.X.lb - m.F.ub * m.X.lb,
            doc="McCormick underestimator")
        m.max_demand = Constraint(expr=m.P <= m.d, doc="product demand")
        m.profit = Objective(expr=m.c[1] * m.P - m.c[2] * m.F - m.C_rxn,
                             sense=maximize)
    else:
        m.max_demand = Constraint(expr=m.F * m.X <= m.d, doc="product demand")
        m.profit = Objective(expr=m.c[1] * m.F * m.X - m.c[2] * m.F - m.C_rxn,
                             sense=maximize)

    return m
예제 #27
0
    def test_gdp_tree_nested_indexed_disjunction(self):
        m = ConcreteModel()
        m.I = RangeSet(1, 4)
        m.x = Var(m.I, bounds=(-2, 6))
        m.disj1 = Disjunct()
        self.add_indexed_disjunction(m.disj1, m)
        m.disj2 = Disjunct()
        m.another_disjunction = Disjunction(expr=[m.disj1, m.disj2])

        # First, we still just give the indexed disjunction as a target, and
        # make sure that we don't pick up the parent Disjunct in the tree, since
        # it is not in targets.
        targets = (m.disj1.indexed, )
        knownBlocks = {}
        tree = get_gdp_tree(targets, m, knownBlocks)

        vertices = tree.vertices
        self.assertEqual(len(vertices), 6)
        in_degrees = {
            m.disj1.indexed[0]: 0,
            m.disj1.indexed[1]: 0,
            m.disj1.indexed[0].disjuncts[0]: 1,
            m.disj1.indexed[0].disjuncts[1]: 1,
            m.disj1.indexed[1].disjuncts[0]: 1,
            m.disj1.indexed[1].disjuncts[1]: 1
        }
        for key, val in in_degrees.items():
            self.assertEqual(tree.in_degree(key), val)

        topo_sort = [
            m.disj1.indexed[0], m.disj1.indexed[0].disjuncts[1],
            m.disj1.indexed[0].disjuncts[0], m.disj1.indexed[1],
            m.disj1.indexed[1].disjuncts[1], m.disj1.indexed[1].disjuncts[0]
        ]
        sort = tree.topological_sort()
        for i, node in enumerate(sort):
            self.assertIs(node, topo_sort[i])

        # Now, let targets be everything and make sure that we get the correct
        # tree.
        targets = (m, )
        tree = get_gdp_tree(targets, m, knownBlocks)
        vertices = tree.vertices
        self.assertEqual(len(vertices), 9)
        # update that now the disjunctions have a parent
        in_degrees[m.disj1.indexed[0]] = 1
        in_degrees[m.disj1.indexed[1]] = 1
        # and add new nodes
        in_degrees[m.disj1] = 1
        in_degrees[m.disj2] = 1
        in_degrees[m.another_disjunction] = 0
        for key, val in in_degrees.items():
            self.assertEqual(tree.in_degree(key), val)

        topo_sort = [
            m.another_disjunction, m.disj2, m.disj1, m.disj1.indexed[1],
            m.disj1.indexed[1].disjuncts[1], m.disj1.indexed[1].disjuncts[0],
            m.disj1.indexed[0], m.disj1.indexed[0].disjuncts[1],
            m.disj1.indexed[0].disjuncts[0]
        ]
        sort = tree.topological_sort()
        for i, node in enumerate(sort):
            self.assertIs(node, topo_sort[i])