def test_numerical_instability_almost_canceling(self):
        # It's possible that we get almost-but-not-quite zero on the variable
        # being eliminated when we are doing this with floating point
        # arithmetic. This can get ugly later becuase it might get muliplied by
        # a large number later and start to "reappear"
        m = ConcreteModel()
        m.x = Var()
        m.x0 = Var()
        m.y = Var()

        m.cons1 = Constraint(expr=(1.342 + 2.371e-8)*m.x0 <= m.x + 17*m.y)
        m.cons2 = Constraint(expr=(17.56 + 3.2e-7)*m.x0 >= m.y)
        
        fme = TransformationFactory('contrib.fourier_motzkin_elimination')
        
        fme.apply_to(m, vars_to_eliminate=[m.x0], verbose=True,
                     zero_tolerance=1e-9)

        constraints = m._pyomo_contrib_fme_transformation.projected_constraints

        # There's going to be numerical error here, and I can't really help
        # it. What I care about is that x0 really is gone.

        useful = constraints[1]
        repn = generate_standard_repn(useful.body)
        self.assertTrue(repn.is_linear())
        self.assertEqual(len(repn.linear_coefs), 2) # this is the real test
        self.assertEqual(useful.lower, 0)
        self.assertIs(repn.linear_vars[0], m.x)
        self.assertAlmostEqual(repn.linear_coefs[0], 0.7451564696962295)
        self.assertIs(repn.linear_vars[1], m.y)
        self.assertAlmostEqual(repn.linear_coefs[1], 12.610712377673217)
        self.assertEqual(repn.constant, 0)
        self.assertIsNone(useful.upper)
    def create_hull_model(self):
        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])

        m.obj = Objective(expr=m.p[1] + m.p[2])

        hull = TransformationFactory('gdp.hull')
        hull.apply_to(m)
        disaggregatedVars = ComponentSet([
            hull.get_disaggregated_var(m.p[1], m.time1.disjuncts[0]),
            hull.get_disaggregated_var(m.p[1], m.time1.disjuncts[1]),
            hull.get_disaggregated_var(m.p[1], m.on),
            hull.get_disaggregated_var(m.p[2], m.on),
            hull.get_disaggregated_var(m.p[1], m.startup),
            hull.get_disaggregated_var(m.p[2], m.startup),
            hull.get_disaggregated_var(m.p[1], m.off),
            hull.get_disaggregated_var(m.p[2], m.off)
        ])

        return m, disaggregatedVars
    def test_simple_hull_example(self):
        m = ConcreteModel()
        m.x0 = Var(bounds=(0, 3))
        m.x1 = Var(bounds=(0, 3))
        m.x = Var(bounds=(0, 3))
        m.disaggregation = Constraint(expr=m.x == m.x0 + m.x1)
        m.y = Var(domain=Binary)
        m.cons = Constraint(expr=2 * m.y <= m.x1)

        fme = TransformationFactory('contrib.fourier_motzkin_elimination')
        fme.apply_to(m, vars_to_eliminate=[m.x0, m.x1])

        constraints = m._pyomo_contrib_fme_transformation.projected_constraints
        constraints.pprint()

        self.assertEqual(len(constraints), 1)
        cons = constraints[1]
        self.assertIsNone(cons.upper)
        self.assertEqual(value(cons.lower), 0)
        repn = generate_standard_repn(cons.body)
        self.assertEqual(repn.constant, 0)
        self.assertEqual(len(repn.linear_vars), 2)
        self.assertIs(repn.linear_vars[0], m.x)
        self.assertEqual(repn.linear_coefs[0], 1)
        self.assertIs(repn.linear_vars[1], m.y)
        self.assertEqual(repn.linear_coefs[1], -2)
        self.assertTrue(repn.is_linear())
    def test_projected_constraints_named_correctly(self):
        m = self.make_tiny_model_where_bounds_matter()
        fme = TransformationFactory('contrib.fourier_motzkin_elimination')
        fme.apply_to(m.b, vars_to_eliminate=[m.y],
                     projected_constraints_name='fme_constraints')
        self.assertIsInstance(m.b.component("fme_constraints"), Constraint)
        self.check_tiny_model_constraints(m.b.fme_constraints)

        self.assertIsNone(m.b._pyomo_contrib_fme_transformation.component(
            "projected_constraints"))
Exemplo n.º 5
0
def make_model():
    m = ConcreteModel()
    m.time = ContinuousSet(bounds=(0, 10))
    m.space = ContinuousSet(bounds=(0, 5))
    m.set1 = Set(initialize=['a', 'b', 'c'])
    m.set2 = Set(initialize=['d', 'e', 'f'])
    m.fs = Block()

    m.fs.v0 = Var(m.space, initialize=1)

    @m.fs.Block()
    def b1(b):
        b.v = Var(m.time, m.space, initialize=1)
        b.dv = DerivativeVar(b.v, wrt=m.time, initialize=0)

        b.con = Constraint(m.time,
                           m.space,
                           rule=lambda b, t, x: b.dv[t, x] == 7 - b.v[t, x])
        # Inconsistent

        @b.Block(m.time)
        def b2(b, t):
            b.v = Var(initialize=2)

    @m.fs.Block(m.time, m.space)
    def b2(b, t, x):
        b.v = Var(m.set1, initialize=2)

        @b.Block(m.set1)
        def b3(b, c):
            b.v = Var(m.set2, initialize=3)

            @b.Constraint(m.set2)
            def con(b, s):
                return (5 * b.v[s] == m.fs.b2[m.time.first(),
                                              m.space.first()].v[c])
                # inconsistent

    @m.fs.Constraint(m.time)
    def con1(fs, t):
        return fs.b1.v[t, m.space.last()] == 5

    # Will be inconsistent

    @m.fs.Constraint(m.space)
    def con2(fs, x):
        return fs.b1.v[m.time.first(), x] == fs.v0[x]

    # will be consistent

    disc = TransformationFactory('dae.collocation')
    disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')
    disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')

    return m
    def test_use_all_var_bounds(self):
        m = self.make_tiny_model_where_bounds_matter()

        fme = TransformationFactory('contrib.fourier_motzkin_elimination')
        fme.apply_to(m.b, vars_to_eliminate=[m.y])
        constraints = m.b.\
                      _pyomo_contrib_fme_transformation.projected_constraints

        # if we hadn't included y's bounds, then we wouldn't get any constraints
        # and y wouldn't be eliminated. If we do include y's bounds, we get new
        # information that x <= 5:
        self.check_tiny_model_constraints(constraints)
Exemplo n.º 7
0
 def _presolve(self, *args, **kwds):
     if not isinstance(args[0], six.string_types):
         self._instance = args[0]
         xfrm = TransformationFactory('mpec.nl')
         xfrm.apply_to(self._instance)
         if len(self._instance._transformation_data['mpec.nl'].compl_cuids) == 0:
             # There were no complementarity conditions
             # so we don't hold onto the instance
             self._instance = None
         else:
             args = (self._instance,)
     else:
         self._instance = None
     #
     SystemCallSolver._presolve(self, *args, **kwds)
Exemplo n.º 8
0
 def _presolve(self, *args, **kwds):
     if not isinstance(args[0], six.string_types):
         self._instance = args[0]
         xfrm = TransformationFactory('mpec.nl')
         xfrm.apply_to(self._instance)
         if len(self._instance._transformation_data['mpec.nl'].compl_cuids
                ) == 0:
             # There were no complementarity conditions
             # so we don't hold onto the instance
             self._instance = None
         else:
             args = (self._instance, )
     else:
         self._instance = None
     #
     SystemCallSolver._presolve(self, *args, **kwds)
Exemplo n.º 9
0
    def create_chull_model(self):
        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])

        m.obj = Objective(expr=m.p[1] + m.p[2])

        chull = TransformationFactory('gdp.chull')
        chull.apply_to(m)
        disaggregatedVars = ComponentSet([
            chull.get_disaggregated_var(m.p[1], m.time1.disjuncts[0]),
            chull.get_disaggregated_var(m.p[1], m.time1.disjuncts[1]),
            chull.get_disaggregated_var(m.p[1], m.on),
            chull.get_disaggregated_var(m.p[2], m.on),
            chull.get_disaggregated_var(m.p[1], m.startup),
            chull.get_disaggregated_var(m.p[2], m.startup),
            chull.get_disaggregated_var(m.p[1], m.off),
            chull.get_disaggregated_var(m.p[2], m.off)
        ])

        # from nose.tools import set_trace
        # set_trace()
        # 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]")])

        return m, disaggregatedVars
    def test_integer_arithmetic_non1_coefficients(self):
        m = ConcreteModel()
        m.x = Var(bounds=(0, 9))
        m.y = Var(bounds=(-5, 5))
        m.c1 = Constraint(expr=4 * m.x + m.y >= 4)
        m.c2 = Constraint(expr=m.y >= 2 * m.x)

        fme = TransformationFactory('contrib.fourier_motzkin_elimination')

        fme.apply_to(m,
                     vars_to_eliminate=m.x,
                     constraint_filtering_callback=None,
                     do_integer_arithmetic=True,
                     verbose=True)

        constraints = m._pyomo_contrib_fme_transformation.projected_constraints

        self.assertEqual(len(constraints), 3)

        cons = constraints[3]
        self.assertEqual(value(cons.lower), -32)
        self.assertIs(cons.body, m.y)
        self.assertIsNone(cons.upper)

        cons = constraints[2]
        self.assertEqual(value(cons.lower), 0)
        self.assertIsNone(cons.upper)
        repn = generate_standard_repn(cons.body)
        self.assertTrue(repn.is_linear())
        self.assertEqual(len(repn.linear_coefs), 1)
        self.assertIs(repn.linear_vars[0], m.y)
        self.assertEqual(repn.linear_coefs[0], 2)

        cons = constraints[1]
        self.assertEqual(value(cons.lower), 4)
        self.assertIsNone(cons.upper)
        repn = generate_standard_repn(cons.body)
        self.assertTrue(repn.is_linear())
        self.assertEqual(len(repn.linear_coefs), 1)
        self.assertIs(repn.linear_vars[0], m.y)
        self.assertEqual(repn.linear_coefs[0], 3)
    def test_post_processing(self):
        m, disaggregatedVars = self.create_hull_model()
        fme = TransformationFactory('contrib.fourier_motzkin_elimination')
        fme.apply_to(m, vars_to_eliminate=disaggregatedVars)
        # post-process
        fme.post_process_fme_constraints(m, SolverFactory('glpk'))

        constraints = m._pyomo_contrib_fme_transformation.projected_constraints
        self.assertEqual(len(constraints), 11)

        # They should be the same as the above, but now these are *all* the
        # constraints
        self.check_hull_projected_constraints(
            m, constraints, [6, 5, 16, 17, 15, 9, 8, 1, 2, 3, 4])

        # and check that we didn't change the model
        for disj in m.component_data_objects(Disjunct):
            self.assertIs(disj.indicator_var.domain, Binary)
        self.assertEqual(len([o for o in m.component_data_objects(Objective)]),
                         1)
        self.assertIsInstance(m.component("obj"), Objective)
        self.assertTrue(m.obj.active)
    def test_use_all_var_bounds(self):
        m = ConcreteModel()
        m.b = Block()
        m.x = Var(bounds=(0, 15))
        m.y = Var(bounds=(3, 5))
        m.b.c = Constraint(expr=m.x + m.y <= 8)

        fme = TransformationFactory('contrib.fourier_motzkin_elimination')
        fme.apply_to(m.b, vars_to_eliminate=[m.y])
        constraints = m.b.\
                      _pyomo_contrib_fme_transformation.projected_constraints

        # if we hadn't included y's bounds, then we wouldn't get any constraints
        # and y wouldn't be eliminated. If we do include y's bounds, we get new
        # information that x <= 5:
        self.assertEqual(len(constraints), 1)
        cons = constraints[1]
        self.assertEqual(value(cons.lower), -5)
        self.assertIsNone(cons.upper)
        repn = generate_standard_repn(cons.body)
        self.assertEqual(repn.constant, 0)
        self.assertEqual(len(repn.linear_vars), 1)
        self.assertIs(repn.linear_vars[0], m.x)
        self.assertEqual(repn.linear_coefs[0], -1)
Exemplo n.º 13
0
    def apply_discretization(self, transformation, **kwargs):
        """Discretizes the model.

        :param str transformation: The type of transformation (only dae.collocation...)
        :param dict kwargs: The options for the discretization

        :return: None

        """
        fixed_times = kwargs.pop('fixed_times', None)

        if not self.model.alltime.get_discretization_info():

            discretizer = TransformationFactory(transformation)

            if fixed_times == None:
                discretizer.apply_to(self.model,
                                     wrt=self.model.alltime,
                                     **kwargs)
            else:
                discretizer.apply_to(self.model, wrt=fixed_times, **kwargs)

            self._alltimes = sorted(self.model.alltime)
            self._n_alltimes = len(self._alltimes)

            # This needs to be looked at in more detail to see if it is still needed.

            #added for optional smoothing parameter with reading values from file CS:
            # if self._smoothparam_given:
            #     dfps = pd.DataFrame(index=self.model.alltime, columns=self.model.smoothparameter_names)
            #     for t in self.model.alltime:
            #         if t not in self.model.allsmooth_times:  # for points that are the same in original meas times and feed times
            #             dfps.loc[t] = float(22.) #something that is not between 0 and 1
            #         else:
            #             ps_dict_help = dict()
            #             for p in self.model.smoothparameter_names:
            #                 ps_dict_help[t, p] = value(self.model.smooth_param_data[t, p])
            #             dfps.loc[t] = [ps_dict_help[t, p] for p in self.model.smoothparameter_names]
            #     dfallps = dfps
            #     dfallps.sort_index(inplace=True)
            #     dfallps.index = dfallps.index.to_series().apply(
            #         lambda x: np.round(x, 6))  # time from data rounded to 6 digits

            #     dfallpsall = pd.DataFrame(index=self.model.alltime, columns=self.model.smoothparameter_names)
            #     dfsmoothdata = pd.DataFrame(index=sorted(self.model.smooth_param_datatimes), columns=self.model.smoothparameter_names)

            #     for t in self.model.smooth_param_datatimes:
            #         dfsmoothdata.loc[t] = [value(self.model.smooth_param_data[t, p]) for p in self.model.smoothparameter_names]

            #     for p in self.model.smoothparameter_names:
            #         values = interpolate_trajectory(self.model.alltime, dfsmoothdata[p])
            #         for i, ti in enumerate(self.model.alltime):
            #             if float(dfallps[p][ti]) > 1:
            #                 valueinterp=values[i]
            #                 dfallpsall[p][ti] = float(valueinterp)
            #             else:
            #                 dfallpsall.loc[ti] = float(dfallps[p][ti])

            self._default_initialization()

            # if hasattr(self.model, 'K'):
            #     print('Scaling the parameters')
            #     self.scale_parameters()

        else:
            print(
                '***WARNING: Model already discretized. Ignoring second discretization'
            )
    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,
                     constraint_filtering_callback=None)
        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))
        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[4].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'))
        # 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'))
        # 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(5))
Exemplo n.º 15
0
    def test_get_index_set_except(self):
        '''
        Tests:
          For components indexed by 0, 1, 2, 3, 4 sets:
            get_index_set_except one, then two (if any) of those sets
            check two items that should be in set_except
            insert item(s) back into these sets via index_getter
        '''
        m = ConcreteModel()
        m.time = ContinuousSet(bounds=(0, 10))
        m.space = ContinuousSet(bounds=(0, 10))
        m.set1 = Set(initialize=['a', 'b', 'c'])
        m.set2 = Set(initialize=['d', 'e', 'f'])
        m.v = Var()
        m.v1 = Var(m.time)
        m.v2 = Var(m.time, m.space)
        m.v3 = Var(m.time, m.space, m.set1)
        m.v4 = Var(m.time, m.space, m.set1, m.set2)

        # Multi-dimensional set:
        m.set3 = Set(initialize=[('a', 1), ('b', 2)])
        m.v5 = Var(m.set3)
        m.v6 = Var(m.time, m.space, m.set3)
        m.v7 = Var(m.set3, m.space, m.time)

        disc = TransformationFactory('dae.collocation')
        disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')
        disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')

        # Want this to give a TypeError
        # info = get_index_set_except(m.v, m.time)

        # Indexed by one set
        info = get_index_set_except(m.v1, m.time)
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertTrue(set_except == [None])
        # Variable is not indexed by anything except time
        # Test that index_getter returns only the new value given,
        # regardless of whether it was part of the set excluded (time):
        self.assertEqual(index_getter((), -1), -1)

        # Indexed by two sets
        info = get_index_set_except(m.v2, m.time)
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertTrue(m.space[1] in set_except
                        and m.space.last() in set_except)
	# Here (2,) is the partial index, corresponding to space.
        # Can be provided as a scalar or tuple. 4, the time index,
        # should be inserted before (2,)
        self.assertEqual(index_getter((2,), 4), (4, 2))
        self.assertEqual(index_getter(2, 4), (4, 2))

        # Case where every set is "omitted," now for multiple sets
        info = get_index_set_except(m.v2, m.space, m.time)
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertTrue(set_except == [None])
        # 5, 7 are the desired index values for space, time 
        # index_getter should put them in the right order for m.v2,
        # even if they are not valid indices for m.v2
        self.assertEqual(index_getter((), 5, 7), (7, 5))

        # Indexed by three sets
        info = get_index_set_except(m.v3, m.time)
        # In this case set_except is a product of the two non-time sets
        # indexing v3
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertTrue((m.space[1], 'b') in set_except
                        and (m.space.last(), 'a') in set_except)
        # index_getter inserts a scalar index into an index of length 2
        self.assertEqual(index_getter((2, 'b'), 7), (7, 2, 'b'))

        info = get_index_set_except(m.v3, m.space, m.time)
        # Two sets omitted. Now set_except is just set1
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertTrue('a' in set_except)
        # index_getter inserts the two new indices in the right order
        self.assertEqual(index_getter('b', 1.2, 1.1), (1.1, 1.2, 'b'))

        # Indexed by four sets
        info = get_index_set_except(m.v4, m.set1, m.space)
        # set_except is a product, and there are two indices to insert
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertTrue((m.time[1], 'd') in set_except)
        self.assertEqual(index_getter((4, 'f'), 'b', 8), (4, 8, 'b', 'f'))
        
        # The intended usage of this function looks something like:
        index_set = m.v4.index_set()
        for partial_index in set_except:
            complete_index = index_getter(partial_index, 'a', m.space[2])
            self.assertTrue(complete_index in index_set)
            # Do something for every index of v4 at 'a' and space[2]

        # Indexed by a multi-dimensional set
        info = get_index_set_except(m.v5, m.set3)
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertEqual(set_except, [None])
        self.assertEqual(index_getter((), ('a', 1)), ('a', 1))

        info = get_index_set_except(m.v6, m.set3, m.time)
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertTrue(m.space[1] in set_except)
        self.assertEqual(index_getter(m.space[1], ('b', 2), m.time[1]),
                (m.time[1], m.space[1], 'b', 2))

        info = get_index_set_except(m.v7, m.time)
        set_except = info['set_except']
        index_getter = info['index_getter']
        self.assertIn(('a', 1, m.space[1]), set_except)
        self.assertEqual(index_getter(('a', 1, m.space[1]), m.time[1]),
                         ('a', 1, m.space[1], m.time[1]))

        m.v8 = Var(m.time, m.set3, m.time)
        with self.assertRaises(ValueError):
            info = get_index_set_except(m.v8, m.time)
        with self.assertRaises(ValueError):
            info = get_index_set_except(m.v8, m.space)
Exemplo n.º 16
0
    def test_indexed_by(self):
        m = ConcreteModel()
        m.time = ContinuousSet(bounds=(0, 10))
        m.space = ContinuousSet(bounds=(0, 10))
        m.set = Set(initialize=['a', 'b', 'c'])
        m.set2 = Set(initialize=[('a', 1), ('b', 2)])
        m.v = Var()
        m.v1 = Var(m.time)
        m.v2 = Var(m.time, m.space)
        m.v3 = Var(m.set, m.space, m.time)
        m.v4 = Var(m.time, m.set2)
        m.v5 = Var(m.set2, m.time, m.space)

        @m.Block()
        def b(b):
            b.v = Var()
            b.v1 = Var(m.time)
            b.v2 = Var(m.time, m.space)
            b.v3 = Var(m.set, m.space, m.time)

        @m.Block(m.time)
        def b1(b):
            b.v = Var()
            b.v1 = Var(m.space)
            b.v2 = Var(m.space, m.set)

        @m.Block(m.time, m.space)
        def b2(b):
            b.v = Var()
            b.v1 = Var(m.set)

            @b.Block()
            def b(bl):
                bl.v = Var()
                bl.v1 = Var(m.set)
                bl.v2 = Var(m.time)

        @m.Block(m.set2, m.time)
        def b3(b):
            b.v = Var()
            b.v1 = Var(m.space)

            @b.Block(m.space)
            def b(bb):
                bb.v = Var(m.set)

        disc = TransformationFactory('dae.collocation')
        disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')
        disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')

        self.assertFalse(is_explicitly_indexed_by(m.v, m.time))
        self.assertTrue(is_explicitly_indexed_by(m.b.v2, m.space))
        self.assertTrue(is_explicitly_indexed_by(m.b.v3, m.time, m.space))

        self.assertFalse(is_in_block_indexed_by(m.v1, m.time))
        self.assertFalse(is_in_block_indexed_by(m.v2, m.set))
        self.assertTrue(is_in_block_indexed_by(m.b1[m.time[1]].v2, m.time))

        self.assertTrue(is_in_block_indexed_by(
            m.b2[m.time[1], m.space[1]].b.v1, m.time))
        self.assertTrue(is_in_block_indexed_by(
            m.b2[m.time[1], m.space[1]].b.v2, m.time))
        self.assertTrue(is_explicitly_indexed_by(
            m.b2[m.time[1], m.space[1]].b.v2, m.time))
        self.assertFalse(is_in_block_indexed_by(
            m.b2[m.time[1], m.space[1]].b.v1, m.set))

        self.assertFalse(is_in_block_indexed_by(
            m.b2[m.time[1], m.space[1]].b.v1, 
            m.space, stop_at=m.b2[m.time[1], m.space[1]]))

        # Explicit indexing with multi-dimensional set:
        self.assertTrue(is_explicitly_indexed_by(m.v4, m.time, m.set2))
        self.assertTrue(is_explicitly_indexed_by(m.v5, m.time, m.set2, m.space))

        # Implicit indexing with multi-dimensional set:
        self.assertTrue(is_in_block_indexed_by(
            m.b3['a', 1, m.time[1]].v, m.set2))
        self.assertTrue(is_in_block_indexed_by(
            m.b3['a', 1, m.time[1]].v, m.time))
        self.assertTrue(is_in_block_indexed_by(
            m.b3['a', 1, m.time[1]].v1[m.space[1]], m.set2))
        self.assertFalse(is_in_block_indexed_by(
            m.b3['a', 1, m.time[1]].v1[m.space[1]], m.space))
        self.assertTrue(is_in_block_indexed_by(
            m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.set2))
        self.assertTrue(is_in_block_indexed_by(
            m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time))
        self.assertTrue(is_in_block_indexed_by(
            m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.space))
        self.assertFalse(is_in_block_indexed_by(
            m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.set))
        self.assertFalse(is_in_block_indexed_by(
            m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time,
            stop_at=m.b3['b', 2, m.time[2]]))
        self.assertFalse(is_in_block_indexed_by(
            m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time,
            stop_at=m.b3))
    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)