Exemple #1
0
def localVar():
    """Two-term disjunction which declares a local variable y on one of the 
    disjuncts, which is used in the objective function as well.

    Used to test that we will treat y as global in the transformations, 
    despite where it is declared.
    """
    # y appears in a global constraint and a single disjunct.
    m = ConcreteModel()
    m.x = Var(bounds=(0, 3))

    m.disj1 = Disjunct()
    m.disj1.cons = Constraint(expr=m.x >= 1)

    m.disj2 = Disjunct()
    m.disj2.y = Var(bounds=(1, 3))
    m.disj2.cons = Constraint(expr=m.x + m.disj2.y == 3)

    m.disjunction = Disjunction(expr=[m.disj1, m.disj2])

    # This makes y global actually... But in disguise.
    m.objective = Objective(expr=m.x + m.disj2.y)
    return m
Exemple #2
0
def generate_norm_inf_objective_function(model,
                                         setpoint_model,
                                         discrete_only=False):
    """
    This function generates objective (PF-OA main problem) for minimum Norm Infinity distance to setpoint_model
    Norm-Infinity distance of (x,y) = \max_i |x_i - y_i|

    Parameters
    ----------
    model: Pyomo model
        the model that needs new objective function
    setpoint_model: Pyomo model
        the model that provides the base point for us to calculate the distance
    discrete_only: Bool
        only optimize on distance between the discrete variables
    """
    # skip objective_value variable and slack_var variables
    var_filter = (lambda v: v.is_integer()) if discrete_only \
        else (lambda v: v.name != 'MindtPy_utils.objective_value' and
              'MindtPy_utils.feas_opt.slack_var' not in v.name)
    model_vars = list(filter(var_filter, model.component_data_objects(Var)))
    setpoint_vars = list(
        filter(var_filter, setpoint_model.component_data_objects(Var)))
    assert len(model_vars) == len(
        setpoint_vars
    ), 'Trying to generate Norm Infinity objective function for models with different number of variables'
    model.MindtPy_utils.del_component('L_infinity_obj')
    obj_blk = model.MindtPy_utils.L_infinity_obj = Block()
    obj_blk.L_infinity_obj_var = Var(domain=Reals, bounds=(0, None))
    obj_blk.abs_reform = ConstraintList()
    for v_model, v_setpoint in zip(model_vars, setpoint_vars):
        obj_blk.abs_reform.add(
            expr=v_model - v_setpoint.value >= -obj_blk.L_infinity_obj_var)
        obj_blk.abs_reform.add(
            expr=v_model - v_setpoint.value <= obj_blk.L_infinity_obj_var)

    return Objective(expr=obj_blk.L_infinity_obj_var)
Exemple #3
0
    def _generate_model(self):
        self.model = None
        self.model = ConcreteModel()
        model = self.model
        model._name = self.description

        model.x = Var(domain=RealInterval(bounds=(float('-inf'), None)))
        model.y = Var(bounds=(None, float('inf')))
        model.obj = Objective(expr=model.x - model.y)
        model.c = ConstraintList()
        model.c.add(model.x >= -2)
        model.c.add(model.y <= 3)
        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 == 0
        assert cdata.upper is None
        assert cdata.body() == 1
        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
Exemple #4
0
    def _apply_to(self, instance):
        for c in chain(
                self.get_adjustable_components(instance),
                self.get_adjustable_components(instance, component=Objective)):
            # Collect adjustable var
            adjvar = collect_adjustable(c)
            # Get regular var
            if adjvar.name not in self._adjvar_dict:
                var = Var(adjvar.index_set(), bounds=adjvar._bounds_init_value)
                setattr(instance, adjvar.name + '_nominal', var)
                self._adjvar_dict[adjvar.name] = var
                for i in adjvar:
                    var[i].fixed = adjvar[i].fixed
                    var[i].setlb(adjvar[i].lb)
                    var[i].setub(adjvar[i].ub)
                    var[i].value = adjvar[i].value
            else:
                var = self._adjvar_dict[adjvar.name]
            # Construct substitution map
            sub_map = {id(adjvar[i]): var[i] for i in adjvar}
            # Replace AdjustableVar with Var
            if c.ctype is Objective:
                e_new = replace_expressions(c.expr, substitution_map=sub_map)
                c_new = Objective(expr=e_new, sense=c.sense)
            else:
                e_new = replace_expressions(c.body, substitution_map=sub_map)
                if c.equality:
                    c_new = Constraint(expr=e_new == c.upper)
                else:
                    c_new = Constraint(
                        expr=inequality(c.lower, e_new, c.upper))
            setattr(instance, c.name + '_nominal', c_new)

            self._cons_dict[c.name] = (c, c_new)

            c.deactivate()
Exemple #5
0
def define_model(**kwds):

    model = ConcreteModel()

    model.x = Var(INDEX_SET1, INDEX_SET2, bounds=(-5, 4))  # domain variable
    model.Fx = Var(INDEX_SET1, INDEX_SET2)  # range variable
    model.p = Param(INDEX_SET1, INDEX_SET2, initialize=1.0)

    model.obj = Objective(expr=sum_product(model.Fx),
                          sense=kwds.pop('sense', maximize))

    model.piecewise = Piecewise(INDEX_SET1,
                                INDEX_SET2,
                                model.Fx,
                                model.x,
                                pw_pts=DOMAIN_PTS,
                                f_rule=F,
                                **kwds)

    #Fix the answer for testing purpose
    model.set_answer_constraint1 = Constraint(expr=model.x[1, 0] == -5.0)
    model.set_answer_constraint2 = Constraint(expr=model.x[2, 0] == -3.0)
    model.set_answer_constraint3 = Constraint(expr=model.x[3, 0] == -2.5)
    model.set_answer_constraint4 = Constraint(expr=model.x[4, 0] == -1.5)
    model.set_answer_constraint5 = Constraint(expr=model.x[5, 0] == 2.0)
    model.set_answer_constraint6 = Constraint(expr=model.x[6, 0] == 3.5)
    model.set_answer_constraint7 = Constraint(expr=model.x[7, 0] == 4.0)
    model.set_answer_constraint8 = Constraint(expr=model.x[1, 1] == -5.0)
    model.set_answer_constraint9 = Constraint(expr=model.x[2, 1] == -3.0)
    model.set_answer_constraint10 = Constraint(expr=model.x[3, 1] == -2.5)
    model.set_answer_constraint11 = Constraint(expr=model.x[4, 1] == -1.5)
    model.set_answer_constraint12 = Constraint(expr=model.x[5, 1] == 2.0)
    model.set_answer_constraint13 = Constraint(expr=model.x[6, 1] == 3.5)
    model.set_answer_constraint14 = Constraint(expr=model.x[7, 1] == 4.0)

    return model
Exemple #6
0
def define_model(**kwds):

    model = ConcreteModel()

    model.x = Var(INDEX) # domain variable
    
    model.Fx = Var(INDEX) # range variable

    model.obj = Objective(expr=sum_product(model.Fx)+sum_product(model.x), sense=kwds.pop('sense',maximize))

    model.piecewise = Piecewise(INDEX,model.Fx,model.x,
                                  pw_pts=DOMAIN_PTS,
                                  f_rule=F,
                                  unbounded_domain_var=True,
                                  **kwds)

    #Fix the answer for testing purposes
    model.set_answer_constraint1 = Constraint(expr= model.x[1] == 0.5) # Fx1 should solve to 0
    model.set_answer_constraint2 = Constraint(expr= model.x[2] == 1.0)  # 
    model.set_answer_constraint3 = Constraint(expr= model.Fx[2] == 0.5) # 
    model.set_answer_constraint4 = Constraint(expr= model.x[3] == 1.5) # Fx3 should solve to 1
    model.set_answer_constraint5 = Constraint(expr= model.x[4] == 2.5) # Fx4 should solve to 1.5
    
    return model
Exemple #7
0
def solve_set_cover_mip(model, disj_needs_cover, solve_data, config):
    """Solve the set covering MIP to determine next configuration."""
    m = model
    GDPopt = m.GDPopt_utils
    # number of disjuncts that still need to be covered
    num_needs_cover = sum(1 for disj_bool in disj_needs_cover if disj_bool)
    # number of disjuncts that have been covered
    num_covered = len(disj_needs_cover) - num_needs_cover
    # weights for the set covering problem
    weights = list((num_covered + 1 if disj_bool else 1)
                   for disj_bool in disj_needs_cover)
    # Set up set covering objective
    if hasattr(GDPopt, "set_cover_obj"):
        del GDPopt.set_cover_obj
    GDPopt.set_cover_obj = Objective(expr=sum(
        weight * disj.binary_indicator_var
        for (weight, disj) in zip(weights, GDPopt.disjunct_list)),
                                     sense=maximize)

    mip_results = solve_linear_GDP(m.clone(), solve_data, config)
    if mip_results.feasible:
        config.logger.info('Solved set covering MIP')
    else:
        config.logger.info('Set covering problem is infeasible. '
                           'Problem may have no more feasible '
                           'disjunctive realizations.')
        if solve_data.mip_iteration <= 1:
            config.logger.warning('Set covering problem was infeasible. '
                                  'Check your linear and logical constraints '
                                  'for contradictions.')
        if solve_data.objective_sense == minimize:
            solve_data.LB = float('inf')
        else:
            solve_data.UB = float('-inf')

    return mip_results
Exemple #8
0
def init_max_binaries(solve_data, config):
    """Initialize by maximizing binary variables and disjuncts.

    This function activates as many binary variables and disjucts as
    feasible.

    """
    solve_data.mip_iteration += 1
    linear_GDP = solve_data.linear_GDP.clone()
    config.logger.info("Generating initial linear GDP approximation by "
                       "solving a subproblem that maximizes "
                       "the sum of all binary and logical variables.")
    # Set up binary maximization objective
    linear_GDP.GDPopt_utils.objective.deactivate()
    binary_vars = (v for v in linear_GDP.component_data_objects(
        ctype=Var, descend_into=(Block, Disjunct))
                   if v.is_binary() and not v.fixed)
    linear_GDP.GDPopt_utils.max_binary_obj = Objective(expr=sum(binary_vars),
                                                       sense=maximize)

    # Solve
    mip_results = solve_data.mip_solve_function(linear_GDP, solve_data, config)
    if mip_results.feasible:
        nlp_result = solve_data.nlp_solve_function(mip_results.var_values,
                                                   solve_data, config)
        if nlp_result.feasible:
            solve_data.cut_generation_function(nlp_result, solve_data, config)
        solve_data.integer_cut_function(mip_results.var_values,
                                        solve_data,
                                        config,
                                        feasible=nlp_result.feasible)
    else:
        config.logger.info(
            "Linear relaxation for initialization was infeasible. "
            "Problem is infeasible.")
        return False
Exemple #9
0
def generate_norm1_objective_function(model, setpoint_model, discrete_only=False):
    """This function generates objective (PF-OA main problem) for minimum Norm1 distance to setpoint_model.

    Norm1 distance of (x,y) = \sum_i |x_i - y_i|.

    Args:
        model (Pyomo model): the model that needs new objective function.
        setpoint_model (Pyomo model): the model that provides the base point for us to calculate the distance.
        discrete_only (bool, optional): whether only optimize on distance between the discrete variables. Defaults to False.

    Returns:
        Objective: the norm1 objective function
    """
    # skip objective_value variable and slack_var variables
    var_filter = (lambda v: v.is_integer()) if discrete_only \
        else (lambda v: v.name != 'MindtPy_utils.objective_value' and
              'MindtPy_utils.feas_opt.slack_var' not in v.name)
    model_vars = list(filter(var_filter, model.MindtPy_utils.variable_list))
    setpoint_vars = list(
        filter(var_filter, setpoint_model.MindtPy_utils.variable_list))
    assert len(model_vars) == len(
        setpoint_vars), 'Trying to generate Norm1 objective function for models with different number of variables'
    model.MindtPy_utils.del_component('L1_obj')
    obj_blk = model.MindtPy_utils.L1_obj = Block()
    obj_blk.L1_obj_idx = RangeSet(len(model_vars))
    obj_blk.L1_obj_var = Var(
        obj_blk.L1_obj_idx, domain=Reals, bounds=(0, None))
    obj_blk.abs_reform = ConstraintList()
    for idx, v_model, v_setpoint in zip(obj_blk.L1_obj_idx, model_vars,
                                        setpoint_vars):
        obj_blk.abs_reform.add(
            expr=v_model - v_setpoint.value >= -obj_blk.L1_obj_var[idx])
        obj_blk.abs_reform.add(
            expr=v_model - v_setpoint.value <= obj_blk.L1_obj_var[idx])

    return Objective(expr=sum(obj_blk.L1_obj_var[idx] for idx in obj_blk.L1_obj_idx))
Exemple #10
0
    def add_cut(self,first=False):
        self._iter += 1
        model = self._model

        self._wprod[self._iter] = self._compute_weight_weight_inner_product()
        if first is True:
            self._alphas[self._iter] = -( self._compute_objective_term() + (self._ph._rho/2.0)*self._wprod[self._iter] )
        else:
            self._alphas[self._iter] = -(self._compute_objective_term()) + self._compute_xbar_weight_inner_product()

        if self._solved is True:
            if self._compute_convergence() is True:
                return True

        model.del_component('cuts')
        model.cuts = Set(initialize=sorted(self._alphas.keys()))
        model.del_component('beta')
        model.beta = Var(model.cuts,within=NonNegativeReals)
        model.del_component('beta_sum_one')
        model.beta_sum_one = Constraint(expr=sum_product(model.beta)==1)
        model.del_component('obj')
        model.obj = Objective(expr=sum(self._alphas[i]*model.beta[i] for i in model.cuts))

        self._wbars[self._iter] = {}
        for stage in self._ph._scenario_tree._stages[:-1]: # all blended stages
            for tree_node in stage._tree_nodes:
                self._wbars[self._iter][tree_node._name] = copy.deepcopy(tree_node._wbars)
                block = getattr(model,tree_node._name)
                def _c_rule(block,i):
                    lhs = sum(model.beta[k]*self._wbars[k][tree_node._name][block.id_to_var[i][0]][block.id_to_var[i][1]] for k in model.beta.index_set())
                    if not isinstance(lhs,ExpressionBase):
                        return Constraint.Skip
                    return lhs == 0
                block.del_component('con')
                block.con = Constraint(block.var_index, rule=_c_rule)
        return False
Exemple #11
0
    def _generate_model(self):
        self.model = ConcreteModel()
        model = self.model
        model._name = self.description

        model.f = Var()
        model.x = Var(bounds=(1, 3))
        model.fi = Param([1, 2, 3], mutable=True)
        model.fi[1] = 1.0
        model.fi[2] = 2.0
        model.fi[3] = 0.0
        model.xi = Param([1, 2, 3], mutable=True)
        model.xi[1] = 1.0
        model.xi[2] = 2.0
        model.xi[3] = 3.0
        model.p = Var(within=NonNegativeReals)
        model.n = Var(within=NonNegativeReals)
        model.lmbda = Var([1, 2, 3])
        model.obj = Objective(expr=model.p + model.n)
        model.c1 = ConstraintList()
        model.c1.add((0.0, model.lmbda[1], 1.0))
        model.c1.add((0.0, model.lmbda[2], 1.0))
        model.c1.add(0.0 <= model.lmbda[3])
        model.c2 = SOSConstraint(var=model.lmbda, index=[1, 2, 3], sos=2)
        model.c3 = Constraint(expr=sum_product(model.lmbda) == 1)
        model.c4 = Constraint(
            expr=model.f == sum_product(model.fi, model.lmbda))
        model.c5 = Constraint(
            expr=model.x == sum_product(model.xi, model.lmbda))
        model.x = 2.75
        model.x.fixed = True

        # Make an empty SOSConstraint
        model.c6 = SOSConstraint(var=model.lmbda, index=[1, 2, 3], sos=2)
        model.c6.set_items([], [])
        assert len(list(model.c6.get_items())) == 0
Exemple #12
0
def process_objective(solve_data, config, move_linear_objective=False, use_mcpp=True, updata_var_con_list=True):
    """Process model objective function.

    Check that the model has only 1 valid objective.
    If the objective is nonlinear, move it into the constraints.
    If no objective function exists, emit a warning and create a dummy objective.

    Parameters
    ----------
    solve_data (GDPoptSolveData): solver environment data class
    config (ConfigBlock): solver configuration options
    move_linear_objective (bool): if True, move even linear
        objective functions to the constraints

    """
    m = solve_data.working_model
    util_blk = getattr(m, solve_data.util_block_name)
    # Handle missing or multiple objectives
    active_objectives = list(m.component_data_objects(
        ctype=Objective, active=True, descend_into=True))
    solve_data.results.problem.number_of_objectives = len(active_objectives)
    if len(active_objectives) == 0:
        config.logger.warning(
            'Model has no active objectives. Adding dummy objective.')
        util_blk.dummy_objective = Objective(expr=1)
        main_obj = util_blk.dummy_objective
    elif len(active_objectives) > 1:
        raise ValueError('Model has multiple active objectives.')
    else:
        main_obj = active_objectives[0]
    solve_data.results.problem.sense = ProblemSense.minimize if main_obj.sense == 1 else ProblemSense.maximize
    solve_data.objective_sense = main_obj.sense

    # Move the objective to the constraints if it is nonlinear
    if main_obj.expr.polynomial_degree() not in (1, 0) \
            or move_linear_objective:
        if move_linear_objective:
            config.logger.info("Moving objective to constraint set.")
        else:
            config.logger.info(
                "Objective is nonlinear. Moving it to constraint set.")

        util_blk.objective_value = Var(domain=Reals, initialize=0)
        if mcpp_available() and use_mcpp:
            mc_obj = McCormick(main_obj.expr)
            util_blk.objective_value.setub(mc_obj.upper())
            util_blk.objective_value.setlb(mc_obj.lower())
        else:
            # Use Pyomo's contrib.fbbt package
            lb, ub = compute_bounds_on_expr(main_obj.expr)
            if solve_data.results.problem.sense == ProblemSense.minimize:
                util_blk.objective_value.setlb(lb)
            else:
                util_blk.objective_value.setub(ub)

        if main_obj.sense == minimize:
            util_blk.objective_constr = Constraint(
                expr=util_blk.objective_value >= main_obj.expr)
        else:
            util_blk.objective_constr = Constraint(
                expr=util_blk.objective_value <= main_obj.expr)
        # Deactivate the original objective and add this new one.
        main_obj.deactivate()
        util_blk.objective = Objective(
            expr=util_blk.objective_value, sense=main_obj.sense)
        # Add the new variable and constraint to the working lists
        if main_obj.expr.polynomial_degree() not in (1, 0) or (move_linear_objective and updata_var_con_list):
            util_blk.variable_list.append(util_blk.objective_value)
            util_blk.continuous_variable_list.append(util_blk.objective_value)
            util_blk.constraint_list.append(util_blk.objective_constr)
            util_blk.objective_list.append(util_blk.objective)
            if util_blk.objective_constr.body.polynomial_degree() in (0, 1):
                util_blk.linear_constraint_list.append(util_blk.objective_constr)
            else:
                util_blk.nonlinear_constraint_list.append(
                    util_blk.objective_constr)
Exemple #13
0
def build_nonexclusive_model():
    m = ConcreteModel()
    m.streams = RangeSet(25)
    m.x = Var(m.streams, bounds=(0, 50), initialize=5)

    m.stage1_split = Constraint(expr=m.x[1] == m.x[2] + m.x[4])
    m.unit1 = Disjunction(expr=[
        [
            # Unit 1
            m.x[2] == exp(m.x[3]) - 1,
        ],
        [
            # No Unit 1
            m.x[2] == 0, m.x[3] == 0
        ]
    ])
    m.unit2 = Disjunction(expr=[
        [
            # Unit 2
            m.x[5] == log(m.x[4] + 1),
        ],
        [
            # No Unit 2
            m.x[4] == 0, m.x[5] == 0
        ]
    ])
    m.stage1_mix = Constraint(expr=m.x[3] + m.x[5] == m.x[6])
    m.stage2_split = Constraint(expr=m.x[6] == sum(m.x[i] for i in (7, 9, 11, 13)))
    m.unit3 = Disjunction(expr=[
        [
            # Unit 3
            m.x[8] == 2 * log(m.x[7]) + 3,
            m.x[7] >= 0.2,
        ],
        [
            # No Unit 3
            m.x[7] == 0, m.x[8] == 0
        ]
    ])
    m.unit4 = Disjunction(expr=[
        [
            # Unit 4
            m.x[10] == 1.8 * log(m.x[9] + 4),
        ],
        [
            # No Unit 4
            m.x[9] == 0, m.x[10] == 0
        ]
    ])
    m.unit5 = Disjunction(expr=[
        [
            # Unit 5
            m.x[12] == 1.2 * log(m.x[11]) + 2,
            m.x[11] >= 0.001,
        ],
        [
            # No Unit 5
            m.x[11] == 0, m.x[12] == 0
        ]
    ])
    m.unit6 = Disjunction(expr=[
        [
            # Unit 6
            m.x[15] == sqrt(m.x[14] - 3) * m.x[23] + 1,
            m.x[14] >= 5, m.x[14] <= 20,
        ],
        [
            # No Unit 6
            m.x[14] == 0, m.x[15] == 0
        ]
    ])
    m.stage2_special_mix = Constraint(expr=m.x[14] == m.x[13] + m.x[23])
    m.stage2_mix = Constraint(expr=sum(m.x[i] for i in (8, 10, 12, 15)) == m.x[16])
    m.stage3_split = Constraint(expr=m.x[16] == sum(m.x[i] for i in (17, 19, 21)))
    m.unit7 = Disjunction(expr=[
        [
            # Unit 7
            m.x[18] == m.x[17] * 0.9,
        ],
        [
            # No Unit 7
            m.x[17] == 0, m.x[18] == 0
        ]
    ])
    m.unit8 = Disjunction(expr=[
        [
            # Unit 8
            m.x[20] == log(m.x[19] ** 1.5) + 2,
            m.x[19] >= 1,
        ],
        [
            # No Unit 8
            m.x[19] == 0, m.x[20] == 0
        ]
    ])
    m.unit9 = Disjunction(expr=[
        [
            # Unit 9
            m.x[22] == log(m.x[21] + sqrt(m.x[21])) + 1,
            m.x[21] >= 4,
        ],
        [
            # No Unit 9
            m.x[21] == 0, m.x[22] == 0
        ]
    ])
    m.stage3_special_split = Constraint(expr=m.x[22] == m.x[23] + m.x[24])
    m.stage3_mix = Constraint(expr=m.x[25] == sum(m.x[i] for i in (18, 20, 24)))

    m.obj = Objective(expr=-10 * m.x[25] + m.x[1])

    return m
Exemple #14
0
def build_model():
    """
    Base Model

    Optimal solution:
    Select units 1, 3, 8
    Objective value -36.62
    """
    m = ConcreteModel()
    m.streams = RangeSet(25)
    m.x = Var(m.streams, bounds=(0, 50), initialize=5)

    m.stage1_split = Constraint(expr=m.x[1] == m.x[2] + m.x[4])
    m.first_stage = Disjunction(expr=[
        [
            # Unit 1
            m.x[2] == exp(m.x[3]) - 1,
            m.x[4] == 0, m.x[5] == 0
        ],
        [
            # Unit 2
            m.x[5] == log(m.x[4] + 1),
            m.x[2] == 0, m.x[3] == 0
        ]
    ])
    m.stage1_mix = Constraint(expr=m.x[3] + m.x[5] == m.x[6])
    m.stage2_split = Constraint(expr=m.x[6] == sum(m.x[i] for i in (7, 9, 11, 13)))
    m.second_stage = Disjunction(expr=[
        [
            # Unit 3
            m.x[8] == 2 * log(m.x[7]) + 3,
            m.x[7] >= 0.2,
        ] + [m.x[i] == 0 for i in (9, 10, 11, 12, 14, 15)],
        [
            # Unit 4
            m.x[10] == 1.8 * log(m.x[9] + 4),
        ] + [m.x[i] == 0 for i in (7, 8, 11, 12, 14, 15)],
        [
            # Unit 5
            m.x[12] == 1.2 * log(m.x[11]) + 2,
            m.x[11] >= 0.001,
        ] + [m.x[i] == 0 for i in (7, 8, 9, 10, 14, 15)],
        [
            # Unit 6
            m.x[15] == sqrt(m.x[14] - 3) * m.x[23] + 1,
            m.x[14] >= 5, m.x[14] <= 20,
        ] + [m.x[i] == 0 for i in (7, 8, 9, 10, 11, 12)]
    ])
    m.stage2_special_mix = Constraint(expr=m.x[14] == m.x[13] + m.x[23])
    m.stage2_mix = Constraint(expr=sum(m.x[i] for i in (8, 10, 12, 15)) == m.x[16])
    m.stage3_split = Constraint(expr=m.x[16] == sum(m.x[i] for i in (17, 19, 21)))
    m.third_stage = Disjunction(expr=[
        [
            # Unit 7
            m.x[18] == m.x[17] * 0.9,
        ] + [m.x[i] == 0 for i in (19, 20, 21, 22)],
        [
            # Unit 8
            m.x[20] == log(m.x[19] ** 1.5) + 2,
            m.x[19] >= 1,
        ] + [m.x[i] == 0 for i in (17, 18, 21, 22)],
        [
            # Unit 9
            m.x[22] == log(m.x[21] + sqrt(m.x[21])) + 1,
            m.x[21] >= 4,
        ] + [m.x[i] == 0 for i in (17, 18, 19, 20)]
    ])
    m.stage3_special_split = Constraint(expr=m.x[22] == m.x[23] + m.x[24])
    m.stage3_mix = Constraint(expr=m.x[25] == sum(m.x[i] for i in (18, 20, 24)))

    m.obj = Objective(expr=-10 * m.x[25] + m.x[1])

    return m
Exemple #15
0
def model_is_valid(solve_data, config):
    """Validate that the model is solveable by GDPopt.

    Also preforms some preprocessing such as moving the objective to the
    constraints.

    """
    m = solve_data.working_model
    GDPopt = m.GDPopt_utils

    # Handle LP/NLP being passed to the solver
    prob = solve_data.results.problem
    if (prob.number_of_binary_variables == 0 and
        prob.number_of_integer_variables == 0 and
            prob.number_of_disjunctions == 0):
        config.logger.info('Problem has no discrete decisions.')
        if len(GDPopt.working_nonlinear_constraints) > 0:
            config.logger.info(
                "Your model is an NLP (nonlinear program). "
                "Using NLP solver %s to solve." % config.nlp)
            SolverFactory(config.nlp).solve(
                solve_data.original_model, **config.nlp_options)
            return False
        else:
            config.logger.info(
                "Your model is an LP (linear program). "
                "Using LP solver %s to solve." % config.mip)
            SolverFactory(config.mip).solve(
                solve_data.original_model, **config.mip_options)
            return False

    # Handle missing or multiple objectives
    objs = list(m.component_data_objects(
        ctype=Objective, active=True, descend_into=True))
    num_objs = len(objs)
    solve_data.results.problem.number_of_objectives = num_objs
    if num_objs == 0:
        config.logger.warning(
            'Model has no active objectives. Adding dummy objective.')
        GDPopt.dummy_objective = Objective(expr=1)
        main_obj = GDPopt.dummy_objective
    elif num_objs > 1:
        raise ValueError('Model has multiple active objectives.')
    else:
        main_obj = objs[0]
    solve_data.working_objective_expr = main_obj.expr

    # Move the objective to the constraints

    # TODO only move the objective if nonlinear?
    GDPopt.objective_value = Var(domain=Reals, initialize=0)
    solve_data.objective_sense = main_obj.sense
    if main_obj.sense == minimize:
        GDPopt.objective_expr = Constraint(
            expr=GDPopt.objective_value >= main_obj.expr)
        solve_data.results.problem.sense = ProblemSense.minimize
    else:
        GDPopt.objective_expr = Constraint(
            expr=GDPopt.objective_value <= main_obj.expr)
        solve_data.results.problem.sense = ProblemSense.maximize
    main_obj.deactivate()
    GDPopt.objective = Objective(
        expr=GDPopt.objective_value, sense=main_obj.sense)

    # TODO if any continuous variables are multipled with binary ones, need
    # to do some kind of transformation (Glover?) or throw an error message
    return True
Exemple #16
0
def solve_OA_master(solve_data, config):
    solve_data.mip_iter += 1
    MindtPy = solve_data.mip.MindtPy_utils
    config.logger.info('MIP %s: Solve master problem.' %
                       (solve_data.mip_iter, ))
    # Set up MILP
    for c in MindtPy.constraint_list:
        if c.body.polynomial_degree() not in (1, 0):
            c.deactivate()

    MindtPy.MindtPy_linear_cuts.activate()
    main_objective = next(
        solve_data.mip.component_data_objects(Objective, active=True))
    main_objective.deactivate()

    sign_adjust = 1 if main_objective.sense == minimize else -1
    MindtPy.del_component('MindtPy_oa_obj')

    if config.add_slack:
        MindtPy.del_component('MindtPy_penalty_expr')

        MindtPy.MindtPy_penalty_expr = Expression(
            expr=sign_adjust * config.OA_penalty_factor *
            sum(v for v in MindtPy.MindtPy_linear_cuts.slack_vars[...]))

        MindtPy.MindtPy_oa_obj = Objective(expr=main_objective.expr +
                                           MindtPy.MindtPy_penalty_expr,
                                           sense=main_objective.sense)
    else:
        MindtPy.MindtPy_oa_obj = Objective(expr=main_objective.expr,
                                           sense=main_objective.sense)
    # Deactivate extraneous IMPORT/EXPORT suffixes
    getattr(solve_data.mip, 'ipopt_zL_out', _DoNothing()).deactivate()
    getattr(solve_data.mip, 'ipopt_zU_out', _DoNothing()).deactivate()

    masteropt = SolverFactory(config.mip_solver)
    # determine if persistent solver is called.
    if isinstance(masteropt, PersistentSolver):
        masteropt.set_instance(solve_data.mip, symbolic_solver_labels=True)
    if config.single_tree:
        # Configuration of lazy callback
        lazyoa = masteropt._solver_model.register_callback(
            single_tree.LazyOACallback_cplex)
        # pass necessary data and parameters to lazyoa
        lazyoa.master_mip = solve_data.mip
        lazyoa.solve_data = solve_data
        lazyoa.config = config
        lazyoa.opt = masteropt
        masteropt._solver_model.set_warning_stream(None)
        masteropt._solver_model.set_log_stream(None)
        masteropt._solver_model.set_error_stream(None)
        masteropt.options['timelimit'] = config.time_limit
    master_mip_results = masteropt.solve(
        solve_data.mip, **config.mip_solver_args)  # , tee=True)

    if master_mip_results.solver.termination_condition is tc.optimal:
        if config.single_tree:
            if main_objective.sense == minimize:
                solve_data.LB = max(master_mip_results.problem.lower_bound,
                                    solve_data.LB)
                solve_data.LB_progress.append(solve_data.LB)

                solve_data.UB = min(master_mip_results.problem.upper_bound,
                                    solve_data.UB)
                solve_data.UB_progress.append(solve_data.UB)

    elif master_mip_results.solver.termination_condition is tc.infeasibleOrUnbounded:
        # Linear solvers will sometimes tell me that it's infeasible or
        # unbounded during presolve, but fails to distinguish. We need to
        # resolve with a solver option flag on.
        master_mip_results, _ = distinguish_mip_infeasible_or_unbounded(
            solve_data.mip, config)

    return solve_data.mip, master_mip_results
Exemple #17
0
    def test_handle_termination_condition(self):
        """Test the outer approximation decomposition algorithm."""
        model = SimpleMINLP()
        config = _get_MindtPy_config()
        solve_data = set_up_solve_data(model, config)
        with time_code(solve_data.timing, 'total', is_main_timer=True), \
                create_utility_block(solve_data.working_model, 'MindtPy_utils', solve_data):

            MindtPy = solve_data.working_model.MindtPy_utils

            MindtPy = solve_data.working_model.MindtPy_utils
            setup_results_object(solve_data, config)
            process_objective(
                solve_data,
                config,
                move_linear_objective=(config.init_strategy == 'FP' or
                                       config.add_regularization is not None),
                use_mcpp=config.use_mcpp,
                update_var_con_list=config.add_regularization is None)
            feas = MindtPy.feas_opt = Block()
            feas.deactivate()
            feas.feas_constraints = ConstraintList(
                doc='Feasibility Problem Constraints')

            lin = MindtPy.cuts = Block()
            lin.deactivate()

            if config.feasibility_norm == 'L1' or config.feasibility_norm == 'L2':
                feas.nl_constraint_set = RangeSet(
                    len(MindtPy.nonlinear_constraint_list),
                    doc='Integer index set over the nonlinear constraints.')
                # Create slack variables for feasibility problem
                feas.slack_var = Var(feas.nl_constraint_set,
                                     domain=NonNegativeReals,
                                     initialize=1)
            else:
                feas.slack_var = Var(domain=NonNegativeReals, initialize=1)

            # no-good cuts exclude particular discrete decisions
            lin.no_good_cuts = ConstraintList(doc='no-good cuts')

            fixed_nlp = solve_data.working_model.clone()
            TransformationFactory('core.fix_integer_vars').apply_to(fixed_nlp)

            MindtPy_initialize_main(solve_data, config)

            # test handle_subproblem_other_termination
            termination_condition = tc.maxIterations
            config.add_no_good_cuts = True
            handle_subproblem_other_termination(fixed_nlp,
                                                termination_condition,
                                                solve_data, config)
            self.assertEqual(
                len(solve_data.mip.MindtPy_utils.cuts.no_good_cuts), 1)

            # test handle_main_other_conditions
            main_mip, main_mip_results = solve_main(solve_data, config)
            main_mip_results.solver.termination_condition = tc.infeasible
            handle_main_other_conditions(solve_data.mip, main_mip_results,
                                         solve_data, config)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.feasible)

            main_mip_results.solver.termination_condition = tc.unbounded
            handle_main_other_conditions(solve_data.mip, main_mip_results,
                                         solve_data, config)
            self.assertIn(main_mip.MindtPy_utils.objective_bound,
                          main_mip.component_data_objects(ctype=Constraint))

            main_mip.MindtPy_utils.del_component('objective_bound')
            main_mip_results.solver.termination_condition = tc.infeasibleOrUnbounded
            handle_main_other_conditions(solve_data.mip, main_mip_results,
                                         solve_data, config)
            self.assertIn(main_mip.MindtPy_utils.objective_bound,
                          main_mip.component_data_objects(ctype=Constraint))

            main_mip_results.solver.termination_condition = tc.maxTimeLimit
            handle_main_other_conditions(solve_data.mip, main_mip_results,
                                         solve_data, config)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.maxTimeLimit)

            main_mip_results.solver.termination_condition = tc.other
            main_mip_results.solution.status = SolutionStatus.feasible
            handle_main_other_conditions(solve_data.mip, main_mip_results,
                                         solve_data, config)
            for v1, v2 in zip(
                    main_mip.MindtPy_utils.variable_list,
                    solve_data.working_model.MindtPy_utils.variable_list):
                self.assertEqual(v1.value, v2.value)

            # test handle_feasibility_subproblem_tc
            feas_subproblem = solve_data.working_model.clone()
            add_feas_slacks(feas_subproblem, config)
            MindtPy = feas_subproblem.MindtPy_utils
            MindtPy.feas_opt.activate()
            if config.feasibility_norm == 'L1':
                MindtPy.feas_obj = Objective(expr=sum(
                    s for s in MindtPy.feas_opt.slack_var[...]),
                                             sense=minimize)
            elif config.feasibility_norm == 'L2':
                MindtPy.feas_obj = Objective(expr=sum(
                    s * s for s in MindtPy.feas_opt.slack_var[...]),
                                             sense=minimize)
            else:
                MindtPy.feas_obj = Objective(expr=MindtPy.feas_opt.slack_var,
                                             sense=minimize)

            handle_feasibility_subproblem_tc(tc.optimal, MindtPy, solve_data,
                                             config)
            handle_feasibility_subproblem_tc(tc.infeasible, MindtPy,
                                             solve_data, config)
            self.assertIs(solve_data.should_terminate, True)
            self.assertIs(solve_data.results.solver.status, SolverStatus.error)

            solve_data.should_terminate = False
            solve_data.results.solver.status = None
            handle_feasibility_subproblem_tc(tc.maxIterations, MindtPy,
                                             solve_data, config)
            self.assertIs(solve_data.should_terminate, True)
            self.assertIs(solve_data.results.solver.status, SolverStatus.error)

            solve_data.should_terminate = False
            solve_data.results.solver.status = None
            handle_feasibility_subproblem_tc(tc.solverFailure, MindtPy,
                                             solve_data, config)
            self.assertIs(solve_data.should_terminate, True)
            self.assertIs(solve_data.results.solver.status, SolverStatus.error)

            # test NLP subproblem infeasible
            solve_data.working_model.Y[1].value = 0
            solve_data.working_model.Y[2].value = 0
            solve_data.working_model.Y[3].value = 0
            fixed_nlp, fixed_nlp_results = solve_subproblem(solve_data, config)
            solve_data.working_model.Y[1].value = None
            solve_data.working_model.Y[2].value = None
            solve_data.working_model.Y[3].value = None

            # test handle_nlp_subproblem_tc
            fixed_nlp_results.solver.termination_condition = tc.maxTimeLimit
            handle_nlp_subproblem_tc(fixed_nlp, fixed_nlp_results, solve_data,
                                     config)
            self.assertIs(solve_data.should_terminate, True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.maxTimeLimit)

            fixed_nlp_results.solver.termination_condition = tc.maxEvaluations
            handle_nlp_subproblem_tc(fixed_nlp, fixed_nlp_results, solve_data,
                                     config)
            self.assertIs(solve_data.should_terminate, True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.maxEvaluations)

            fixed_nlp_results.solver.termination_condition = tc.maxIterations
            handle_nlp_subproblem_tc(fixed_nlp, fixed_nlp_results, solve_data,
                                     config)
            self.assertIs(solve_data.should_terminate, True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.maxEvaluations)

            # test handle_fp_main_tc
            config.init_strategy = 'FP'
            solve_data.fp_iter = 1
            init_rNLP(solve_data, config)
            feas_main, feas_main_results = solve_main(solve_data,
                                                      config,
                                                      fp=True)
            feas_main_results.solver.termination_condition = tc.optimal
            fp_should_terminate = handle_fp_main_tc(feas_main_results,
                                                    solve_data, config)
            self.assertIs(fp_should_terminate, False)

            feas_main_results.solver.termination_condition = tc.maxTimeLimit
            fp_should_terminate = handle_fp_main_tc(feas_main_results,
                                                    solve_data, config)
            self.assertIs(fp_should_terminate, True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.maxTimeLimit)

            feas_main_results.solver.termination_condition = tc.infeasible
            fp_should_terminate = handle_fp_main_tc(feas_main_results,
                                                    solve_data, config)
            self.assertIs(fp_should_terminate, True)

            feas_main_results.solver.termination_condition = tc.unbounded
            fp_should_terminate = handle_fp_main_tc(feas_main_results,
                                                    solve_data, config)
            self.assertIs(fp_should_terminate, True)

            feas_main_results.solver.termination_condition = tc.other
            feas_main_results.solution.status = SolutionStatus.feasible
            fp_should_terminate = handle_fp_main_tc(feas_main_results,
                                                    solve_data, config)
            self.assertIs(fp_should_terminate, False)

            feas_main_results.solver.termination_condition = tc.solverFailure
            fp_should_terminate = handle_fp_main_tc(feas_main_results,
                                                    solve_data, config)
            self.assertIs(fp_should_terminate, True)

            # test generate_norm_constraint
            fp_nlp = solve_data.working_model.clone()
            config.fp_main_norm = 'L1'
            generate_norm_constraint(fp_nlp, solve_data, config)
            self.assertIsNotNone(
                fp_nlp.MindtPy_utils.find_component('L1_norm_constraint'))

            config.fp_main_norm = 'L2'
            generate_norm_constraint(fp_nlp, solve_data, config)
            self.assertIsNotNone(fp_nlp.find_component('norm_constraint'))

            fp_nlp.del_component('norm_constraint')
            config.fp_main_norm = 'L_infinity'
            generate_norm_constraint(fp_nlp, solve_data, config)
            self.assertIsNotNone(fp_nlp.find_component('norm_constraint'))

            # test set_solver_options
            config.mip_solver = 'gams'
            config.threads = 1
            opt = SolverFactory(config.mip_solver)
            set_solver_options(opt,
                               solve_data,
                               config,
                               'mip',
                               regularization=False)

            config.mip_solver = 'gurobi'
            config.mip_regularization_solver = 'gurobi'
            config.regularization_mip_threads = 1
            opt = SolverFactory(config.mip_solver)
            set_solver_options(opt,
                               solve_data,
                               config,
                               'mip',
                               regularization=True)

            config.nlp_solver = 'gams'
            config.nlp_solver_args['solver'] = 'ipopt'
            set_solver_options(opt,
                               solve_data,
                               config,
                               'nlp',
                               regularization=False)

            config.nlp_solver_args['solver'] = 'ipopth'
            set_solver_options(opt,
                               solve_data,
                               config,
                               'nlp',
                               regularization=False)

            config.nlp_solver_args['solver'] = 'conopt'
            set_solver_options(opt,
                               solve_data,
                               config,
                               'nlp',
                               regularization=False)

            config.nlp_solver_args['solver'] = 'msnlp'
            set_solver_options(opt,
                               solve_data,
                               config,
                               'nlp',
                               regularization=False)

            config.nlp_solver_args['solver'] = 'baron'
            set_solver_options(opt,
                               solve_data,
                               config,
                               'nlp',
                               regularization=False)

            # test algorithm_should_terminate
            solve_data.should_terminate = True
            solve_data.UB = float('inf')
            self.assertIs(
                algorithm_should_terminate(solve_data,
                                           config,
                                           check_cycling=False), True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.noSolution)

            solve_data.UB = 100
            self.assertIs(
                algorithm_should_terminate(solve_data,
                                           config,
                                           check_cycling=False), True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.feasible)

            solve_data.objective_sense = maximize
            solve_data.LB = float('-inf')
            self.assertIs(
                algorithm_should_terminate(solve_data,
                                           config,
                                           check_cycling=False), True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.noSolution)

            solve_data.LB = 100
            self.assertIs(
                algorithm_should_terminate(solve_data,
                                           config,
                                           check_cycling=False), True)
            self.assertIs(solve_data.results.solver.termination_condition,
                          tc.feasible)
    def post_process_fme_constraints(self, m, solver_factory, tolerance=0):
        """Function that solves a sequence of LPs problems to check if
        constraints are implied by each other. Deletes any that are.

        Parameters
        ----------------
        m: A model, already transformed with FME. Note that if constraints
           have been added, activated, or deactivated, we will check for
           redundancy against the whole active part of the model. If you call
           this straight after FME, you are only checking within the projected
           constraints, but otherwise it is up to the user.
        solver_factory: A SolverFactory object (constructed with a solver
                        which can solve the continuous relaxation of the
                        active constraints on the model. That is, if you
                        had nonlinear constraints unrelated to the variables
                        being projected, you need to either deactivate them or
                        provide a solver which will do the right thing.)
        tolerance: Tolerance at which we decide a constraint is implied by the
                   others. Default is 0, meaning we remove the constraint if
                   the LP solve finds the constraint can be tight but not
                   violated. Setting this to a small positive value would
                   remove constraints more conservatively. Setting it to a
                   negative value would result in a relaxed problem.
        """
        # make sure m looks like what we expect
        if not hasattr(m, "_pyomo_contrib_fme_transformation"):
            raise RuntimeError("It looks like model %s has not been "
                               "transformed with the "
                               "fourier_motzkin_elimination transformation!" %
                               m.name)
        transBlock = m._pyomo_contrib_fme_transformation
        constraints = transBlock.projected_constraints

        # relax integrality so that we can do this with LP solves.
        TransformationFactory('core.relax_integer_vars').apply_to(
            m, transform_deactivated_blocks=True)
        # deactivate any active objectives on the model, and save what we did so
        # we can undo it after.
        active_objs = []
        for obj in m.component_data_objects(Objective, descend_into=True):
            if obj.active:
                active_objs.append(obj)
            obj.deactivate()
        # add placeholder for our own objective
        obj_name = unique_component_name(m, '_fme_post_process_obj')
        obj = Objective(expr=0)
        m.add_component(obj_name, obj)
        for i in constraints:
            # If someone wants us to ignore it and leave it in the model, we
            # can.
            if not constraints[i].active:
                continue
            # deactivate the constraint
            constraints[i].deactivate()
            m.del_component(obj)
            # make objective to maximize its infeasibility
            obj = Objective(expr=constraints[i].body - constraints[i].lower)
            m.add_component(obj_name, obj)
            results = solver_factory.solve(m)
            if results.solver.termination_condition == \
               TerminationCondition.unbounded:
                obj_val = -float('inf')
            elif results.solver.termination_condition != \
               TerminationCondition.optimal:
                raise RuntimeError(
                    "Unsuccessful subproblem solve when checking"
                    "constraint %s.\n\t"
                    "Termination Condition: %s" %
                    (constraints[i].name,
                     results.solver.termination_condition))
            else:
                obj_val = value(obj)
            # if we couldn't make it infeasible, it's useless
            if obj_val >= tolerance:
                m.del_component(constraints[i])
                del constraints[i]
            else:
                constraints[i].activate()

        # clean up
        m.del_component(obj)
        for obj in active_objs:
            obj.activate()
        # undo relax integrality
        TransformationFactory('core.relax_integer_vars').apply_to(m, undo=True)
Exemple #19
0
 def _get_mock_model(self):
     model = ConcreteModel()
     model.X = Var(within=NonNegativeReals, initialize=1.5)
     model.Y = Var(within=Binary, initialize=0)
     model.O = Objective(expr=model.X * model.Y)
     return model
Exemple #20
0
def device_scheduler(
    device_constraints: List[DataFrame],
    ems_constraints: DataFrame,
    commitment_quantities: List[Series],
    commitment_downwards_deviation_price: Union[List[Series], List[float]],
    commitment_upwards_deviation_price: Union[List[Series], List[float]],
) -> Tuple[List[Series], List[float]]:
    """Schedule devices given constraints on a device and EMS level, and given a list of commitments by the EMS.
    The commitments are assumed to be with regards to the flow of energy to the device (positive for consumption,
    negative for production). The solver minimises the costs of deviating from the commitments, and returns the costs
    per commitment.
    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
        derivative max: maximum flow (e.g. in MW or boxes/h)
        derivative min: minimum flow
        derivative equals: exact amount of flow
    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 [], [] * len(commitment_quantities)

    # Check if commitments have the same time window and resolution as the constraints
    start = device_constraints[0].index.values[0]
    resolution = to_timedelta(device_constraints[0].index.freq)
    end = device_constraints[0].index.values[-1] + resolution
    if len(commitment_quantities) != 0:
        start_c = commitment_quantities[0].index.values[0]
        resolution_c = to_timedelta(commitment_quantities[0].index.freq)
        end_c = commitment_quantities[0].index.values[-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(not isinstance(price, Series)
               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(not isinstance(price, Series)
               for price in commitment_upwards_deviation_price):
            commitment_upwards_deviation_price = [
                initialize_series(price, start, end, resolution)
                for price in commitment_upwards_deviation_price
            ]

    # Determine appropriate overall bounds for power and price
    min_down_price = min(min(p) for p in commitment_downwards_deviation_price)
    max_down_price = max(max(p) for p in commitment_downwards_deviation_price)
    min_up_price = min(min(p) for p in commitment_upwards_deviation_price)
    max_up_price = max(max(p) for p in commitment_upwards_deviation_price)
    overall_min_price = min(min_down_price, min_up_price)
    overall_max_price = max(max_down_price, max_up_price)
    overall_min_power = min(ems_constraints["derivative min"])
    overall_max_power = max(ems_constraints["derivative max"])

    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.values) - 1,
                       doc="Set of datetimes")
    model.c = RangeSet(0,
                       len(commitment_quantities) - 1,
                       doc="Set of commitments")

    # Add parameters
    def commitment_quantity_select(m, c, j):
        v = commitment_quantities[c].iloc[j]
        if isnan(v):  # Discount this nan commitment by setting the prices to 0
            commitment_downwards_deviation_price[c].iloc[j] = 0
            commitment_upwards_deviation_price[c].iloc[j] = 0
            return 0
        else:
            return v

    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 device_max_select(m, d, j):
        v = device_constraints[d]["max"].iloc[j]
        if isnan(v):
            return infinity
        else:
            return v

    def device_min_select(m, d, j):
        v = device_constraints[d]["min"].iloc[j]
        if isnan(v):
            return -infinity
        else:
            return 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 isnan(max_v) and isnan(equal_v):
            return infinity
        else:
            return nanmin([max_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 isnan(min_v) and isnan(equal_v):
            return -infinity
        else:
            return nanmax([min_v])

    def device_derivative_equal_select(m, d, j):
        min_v = device_constraints[d]["derivative min"].iloc[j]
        equal_v = device_constraints[d]["derivative equals"].iloc[j]
        if isnan(equal_v):
            return 0
        else:
            return nanmax([equal_v])

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

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

    model.commitment_quantity = Param(model.c,
                                      model.j,
                                      initialize=commitment_quantity_select)
    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.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.device_derivative_equal = Param(
        model.d, model.j, initialize=device_derivative_equal_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)

    # Add variables
    model.power = Var(
        model.d,
        model.j,
        domain=Reals,
        initialize=0,
        bounds=(overall_min_power, overall_max_power),
    )

    # 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.power[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.power[d, j] - m.device_derivative_equal[d, j],
            m.device_derivative_max[d, j],
        )

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

    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.ems_power_bounds = Constraint(model.j, rule=ems_derivative_bounds)

    # Add logical disjunction for deviations
    model.price = Var(model.c,
                      model.j,
                      initialize=0,
                      bounds=(overall_min_price, overall_max_price))

    def up_linker(b, c, d, j):
        # print("In up linker")
        m = b.model()
        ems_power_in_j = sum(m.power[d, j] for d in m.d)
        ems_power_deviation = ems_power_in_j - m.commitment_quantity[c, j]
        # try:
        # print(value(ems_power_deviation))
        # except:
        # pass
        b.linker = Constraint(expr=m.price[c, j] == m.up_price[c, j])
        b.constr = Constraint(expr=ems_power_deviation >= 0)
        b.BigM = Suffix(direction=Suffix.LOCAL)
        b.BigM[b.linker] = 10e5
        return

    def down_linker(b, c, d, j):
        # print("In down linker")
        m = b.model()
        ems_power_in_j = sum(m.power[d, j] for d in m.d)
        ems_power_deviation = ems_power_in_j - m.commitment_quantity[c, j]
        # try:
        # print(value(ems_power_deviation))
        # except:
        # pass
        b.linker = Constraint(expr=m.price[c, j] == m.down_price[c, j])
        b.constr = Constraint(expr=ems_power_deviation <= 0)
        b.BigM = Suffix(direction=Suffix.LOCAL)
        b.BigM[b.linker] = 10e5
        return

    # def zero_linker(b, c, d, j):
    #     #print("In down linker")
    #     m = b.model()
    #     ems_power_in_j = sum(m.power[d, j] for d in m.d)
    #     ems_power_deviation = ems_power_in_j - m.commitment_quantity[c, j]
    #     #try:
    #         #print(value(ems_power_deviation))
    #     #except:
    #         #pass
    #     b.linker = Constraint(expr=m.price[c, j] == 0)
    #     b.constr = Constraint(expr=ems_power_deviation == 0)
    #     #b.BigM = Suffix(direction=Suffix.LOCAL)
    #     #b.BigM[b.linker] = 10e10
    #     return

    model.up_deviation = Disjunct(model.c, model.d, model.j, rule=up_linker)
    model.down_deviation = Disjunct(model.c,
                                    model.d,
                                    model.j,
                                    rule=down_linker)

    # model.zero_deviation = Disjunct(model.c, model.d, model.j, rule=zero_linker)

    def bind_prices(m, c, d, j):
        return [
            model.up_deviation[c, d, j],
            model.down_deviation[c, d, j],
            # model.zero_deviation[c, d, j]
        ]

    model.up_or_down_deviation = Disjunction(model.c,
                                             model.d,
                                             model.j,
                                             rule=bind_prices,
                                             xor=True)

    # Add objective
    def cost_function(m):
        costs = 0
        for j in m.j:
            for c in m.c:
                ems_power_in_j = sum(m.power[d, j] for d in m.d)
                ems_power_deviation = ems_power_in_j - m.commitment_quantity[c,
                                                                             j]
                costs += ems_power_deviation * m.price[c, j]
        return costs

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

    # def xfrm(m):
    #     TransformationFactory('gdp.chull').apply_to(m)
    # model.xfrm = BuildAction(rule=xfrm)

    # Transform and solve
    xfrm = TransformationFactory("gdp.bigm")
    xfrm.apply_to(model)
    solver = SolverFactory(
        "cplex", executable="D:/CPLEX/Studio/cplex/bin/x64_win64/cplex")
    # solver.options['CPXchgprobtype'] = "CPXPROB_QP"
    # solver.options["solver"] = "CPXqpopt"
    solver.options["qpmethod"] = 1
    solver.options["optimalitytarget"] = 3

    # solver.options["acceptable_constr_viol_tol"] = 10
    # solver.options['acceptable_tol'] = 1
    # solver.options['acceptable_dual_inf_tol'] = 10
    # solver.options['acceptable_compl_inf_tol'] = 10
    results = solver.solve(model, tee=False)

    planned_costs = value(model.costs)
    planned_power_per_device = []
    for d in model.d:
        planned_device_power = [
            round(model.power[d, j].value, 3) for j in model.j
        ]
        planned_power_per_device.append(
            initialize_series(planned_device_power,
                              start=start,
                              end=end,
                              resolution=resolution))
    # model.display()
    # results.pprint()
    # model.down_deviation.pprint()
    # model.up_deviation.pprint()
    # model.power.pprint()

    # print(planned_power_per_device)
    # input()

    # Redo the cost calculation, because before the solver actually approximated the prices.
    def redo_cost_calculation(m):
        commitments_costs = []
        for c in m.c:
            commitment_cost = 0
            for j in m.j:

                ems_power_in_j = sum(m.power[d, j] for d in m.d)
                ems_power_deviation = ems_power_in_j - m.commitment_quantity[c,
                                                                             j]

                if value(ems_power_deviation) >= 0:
                    commitment_cost += round(
                        value(ems_power_deviation * m.up_price[c, j]), 3)

                else:
                    commitment_cost += round(
                        value(ems_power_deviation * m.down_price[c, j]), 3)

            commitments_costs.append(commitment_cost)
        return commitments_costs

    planned_costs_per_commitment = redo_cost_calculation(model)
    # print(planned_costs_per_commitment)

    return planned_power_per_device, planned_costs_per_commitment
Exemple #21
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.x, sense=maximize)

model.c = Constraint(expr=model.x+model.y >= 3)
Exemple #22
0
    def _apply_to_impl(self, instance, **kwds):
        config = self.CONFIG(kwds.pop('options', {}))
        config.set_value(kwds)
        targets = config.targets

        if targets is None:
            constraintDatas = instance.component_data_objects(
                Constraint, descend_into=True)
        else:
            constraintDatas = []
            for t in targets:
                if isinstance(t, ComponentUID):
                    cons = t.find_component(instance)
                    if cons.is_indexed():
                        for i in cons:
                            constraintDatas.append(cons[i])
                    else:
                        constraintDatas.append(cons)
                else:
                    # we know it's a constraint because that's all we let
                    # through the config block validation.
                    if t.is_indexed():
                        for i in t:
                            constraintDatas.append(t[i])
                    else:
                        constraintDatas.append(t)

        # deactivate the objective
        for o in instance.component_data_objects(Objective):
            o.deactivate()

        # create block where we can add slack variables safely
        xblockname = unique_component_name(instance, "_core_add_slack_variables")
        instance.add_component(xblockname, Block())
        xblock = instance.component(xblockname)

        obj_expr = 0
        for cons in constraintDatas:
            if (cons.lower is not None and cons.upper is not None) and \
               value(cons.lower) > value(cons.upper):
                # this is a structural infeasibility so slacks aren't going to
                # help:
                raise RuntimeError("Lower bound exceeds upper bound in "
                                   "constraint %s" % cons.name)
            if not cons.active: continue
            cons_name = cons.getname(fully_qualified=True,
                                     name_buffer=NAME_BUFFER)
            if cons.lower is not None:
                # we add positive slack variable to body:
                # declare positive slack
                varName = "_slack_plus_" + cons_name
                posSlack = Var(within=NonNegativeReals)
                xblock.add_component(varName, posSlack)
                # add positive slack to body expression
                cons._body += posSlack
                # penalize slack in objective
                obj_expr += posSlack
            if cons.upper is not None:
                # we subtract a positive slack variable from the body:
                # declare slack
                varName = "_slack_minus_" + cons_name
                negSlack = Var(within=NonNegativeReals)
                xblock.add_component(varName, negSlack)
                # add negative slack to body expression
                cons._body -= negSlack
                # add slack to objective
                obj_expr += negSlack

        # make a new objective that minimizes sum of slack variables
        xblock._slack_objective = Objective(expr=obj_expr)
Exemple #23
0
    def _generate_model(self):
        self.model = ConcreteModel()
        model = self.model
        model._name = self.description

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

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

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

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

        model.x = Var(within=RangeSet(None, None))
        model.x.stale = False

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

        model.X = Var(model.s, within=Integers)
        model.X_initialy_stale = Var(model.s, within=Integers)
        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 + \
                                    sum_product(model.X) + \
                                    sum_product(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 get set
        # 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
Exemple #24
0
    def _create_using(self, model, **kwds):
        """
        Force all variables to lie in the nonnegative orthant.

        Required arguments:
            model       The model to transform.

        Optional keyword arguments:
          pos_suffix    The suffix applied to the 'positive' component of
                            converted variables. Default is '_plus'.
          neg_suffix    The suffix applied to the 'positive' component of
                            converted variables. Default is '_minus'.
        """
        #
        # Optional naming schemes
        #
        pos_suffix = kwds.pop("pos_suffix", "_plus")
        neg_suffix = kwds.pop("neg_suffix", "_minus")
        #
        # We first perform an abstract problem transformation. Then, if model
        # data is available, we instantiate the new model. If not, we construct
        # a mapping that can later be used to populate the new model.
        #
        nonneg = model.clone()
        components = collectAbstractComponents(nonneg)

        # Map from variable base names to a {index, rule} map
        constraint_rules = {}

        # Map from variable base names to a rule defining the domains for that
        # variable
        domain_rules = {}

        # Map from variable base names to its set of indices
        var_indices = {}

        # Map from fully qualified variable names to replacement expressions.
        # For now, it is actually a map from a variable name to a closure that
        # must later be evaulated with a model containing the replacement
        # variables.
        var_map = {}

        #
        # Get the constraints that enforce the bounds and domains of each
        # variable
        #
        for var_name in components["Var"]:
            var = nonneg.__getattribute__(var_name)

            # Individual bounds and domains
            orig_bounds = {}
            orig_domain = {}

            # New indices
            indices = set()

            # Map from constraint names to a constraint rule.
            constraints = {}

            # Map from variable indices to a domain
            domains = {}

            for ndx in var:
                # Fully qualified variable name
                vname = create_name(str(var_name), ndx)

                # We convert each index to a string to avoid difficult issues
                # regarding appending a suffix to tuples.
                #
                # If the index is None, this casts the index to a string,
                # which doesn't match up with how Pyomo treats None indices
                # internally. Replace with "" to be consistent.
                if ndx is None:
                    v_ndx = ""
                else:
                    v_ndx = str(ndx)

                # Get the variable bounds
                lb = value(var[ndx].lb)
                ub = value(var[ndx].ub)
                orig_bounds[ndx] = (lb, ub)

                # Get the variable domain
                if var[ndx].domain is not None:
                    orig_domain[ndx] = var[ndx].domain
                else:
                    orig_domain[ndx] = var.domain

                # Determine the replacement expression. Either a new single
                # variable with the same attributes, or a sum of two new
                # variables.
                #
                # If both the bounds and domain allow for negative values,
                # replace the variable with the sum of nonnegative ones.

                bounds_neg = (orig_bounds[ndx] == (None, None)
                              or orig_bounds[ndx][0] is None
                              or orig_bounds[ndx][0] < 0)
                domain_neg = (orig_domain[ndx] is None
                              or orig_domain[ndx].bounds()[0] is None
                              or orig_domain[ndx].bounds()[0] < 0)
                if bounds_neg and domain_neg:
                    # Make two new variables.
                    posVarSuffix = "%s%s" % (v_ndx, pos_suffix)
                    negVarSuffix = "%s%s" % (v_ndx, neg_suffix)

                    new_indices = (posVarSuffix, negVarSuffix)

                    # Replace the original variable with a sum expression
                    expr_dict = {posVarSuffix: 1, negVarSuffix: -1}
                else:
                    # Add the new index. Lie if is 'None', since Pyomo treats
                    # 'None' specially as a key.
                    #
                    # More lies: don't let a blank index exist. Replace it with
                    # '_'. I don't actually have a justification for this other
                    # than that allowing "" as a key will eventually almost
                    # certainly lead to a strange bug.
                    if v_ndx is None:
                        t_ndx = "None"
                    elif v_ndx == "":
                        t_ndx = "_"
                    else:
                        t_ndx = v_ndx

                    new_indices = (t_ndx, )

                    # Replace the original variable with a sum expression
                    expr_dict = {t_ndx: 1}

                # Add the new indices
                for x in new_indices:
                    indices.add(x)

                # Replace the original variable with an expression
                var_map[vname] = partial(self.sumRule, var_name, expr_dict)

                # Enforce bounds as constraints
                if orig_bounds[ndx] != (None, None):
                    cname = "%s_%s" % (vname, "bounds")
                    tmp = orig_bounds[ndx]
                    constraints[cname] = partial(self.boundsConstraintRule,
                                                 tmp[0], tmp[1], var_name,
                                                 expr_dict)

                # Enforce the bounds of the domain as constraints
                if orig_domain[ndx] != None:
                    cname = "%s_%s" % (vname, "domain_bounds")
                    tmp = orig_domain[ndx].bounds()
                    constraints[cname] = partial(self.boundsConstraintRule,
                                                 tmp[0], tmp[1], var_name,
                                                 expr_dict)

                # Domain will either be NonNegativeReals, NonNegativeIntegers,
                # or Binary. We consider Binary because some solvers may
                # optimize over binary variables.
                if var[ndx].is_continuous():
                    for x in new_indices:
                        domains[x] = NonNegativeReals
                elif var[ndx].is_binary():
                    for x in new_indices:
                        domains[x] = Binary
                elif var[ndx].is_integer():
                    for x in new_indices:
                        domains[x] = NonNegativeIntegers
                else:
                    logger.warning("Warning: domain '%s' not recognized, "
                                   "defaulting to 'NonNegativeReals'" %
                                   (var.domain, ))
                    for x in new_indices:
                        domains[x] = NonNegativeReals

            constraint_rules[var_name] = constraints
            domain_rules[var_name] = partial(self.exprMapRule, domains)
            var_indices[var_name] = indices

        # Remove all existing variables.
        toRemove = []
        for (attr_name, attr) in nonneg.__dict__.items():
            if isinstance(attr, Var):
                toRemove.append(attr_name)
        for attr_name in toRemove:
            nonneg.__delattr__(attr_name)

        # Add the sets defining the variables, then the variables
        for (k, v) in var_indices.items():
            sname = "%s_indices" % k
            nonneg.__setattr__(sname, Set(initialize=v))
            nonneg.__setattr__(
                k,
                Var(nonneg.__getattribute__(sname),
                    domain=domain_rules[k],
                    bounds=(0, None)))

        # Construct the model to get the variables and their indices
        # recognized in the model
        ##nonneg = nonneg.create()

        # Safe to evaluate the modifiedVars mapping
        for var in var_map:
            var_map[var] = var_map[var](nonneg)

        # Map from constraint base names to maps from indices to expressions
        constraintExprs = {}

        #
        # Convert all modified variables in all constraints in the original
        # problem
        #
        for conName in components["Constraint"]:
            con = nonneg.__getattribute__(conName)

            # Map from constraint indices to a corrected expression
            exprMap = {}

            for (ndx, cdata) in con._data.items():
                lower = _walk_expr(cdata.lower, var_map)
                body = _walk_expr(cdata.body, var_map)
                upper = _walk_expr(cdata.upper, var_map)

                # Lie if ndx is None. Pyomo treats 'None' indices specially.
                if ndx is None:
                    ndx = "None"

                # Cast indices to strings, otherwise tuples ruin everything
                exprMap[str(ndx)] = (lower, body, upper)

            # Add to list of expression maps
            constraintExprs[conName] = exprMap

        # Map from constraint base names to maps from indices to expressions
        objectiveExprs = {}

        #
        # Convert all modified variables in all objectives in the original
        # problem
        #
        for objName in components["Objective"]:
            obj = nonneg.__getattribute__(objName)

            # Map from objective indices to a corrected expression
            exprMap = {}

            for (ndx, odata) in obj._data.items():
                exprMap[ndx] = _walk_expr(odata.expr, var_map)

            # Add to list of expression maps
            objectiveExprs[objName] = exprMap

        # Make the modified original constraints
        for (conName, ruleMap) in constraintExprs.items():
            # Make the set of indices
            sname = conName + "_indices"
            _set = Set(initialize=ruleMap.keys())
            nonneg.__setattr__(sname, _set)
            _set.construct()

            # Define the constraint
            _con = Constraint(nonneg.__getattribute__(sname),
                              rule=partial(self.exprMapRule, ruleMap))
            nonneg.__setattr__(conName, _con)
            _con.construct()

        # Make the bounds constraints
        for (varName, ruleMap) in constraint_rules.items():
            conName = varName + "_constraints"
            # Make the set of indices
            sname = conName + "_indices"
            _set = Set(initialize=ruleMap.keys())
            nonneg.__setattr__(sname, _set)
            _set.construct()

            # Define the constraint
            _con = Constraint(nonneg.__getattribute__(sname),
                              rule=partial(self.delayedExprMapRule, ruleMap))
            nonneg.__setattr__(conName, _con)
            _con.construct()

        # Make the objectives
        for (objName, ruleMap) in objectiveExprs.items():
            # Make the set of indices
            sname = objName + "_indices"
            _set = Set(initialize=ruleMap.keys())
            nonneg.__setattr__(sname, _set)
            _set.construct()

            # Define the constraint
            _obj = Objective(nonneg.__getattribute__(sname),
                             rule=partial(self.exprMapRule, ruleMap))
            nonneg.__setattr__(objName, _obj)
            _obj.construct()

        return nonneg
Exemple #25
0
    return model.x[t1, t2] == sum(model.y[t1, t2, i] * PIECEWISE_PTS[t1, t2][i]
                                  for i in xrange(len(PIECEWISE_PTS[t1, t2])))


def constraint2_rule(model, t1, t2):
    return model.Fx[t1,
                    t2] == sum(model.y[t1, t2, i] * F(PIECEWISE_PTS[t1, t2][i])
                               for i in xrange(len(PIECEWISE_PTS[t1, t2])))


def constraint3_rule(model, t1, t2):
    return sum(model.y[t1, t2, j]
               for j in xrange(len(PIECEWISE_PTS[t1, t2]))) == 1


model.obj = Objective(expr=sum_product(model.Fx), sense=maximize)
model.constraint1 = Constraint(INDEX_SET1, INDEX_SET2, rule=constraint1_rule)
model.constraint2 = Constraint(INDEX_SET1, INDEX_SET2, rule=constraint2_rule)
model.constraint3 = Constraint(INDEX_SET1, INDEX_SET2, rule=constraint3_rule)
model.SOS_set_constraint = SOSConstraint(INDEX_SET1,
                                         INDEX_SET2,
                                         var=model.y,
                                         index=model.SOS_indices,
                                         sos=2)

#Fix the answer for testing purposes
model.set_answer_constraint1 = Constraint(expr=model.x[1, 1] == 2.5)
model.set_answer_constraint2 = Constraint(expr=model.x[2, 1] == 1.5)
model.set_answer_constraint3 = Constraint(expr=model.x[1, 2] == 2.5)
model.set_answer_constraint4 = Constraint(expr=model.x[2, 2] == 1.5)
model.set_answer_constraint5 = Constraint(expr=model.x[1, 3] == 2.5)
Exemple #26
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

model = ConcreteModel()

model.x = Var()
model.y = Var()

model.o = Objective(expr=model.x + model.y)
Exemple #27
0
# Objective function:
def obj_rule(m):
    c = len(workers)
    # Our primary objective is to minimize number of workers needed -> sum(c * m.needed[worker])
    # We multiply by a constant 'c' to make sure that this part of the objective is most important.
    # Secondary objective is no_pref (avoiding scheduling 1 days in the weekends)
    return sum(m.no_pref[worker]
               for worker in workers) + sum(c * m.needed[worker]
                                            for worker in workers)


# Now we can add the objective function to the model and set it to be minimized.
# The objective now is to find a schedule minimizing the number of workers needed and once that is done, also reduce
# the number of workers who have to work on Sundays but not on Saturdays.
# The constant used to multiply needed workers makes sure that this is the primary objective,
model.obj = Objective(rule=obj_rule, sense=minimize)

# Now we can add the constraints that describe our food store.

# We create a set of constraints on the model.
model.constraints = ConstraintList()

# 1. Constraint to make sure that all shifts are assigned and appropriate number of workers are working,
for day in days:
    for shift in days_shifts[day]:
        if day != 'Sun' and shift in ['morning', 'evening']:
            # Weekdays and Saturday, morning and evenings have 2 workers.
            # Note that constraints are booleans!
            # Here we make sure that for each variable in works for a given worker, day, shift the sum of Binary values
            # is exactly 2.
            model.constraints.add(
Exemple #28
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
Exemple #29
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
Exemple #30
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.config.solver)
        opt.options.update(self.config.solver_options)
        #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