def point_in_set(self, point): """ Calculates if supplied ``point`` is contained in the uncertainty set. Returns True or False. Args: point: The point being checked for membership in the set. The coordinates of the point should be supplied in the same order as the elements of ``uncertain_params`` that is to be supplied to the PyROS solve statement. This point must match the dimension of the uncertain parameters of the set. """ # === Ensure point is of correct dimensionality as the uncertain parameters if len(point) != self.dim: raise AttributeError("Point must have same dimensions as uncertain parameters.") m = ConcreteModel() the_params = [] for i in range(self.dim): m.add_component("x_%s" % i, Var(initialize=point[i])) the_params.append(getattr(m, "x_%s" % i)) # === Generate constraint for set set_constraint = self.set_as_constraint(uncertain_params=the_params) # === value() returns True if the constraint is satisfied, False else. is_in_set = all(value(con.expr) for con in set_constraint.values()) return is_in_set
def test_remove(self): model = self.model model = ConcreteModel() index = range(5) model.c = self._ctype(self._cdatatype(self._arg) for i in index) for i in index: cdata = model.c[0] self.assertEqual(cdata in model.c, True) model.c.remove(cdata) self.assertEqual(cdata in model.c, False)
def compile(self, start_time='20140101', recompile=False): """ Compile the optimization problem :param start_time: Start time of this modesto instance. Either a pandas Timestamp object or a string of format 'yyyymmdd'. Default '20140101'. :param recompile: True if model should be recompiled. If False, only mutable parameters are reloaded. :return: """ # Set time if isinstance(start_time, str): self.start_time = pd.Timestamp(start_time) elif isinstance(start_time, pd.Timestamp): self.start_time = start_time else: raise IOError( "start_time specifier not recognized. Should be " "either string of format 'yyyymmdd' or pd.Timestamp.") # Check if not compiled already if self.compiled: if not recompile and not self.temperature_driven: self.logger.info( 'Model was already compiled. Only changing mutable parameters.' ) else: self.model = ConcreteModel() self.compiled = False for comp in self.components: self.components[comp].reinit() self.logger.info('Recompiling model.') # Check whether all necessary parameters are there self.check_data() self.update_time(self.start_time) # Components for name in self.get_edges(): edge_obj = self.get_component(name=name) edge_obj.compile(self.model, start_time) nodes = self.get_nodes() for node in nodes: node_obj = self.get_component(name=node) node_obj.compile(self.model, start_time) if not self.compiled or recompile: self.__build_objectives() self.compiled = True # Change compilation flag return
def is_bounded(self, config): """ Return True if the uncertainty set is bounded, else False. """ # === Determine bounds on all uncertain params bounding_model = ConcreteModel() bounding_model.util = Block() # So that boundedness checks work for Cardinality and FactorModel sets bounding_model.uncertain_param_vars = IndexedVar(range(len(config.uncertain_params)), initialize=1) for idx, param in enumerate(config.uncertain_params): bounding_model.uncertain_param_vars[idx].value = param.value bounding_model.add_component("uncertainty_set_constraint", config.uncertainty_set.set_as_constraint( uncertain_params=bounding_model.uncertain_param_vars, model=bounding_model, config=config )) for idx, param in enumerate(list(bounding_model.uncertain_param_vars.values())): bounding_model.add_component("lb_obj_" + str(idx), Objective(expr=param, sense=minimize)) bounding_model.add_component("ub_obj_" + str(idx), Objective(expr=param, sense=maximize)) for o in bounding_model.component_data_objects(Objective): o.deactivate() for i in range(len(bounding_model.uncertain_param_vars)): for limit in ("lb", "ub"): getattr(bounding_model, limit + "_obj_" + str(i)).activate() res = config.global_solver.solve(bounding_model, tee=False) getattr(bounding_model, limit + "_obj_" + str(i)).deactivate() if not check_optimal_termination(res): return False return True
def test_setitem(self): model = self.model model = ConcreteModel() model.c = self._ctype() index = ['a', 1, None, (1,), (1,2)] for i in index: self.assertTrue(i not in model.c) for cnt, i in enumerate(index, 1): model.c[i] = self._cdatatype(self._arg) self.assertEqual(len(model.c), cnt) self.assertTrue(i in model.c)
def test_setitem(self): model = self.model model = ConcreteModel() model.c = self._ctype() index = ['a', 1, None, (1, ), (1, 2)] for i in index: self.assertTrue(i not in model.c) for cnt, i in enumerate(index, 1): model.c[i] = self._cdatatype(self._arg()) self.assertEqual(len(model.c), cnt) self.assertTrue(i in model.c)
def make_model_tri(n, small_val=1e-7, big_val=1e2): m = ConcreteModel() m.x = Var(range(n), initialize=0.5) def c_rule(m, i): return big_val*m.x[i-1] + small_val*m.x[i] + big_val*m.x[i+1] == 1 m.c = Constraint(range(1,n-1), rule=c_rule) m.obj = Objective(expr=small_val*sum((m.x[i]-1)**2 for i in range(n))) return m
def test_active(self): model = self.model model = ConcreteModel() model.c = self._ctype() self.assertEqual(model.c.active, True) model.c.deactivate() self.assertEqual(model.c.active, False) model.c.append(self._cdatatype(self._arg)) self.assertEqual(model.c.active, True) model.c.deactivate() self.assertEqual(model.c.active, False) model.c.insert(0, self._cdatatype(self._arg)) self.assertEqual(model.c.active, True)
def add_bounds_for_uncertain_parameters(model, config): ''' This function solves a set of optimization problems to determine bounds on the uncertain parameters given the uncertainty set description. These bounds will be added as additional constraints to the uncertainty_set_constr constraint. Should only be called once set_as_constraint() has been called on the separation_model object. :param separation_model: the model on which to add the bounds :param config: solver config :return: ''' # === Determine bounds on all uncertain params uncertain_param_bounds = [] bounding_model = ConcreteModel() bounding_model.util = Block() bounding_model.util.uncertain_param_vars = IndexedVar( model.util.uncertain_param_vars.index_set()) for tup in model.util.uncertain_param_vars.items(): bounding_model.util.uncertain_param_vars[tup[0]].value = tup[1].value bounding_model.add_component( "uncertainty_set_constraint", config.uncertainty_set.set_as_constraint( uncertain_params=bounding_model.util.uncertain_param_vars, model=bounding_model, config=config)) for idx, param in enumerate( list(bounding_model.util.uncertain_param_vars.values())): bounding_model.add_component("lb_obj_" + str(idx), Objective(expr=param, sense=minimize)) bounding_model.add_component("ub_obj_" + str(idx), Objective(expr=param, sense=maximize)) for o in bounding_model.component_data_objects(Objective): o.deactivate() for i in range(len(bounding_model.util.uncertain_param_vars)): bounds = [] for limit in ("lb", "ub"): getattr(bounding_model, limit + "_obj_" + str(i)).activate() res = config.global_solver.solve(bounding_model, tee=False) bounds.append(bounding_model.util.uncertain_param_vars[i].value) getattr(bounding_model, limit + "_obj_" + str(i)).deactivate() uncertain_param_bounds.append(bounds) # === Add bounds as constraints to uncertainty_set_constraint ConstraintList for idx, bound in enumerate(uncertain_param_bounds): model.util.uncertain_param_vars[idx].setlb(bound[0]) model.util.uncertain_param_vars[idx].setub(bound[1]) return
def initial_construct_master(model_data): """ Constructs the iteration 0 master problem return: a MasterProblemData object containing the master_model object """ m = ConcreteModel() m.scenarios = Block(NonNegativeIntegers, NonNegativeIntegers) master_data = MasterProblemData() master_data.original = model_data.working_model.clone() master_data.master_model = m master_data.timing = model_data.timing return master_data
def __init__(self, pipe_model, graph, repr_days=None): """ This class allows setting up optimization problems for district energy systems :param horizon: The horizon of the optimization problem, in seconds :param time_step: The time step between two points :param objective: String describing the objective of the optimization problem :param pipe_model: String describing the type of model to be used for the pipes :param graph: networkx object, describing the structure of the network :param repr_days: None if regular optimization. Dict of days of year mapped to representative days if used. """ self.model = ConcreteModel(name=Modesto) self.results = None self.pipe_model = pipe_model if pipe_model == 'NodeMethod': self.temperature_driven = True else: self.temperature_driven = False self.allow_flow_reversal = True self.start_time = None if repr_days is not None: self.repr_days = {i: int(round(j)) for i, j in repr_days.items()} else: self.repr_days = repr_days self.graph = graph self.edges = {} self.nodes = {} self.components = {} self.params = self.create_params() self.logger = logging.getLogger('modesto.main.Modesto') self.build(graph) self.compiled = False self.objectives = {} self.act_objective = None
def two_objective_model(): model = ConcreteModel() # Define variables model.x1 = Var(within=NonNegativeReals) model.x2 = Var(within=NonNegativeReals) # -------------------------------------- # Define the objective functions # -------------------------------------- def objective1(model): return model.x1 def objective2(model): return 3 * model.x1 + 4 * model.x2 # -------------------------------------- # Define the regular constraints # -------------------------------------- def constraint1(model): return model.x1 <= 20 def constraint2(model): return model.x2 <= 40 def constraint3(model): return 5 * model.x1 + 4 * model.x2 <= 200 # -------------------------------------- # Add components to the model # -------------------------------------- # Add the constraints to the model model.con1 = Constraint(rule=constraint1) model.con2 = Constraint(rule=constraint2) model.con3 = Constraint(rule=constraint3) # Add the objective functions to the model using ObjectiveList(). Note # that the first index is 1 instead of 0! model.obj_list = ObjectiveList() model.obj_list.add(expr=objective1(model), sense=maximize) model.obj_list.add(expr=objective2(model), sense=maximize) # By default deactivate all the objective functions for o in range(len(model.obj_list)): model.obj_list[o + 1].deactivate() return model
def make_model(): m = ConcreteModel() m.time = ContinuousSet(bounds=(0, 10)) m.space = ContinuousSet(bounds=(0, 5)) m.set1 = Set(initialize=['a', 'b', 'c']) m.set2 = Set(initialize=['d', 'e', 'f']) m.fs = Block() m.fs.v0 = Var(m.space, initialize=1) @m.fs.Block() def b1(b): b.v = Var(m.time, m.space, initialize=1) b.dv = DerivativeVar(b.v, wrt=m.time, initialize=0) b.con = Constraint(m.time, m.space, rule=lambda b, t, x: b.dv[t, x] == 7 - b.v[t, x]) # Inconsistent @b.Block(m.time) def b2(b, t): b.v = Var(initialize=2) @m.fs.Block(m.time, m.space) def b2(b, t, x): b.v = Var(m.set1, initialize=2) @b.Block(m.set1) def b3(b, c): b.v = Var(m.set2, initialize=3) @b.Constraint(m.set2) def con(b, s): return (5 * b.v[s] == m.fs.b2[m.time.first(), m.space.first()].v[c]) # inconsistent @m.fs.Constraint(m.time) def con1(fs, t): return fs.b1.v[t, m.space.last()] == 5 # Will be inconsistent @m.fs.Constraint(m.space) def con2(fs, x): return fs.b1.v[m.time.first(), x] == fs.v0[x] # will be consistent disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') return m
def make_model_2(): m = ConcreteModel() m.x = Var(initialize=0.1, bounds=(0, 1)) m.y = Var(initialize=0.1, bounds=(0, 1)) m.obj = Objective(expr=-m.x**2 - m.y**2) m.c = Constraint(expr=m.y <= pe.exp(-m.x)) return m
def is_empty_intersection(self, uncertain_params, nlp_solver): """ Determine if intersection is empty Args: uncertain_params: list of uncertain parameters nlp_solver: a Pyomo Solver object for solving NLPs """ # === Non-emptiness check for the set intersection is_empty_intersection = True if any(a_set.type == "discrete" for a_set in self.all_sets): disc_sets = (a_set for a_set in self.all_sets if a_set.type == "discrete") disc_set = min(disc_sets, key=lambda x: len(x.scenarios)) # minimum set of scenarios # === Ensure there is at least one scenario from this discrete set which is a member of all other sets for scenario in disc_set.scenarios: if all(a_set.point_in_set(point=scenario) for a_set in self.all_sets): is_empty_intersection = False break else: # === Compile constraints and solve NLP m = ConcreteModel() m.obj = Objective(expr=0) # dummy objective required if using baron m.param_vars = Var(uncertain_params.index_set()) for a_set in self.all_sets: m.add_component(a_set.type + "_constraints", a_set.set_as_constraint(uncertain_params=m.param_vars)) try: res = nlp_solver.solve(m) except: raise ValueError("Solver terminated with an error while checking set intersection non-emptiness.") if check_optimal_termination(res): is_empty_intersection = False return is_empty_intersection
def two_kp_model(type): model = ConcreteModel() # Define input files xlsx = pd.ExcelFile( f"{Path(__file__).parent.absolute()}/input/{type}.xlsx", engine="openpyxl") a = pd.read_excel(xlsx, index_col=0, sheet_name="a").to_numpy() b = pd.read_excel(xlsx, index_col=0, sheet_name="b").to_numpy() c = pd.read_excel(xlsx, index_col=0, sheet_name="c").to_numpy() # Define variables model.ITEMS = Set(initialize=range(len(a[0]))) model.x = Var(model.ITEMS, within=Binary) # -------------------------------------- # Define the objective functions # -------------------------------------- def objective1(model): return sum(c[0][i] * model.x[i] for i in model.ITEMS) def objective2(model): return sum(c[1][i] * model.x[i] for i in model.ITEMS) # -------------------------------------- # Define the regular constraints # -------------------------------------- def constraint1(model): return sum(a[0][i] * model.x[i] for i in model.ITEMS) <= b[0][0] def constraint2(model): return sum(a[1][i] * model.x[i] for i in model.ITEMS) <= b[1][0] # -------------------------------------- # Add components to the model # -------------------------------------- # Add the constraints to the model model.con1 = Constraint(rule=constraint1) model.con2 = Constraint(rule=constraint2) # Add the objective functions to the model using ObjectiveList(). Note # that the first index is 1 instead of 0! model.obj_list = ObjectiveList() model.obj_list.add(expr=objective1(model), sense=maximize) model.obj_list.add(expr=objective2(model), sense=maximize) # By default deactivate all the objective functions for o in range(len(model.obj_list)): model.obj_list[o + 1].deactivate() return model
def make_model(): m = ConcreteModel() m.x = Var([1,2,3], initialize=0) m.f = Var([1,2,3], initialize=0) m.F = Var(initialize=0) m.f[1].fix(1) m.f[2].fix(2) m.sum_con = Constraint(expr= (1 == m.x[1] + m.x[2] + m.x[3])) def bilin_rule(m, i): return m.F*m.x[i] == m.f[i] m.bilin_con = Constraint([1,2,3], rule=bilin_rule) m.obj = Objective(expr=m.F**2) return m
def convert(options=Bunch(), parser=None, model_format=None): global _format if not model_format is None: _format = model_format # # Import plugins # import pyomo.environ if options.model.save_file is None: if _format == ProblemFormat.cpxlp: options.model.save_file = 'unknown.lp' else: options.model.save_file = 'unknown.' + str(_format) options.model.save_format = _format data = Bunch(options=options) model_data = None try: pyomo.scripting.util.setup_environment(data) pyomo.scripting.util.apply_preprocessing(data, parser=parser) if data.error: return Bunch() model_data = pyomo.scripting.util.create_model(data) model_data.options = options except: # TBD: I should be able to call this function in the case of # an exception to perform cleanup. However, as it stands # calling finalize with its default keyword value for # model(=None) results in an a different error related to # task port values. Not sure how to interpret that. pyomo.scripting.util.finalize(data, model=ConcreteModel(), instance=None, results=None) raise else: pyomo.scripting.util.finalize(data, model=model_data.model) return model_data
def _dualize(self, block, unfixed=[]): """ Generate the dual of a block """ # # Collect linear terms from the block # A, b_coef, c_rhs, c_sense, d_sense, vnames, cnames, v_domain = collect_linear_terms( block, unfixed) # # Construct the block # if isinstance(block, Model): dual = ConcreteModel() else: dual = Block() for v, is_indexed in vnames: if is_indexed: setattr(dual, v + '_Index', Set(dimen=None)) setattr(dual, v, Var(getattr(dual, v + '_Index'))) else: setattr(dual, v, Var()) for cname, is_indexed in cnames: if is_indexed: setattr(dual, cname + '_Index', Set(dimen=None)) setattr(dual, cname, Constraint(getattr(dual, cname + '_Index'))) setattr(dual, cname + '_lower_', Var(getattr(dual, cname + '_Index'))) setattr(dual, cname + '_upper_', Var(getattr(dual, cname + '_Index'))) else: setattr(dual, cname, Constraint()) setattr(dual, cname + '_lower_', Var()) setattr(dual, cname + '_upper_', Var()) dual.construct() # # Add variables # # TODO: revisit this hack. We shouldn't be calling # _getitem_when_not_present() # for name, ndx in b_coef: v = getattr(dual, name) if not ndx in v: v._getitem_when_not_present(ndx) # # Construct the objective # if d_sense == minimize: dual.o = Objective(expr=sum(-b_coef[name, ndx] * getattr(dual, name)[ndx] for name, ndx in b_coef), sense=d_sense) else: dual.o = Objective(expr=sum(b_coef[name, ndx] * getattr(dual, name)[ndx] for name, ndx in b_coef), sense=d_sense) # # Construct the constraints # for cname in A: c = getattr(dual, cname) c_index = getattr(dual, cname + "_Index") if c.is_indexed() else None for ndx, terms in iteritems(A[cname]): if not c_index is None and not ndx in c_index: c_index.add(ndx) expr = 0 for term in terms: v = getattr(dual, term.var) if not term.ndx in v: v.add(term.ndx) expr += term.coef * v[term.ndx] if not (cname, ndx) in c_rhs: c_rhs[cname, ndx] = 0.0 if c_sense[cname, ndx] == 'e': c.add(ndx, expr - c_rhs[cname, ndx] == 0) elif c_sense[cname, ndx] == 'l': c.add(ndx, expr - c_rhs[cname, ndx] <= 0) else: c.add(ndx, expr - c_rhs[cname, ndx] >= 0) for (name, ndx), domain in iteritems(v_domain): v = getattr(dual, name) flag = type(ndx) is tuple and (ndx[-1] == 'lb' or ndx[-1] == 'ub') if domain == 1: if flag: v[ndx].domain = NonNegativeReals else: v.domain = NonNegativeReals elif domain == -1: if flag: v[ndx].domain = NonPositiveReals else: v.domain = NonPositiveReals else: if flag: # TODO: verify that this case is possible v[ndx].domain = Reals else: v.domain = Reals return dual
return m.Vm[i, k] == m.x[i, k] * ((1/2288) * 0.2685**(1 + (1 - m.T[i, k]/512.4)**0.2453)) + \ (1 - m.x[i, k]) * ((1/1235) * 0.27136**(1 + (1 - m.T[i, k]/536.4)**0.24)) else: return Constraint.Skip # Initial conditions for the given noisy-filter def acm(m, k): return m.M[0, k] == m.M_ic[k] def acx(m, k): return m.x[0, k] == m.x_ic[k] # --------------------------------------------------------------------------------------------------------------------- mod = ConcreteModel() mod.t = ContinuousSet(bounds=(0, 1)) mod.Ntray = Ntray = 42 mod.tray = Set(initialize=[i for i in range(1, mod.Ntray + 1)]) mod.feed = Param(mod.tray, initialize=lambda m, k: 57.5294 if k == 21 else 0.0, mutable=True) mod.xf = Param(initialize=0.32, mutable=True) # feed mole fraction mod.hf = Param(initialize=9081.3) # feed enthalpy mod.hlm0 = Param(initialize=2.6786e-04) mod.hlma = Param(initialize=-0.14779) mod.hlmb = Param(initialize=97.4289)
def _dualize(self, block, unfixed=[]): """ Generate the dual of a block """ # # Collect linear terms from the block # A, b_coef, c_rhs, c_sense, d_sense, vnames, cnames, v_domain = collect_linear_terms(block, unfixed) # # Construct the block # if isinstance(block, Model): dual = ConcreteModel() else: dual = Block() for v, is_indexed in vnames: if is_indexed: setattr(dual, v+'_Index', Set(dimen=None)) setattr(dual, v, Var(getattr(dual, v+'_Index'))) else: setattr(dual, v, Var()) for cname, is_indexed in cnames: if is_indexed: setattr(dual, cname+'_Index', Set(dimen=None)) setattr(dual, cname, Constraint(getattr(dual, cname+'_Index'))) setattr(dual, cname+'_lower_', Var(getattr(dual, cname+'_Index'))) setattr(dual, cname+'_upper_', Var(getattr(dual, cname+'_Index'))) else: setattr(dual, cname, Constraint()) setattr(dual, cname+'_lower_', Var()) setattr(dual, cname+'_upper_', Var()) dual.construct() # # Add variables # # TODO: revisit this hack. We shouldn't be calling _default() # for name, ndx in b_coef: v = getattr(dual, name) if not ndx in v: v._default(ndx) # # Construct the objective # if d_sense == minimize: dual.o = Objective(expr=sum(- b_coef[name,ndx]*getattr(dual,name)[ndx] for name,ndx in b_coef), sense=d_sense) else: dual.o = Objective(expr=sum(b_coef[name,ndx]*getattr(dual,name)[ndx] for name,ndx in b_coef), sense=d_sense) # # Construct the constraints # for cname in A: c = getattr(dual, cname) c_index = getattr(dual, cname+"_Index") if c.is_indexed() else None for ndx,terms in iteritems(A[cname]): if not c_index is None and not ndx in c_index: c_index.add(ndx) expr = 0 for term in terms: v = getattr(dual,term.var) if not term.ndx in v: v.add(term.ndx) expr += term.coef * v[term.ndx] if not (cname, ndx) in c_rhs: c_rhs[cname, ndx] = 0.0 if c_sense[cname,ndx] == 'e': c.add(ndx, expr - c_rhs[cname,ndx] == 0) elif c_sense[cname,ndx] == 'l': c.add(ndx, expr - c_rhs[cname,ndx] <= 0) else: c.add(ndx, expr - c_rhs[cname,ndx] >= 0) for (name, ndx), domain in iteritems(v_domain): v = getattr(dual, name) flag = type(ndx) is tuple and (ndx[-1] == 'lb' or ndx[-1] == 'ub') if domain == 1: if flag: v[ndx].domain = NonNegativeReals else: v.domain = NonNegativeReals elif domain == -1: if flag: v[ndx].domain = NonPositiveReals else: v.domain = NonPositiveReals else: if flag: # TODO: verify that this case is possible v[ndx].domain = Reals else: v.domain = Reals return dual
def _dualize(self, block, unfixed=[]): """ Generate the dual of a block """ # # Collect linear terms from the block # A, b_coef, c_rhs, c_sense, d_sense, vnames, cnames, v_domain = collect_linear_terms(block, unfixed) ##print(A) ##print(vnames) ##print(cnames) ##print(list(A.keys())) ##print("---") ##print(A.keys()) ##print(c_sense) ##print(c_rhs) # # Construct the block # if isinstance(block, Model): dual = ConcreteModel() else: dual = Block() dual.construct() _vars = {} def getvar(name, ndx=None): v = _vars.get((name,ndx), None) if v is None: v = Var() if ndx is None: v_name = name elif type(ndx) is tuple: v_name = "%s[%s]" % (name, ','.join(map(str,ndx))) else: v_name = "%s[%s]" % (name, str(ndx)) setattr(dual, v_name, v) _vars[name,ndx] = v return v # # Construct the objective # if d_sense == minimize: dual.o = Objective(expr=sum(- b_coef[name,ndx]*getvar(name,ndx) for name,ndx in b_coef), sense=d_sense) else: dual.o = Objective(expr=sum(b_coef[name,ndx]*getvar(name,ndx) for name,ndx in b_coef), sense=d_sense) # # Construct the constraints # for cname in A: for ndx, terms in iteritems(A[cname]): expr = 0 for term in terms: expr += term.coef * getvar(term.var, term.ndx) if not (cname, ndx) in c_rhs: c_rhs[cname, ndx] = 0.0 if c_sense[cname, ndx] == 'e': e = expr - c_rhs[cname,ndx] == 0 elif c_sense[cname, ndx] == 'l': e = expr - c_rhs[cname,ndx] <= 0 else: e = expr - c_rhs[cname,ndx] >= 0 c = Constraint(expr=e) if ndx is None: c_name = cname elif type(ndx) is tuple: c_name = "%s[%s]" % (cname, ','.join(map(str,ndx))) else: c_name = "%s[%s]" % (cname, str(ndx)) setattr(dual, c_name, c) # for (name, ndx), domain in iteritems(v_domain): v = getvar(name, ndx) flag = type(ndx) is tuple and (ndx[-1] == 'lb' or ndx[-1] == 'ub') if domain == 1: v.domain = NonNegativeReals elif domain == -1: v.domain = NonPositiveReals else: # TODO: verify that this case is possible v.domain = Reals return dual
def solveropfnlp_2(ppc, solver="ipopt"): if solver == "ipopt": opt = SolverFactory("ipopt", executable="/home/iso/PycharmProjects/opfLC_python3/Python3/py_solvers/ipopt-linux64/ipopt") if solver == "bonmin": opt = SolverFactory("bonmin", executable="/home/iso/PycharmProjects/opfLC_python3/Python3/py_solvers/bonmin-linux64/bonmin") if solver == "knitro": opt = SolverFactory("knitro", executable="D:/ICT/Artelys/Knitro 10.2.1/knitroampl/knitroampl") ppc = ext2int(ppc) # convert to continuous indexing starting from 0 # Gather information about the system # ============================================================= baseMVA, bus, gen, branch = \ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"] nb = bus.shape[0] # number of buses ng = gen.shape[0] # number of generators nl = branch.shape[0] # number of lines # generator buses gb = tolist(np.array(gen[:, GEN_BUS]).astype(int)) sb = find((bus[:, BUS_TYPE] == REF)) # slack bus index fr = branch[:, F_BUS].astype(int) # from bus indices to = branch[:, T_BUS].astype(int) # to bus indices tr = branch[:, TAP] # transformation ratios tr[find(tr == 0)] = 1 # set to 1 transformation ratios that are 0 r = branch[:, BR_R] # branch resistances x = branch[:, BR_X] # branch reactances b = branch[:, BR_B] # branch susceptances start_time = time.clock() # Admittance matrix computation # ============================================================= y = makeYbus(baseMVA, bus, branch)[0] # admittance matrix yk = 1./(r+x*1j) # branch admittance yft = yk + 0.5j*b # branch admittance + susceptance gk = yk.real # branch resistance yk = yk/tr # include /tr in yk # Optimization # ============================================================= branch[find(branch[:, RATE_A] == 0), RATE_A] = 9999 # set undefined Sflow limit to 9999 Smax = branch[:, RATE_A] / baseMVA # Max. Sflow # Power demand parameters Pd = bus[:, PD] / baseMVA Qd = bus[:, QD] / baseMVA # Max and min Pg and Qg Pg_max = zeros(nb) Pg_max[gb] = gen[:, PMAX] / baseMVA Pg_min = zeros(nb) Pg_min[gb] = gen[:, PMIN] / baseMVA Qg_max = zeros(nb) Qg_max[gb] = gen[:, QMAX] / baseMVA Qg_min = zeros(nb) Qg_min[gb] = gen[:, QMIN] / baseMVA # Vmax and Vmin vectors Vmax = bus[:, VMAX] Vmin = bus[:, VMIN] vm = bus[:, VM] va = bus[:, VA]*pi/180 # create a new optimization model model = ConcreteModel() # Define sets # ------------ model.bus = Set(ordered=True, initialize=range(nb)) # Set of all buses model.gen = Set(ordered=True, initialize=gb) # Set of buses with generation model.line = Set(ordered=True, initialize=range(nl)) # Set of all lines # Define variables # ----------------- # Voltage magnitudes vector (vm) model.vm = Var(model.bus) # Voltage angles vector (va) model.va = Var(model.bus) # Reactive power generation, synchronous machines(SM) (Qg) model.Qg = Var(model.gen) Qg0 = zeros(nb) Qg0[gb] = gen[:, QG]/baseMVA # Active power generation, synchronous machines(SM) (Pg) model.Pg = Var(model.gen) Pg0 = zeros(nb) Pg0[gb] = gen[:, PG] / baseMVA # Active and reactive power from at all branches model.Pf = Var(model.line) model.Qf = Var(model.line) # Active and reactive power to at all branches model.Pt = Var(model.line) model.Qt = Var(model.line) # Warm start the problem # ------------------------ for i in range(nb): model.vm[i] = vm[i] model.va[i] = va[i] if i in gb: model.Pg[i] = Pg0[i] model.Qg[i] = Qg0[i] for i in range(nl): model.Pf[i] = vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.cos(-ang(yft[i])) -\ vm[fr[i]] * vm[to[i]] * abs(yk[i]) * np.cos(va[fr[i]] - va[to[i]] - ang(yk[i])) model.Qf[i] = vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.sin(-ang(yft[i])) -\ vm[fr[i]] * vm[to[i]] * abs(yk[i]) * np.sin(va[fr[i]] - va[to[i]] - ang(yk[i])) model.Pt[i] = vm[to[i]] ** 2 * abs(yft[i]) * np.cos(-ang(yft[i])) -\ vm[to[i]] * vm[fr[i]] * abs(yk[i]) * np.cos(va[to[i]] - va[fr[i]] - ang(yk[i])) model.Qt[i] = vm[to[i]] ** 2 * abs(yft[i]) * np.sin(-ang(yft[i])) -\ vm[to[i]] * vm[fr[i]] * abs(yk[i]) * np.sin(va[to[i]] - va[fr[i]] - ang(yk[i])) # Define constraints # ---------------------------- # Equalities: # ------------ # Active power flow equalities def powerflowact(model, i): if i in gb: return model.Pg[i]-Pd[i] == sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * cos(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) else: return sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * cos(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) == -Pd[i] model.const1 = Constraint(model.bus, rule=powerflowact) # Reactive power flow equalities def powerflowreact(model, i): if i in gb: return model.Qg[i]-Qd[i] == sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * sin(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) else: return sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * sin(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) == -Qd[i] model.const2 = Constraint(model.bus, rule=powerflowreact) # Active power from def pfrom(model, i): return model.Pf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.cos(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) * \ cos(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) model.const3 = Constraint(model.line, rule=pfrom) # Reactive power from def qfrom(model, i): return model.Qf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.sin(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) * \ sin(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) model.const4 = Constraint(model.line, rule=qfrom) # Active power to def pto(model, i): return model.Pt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.cos(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) * \ cos(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) model.const5 = Constraint(model.line, rule=pto) # Reactive power to def qto(model, i): return model.Qt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.sin(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) * \ sin(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) model.const6 = Constraint(model.line, rule=qto) # Slack bus phase angle model.const7 = Constraint(expr=model.va[sb[0]] == 0) # Inequalities: # ---------------- # Active power generator limits Pg_min <= Pg <= Pg_max def genplimits(model, i): return Pg_min[i] <= model.Pg[i] <= Pg_max[i] model.const8 = Constraint(model.gen, rule=genplimits) # Reactive power generator limits Qg_min <= Qg <= Qg_max def genqlimits(model, i): return Qg_min[i] <= model.Qg[i] <= Qg_max[i] model.const9 = Constraint(model.gen, rule=genqlimits) # Voltage constraints ( Vmin <= V <= Vmax ) def vlimits(model, i): return Vmin[i] <= model.vm[i] <= Vmax[i] model.const10 = Constraint(model.bus, rule=vlimits) # Sfrom line limit def sfrommax(model, i): return model.Pf[i]**2 + model.Qf[i]**2 <= Smax[i]**2 model.const11 = Constraint(model.line, rule=sfrommax) # Sto line limit def stomax(model, i): return model.Pt[i]**2 + model.Qt[i]**2 <= Smax[i]**2 model.const12 = Constraint(model.line, rule=stomax) # Set objective function # ------------------------ def obj_fun(model): return sum(gk[i] * ((model.vm[fr[i]] / tr[i])**2 + model.vm[to[i]]**2 - 2/tr[i] * model.vm[fr[i]] * model.vm[to[i]] * cos(model.va[fr[i]] - model.va[to[i]])) for i in range(nl)) model.obj = Objective(rule=obj_fun, sense=minimize) mt = time.clock() - start_time # Modeling time # Execute solve command with the selected solver # ------------------------------------------------ start_time = time.clock() results = opt.solve(model, tee=True) et = time.clock() - start_time # Elapsed time print(results) # Update the case info with the optimized variables # ================================================== for i in range(nb): bus[i, VM] = model.vm[i].value # Bus voltage magnitudes bus[i, VA] = model.va[i].value*180/pi # Bus voltage angles # Include Pf - Qf - Pt - Qt in the branch matrix branchsol = zeros((nl, 17)) branchsol[:, :-4] = branch for i in range(nl): branchsol[i, PF] = model.Pf[i].value * baseMVA branchsol[i, QF] = model.Qf[i].value * baseMVA branchsol[i, PT] = model.Pt[i].value * baseMVA branchsol[i, QT] = model.Qt[i].value * baseMVA # Update gen matrix variables for i in range(ng): gen[i, PG] = model.Pg[gb[i]].value * baseMVA gen[i, QG] = model.Qg[gb[i]].value * baseMVA gen[i, VG] = bus[gb[i], VM] # Convert to external (original) numbering and save case results ppc = int2ext(ppc) ppc['bus'][:, 1:] = bus[:, 1:] branchsol[:, 0:2] = ppc['branch'][:, 0:2] ppc['branch'] = branchsol ppc['gen'][:, 1:] = gen[:, 1:] ppc['obj'] = value(obj_fun(model)) ppc['ploss'] = value(obj_fun(model)) * baseMVA ppc['et'] = et ppc['mt'] = mt ppc['success'] = 1 # ppc solved case is returned return ppc
def unit_commitment_model(): model = ConcreteModel() # Define input files xlsx = pd.ExcelFile( f"{Path(__file__).parent.absolute()}/input/unit_commitment.xlsx", engine="openpyxl", ) system_demand = Helper.read_excel(xlsx, "SystemDemand") storage_systems = Helper.read_excel(xlsx, "StorageSystems") generators = Helper.read_excel(xlsx, "Generators") generator_step_size = Helper.read_excel(xlsx, "GeneratorStepSize") generator_step_cost = Helper.read_excel(xlsx, "GeneratorStepCost") pv_generation = Helper.read_excel(xlsx, "PVGeneration") # Define sets model.T = Set(ordered=True, initialize=system_demand.index) model.I = Set(ordered=True, initialize=generators.index) model.F = Set(ordered=True, initialize=generator_step_size.columns) model.S = Set(ordered=True, initialize=storage_systems.index) # Define parameters model.Pmax = Param(model.I, within=NonNegativeReals, mutable=True) model.Pmin = Param(model.I, within=NonNegativeReals, mutable=True) model.RU = Param(model.I, within=NonNegativeReals, mutable=True) model.RD = Param(model.I, within=NonNegativeReals, mutable=True) model.SUC = Param(model.I, within=NonNegativeReals, mutable=True) model.SDC = Param(model.I, within=NonNegativeReals, mutable=True) model.Pini = Param(model.I, within=NonNegativeReals, mutable=True) model.uini = Param(model.I, within=Binary, mutable=True) model.C = Param(model.I, model.F, within=NonNegativeReals, mutable=True) model.B = Param(model.I, model.F, within=NonNegativeReals, mutable=True) model.SystemDemand = Param(model.T, within=NonNegativeReals, mutable=True) model.Emissions = Param(model.I, within=NonNegativeReals, mutable=True) model.PV = Param(model.T, within=NonNegativeReals, mutable=True) model.ESS_Pmax = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_SOEmax = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_SOEini = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_Eff = Param(model.S, within=NonNegativeReals, mutable=True) # Give values to parameters of the generators for i in model.I: model.Pmin[i] = generators.loc[i, "Pmin"] model.Pmax[i] = generators.loc[i, "Pmax"] model.RU[i] = generators.loc[i, "RU"] model.RD[i] = generators.loc[i, "RD"] model.SUC[i] = generators.loc[i, "SUC"] model.SDC[i] = generators.loc[i, "SDC"] model.Pini[i] = generators.loc[i, "Pini"] model.uini[i] = generators.loc[i, "uini"] model.Emissions[i] = generators.loc[i, "Emissions"] for f in model.F: model.B[i, f] = generator_step_size.loc[i, f] model.C[i, f] = generator_step_cost.loc[i, f] # Add system demand and PV generation for t in model.T: model.SystemDemand[t] = system_demand.loc[t, "SystemDemand"] model.PV[t] = pv_generation.loc[t, "PVGeneration"] # Give values to ESS parameters for s in model.S: model.ESS_Pmax[s] = storage_systems.loc[s, "Power"] model.ESS_SOEmax[s] = storage_systems.loc[s, "Energy"] model.ESS_SOEini[s] = storage_systems.loc[s, "SOEini"] model.ESS_Eff[s] = storage_systems.loc[s, "Eff"] # Define decision variables model.P = Var(model.I, model.T, within=NonNegativeReals) model.Pres = Var(model.T, within=NonNegativeReals) model.b = Var(model.I, model.F, model.T, within=NonNegativeReals) model.u = Var(model.I, model.T, within=Binary) model.CSU = Var(model.I, model.T, within=NonNegativeReals) model.CSD = Var(model.I, model.T, within=NonNegativeReals) model.SOE = Var(model.S, model.T, within=NonNegativeReals) model.Pch = Var(model.S, model.T, within=NonNegativeReals) model.Pdis = Var(model.S, model.T, within=NonNegativeReals) model.u_ess = Var(model.S, model.T, within=Binary) # -------------------------------------- # Define the objective functions # -------------------------------------- def cost_objective(model): return sum( sum( sum(model.C[i, f] * model.b[i, f, t] for f in model.F) + model.CSU[i, t] + model.CSD[i, t] for i in model.I) for t in model.T) def emissions_objective(model): return sum( sum(model.P[i, t] * model.Emissions[i] for i in model.I) for t in model.T) def unmet_objective(model): return sum(model.Pres[t] for t in model.T) # -------------------------------------- # Define the regular constraints # -------------------------------------- def power_decomposition_rule1(model, i, t): return model.P[i, t] == sum(model.b[i, f, t] for f in model.F) def power_decomposition_rule2(model, i, f, t): return model.b[i, f, t] <= model.B[i, f] def power_min_rule(model, i, t): return model.P[i, t] >= model.Pmin[i] * model.u[i, t] def power_max_rule(model, i, t): return model.P[i, t] <= model.Pmax[i] * model.u[i, t] def ramp_up_rule(model, i, t): if model.T.ord(t) == 1: return model.P[i, t] - model.Pini[i] <= 60 * model.RU[i] if model.T.ord(t) > 1: return model.P[i, t] - model.P[i, model.T.prev(t)] <= 60 * model.RU[i] def ramp_down_rule(model, i, t): if model.T.ord(t) == 1: return (model.Pini[i] - model.P[i, t]) <= 60 * model.RD[i] if model.T.ord(t) > 1: return (model.P[i, model.T.prev(t)] - model.P[i, t]) <= 60 * model.RD[i] def start_up_cost(model, i, t): if model.T.ord(t) == 1: return model.CSU[i, t] >= model.SUC[i] * (model.u[i, t] - model.uini[i]) if model.T.ord(t) > 1: return model.CSU[i, t] >= model.SUC[i] * ( model.u[i, t] - model.u[i, model.T.prev(t)]) def shut_down_cost(model, i, t): if model.T.ord(t) == 1: return model.CSD[i, t] >= model.SDC[i] * (model.uini[i] - model.u[i, t]) if model.T.ord(t) > 1: return model.CSD[i, t] >= model.SDC[i] * ( model.u[i, model.T.prev(t)] - model.u[i, t]) def ESS_SOEupdate(model, s, t): if model.T.ord(t) == 1: return (model.SOE[s, t] == model.ESS_SOEini[s] + model.ESS_Eff[s] * model.Pch[s, t] - model.Pdis[s, t] / model.ESS_Eff[s]) if model.T.ord(t) > 1: return (model.SOE[s, t] == model.SOE[s, model.T.prev(t)] + model.ESS_Eff[s] * model.Pch[s, t] - model.Pdis[s, t] / model.ESS_Eff[s]) def ESS_SOElimit(model, s, t): return model.SOE[s, t] <= model.ESS_SOEmax[s] def ESS_Charging(model, s, t): return model.Pch[s, t] <= model.ESS_Pmax[s] * model.u_ess[s, t] def ESS_Discharging(model, s, t): return model.Pdis[s, t] <= model.ESS_Pmax[s] * (1 - model.u_ess[s, t]) def Balance(model, t): return model.PV[t] + sum(model.P[i, t] for i in model.I) + sum( model.Pdis[s, t] for s in model.S) == model.SystemDemand[t] - model.Pres[t] + sum( model.Pch[s, t] for s in model.S) def Pres_max(model, t): return model.Pres[t] <= 0.1 * model.SystemDemand[t] # -------------------------------------- # Add components to the model # -------------------------------------- # Add the constraints to the model model.power_decomposition_rule1 = Constraint( model.I, model.T, rule=power_decomposition_rule1) model.power_decomposition_rule2 = Constraint( model.I, model.F, model.T, rule=power_decomposition_rule2) model.power_min_rule = Constraint(model.I, model.T, rule=power_min_rule) model.power_max_rule = Constraint(model.I, model.T, rule=power_max_rule) model.start_up_cost = Constraint(model.I, model.T, rule=start_up_cost) model.shut_down_cost = Constraint(model.I, model.T, rule=shut_down_cost) model.ConSOEUpdate = Constraint(model.S, model.T, rule=ESS_SOEupdate) model.ConCharging = Constraint(model.S, model.T, rule=ESS_Charging) model.ConDischarging = Constraint(model.S, model.T, rule=ESS_Discharging) model.ConSOElimit = Constraint(model.S, model.T, rule=ESS_SOElimit) model.ConGenUp = Constraint(model.I, model.T, rule=ramp_up_rule) model.ConGenDown = Constraint(model.I, model.T, rule=ramp_down_rule) model.ConBalance = Constraint(model.T, rule=Balance) model.Pres_max = Constraint(model.T, rule=Pres_max) # Add the objective functions to the model using ObjectiveList(). Note # that the first index is 1 instead of 0! model.obj_list = ObjectiveList() model.obj_list.add(expr=cost_objective(model), sense=minimize) model.obj_list.add(expr=emissions_objective(model), sense=minimize) model.obj_list.add(expr=unmet_objective(model), sense=minimize) # By default deactivate all the objective functions for o in range(len(model.obj_list)): model.obj_list[o + 1].deactivate() return model
def test_len1(self): model = self.model model = ConcreteModel() model.c = self._ctype() self.assertEqual(len(model.c), 0)
def setUp(self): self.model = ConcreteModel() self.model.x = Var() # set by derived class self._arg = None
def __init__(self, nfe_t, ncp_t, **kwargs): ConcreteModel.__init__(self) steady = kwargs.pop('steady', False) _t = kwargs.pop('_t', 1.0) Ntray = kwargs.pop('Ntray', 42) # -------------------------------------------------------------------------------------------------------------- # Orthogonal Collocation Parameters section # Radau self._alp_gauB_t = 1 self._bet_gauB_t = 0 if steady: print("[I] " + str(self.__class__.__name__) + " NFE and NCP Overriden - Steady state mode") self.nfe_t = 1 self.ncp_t = 1 else: self.nfe_t = nfe_t self.ncp_t = ncp_t self.tau_t = collptsgen(self.ncp_t, self._alp_gauB_t, self._bet_gauB_t) # start at zero self.tau_i_t = {0: 0.} # create a list for ii in range(1, self.ncp_t + 1): self.tau_i_t[ii] = self.tau_t[ii - 1] # ======= SETS ======= # # For finite element = 1 .. NFE # This has to be > 0 self.fe_t = Set(initialize=[ii for ii in range(1, self.nfe_t + 1)]) # collocation points # collocation points for differential variables self.cp_t = Set(initialize=[ii for ii in range(0, self.ncp_t + 1)]) # collocation points for algebraic variables self.cp_ta = Set(within=self.cp_t, initialize=[ii for ii in range(1, self.ncp_t + 1)]) # create collocation param self.taucp_t = Param(self.cp_t, initialize=self.tau_i_t) self.ldot_t = Param(self.cp_t, self.cp_t, initialize= (lambda m, j, k: lgrdot(k, m.taucp_t[j], self.ncp_t, self._alp_gauB_t, self._bet_gauB_t))) #: watch out for this! self.l1_t = Param(self.cp_t, initialize= (lambda m, j: lgr(j, 1, self.ncp_t, self._alp_gauB_t, self._bet_gauB_t))) # -------------------------------------------------------------------------------------------------------------- # Model parameters self.Ntray = Ntray self.tray = Set(initialize=[i for i in range(1, Ntray + 1)]) self.feed = Param(self.tray, initialize=lambda m, t: 57.5294 if t == 21 else 0.0, mutable=True) self.xf = Param(initialize=0.32, mutable=True) # feed mole fraction self.hf = Param(initialize=9081.3) # feed enthalpy self.hlm0 = Param(initialize=2.6786e-04) self.hlma = Param(initialize=-0.14779) self.hlmb = Param(initialize=97.4289) self.hlmc = Param(initialize=-2.1045e04) self.hln0 = Param(initialize=4.0449e-04) self.hlna = Param(initialize=-0.1435) self.hlnb = Param(initialize=121.7981) self.hlnc = Param(initialize=-3.0718e04) self.r = Param(initialize=8.3147) self.a = Param(initialize=6.09648) self.b = Param(initialize=1.28862) self.c1 = Param(initialize=1.016) self.d = Param(initialize=15.6875) self.l = Param(initialize=13.4721) self.f = Param(initialize=2.615) self.gm = Param(initialize=0.557) self.Tkm = Param(initialize=512.6) self.Pkm = Param(initialize=8.096e06) self.gn = Param(initialize=0.612) self.Tkn = Param(initialize=536.7) self.Pkn = Param(initialize=5.166e06) self.CapAm = Param(initialize=23.48) self.CapBm = Param(initialize=3626.6) self.CapCm = Param(initialize=-34.29) self.CapAn = Param(initialize=22.437) self.CapBn = Param(initialize=3166.64) self.CapCn = Param(initialize=-80.15) self.pstrip = Param(initialize=250) self.prect = Param(initialize=190) def _p_init(m, t): ptray = 9.39e04 if t <= 20: return _p_init(m, 21) + m.pstrip * (21 - t) elif 20 < t < m.Ntray: return ptray + m.prect * (m.Ntray - t) elif t == m.Ntray: return 9.39e04 self.p = Param(self.tray, initialize=_p_init) self.T29_des = Param(initialize=343.15) self.T15_des = Param(initialize=361.15) self.Dset = Param(initialize=1.83728) self.Qcset = Param(initialize=1.618890) self.Qrset = Param(initialize=1.786050) # self.Recset = Param() self.alpha_T29 = Param(initialize=1) self.alpha_T15 = Param(initialize=1) self.alpha_D = Param(initialize=1) self.alpha_Qc = Param(initialize=1) self.alpha_Qr = Param(initialize=1) self.alpha_Rec = Param(initialize=1) def _alpha_init(m, i): if i <= 21: return 0.62 else: return 0.35 self.alpha = Param(self.tray, initialize=lambda m, t: 0.62 if t <= 21 else 0.35) # -------------------------------------------------------------------------------------------------------------- #: First define differential state variables (state: x, ic-Param: x_ic, derivative-Var:dx_dt #: States (differential) section zero_tray = dict.fromkeys(self.tray) zero3 = dict.fromkeys(self.fe_t * self.cp_t * self.tray) for key in zero3.keys(): zero3[key] = 0.0 def __m_init(m, i, j, t): if t < m.Ntray: return 4000. elif t == 1: return 104340. elif t == m.Ntray: return 5000. #: Liquid hold-up self.M = Var(self.fe_t, self.cp_t, self.tray, initialize=__m_init) #: Mole-fraction self.x = Var(self.fe_t, self.cp_t, self.tray, initialize=lambda m, i, j, t: 0.999 * t / m.Ntray) #: Initial state-Param self.M_ic = zero_tray if steady else Param(self.tray, initialize=0.0, mutable=True) self.x_ic = zero_tray if steady else Param(self.tray, initialize=0.0, mutable=True) #: Derivative-var self.dM_dt = zero3 if steady else Var(self.fe_t, self.cp_t, self.tray, initialize=0.0) self.dx_dt = zero3 if steady else Var(self.fe_t, self.cp_t, self.tray, initialize=0.0) # -------------------------------------------------------------------------------------------------------------- # States (algebraic) section # Tray temperature self.T = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: ((370.781 - 335.753) / m.Ntray) * t + 370.781) self.Tdot = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e-05) #: Not really a der_var # saturation pressures self.pm = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e4) self.pn = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e4) # Vapor mole flowrate self.V = Var(self.fe_t, self.cp_ta, self.tray, initialize=44.0) def _l_init(m, i, j, t): if 2 <= t <= 21: return 83. elif 22 <= t <= 42: return 23 elif t == 1: return 40 # Liquid mole flowrate self.L = Var(self.fe_t, self.cp_ta, self.tray, initialize=_l_init) # Vapor mole frac & diff var self.y = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: ((0.99 - 0.005) / m.Ntray) * t + 0.005) # Liquid enthalpy # enthalpy self.hl = Var(self.fe_t, self.cp_ta, self.tray, initialize=10000.) # Liquid enthalpy # enthalpy self.hv = Var(self.fe_t, self.cp_ta, self.tray, initialize=5e+04) # Re-boiler & condenser heat self.Qc = Var(self.fe_t, self.cp_ta, initialize=1.6e06) self.D = Var(self.fe_t, self.cp_ta, initialize=18.33) # vol holdups self.Vm = Var(self.fe_t, self.cp_ta, self.tray, initialize=6e-05) self.Mv = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: 0.23 if 1 < t < m.Ntray else 0.0) self.Mv1 = Var(self.fe_t, self.cp_ta, initialize=8.57) self.Mvn = Var(self.fe_t, self.cp_ta, initialize=0.203) hi_t = dict.fromkeys(self.fe_t) for key in hi_t.keys(): hi_t[key] = 1.0 if steady else _t/self.nfe_t self.hi_t = hi_t if steady else Param(self.fe_t, initialize=hi_t) # -------------------------------------------------------------------------------------------------------------- #: Controls self.u1 = Param(self.fe_t, initialize=7.72700925775773761472464684629813E-01, mutable=True) #: Dummy self.u2 = Param(self.fe_t, initialize=1.78604740940007800236344337463379E+06, mutable=True) #: Dummy self.Rec = Var(self.fe_t, initialize=7.72700925775773761472464684629813E-01) self.Qr = Var(self.fe_t, initialize=1.78604740940007800236344337463379E+06) # -------------------------------------------------------------------------------------------------------------- #: Constraints for the differential states #: Then the ode-Con:de_x, collocation-Con:dvar_t_x, noisy-Expr: noisy_x, cp-Constraint: cp_x, initial-Con: x_icc #: Differential equations self.de_M = Constraint(self.fe_t, self.cp_ta, self.tray, rule=m_ode) self.de_x = Constraint(self.fe_t, self.cp_ta, self.tray, rule=x_ode) #: Collocation equations self.dvar_t_M = None if steady else Constraint(self.fe_t, self.cp_ta, self.tray, rule=M_COLL) self.dvar_t_x = None if steady else Constraint(self.fe_t, self.cp_ta, self.tray, rule=x_coll) #: Continuation equations (redundancy here) if self.nfe_t > 1: #: Noisy expressions self.noisy_M = None if steady else Expression(self.fe_t, self.tray, rule=M_CONT) self.noisy_x = None if steady else Expression(self.fe_t, self.tray, rule=x_cont) #: Continuation equations self.cp_M = None if steady else \ Constraint(self.fe_t, self.tray, rule=lambda m, i, t: self.noisy_M[i, t] == 0.0 if i < self.nfe_t else Constraint.Skip) self.cp_x = None if steady else \ Constraint(self.fe_t, self.tray, rule=lambda m, i, t: self.noisy_x[i, t] == 0.0 if i < self.nfe_t else Constraint.Skip) #: Initial condition-Constraints self.M_icc = None if steady else Constraint(self.tray, rule=acm) self.x_icc = None if steady else Constraint(self.tray, rule=acx) # -------------------------------------------------------------------------------------------------------------- #: Constraint section (algebraic equations) self.hrc = Constraint(self.fe_t, self.cp_ta, rule=hrc) self.gh = Constraint(self.fe_t, self.cp_ta, self.tray, rule=gh) self.ghb = Constraint(self.fe_t, self.cp_ta, rule=ghb) self.ghc = Constraint(self.fe_t, self.cp_ta, rule=ghc) self.hkl = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hkl) self.hkv = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hkv) self.lpself = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lpm) self.lpn = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lpn) self.dp = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dp) self.lTdot = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lTdot) self.gy0 = Constraint(self.fe_t, self.cp_ta, rule=gy0) self.gy = Constraint(self.fe_t, self.cp_ta, self.tray, rule=gy) self.dMV = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dMV) self.dMv1 = Constraint(self.fe_t, self.cp_ta, rule=dMv1) self.dMvn = Constraint(self.fe_t, self.cp_ta, rule=dMvn) self.hyd = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hyd) self.hyd1 = Constraint(self.fe_t, self.cp_ta, rule=hyd1) self.hydN = Constraint(self.fe_t, self.cp_ta, rule=hydN) self.dvself = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dvm) # -------------------------------------------------------------------------------------------------------------- #: Control constraint self.u1_e = Expression(self.fe_t, rule=lambda m, i: self.Rec[i]) self.u2_e = Expression(self.fe_t, rule=lambda m, i: self.Qr[i]) self.u1_c = Constraint(self.fe_t, rule=lambda m, i: self.u1[i] == self.u1_e[i]) self.u2_c = Constraint(self.fe_t, rule=lambda m, i: self.u2[i] == self.u2_e[i]) # -------------------------------------------------------------------------------------------------------------- #: Suffixes self.dual = Suffix(direction=Suffix.IMPORT_EXPORT) self.ipopt_zL_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zU_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zL_in = Suffix(direction=Suffix.EXPORT) self.ipopt_zU_in = Suffix(direction=Suffix.EXPORT)
def _rule_t0(m, n): return m.T[0, n] == m.T_ic[n] def _rule_tj0(m, n): return m.Tj[0, n] == m.Tj_ic[n] #: type: (int, int, dict) """ CSTR from Rodrigo's thesis Returns: cstr_rodrigo_dae: The model itmod. Without discretization. """ #: if steady == True fallback to steady-state computation mod = ConcreteModel() #: mod.nfe_t = nfe_t #: #: mod.ncp_t = ncp_t mod.discretized = False ncstr = 1 mod.ncstr = Set(initialize=[i for i in range(0, ncstr)]) mod.t = ContinuousSet(bounds=(0, 1)) mod.Cainb = Param(default=1.0) mod.Tinb = Param(default=275.0) # mod.Tjinb = Param(default=250.0) #: Our control var mod.Tjinb = Var(mod.t, initialize=250) mod.u1 = Param(mod.t, default=250,
def representative(duration_repr, selection, VWat=75000, solArea=2 * (18300 + 15000), VSTC=75000, pipe_model='ExtensivePipe', time_step=3600): """ Args: duration_repr: selection: VWat: solArea: VSTC: pipe_model: time_step: Returns: """ unit_sec = 3600 * 24 # Seconds per unit time of duration (seconds per day) netGraph = CaseFuture.make_graph(repr=True) import pandas as pd import time begin = time.clock() topmodel = ConcreteModel() # In[14]: optimizers = {} epoch = pd.Timestamp('20140101') for start_day, duration in selection.items(): start_time = epoch + pd.Timedelta(days=start_day) optmodel = Modesto(graph=netGraph, pipe_model=pipe_model) for comp in optmodel.get_node_components( filter_type='StorageCondensed').values(): comp.set_reps(num_reps=int(duration)) topmodel.add_component(name='repr_' + str(start_day), val=optmodel.model) ##################### # Assign parameters # ##################### optmodel = CaseFuture.set_params( optmodel, pipe_model=pipe_model, repr=True, horizon=duration_repr * unit_sec, time_step=time_step, ) optmodel.change_param(node='SolarArray', comp='solar', param='area', val=solArea) optmodel.change_param(node='SolarArray', comp='tank', param='volume', val=VSTC) optmodel.change_param(node='WaterscheiGarden', comp='tank', param='volume', val=VWat) optmodel.change_param(node='Production', comp='backup', param='ramp', val=0) optmodel.change_param(node='Production', comp='backup', param='ramp_cost', val=0) optmodel.compile(start_time=start_time) # optmodel.set_objective('energy') optimizers[start_day] = optmodel # In[ ]: ############################## # Compile aggregated problem # ############################## selected_days = selection.keys() for i, next_day in enumerate(selected_days): current = selected_days[i - 1] next_heat = optimizers[next_day].get_node_components( filter_type='StorageCondensed') current_heat = optimizers[current].get_node_components( filter_type='StorageCondensed') for component_id in next_heat: # Link begin and end of representative periods def _link_stor(m): """ Args: m: Returns: """ return next_heat[component_id].get_heat_stor_init() == \ current_heat[component_id].get_heat_stor_final() topmodel.add_component(name='_'.join( [component_id, str(current), 'eq']), val=Constraint(rule=_link_stor)) # print 'State equation added for storage {} in representative week starting on day {}'.format( # component_id, # current) # In[ ]: def _top_objective(m): """ Args: m: Returns: """ return 365 / (duration_repr * (365 // duration_repr)) * sum( repetitions * optimizers[start_day].get_objective(objtype='energy', get_value=False) for start_day, repetitions in selection.items()) # Factor 365/364 to make up for missing day # set get_value to False to return object instead of value of the objective function topmodel.obj = Objective(rule=_top_objective, sense=minimize) # In[ ]: end = time.clock() # print 'Writing time:', str(end - begin) return topmodel, optimizers
def test_indexed_by(self): m = ConcreteModel() m.time = ContinuousSet(bounds=(0, 10)) m.space = ContinuousSet(bounds=(0, 10)) m.set = Set(initialize=['a', 'b', 'c']) m.set2 = Set(initialize=[('a', 1), ('b', 2)]) m.v = Var() m.v1 = Var(m.time) m.v2 = Var(m.time, m.space) m.v3 = Var(m.set, m.space, m.time) m.v4 = Var(m.time, m.set2) m.v5 = Var(m.set2, m.time, m.space) @m.Block() def b(b): b.v = Var() b.v1 = Var(m.time) b.v2 = Var(m.time, m.space) b.v3 = Var(m.set, m.space, m.time) @m.Block(m.time) def b1(b): b.v = Var() b.v1 = Var(m.space) b.v2 = Var(m.space, m.set) @m.Block(m.time, m.space) def b2(b): b.v = Var() b.v1 = Var(m.set) @b.Block() def b(bl): bl.v = Var() bl.v1 = Var(m.set) bl.v2 = Var(m.time) @m.Block(m.set2, m.time) def b3(b): b.v = Var() b.v1 = Var(m.space) @b.Block(m.space) def b(bb): bb.v = Var(m.set) disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') self.assertFalse(is_explicitly_indexed_by(m.v, m.time)) self.assertTrue(is_explicitly_indexed_by(m.b.v2, m.space)) self.assertTrue(is_explicitly_indexed_by(m.b.v3, m.time, m.space)) self.assertFalse(is_in_block_indexed_by(m.v1, m.time)) self.assertFalse(is_in_block_indexed_by(m.v2, m.set)) self.assertTrue(is_in_block_indexed_by(m.b1[m.time[1]].v2, m.time)) self.assertTrue(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v1, m.time)) self.assertTrue(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v2, m.time)) self.assertTrue(is_explicitly_indexed_by( m.b2[m.time[1], m.space[1]].b.v2, m.time)) self.assertFalse(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v1, m.set)) self.assertFalse(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v1, m.space, stop_at=m.b2[m.time[1], m.space[1]])) # Explicit indexing with multi-dimensional set: self.assertTrue(is_explicitly_indexed_by(m.v4, m.time, m.set2)) self.assertTrue(is_explicitly_indexed_by(m.v5, m.time, m.set2, m.space)) # Implicit indexing with multi-dimensional set: self.assertTrue(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v, m.set2)) self.assertTrue(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v, m.time)) self.assertTrue(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v1[m.space[1]], m.set2)) self.assertFalse(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v1[m.space[1]], m.space)) self.assertTrue(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.set2)) self.assertTrue(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time)) self.assertTrue(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.space)) self.assertFalse(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.set)) self.assertFalse(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time, stop_at=m.b3['b', 2, m.time[2]])) self.assertFalse(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time, stop_at=m.b3))
def test_get_index_set_except(self): ''' Tests: For components indexed by 0, 1, 2, 3, 4 sets: get_index_set_except one, then two (if any) of those sets check two items that should be in set_except insert item(s) back into these sets via index_getter ''' m = ConcreteModel() m.time = ContinuousSet(bounds=(0, 10)) m.space = ContinuousSet(bounds=(0, 10)) m.set1 = Set(initialize=['a', 'b', 'c']) m.set2 = Set(initialize=['d', 'e', 'f']) m.v = Var() m.v1 = Var(m.time) m.v2 = Var(m.time, m.space) m.v3 = Var(m.time, m.space, m.set1) m.v4 = Var(m.time, m.space, m.set1, m.set2) # Multi-dimensional set: m.set3 = Set(initialize=[('a', 1), ('b', 2)]) m.v5 = Var(m.set3) m.v6 = Var(m.time, m.space, m.set3) m.v7 = Var(m.set3, m.space, m.time) disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') # Want this to give a TypeError # info = get_index_set_except(m.v, m.time) # Indexed by one set info = get_index_set_except(m.v1, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(set_except == [None]) # Variable is not indexed by anything except time # Test that index_getter returns only the new value given, # regardless of whether it was part of the set excluded (time): self.assertEqual(index_getter((), -1), -1) # Indexed by two sets info = get_index_set_except(m.v2, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(m.space[1] in set_except and m.space.last() in set_except) # Here (2,) is the partial index, corresponding to space. # Can be provided as a scalar or tuple. 4, the time index, # should be inserted before (2,) self.assertEqual(index_getter((2,), 4), (4, 2)) self.assertEqual(index_getter(2, 4), (4, 2)) # Case where every set is "omitted," now for multiple sets info = get_index_set_except(m.v2, m.space, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(set_except == [None]) # 5, 7 are the desired index values for space, time # index_getter should put them in the right order for m.v2, # even if they are not valid indices for m.v2 self.assertEqual(index_getter((), 5, 7), (7, 5)) # Indexed by three sets info = get_index_set_except(m.v3, m.time) # In this case set_except is a product of the two non-time sets # indexing v3 set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue((m.space[1], 'b') in set_except and (m.space.last(), 'a') in set_except) # index_getter inserts a scalar index into an index of length 2 self.assertEqual(index_getter((2, 'b'), 7), (7, 2, 'b')) info = get_index_set_except(m.v3, m.space, m.time) # Two sets omitted. Now set_except is just set1 set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue('a' in set_except) # index_getter inserts the two new indices in the right order self.assertEqual(index_getter('b', 1.2, 1.1), (1.1, 1.2, 'b')) # Indexed by four sets info = get_index_set_except(m.v4, m.set1, m.space) # set_except is a product, and there are two indices to insert set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue((m.time[1], 'd') in set_except) self.assertEqual(index_getter((4, 'f'), 'b', 8), (4, 8, 'b', 'f')) # The intended usage of this function looks something like: index_set = m.v4.index_set() for partial_index in set_except: complete_index = index_getter(partial_index, 'a', m.space[2]) self.assertTrue(complete_index in index_set) # Do something for every index of v4 at 'a' and space[2] # Indexed by a multi-dimensional set info = get_index_set_except(m.v5, m.set3) set_except = info['set_except'] index_getter = info['index_getter'] self.assertEqual(set_except, [None]) self.assertEqual(index_getter((), ('a', 1)), ('a', 1)) info = get_index_set_except(m.v6, m.set3, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(m.space[1] in set_except) self.assertEqual(index_getter(m.space[1], ('b', 2), m.time[1]), (m.time[1], m.space[1], 'b', 2)) info = get_index_set_except(m.v7, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertIn(('a', 1, m.space[1]), set_except) self.assertEqual(index_getter(('a', 1, m.space[1]), m.time[1]), ('a', 1, m.space[1], m.time[1])) m.v8 = Var(m.time, m.set3, m.time) with self.assertRaises(ValueError): info = get_index_set_except(m.v8, m.time) with self.assertRaises(ValueError): info = get_index_set_except(m.v8, m.space)
def three_objective_model(): model = ConcreteModel() # Define variables model.LIGN = Var(within=NonNegativeReals) model.LIGN1 = Var(within=NonNegativeReals) model.LIGN2 = Var(within=NonNegativeReals) model.OIL = Var(within=NonNegativeReals) model.OIL2 = Var(within=NonNegativeReals) model.OIL3 = Var(within=NonNegativeReals) model.NG = Var(within=NonNegativeReals) model.NG1 = Var(within=NonNegativeReals) model.NG2 = Var(within=NonNegativeReals) model.NG3 = Var(within=NonNegativeReals) model.RES = Var(within=NonNegativeReals) model.RES1 = Var(within=NonNegativeReals) model.RES3 = Var(within=NonNegativeReals) # -------------------------------------- # Define the objective functions # -------------------------------------- def objective1(model): return 30 * model.LIGN + 75 * model.OIL + 60 * model.NG + 90 * model.RES def objective2(model): return 1.44 * model.LIGN + 0.72 * model.OIL + 0.45 * model.NG def objective3(model): return model.OIL + model.NG # -------------------------------------- # Define the regular constraints # -------------------------------------- def constraint1(model): return model.LIGN - model.LIGN1 - model.LIGN2 == 0 def constraint2(model): return model.OIL - model.OIL2 - model.OIL3 == 0 def constraint3(model): return model.NG - model.NG1 - model.NG2 - model.NG3 == 0 def constraint4(model): return model.RES - model.RES1 - model.RES3 == 0 def constraint5(model): return model.LIGN <= 31000 def constraint6(model): return model.OIL <= 15000 def constraint7(model): return model.NG <= 22000 def constraint8(model): return model.RES <= 10000 def constraint9(model): return model.LIGN1 + model.NG1 + model.RES1 >= 38400 def constraint10(model): return model.LIGN2 + model.OIL2 + model.NG2 >= 19200 def constraint11(model): return model.OIL3 + model.NG3 + model.RES3 >= 6400 # -------------------------------------- # Add components to the model # -------------------------------------- # Add the constraints to the model model.con1 = Constraint(rule=constraint1) model.con2 = Constraint(rule=constraint2) model.con3 = Constraint(rule=constraint3) model.con4 = Constraint(rule=constraint4) model.con5 = Constraint(rule=constraint5) model.con6 = Constraint(rule=constraint6) model.con7 = Constraint(rule=constraint7) model.con8 = Constraint(rule=constraint8) model.con9 = Constraint(rule=constraint9) model.con10 = Constraint(rule=constraint10) model.con11 = Constraint(rule=constraint11) # Add the objective functions to the model using ObjectiveList(). Note # that the first index is 1 instead of 0! model.obj_list = ObjectiveList() model.obj_list.add(expr=objective1(model), sense=minimize) model.obj_list.add(expr=objective2(model), sense=minimize) model.obj_list.add(expr=objective3(model), sense=minimize) # By default deactivate all the objective functions for o in range(len(model.obj_list)): model.obj_list[o + 1].deactivate() return model
def _dualize(self, block, unfixed=[]): """ Generate the dual of a block """ # # Collect linear terms from the block # A, b_coef, c_rhs, c_sense, d_sense, vnames, cnames, v_domain = collect_linear_terms( block, unfixed) ##print(A) ##print(vnames) ##print(cnames) ##print(list(A.keys())) ##print("---") ##print(A.keys()) ##print(c_sense) ##print(c_rhs) # # Construct the block # if isinstance(block, Model): dual = ConcreteModel() else: dual = Block() dual.construct() _vars = {} def getvar(name, ndx=None): v = _vars.get((name, ndx), None) if v is None: v = Var() if ndx is None: v_name = name elif type(ndx) is tuple: v_name = "%s[%s]" % (name, ','.join(map(str, ndx))) else: v_name = "%s[%s]" % (name, str(ndx)) setattr(dual, v_name, v) _vars[name, ndx] = v return v # # Construct the objective # if d_sense == minimize: dual.o = Objective(expr=sum(-b_coef[name, ndx] * getvar(name, ndx) for name, ndx in b_coef), sense=d_sense) else: dual.o = Objective(expr=sum(b_coef[name, ndx] * getvar(name, ndx) for name, ndx in b_coef), sense=d_sense) # # Construct the constraints # for cname in A: for ndx, terms in iteritems(A[cname]): expr = 0 for term in terms: expr += term.coef * getvar(term.var, term.ndx) if not (cname, ndx) in c_rhs: c_rhs[cname, ndx] = 0.0 if c_sense[cname, ndx] == 'e': e = expr - c_rhs[cname, ndx] == 0 elif c_sense[cname, ndx] == 'l': e = expr - c_rhs[cname, ndx] <= 0 else: e = expr - c_rhs[cname, ndx] >= 0 c = Constraint(expr=e) if ndx is None: c_name = cname elif type(ndx) is tuple: c_name = "%s[%s]" % (cname, ','.join(map(str, ndx))) else: c_name = "%s[%s]" % (cname, str(ndx)) setattr(dual, c_name, c) # for (name, ndx), domain in iteritems(v_domain): v = getvar(name, ndx) flag = type(ndx) is tuple and (ndx[-1] == 'lb' or ndx[-1] == 'ub') if domain == 1: v.domain = NonNegativeReals elif domain == -1: v.domain = NonPositiveReals else: # TODO: verify that this case is possible v.domain = Reals return dual