示例#1
0
    def _transform_constraintData(self, logical_constraint, new_varlists,
                                  transBlocks):
        # first find all the relevant BooleanVars and associate a binary (if
        # they don't have one already)
        for bool_vardata in identify_variables(logical_constraint.expr):
            if bool_vardata.ctype is BooleanVar:
                self._transform_boolean_varData(bool_vardata, new_varlists)

        # now create a transformation block on the constraint's parent block (if
        # we don't have one already)
        parent_block = logical_constraint.parent_block()
        xfrm_block = transBlocks.get(parent_block)
        if xfrm_block is None:
            xfrm_block = self._create_transformation_block(parent_block)
            transBlocks[parent_block] = xfrm_block
        new_constrlist = xfrm_block.transformed_constraints
        new_boolvarlist = xfrm_block.augmented_vars
        new_varlist = xfrm_block.augmented_vars_asbinary

        old_boolvarlist_length = len(new_boolvarlist)

        indicator_map = ComponentMap()
        cnf_statements = to_cnf(logical_constraint.body, new_boolvarlist,
                                indicator_map)
        logical_constraint.deactivate()

        # Associate new Boolean vars to new binary variables
        num_new = len(new_boolvarlist) - old_boolvarlist_length
        list_o_vars = list(new_boolvarlist.values())
        if num_new:
            for bool_vardata in list_o_vars[-num_new:]:
                new_binary_vardata = new_varlist.add()
                bool_vardata.associate_binary_var(new_binary_vardata)

        # Add constraints associated with each CNF statement
        for cnf_statement in cnf_statements:
            for linear_constraint in _cnf_to_linear_constraint_list(
                    cnf_statement):
                new_constrlist.add(expr=linear_constraint)

        # Add bigM associated with special atoms
        # Note: this ad-hoc reformulation may be revisited for tightness in the
        # future.
        old_varlist_length = len(new_varlist)
        for indicator_var, special_atom in indicator_map.items():
            for linear_constraint in _cnf_to_linear_constraint_list(
                    special_atom,
                    indicator_var,
                    new_varlist):
                new_constrlist.add(expr=linear_constraint)

        # Previous step may have added auxiliary binaries. Associate augmented
        # Booleans to them.
        num_new = len(new_varlist) - old_varlist_length
        list_o_vars = list(new_varlist.values())
        if num_new:
            for binary_vardata in list_o_vars[-num_new:]:
                new_bool_vardata = new_boolvarlist.add()
                new_bool_vardata.associate_binary_var(binary_vardata)
    def test_cnf(self):
        m = ConcreteModel()
        m.Y1 = BooleanVar()
        m.Y2 = BooleanVar()

        implication = implies(m.Y1, m.Y2)
        x = to_cnf(implication)[0]
        _check_equivalent(self, implication, x)

        atleast_expr = atleast(1, m.Y1, m.Y2)
        x = to_cnf(atleast_expr)[0]
        self.assertIs(atleast_expr, x)  # should be no change

        nestedatleast = implies(m.Y1, atleast_expr)
        m.extraY = BooleanVarList()
        indicator_map = ComponentMap()
        x = to_cnf(nestedatleast, m.extraY, indicator_map)
        self.assertEqual(str(x[0]), "extraY[1] ∨ ~Y1")
        self.assertIs(indicator_map[m.extraY[1]], atleast_expr)
示例#3
0
def _process_logical_constraints_in_logical_context(context):
    new_xfrm_block_name = unique_component_name(context, 'logic_to_linear')
    new_xfrm_block = Block(doc="Transformation objects for logic_to_linear")
    setattr(context, new_xfrm_block_name, new_xfrm_block)

    new_constrlist = new_xfrm_block.transformed_constraints = ConstraintList()
    new_boolvarlist = new_xfrm_block.augmented_vars = BooleanVarList()
    new_varlist = new_xfrm_block.augmented_vars_asbinary = VarList(
        domain=Binary)

    indicator_map = ComponentMap()
    cnf_statements = []
    # Convert all logical constraints to CNF
    for logical_constraint in context.component_data_objects(
            ctype=LogicalConstraint, active=True):
        cnf_statements.extend(
            to_cnf(logical_constraint.body, new_boolvarlist, indicator_map))
        logical_constraint.deactivate()

    # Associate new Boolean vars to new binary variables
    for bool_vardata in new_boolvarlist.values():
        new_binary_vardata = new_varlist.add()
        bool_vardata.associate_binary_var(new_binary_vardata)

    # Add constraints associated with each CNF statement
    for cnf_statement in cnf_statements:
        for linear_constraint in _cnf_to_linear_constraint_list(cnf_statement):
            new_constrlist.add(expr=linear_constraint)

    # Add bigM associated with special atoms
    # Note: this ad-hoc reformulation may be revisited for tightness in the future.
    old_varlist_length = len(new_varlist)
    for indicator_var, special_atom in indicator_map.items():
        for linear_constraint in _cnf_to_linear_constraint_list(
                special_atom, indicator_var, new_varlist):
            new_constrlist.add(expr=linear_constraint)

    # Previous step may have added auxiliary binaries. Associate augmented Booleans to them.
    num_new = len(new_varlist) - old_varlist_length
    list_o_vars = list(new_varlist.values())
    if num_new:
        for binary_vardata in list_o_vars[-num_new:]:
            new_bool_vardata = new_boolvarlist.add()
            new_bool_vardata.associate_binary_var(binary_vardata)

    # If added components were not used, remove them.
    # Note: it is ok to simply delete the index_set for these components, because by
    # default, a new set object is generated for each [Thing]List.
    if len(new_constrlist) == 0:
        new_xfrm_block.del_component(new_constrlist.index_set())
        new_xfrm_block.del_component(new_constrlist)
    if len(new_boolvarlist) == 0:
        new_xfrm_block.del_component(new_boolvarlist.index_set())
        new_xfrm_block.del_component(new_boolvarlist)
    if len(new_varlist) == 0:
        new_xfrm_block.del_component(new_varlist.index_set())
        new_xfrm_block.del_component(new_varlist)

    # If block was entirely unused, remove it
    if all(
            len(l) == 0
            for l in (new_constrlist, new_boolvarlist, new_varlist)):
        context.del_component(new_xfrm_block)