def model(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.prop_water = iapws95.Iapws95ParameterBlock() n_waterwalls = 10 m.fs.ww_zones = pyo.RangeSet(n_waterwalls) m.fs.Waterwalls = WaterwallSection( m.fs.ww_zones, default={ "dynamic": False, "has_holdup": False, "property_package": m.fs.prop_water, "has_heat_transfer": True, "has_pressure_change": True, }, ) def arc_rule(b, i): return { "source": m.fs.Waterwalls[i].outlet, "destination": m.fs.Waterwalls[i + 1].inlet } m.arc = Arc(pyo.RangeSet(n_waterwalls - 1), rule=arc_rule) # Pyomo expands arcs writing constraints outlet unit 1 = inlet unit 2 pyo.TransformationFactory("network.expand_arcs").apply_to(m) return m
def rp_example3(): """ This example is done multiple ways to test a few common errors where the integrator and fully time-discretized problem differ, and alternative working formulations. Another way to formulate this problem is to fix the derivative. This doesn't work for the integrator because it loses the association between the differential variable and its derivative. Since for users, the result of this formulation may be unexpected, the PETSc utilities will raise an exception if derivatives are fixed to anything other than 0. """ m = pyo.ConcreteModel() m.time = pyodae.ContinuousSet(initialize=(0.0, 10.0)) m.x = pyo.Var(m.time) m.u = pyo.Var(m.time) m.dxdt = pyodae.DerivativeVar(m.x, wrt=m.time) def diff_eq_rule(m, t): return m.dxdt[t] == m.x[t]**2 - m.u[t] m.diff_eq = pyo.Constraint(m.time, rule=diff_eq_rule) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') m.u[0].fix(1.0) m.dxdt[:].fix(2.0) return m
def test_with_gdp(self, name: str, opt_class: Type[PersistentSolver]): opt: PersistentSolver = opt_class() if not opt.available(): raise unittest.SkipTest m = pe.ConcreteModel() m.x = pe.Var(bounds=(-10, 10)) m.y = pe.Var(bounds=(-10, 10)) m.obj = pe.Objective(expr=m.y) m.d1 = gdp.Disjunct() m.d1.c1 = pe.Constraint(expr=m.y >= m.x + 2) m.d1.c2 = pe.Constraint(expr=m.y >= -m.x + 2) m.d2 = gdp.Disjunct() m.d2.c1 = pe.Constraint(expr=m.y >= m.x + 1) m.d2.c2 = pe.Constraint(expr=m.y >= -m.x + 1) m.disjunction = gdp.Disjunction(expr=[m.d2, m.d1]) pe.TransformationFactory("gdp.bigm").apply_to(m) res = opt.solve(m) self.assertAlmostEqual(res.best_feasible_objective, 1) self.assertAlmostEqual(m.x.value, 0) self.assertAlmostEqual(m.y.value, 1) opt: PersistentSolver = opt_class() opt.use_extensions = True res = opt.solve(m) self.assertAlmostEqual(res.best_feasible_objective, 1) self.assertAlmostEqual(m.x.value, 0) self.assertAlmostEqual(m.y.value, 1)
def run_optimization(model, n_time_steps): """Short summary. Parameters ---------- model : pyomo model A pyomo model with all the states, control and constraints described. n_time_steps : int Number of time steps to use in the simulation. Returns ------- m, optimal_values An instance of optimised model and dataframe of all the optimal values. """ # Create a model instance m = model # Transform and solve pyo.TransformationFactory('dae.finite_difference').apply_to( m, nfe=n_time_steps, wrt=m.time, scheme='BACKWARD') opt = pyo.SolverFactory('ipopt') solution = opt.solve(m) # set tee true for detailed resutls # solution.write() # Get the dataframe of all the states and control optimal_values = get_profiles(m) return m, optimal_values, solution
def make_dynamic_model(**disc_args): # Level control model m = pyo.ConcreteModel() m.time = dae.ContinuousSet(initialize=[0.0, 10.0]) m.height = pyo.Var(m.time, initialize=1.0) m.flow_in = pyo.Var(m.time, initialize=1.0) m.flow_out = pyo.Var(m.time, initialize=0.5) m.dhdt = dae.DerivativeVar(m.height, wrt=m.time, initialize=0.0) m.area = pyo.Param(initialize=1.0) m.flow_const = pyo.Param(initialize=0.5) def diff_eqn_rule(m, t): return m.area * m.dhdt[t] - (m.flow_in[t] - m.flow_out[t]) == 0 m.diff_eqn = pyo.Constraint(m.time, rule=diff_eqn_rule) def flow_out_rule(m, t): return m.flow_out[t] - (m.flow_const * pyo.sqrt(m.height[t])) == 0 m.flow_out_eqn = pyo.Constraint(m.time, rule=flow_out_rule) default_disc_args = { "wrt": m.time, "nfe": 5, "scheme": "BACKWARD", } default_disc_args.update(disc_args) discretizer = pyo.TransformationFactory("dae.finite_difference") discretizer.apply_to(m, **default_disc_args) return m
def test_bounds(model): m = model elim = pyo.TransformationFactory("simple_equality_eliminator") m.x[3].setlb(-1) m.x[3].setub(10) m.x[4].setlb(1) m.x[4].setub(12) elim.apply_to(m) # The bounds here come from constraint c5. z4 is 4, x1 is 0, and x4 and x5 # are not fixed, so you get 4 = x3 + x4. I'm not sure if x3 or x4 will be # replaced, so I calculated bounds on both. # For x3 the bounds that come from x4 are 4 - x4.lb and 4 - x4.ub or (-8 and 3) # so the tightest set of bounds from x3 and x4 are (-1, 3) # If instead x3 is replaced, the bounds on x4 that come from x3 are # 4 - 10 and 4 + 1 or (-6, 5). The tightest set of bounds on x4 is (1, 5) if id(m.x[3]) not in elim._subs_map: assert m.x[3].lb == -1 assert m.x[3].ub == 3 else: assert m.x[4].lb == 1 assert m.x[4].ub == 5
def simulate_tvc(ti_controls, tv_controls, sampling_times, model_parameters): tau = np.max(sampling_times) normalized_sampling_times = sampling_times / tau model = create_model_tvc(normalized_sampling_times) """ fixing the control variables """ # time-invariant model.theta_0.fix(model_parameters[0]) model.theta_1.fix(model_parameters[1]) model.alpha_a.fix(model_parameters[2]) model.alpha_b.fix(0) model.nu.fix(model_parameters[3]) model.tau.fix(max(sampling_times)) model.ca[0].fix(ti_controls[0]) model.cb[0].fix(0) """ time-varying controls """ model.tvc[model.temp] = tv_controls[0] """ simulating """ simulator = pod.Simulator(model, package="casadi") simulator.simulate(integrator='idas', varying_inputs=model.tvc) simulator.initialize_model() discretizer = po.TransformationFactory("dae.collocation") discretizer.apply_to(model, nfe=10, ncp=3, scheme="LAGRANGE-RADAU") """" extracting results and returning it in appropriate format """ ca = np.array([model.ca[t].value for t in normalized_sampling_times]) cb = np.array([model.cb[t].value for t in normalized_sampling_times]) return np.array([ca, cb]).T
def rp_example(): """This example is done multiple ways to test a few common errors where the integrator and fully time-discretized problem differ and alternative working formulations. The PETSc utilities raise an exception when a differential variable is fixed. While this is okay for the fully time-discretized problem, the integrator will not correctly link a fixed differential variable (at non-initial time points) with a time derivative. """ m = pyo.ConcreteModel() m.time = pyodae.ContinuousSet(initialize=(0.0, 10.0)) m.x = pyo.Var(m.time) m.u = pyo.Var(m.time) m.dxdt = pyodae.DerivativeVar(m.x, wrt=m.time) def diff_eq_rule(m, t): return m.dxdt[t] == m.x[t]**2 - m.u[t] m.diff_eq = pyo.Constraint(m.time, rule=diff_eq_rule) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') for t in m.time: m.x[t].fix(2.0 * t) m.u[0].fix(1.0) return m
def test_full_auto_scaling_mbtype_element(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": True, "time_units": pyo.units.s}) m.fs.pp = PhysicalParameterTestBlock() m.fs.rp = ReactionParameterTestBlock(default={"property_package": m.fs.pp}) m.fs.cv = ControlVolume1DBlock( default={ "property_package": m.fs.pp, "reaction_package": m.fs.rp, "transformation_method": "dae.finite_difference", "transformation_scheme": "BACKWARD", "finite_elements": 10 }) m.fs.cv.add_geometry() m.fs.cv.add_state_blocks(has_phase_equilibrium=False) m.fs.cv.add_reaction_blocks(has_equilibrium=False) m.fs.cv.add_total_element_balances(has_mass_transfer=True) m.fs.cv.apply_transformation() m.discretizer = pyo.TransformationFactory('dae.finite_difference') m.discretizer.apply_to(m, nfe=3, wrt=m.fs.time, scheme="BACKWARD") iscale.calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(iscale.unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def rp_example4(): """ This example is done multiple ways to test a few common errors where the integrator and fully time-discretized problem differ, and alternative working formulations. Rather than fixing the derivative, we can add a constraint to set the derivative. This should work as intended for both the fully time-discretized problem and integrator. """ m = pyo.ConcreteModel() m.time = pyodae.ContinuousSet(initialize=(0.0, 10.0)) m.x = pyo.Var(m.time, initialize=1) m.u = pyo.Var(m.time, initialize=1) m.dxdt = pyodae.DerivativeVar(m.x, wrt=m.time) def diff_eq1_rule(m, t): return m.dxdt[t] == m.x[t]**2 - m.u[t] m.diff_eq1 = pyo.Constraint(m.time, rule=diff_eq1_rule) def diff_eq2_rule(m, t): return m.dxdt[t] == 2.0 m.diff_eq2 = pyo.Constraint(m.time, rule=diff_eq2_rule) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') m.u[0].fix(1.0) m.x[0].fix(0.0) m.diff_eq2[0].deactivate() return m
def pyomo_solver(model, solver, config, neos=False): """Solve the continuous NLP by discretizing it using backward finite difference and pyomo solvers Arguments: model {pyomo model} -- a concrete model build using Pyomo solver {string} -- Solver used for the optimization problem. For e.g. ipopt config{yaml} -- configurations of the setting neos {bool} -- Use the neos solver if True """ # time variables if model.tf < 1.0: N = config['freq'] else: N = int(round(model.tf * config['freq'])) # finite difference discretization # pyo.TransformationFactory('dae.finite_difference').apply_to(model, wrt=model.t, nfe=N, scheme='BACKWARD') # direct collocation pyo.TransformationFactory('dae.collocation').apply_to(model, wrt=model.t, nfe=N, ncp=6) # if a particular variable has to be piecewise constant then uncomment the following and replace the var parameter in 'reduce_collocation_points' # pyo.TransformationFactory('dae.collocation').apply_to(model, wrt=model.t, nf=10, ncp=6).reduce_collocation_points(model, var=model.u, ncp=1, contset=model.t) if neos: print("Using NEOS with Pyomo") SolverManagerFactory('neos').solve(model, opt=solver).write() else: pyo.SolverFactory(solver).solve(model).write() return model
def __solve(self) -> None: """ optimization model solver function. The solver function has transformations, which detects fixed variables and detects trival constraints in oder to remove them. """ pyo.TransformationFactory("contrib.detect_fixed_vars").apply_to( self.model) # type: ignore pyo.TransformationFactory( "contrib.deactivate_trivial_constraints").apply_to( self.model) # type: ignore # initialise the solver object self._logger.debug("[ModelSolver] Solver object initiated...") solver = Config.OPTIMISATION_MODEL_CONFIG['SOLVER_TYPE'] opt = pyo.SolverFactory(solver) if Config.OPTIMISATION_MODEL_CONFIG['SOLVER_OPTION'].get( solver) is not None: for k, v in Config.OPTIMISATION_MODEL_CONFIG['SOLVER_OPTION'].get( solver).items(): opt.options[k] = v try: start_time = datetime.now() self._logger.debug("[ModelSolver] Solver starting...") results = opt.solve(self.model, tee=True) self.results = results end_time = datetime.now() self._logger.info( f"[ModelSolver] Solver completed in {end_time - start_time}.") except Exception as e: raise Exception( f"Model optimisation failed with {solver} with error message {e}." ) if (results.solver.status == SolverStatus.ok) and (results.solver.termination_condition == TerminationCondition.optimal): self._logger.info("Solution is feasible and optimal") results.write() elif results.solver.termination_condition == TerminationCondition.infeasible: raise ValueError( "Model optimisation resulted into an infeasible solution") self.model.optimised = True
def _create_pyomo_model(self, repn, rho): M = create_model_replacing_LL_with_kkt(repn) # # Transform the problem to a MIP # xfrm = pe.TransformationFactory('mpec.simple_nonlinear') xfrm.apply_to(M, mpec_bound=rho) return M
def simulate_model(modelparameters): """simulating""" model = create_mdoel(modelparameters=modelparameters) simulator = pod.Simulator(model, package='casadi') results = simulator.simulate(integrator='idas') discretizer = po.TransformationFactory("dae.collocation") discretizer.apply_to(model, nfe=10, ncp=3, scheme="LAGRANGE-RADAU") simulator.initialize_model() rate = [model.reaction_rate[z].value for z in model.z] return results, rate
def test_transform(model): m = model elim = pyo.TransformationFactory("simple_equality_eliminator") elim.apply_to(m) assert degrees_of_freedom(m) == 0 assert len([c for c in m.component_data_objects(pyo.Constraint, active=True)]) == 1 assert m.x[1].fixed assert m.x[2].fixed assert m.y.fixed
def test_disjunct_not_in_disjunction(self): m = pe.ConcreteModel() m.x = pe.Var() m.d1 = gdp.Disjunct() m.d1.c = pe.Constraint(expr=m.x == 1) m.d2 = gdp.Disjunct() m.d2.c = pe.Constraint(expr=m.x == 0) with self.assertRaisesRegexp( gdp.GDP_Error, '.*not found in any Disjunctions.*'): pe.TransformationFactory('gdp.bigm').apply_to(m)
def car_example(): """This is to test problems where a differential variable doesn't appear in a constraint this is based on a Pyomo example here: https://github.com/Pyomo/pyomo/blob/main/examples/dae/car_example.py""" m = pyo.ConcreteModel() m.R = pyo.Param(initialize=0.001) # Friction factor m.L = pyo.Param(initialize=100.0) # Final position m.tau = pyodae.ContinuousSet(bounds=(0, 1)) # Unscaled time m.time = pyo.Var(m.tau) # Scaled time m.tf = pyo.Var() m.x = pyo.Var(m.tau, bounds=(0, m.L + 50)) m.v = pyo.Var(m.tau, bounds=(0, None)) m.a = pyo.Var(m.tau, bounds=(-3.0, 1.0), initialize=0) m.dtime = pyodae.DerivativeVar(m.time) m.dx = pyodae.DerivativeVar(m.x) m.dv = pyodae.DerivativeVar(m.v) m.obj = pyo.Objective(expr=m.tf) def _ode1(m, i): if i == 0: return pyo.Constraint.Skip return m.dx[i] == m.tf * m.v[i] m.ode1 = pyo.Constraint(m.tau, rule=_ode1) def _ode2(m, i): if i == 0: return pyo.Constraint.Skip return m.dv[i] == m.tf * (m.a[i] - m.R * m.v[i]**2) m.ode2 = pyo.Constraint(m.tau, rule=_ode2) def _ode3(m, i): if i == 0: return pyo.Constraint.Skip return m.dtime[i] == m.tf m.ode3 = pyo.Constraint(m.tau, rule=_ode3) def _init(m): yield m.x[0] == 0 #yield m.x[1] == m.L yield m.v[0] == 0 yield m.v[1] == 0 yield m.time[0] == 0 m.initcon = pyo.ConstraintList(rule=_init) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') return m
def test_8(): # Test replace indexed by indexed var that doesn't have enough/right indexes rp = pyo.TransformationFactory("replace_variables") m = pyo.ConcreteModel() m.b1 = pyo.Block() m.b1.b2 = pyo.Block() x = m.b1.b2.x = pyo.Var(["a", "b", "c"], [1,2,3], initialize=2) m.y = pyo.Var(["a", "b", "d"], [1,2,3], initialize=3) with pytest.raises(ValueError): rp.apply_to(m, substitute=[(x, m.y)])
def _discretize(self, _transform_type="dae.finite_difference", _scheme="forward", **kwargs): _model = self._model _parameters = self._parameters discretizer = env.TransformationFactory(_transform_type) discretizer.apply_to(_model, nfe=_parameters["episode_pts"], wrt=_model.x_local, scheme=_scheme, **kwargs) for expr in _model.component_objects(env.Expression): expr.reconstruct()
def test_clone(model): m2 = model.clone() assert (m2.fs.heater.inlet.flow_mol[0] is m2.fs.heater.control_volume.properties_in[0].flow_mol) assert not (m2.fs.heater.inlet.flow_mol[0] is model.fs.heater.control_volume.properties_in[0].flow_mol) pe.TransformationFactory('network.expand_arcs').apply_to(m2) # Check that Arcs were expanded assert isinstance(m2.fs.stream._expanded_block, pe.Block) assert model.fs.stream._expanded_block is None
def test_disjunct_not_in_active_disjunction(self): m = pe.ConcreteModel() m.x = pe.Var() m.d1 = gdp.Disjunct() m.d1.c = pe.Constraint(expr=m.x == 1) m.d2 = gdp.Disjunct() m.d2.c = pe.Constraint(expr=m.x == 0) m.disjunction = gdp.Disjunction(expr=[m.d1, m.d2]) m.disjunction.deactivate() with self.assertRaisesRegexp( gdp.GDP_Error, '.*While it participates in a Disjunction, ' 'that Disjunction is currently deactivated.*'): pe.TransformationFactory('gdp.bigm').apply_to(m)
def test_3(): # Test expression in constraint rp = pyo.TransformationFactory("replace_variables") m = pyo.ConcreteModel() m.x = pyo.Var(["a", "b", "c"], initialize=2) m.y = pyo.Var(initialize=3) m.z = pyo.Var(initialize=0) m.e1 = pyo.Expression(expr=sum(m.x[i] for i in m.x)) m.c1 = pyo.Constraint(expr=m.z==m.e1) assert(m.c1.body() == -6) # hope constraint arrangment is deterministic rp.apply_to(m, substitute=[(m.x["c"], m.y)]) assert(m.c1.body() == -7)
def test_disjunct_not_in_disjunction(self): m = pe.ConcreteModel() m.x = pe.Var() m.d1 = gdp.Disjunct() m.d1.c = pe.Constraint(expr=m.x == 1) m.d2 = gdp.Disjunct() m.d2.c = pe.Constraint(expr=m.x == 0) pe.TransformationFactory('gdp.bigm').apply_to(m) log = StringIO() with LoggingIntercept(log, 'pyomo.gdp', logging.WARNING): check_model_algebraic(m) self.assertRegexpMatches(log.getvalue(), '.*not found in any Disjunctions.*')
def test_scale_arcs(): m = pyo.ConcreteModel() m.x = pyo.Var([1, 2, 3, 4]) m.y = pyo.Var([1, 2, 3, 4]) m.p1 = Port() m.p1.add(m.x[1], name="x") m.p1.add(m.y[1], name="y") m.p = Port([2, 3, 4]) m.p[2].add(m.x[2], name="x") m.p[2].add(m.y[2], name="y") m.p[3].add(m.x[3], name="x") m.p[3].add(m.y[3], name="y") m.p[4].add(m.x[4], name="x") m.p[4].add(m.y[4], name="y") def arc_rule(b, i): if i == 1: return (m.p1, m.p[2]) elif i == 2: return (m.p[3], m.p[4]) m.arcs = Arc([1, 2], rule=arc_rule) sc.set_scaling_factor(m.x, 10) sc.set_scaling_factor(m.y, 20) sc.set_scaling_factor(m.x[1], 5) # make sure there is no error if the scaling is done with unexpanded arcs sc.scale_arc_constraints(m) # expand and make sure it works pyo.TransformationFactory('network.expand_arcs').apply_to(m) sc.scale_arc_constraints(m) m.x[1] = 1 m.x[2] = 2 m.x[3] = 3 m.x[4] = 4 m.y[1] = 11 m.y[2] = 12 m.y[3] = 13 m.y[4] = 14 # for all the arc constraints the differnce is 1 the scale factor is the # smallest scale factor for variables in a constraint. Make sure the # constraints are scaled as expected. assert abs(m.arcs_expanded[1].x_equality.body()) == 5 assert abs(m.arcs_expanded[2].x_equality.body()) == 10 assert abs(m.arcs_expanded[1].y_equality.body()) == 20 assert abs(m.arcs_expanded[2].y_equality.body()) == 20
def test_7(): # Test replace indexed by non-indexed rp = pyo.TransformationFactory("replace_variables") m = pyo.ConcreteModel() m.b1 = pyo.Block() m.b1.b2 = pyo.Block() x = m.b1.b2.x = pyo.Var(["a", "b", "c"], [1,2,3], initialize=2) m.y = pyo.Var(["a", "b", "c", "d"], [1,2,3], initialize=3) m.z = pyo.Var(initialize=0) assert x.is_indexed() assert not m.z.is_indexed() with pytest.raises(TypeError): rp.apply_to(m, substitute=[(x, m.z)])
def initialize_model(m, ntfe=10): disc = pyo.TransformationFactory("dae.finite_difference") disc.apply_to(m, wrt=m.time, nfe=ntfe, scheme="BACKWARD") t0 = m.time.first() m.conc_in[:, "A"].fix(5.0) m.conc_in[:, "B"].fix(0.01) m.flow_in[:].fix(1.0) m.flow_in[t0].fix(0.1) m.conc[t0, "A"].fix(1.0) m.conc[t0, "B"].fix(0.0)
def run_transformationfactory_test(): with LoggingIntercept() as LOG, capture_output(capture_fd=True) as OUT: info = [] for t in sorted(pyo.TransformationFactory): _doc = pyo.TransformationFactory.doc(t) info.append(" %s: %s" % (t, _doc)) if 'DEPRECATED' not in _doc: pyo.TransformationFactory(t) _check_log_and_out(LOG, OUT, 30, t) bigm = pyo.TransformationFactory('gdp.bigm') print("") print("Pyomo Transformations") print("---------------------") print('\n'.join(info)) if not isinstance(bigm, pyo.Transformation): print("TransformationFactory(gdp.bigm) did not return a " "transformation") sys.exit(4) _check_log_and_out(LOG, OUT, 30)
def test_6(): # Test non-variable exception rp = pyo.TransformationFactory("replace_variables") m = pyo.ConcreteModel() m.b1 = pyo.Block() m.b1.b2 = pyo.Block() x = m.b1.b2.x = pyo.Var(["a", "b", "c"], [1,2,3], initialize=2) m.y = pyo.Var(["a", "b", "c", "d"], [1,2,3], initialize=3) m.z = pyo.Var(initialize=0) with pytest.raises(TypeError): rp.apply_to(m, substitute=[(x, m.b1)]) with pytest.raises(TypeError): rp.apply_to(m, substitute=[(m.b1, x)])
def test_10(): # test with more than one variable in the list rp = pyo.TransformationFactory("replace_variables") m = pyo.ConcreteModel() m.x = pyo.Var(["a", "b", "c"], initialize=2) m.a = pyo.Var(initialize=5) m.b = pyo.Var(initialize=6) m.c = pyo.Var(initialize=7) m.e1 = pyo.Expression(expr=sum(m.x[i] for i in m.x)) assert(pyo.value(m.e1)==6) rp.apply_to(m, substitute=[(m.x["a"], m.a), (m.x["b"], m.b), (m.x["c"], m.c)]) assert(pyo.value(m.e1)==18)
def test_4(): # Test expression in objective rp = pyo.TransformationFactory("replace_variables") m = pyo.ConcreteModel() m.x = pyo.Var(["a", "b", "c"], initialize=2) m.y = pyo.Var(initialize=3) m.z = pyo.Var(initialize=0) m.e1 = pyo.Expression(expr=sum(m.x[i] for i in m.x)) m.c1 = pyo.Constraint(expr=m.z==m.e1) m.o1 = pyo.Objective(expr=m.e1) assert(pyo.value(m.o1) == 6) rp.apply_to(m, substitute=[(m.x["c"], m.y)]) assert(pyo.value(m.o1) == 7)