diff --git a/_build/.doctrees/Material/Dynamic Exercises.doctree b/_build/.doctrees/Material/Dynamic Exercises.doctree new file mode 100644 index 00000000..a9270305 Binary files /dev/null and b/_build/.doctrees/Material/Dynamic Exercises.doctree differ diff --git a/_build/.doctrees/Material/Dynamic Exercises/colloc_matrix.doctree b/_build/.doctrees/Material/Dynamic Exercises/colloc_matrix.doctree new file mode 100644 index 00000000..a3b46fe5 Binary files /dev/null and b/_build/.doctrees/Material/Dynamic Exercises/colloc_matrix.doctree differ diff --git a/_build/.doctrees/Material/Dynamic Exercises/param_est1.doctree b/_build/.doctrees/Material/Dynamic Exercises/param_est1.doctree new file mode 100644 index 00000000..62cce35a Binary files /dev/null and b/_build/.doctrees/Material/Dynamic Exercises/param_est1.doctree differ diff --git a/_build/.doctrees/Material/Dynamic Exercises/param_est2.doctree b/_build/.doctrees/Material/Dynamic Exercises/param_est2.doctree new file mode 100644 index 00000000..775268b9 Binary files /dev/null and b/_build/.doctrees/Material/Dynamic Exercises/param_est2.doctree differ diff --git a/_build/.doctrees/Material/Dynamic Exercises/small_colloc.doctree b/_build/.doctrees/Material/Dynamic Exercises/small_colloc.doctree new file mode 100644 index 00000000..b1902b0d Binary files /dev/null and b/_build/.doctrees/Material/Dynamic Exercises/small_colloc.doctree differ diff --git a/_build/.doctrees/Material/Dynamic Exercises/small_dae.doctree b/_build/.doctrees/Material/Dynamic Exercises/small_dae.doctree new file mode 100644 index 00000000..67398e9d Binary files /dev/null and b/_build/.doctrees/Material/Dynamic Exercises/small_dae.doctree differ diff --git a/_build/.doctrees/Material/Dynamic Exercises/small_findiff.doctree b/_build/.doctrees/Material/Dynamic Exercises/small_findiff.doctree new file mode 100644 index 00000000..c9fc8a96 Binary files /dev/null and b/_build/.doctrees/Material/Dynamic Exercises/small_findiff.doctree differ diff --git a/_build/.doctrees/Material/GDP Exercises.doctree b/_build/.doctrees/Material/GDP Exercises.doctree new file mode 100644 index 00000000..d8fe840f Binary files /dev/null and b/_build/.doctrees/Material/GDP Exercises.doctree differ diff --git a/_build/.doctrees/Material/GDP Exercises/strip_packing.doctree b/_build/.doctrees/Material/GDP Exercises/strip_packing.doctree new file mode 100644 index 00000000..d7d4eee4 Binary files /dev/null and b/_build/.doctrees/Material/GDP Exercises/strip_packing.doctree differ diff --git a/_build/.doctrees/Material/Nonlinear Exercises.doctree b/_build/.doctrees/Material/Nonlinear Exercises.doctree new file mode 100644 index 00000000..a80df290 Binary files /dev/null and b/_build/.doctrees/Material/Nonlinear Exercises.doctree differ diff --git a/_build/.doctrees/Material/Nonlinear Exercises/1.1 Alternative Initialization.doctree b/_build/.doctrees/Material/Nonlinear Exercises/1.1 Alternative Initialization.doctree new file mode 100644 index 00000000..8c94fc9c Binary files /dev/null and b/_build/.doctrees/Material/Nonlinear Exercises/1.1 Alternative Initialization.doctree differ diff --git a/_build/.doctrees/Material/Nonlinear Exercises/1.2 Evaluation errors.doctree b/_build/.doctrees/Material/Nonlinear Exercises/1.2 Evaluation errors.doctree new file mode 100644 index 00000000..41f8fee5 Binary files /dev/null and b/_build/.doctrees/Material/Nonlinear Exercises/1.2 Evaluation errors.doctree differ diff --git a/_build/.doctrees/Material/Nonlinear Exercises/1.3 Alternative Formulations.doctree b/_build/.doctrees/Material/Nonlinear Exercises/1.3 Alternative Formulations.doctree new file mode 100644 index 00000000..4cf69265 Binary files /dev/null and b/_build/.doctrees/Material/Nonlinear Exercises/1.3 Alternative Formulations.doctree differ diff --git a/_build/.doctrees/Material/Nonlinear Exercises/1.4 Reactor design problem.doctree b/_build/.doctrees/Material/Nonlinear Exercises/1.4 Reactor design problem.doctree new file mode 100644 index 00000000..54933c07 Binary files /dev/null and b/_build/.doctrees/Material/Nonlinear Exercises/1.4 Reactor design problem.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals.doctree b/_build/.doctrees/Material/Pyomo Fundamentals.doctree new file mode 100644 index 00000000..9ec77ddf Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/1.1 Knapsack Example.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/1.1 Knapsack Example.doctree new file mode 100644 index 00000000..87ddaa76 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/1.1 Knapsack Example.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/1.2 Knapsack with improved printing.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/1.2 Knapsack with improved printing.doctree new file mode 100644 index 00000000..3bf4e391 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/1.2 Knapsack with improved printing.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/1.3 Changing data.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/1.3 Changing data.doctree new file mode 100644 index 00000000..d86d525d Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/1.3 Changing data.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/1.4 Loading data from Excel.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/1.4 Loading data from Excel.doctree new file mode 100644 index 00000000..4afe4114 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/1.4 Loading data from Excel.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/1.5 NLP vs MIP.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/1.5 NLP vs MIP.doctree new file mode 100644 index 00000000..7f931e63 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/1.5 NLP vs MIP.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/2.1 Knapsack problem with rules.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/2.1 Knapsack problem with rules.doctree new file mode 100644 index 00000000..e7e9277a Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/2.1 Knapsack problem with rules.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/2.2 Integer formulation of the knapsack problem.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/2.2 Integer formulation of the knapsack problem.doctree new file mode 100644 index 00000000..5515138c Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/2.2 Integer formulation of the knapsack problem.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/3.1 Using the decorator notation for rules.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/3.1 Using the decorator notation for rules.doctree new file mode 100644 index 00000000..cb68f964 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/3.1 Using the decorator notation for rules.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/3.2 Changing Parameter values.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/3.2 Changing Parameter values.doctree new file mode 100644 index 00000000..9f8b1beb Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/3.2 Changing Parameter values.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/3.3 Integer cuts.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/3.3 Integer cuts.doctree new file mode 100644 index 00000000..fe49e2a1 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/3.3 Integer cuts.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/3.4 Putting it all together with the lot sizing example.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/3.4 Putting it all together with the lot sizing example.doctree new file mode 100644 index 00000000..45196f21 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/3.4 Putting it all together with the lot sizing example.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 1.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 1.doctree new file mode 100644 index 00000000..f675525f Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 1.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 2.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 2.doctree new file mode 100644 index 00000000..58fe7759 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 2.doctree differ diff --git a/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 3.doctree b/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 3.doctree new file mode 100644 index 00000000..521deaf4 Binary files /dev/null and b/_build/.doctrees/Material/Pyomo Fundamentals/Exercises 3.doctree differ diff --git a/_build/.doctrees/Material/References.doctree b/_build/.doctrees/Material/References.doctree new file mode 100644 index 00000000..f625f8fe Binary files /dev/null and b/_build/.doctrees/Material/References.doctree differ diff --git a/_build/.doctrees/README.doctree b/_build/.doctrees/README.doctree new file mode 100644 index 00000000..3cb33e11 Binary files /dev/null and b/_build/.doctrees/README.doctree differ diff --git a/_build/.doctrees/environment.pickle b/_build/.doctrees/environment.pickle new file mode 100644 index 00000000..0efae98c Binary files /dev/null and b/_build/.doctrees/environment.pickle differ diff --git a/_build/.doctrees/intro.doctree b/_build/.doctrees/intro.doctree new file mode 100644 index 00000000..2f45091a Binary files /dev/null and b/_build/.doctrees/intro.doctree differ diff --git a/_build/.doctrees/markdown-notebooks.doctree b/_build/.doctrees/markdown-notebooks.doctree new file mode 100644 index 00000000..89d411e0 Binary files /dev/null and b/_build/.doctrees/markdown-notebooks.doctree differ diff --git a/_build/html/.buildinfo b/_build/html/.buildinfo new file mode 100644 index 00000000..32d5f904 --- /dev/null +++ b/_build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: b0447c1d44c8bed488ca48d70a7cce9f +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/_build/html/Material/Dynamic Exercises.html b/_build/html/Material/Dynamic Exercises.html new file mode 100644 index 00000000..b3e607c5 --- /dev/null +++ b/_build/html/Material/Dynamic Exercises.html @@ -0,0 +1,536 @@ + + + + + + +
+ + + +import numpy
+
+cp = [0, 0.155051, 0.644949, 1]
+
+a = []
+
+print('[')
+for i in range(len(cp)):
+ ptmp = []
+ tmp = 0
+ for j in range(len(cp)):
+ if j != i:
+ row = []
+ row.insert(0,1/(cp[i]-cp[j]))
+ row.insert(1,-cp[j]/(cp[i]-cp[j]))
+ ptmp.insert(tmp,row)
+ tmp += 1
+ p=[1]
+ for j in range(len(cp)-1):
+ p = numpy.convolve(p,ptmp[j])
+ pder = numpy.polyder(p,1)
+ arow = []
+ for j in range(len(cp)):
+ arow.append(numpy.polyval(pder,cp[j]))
+ a.append(arow)
+ print(str(arow)+',')
+print(']')
+
[
+[np.float64(-9.000001008080126), np.float64(-4.139388773624379), np.float64(1.7393879671602779), np.float64(-3.0000002520200333)],
+[np.float64(10.048810106494384), np.float64(3.2247461916839306), np.float64(-3.567840077120941), np.float64(5.531972415060627)],
+[np.float64(-1.382142403745367), np.float64(1.1678398419022438), np.float64(0.7752546483828548), np.float64(-7.53197233105394)],
+[np.float64(0.33333330533110994), np.float64(-0.25319725996179565), np.float64(1.0531974615778044), np.float64(5.000000168013341)],
+]
+
import pyomo.environ as pyo
+from pyomo.dae import ContinuousSet, DerivativeVar
+
+measurements = {1:0.264, 2:0.594, 3:0.801, 5:0.959}
+
+model = pyo.ConcreteModel()
+model.t = ContinuousSet(initialize=measurements.keys(),bounds=(0, 6))
+
+model.x1 = pyo.Var(model.t)
+model.x2 = pyo.Var(model.t)
+
+model.p1 = pyo.Var(bounds=(-1.5,1.5))
+model.p2 = pyo.Var(bounds=(-1.5,1.5))
+
+model.x1dot = DerivativeVar(model.x1,wrt=model.t)
+model.x2dot = DerivativeVar(model.x2)
+
+def _init_conditions(model):
+ yield model.x1[0] == model.p1
+ yield model.x2[0] == model.p2
+model.init_conditions = pyo.ConstraintList(rule=_init_conditions)
+
+# Alternate way to declare initial conditions
+#def _initx1(model):
+# return model.x1[0] == model.p1
+#model.initx1 = pyo.Constraint(rule=_initx1)
+
+#def _initx2(model):
+# return model.x2[0] == model.p2
+#model.initx2 = pyo.Constraint(rule=_initx2)
+
+def _x1dot(model,i):
+ return model.x1dot[i] == model.x2[i]
+model.x1dotcon = pyo.Constraint(model.t, rule=_x1dot)
+
+def _x2dot(model,i):
+ return model.x2dot[i] == 1-2*model.x2[i]-model.x1[i]
+model.x2dotcon = pyo.Constraint(model.t, rule=_x2dot)
+
+def _obj(model):
+ return sum((model.x1[i]-measurements[i])**2 for i in measurements.keys())
+model.obj = pyo.Objective(rule=_obj)
+
+# Discretize model using Orthogonal Collocation
+discretizer = pyo.TransformationFactory('dae.collocation')
+discretizer.apply_to(model,nfe=8,ncp=5)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+
+results = solver.solve(model,tee=True)
+
+t_meas = sorted(list(measurements.keys()))
+x1_meas = [pyo.value(measurements[i]) for i in sorted(measurements.keys())]
+
+t = list(model.t)
+x1 = [pyo.value(model.x1[i]) for i in model.t]
+
+import matplotlib.pyplot as plt
+
+plt.plot(t,x1)
+plt.plot(t_meas,x1_meas,'o')
+plt.xlabel('t')
+plt.ylabel('x')
+plt.title('Dynamic Parameter Estimation Using Collocation')
+plt.show()
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 51
+ 48 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 49 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 51 results = solver.solve(model,tee=True)
+ 53 t_meas = sorted(list(measurements.keys()))
+ 54 x1_meas = [pyo.value(measurements[i]) for i in sorted(measurements.keys())]
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
Here we work through an example of Kinetic Parameter Estimation.
+First we simulate the kinematic behaviour
+import pyomo.environ as pyo
+from pyomo.dae import ContinuousSet, DerivativeVar, Simulator
+import scipy
+
+m = pyo.ConcreteModel()
+
+m.t = ContinuousSet(bounds=(0,1))
+m.a = pyo.Var(m.t)
+m.b = pyo.Var(m.t)
+
+m.k1 = pyo.Param(initialize=5)
+m.k2 = pyo.Param(initialize=1)
+
+m.dadt = DerivativeVar(m.a)
+m.dbdt = DerivativeVar(m.b)
+
+m.a[0].fix(1)
+m.b[0].fix(0)
+
+def _da(m, t):
+ return m.dadt[t] == -m.k1*m.a[t]
+m.da_con = pyo.Constraint(m.t, rule=_da)
+
+def _db(m, t):
+ return m.dbdt[t] == m.k1*m.a[t] - m.k2*m.b[t]
+m.db_con = pyo.Constraint(m.t, rule=_db)
+
+mysim = Simulator(m, package='scipy')
+tsim, profiles = mysim.simulate(integrator='vode', numpoints=100)
+
+import matplotlib.pyplot as plt
+
+varorder = mysim.get_variable_order()
+for idx, v in enumerate(varorder):
+ plt.plot(tsim, profiles[:, idx], label=v)
+
+plt.xlabel('t')
+plt.legend(loc='best')
+plt.show()
+
+plt.show()
+
Now let’s estimate the parameters
+import pyomo.environ as pyo
+from pyomo.dae import ContinuousSet, DerivativeVar
+
+a_conc = {0.1:0.606, 0.2:0.368, 0.3:0.223, 0.4:0.135, 0.5:0.082,
+ 0.6:0.05, 0.7:0.03, 0.8:0.018, 0.9:0.011, 1.0:0.007}
+
+b_conc = {0.1:0.373, 0.2:0.564, 0.3:0.647, 0.4:0.669, 0.5:0.656,
+ 0.6:0.624, 0.7:0.583, 0.8:0.539, 0.9:0.494, 1.0:0.451}
+
+m = pyo.ConcreteModel()
+
+m.meas_time = pyo.Set(initialize=sorted(a_conc.keys()),ordered=True)
+m.ameas = pyo.Param(m.meas_time, initialize=a_conc)
+m.bmeas = pyo.Param(m.meas_time, initialize=b_conc)
+
+m.time = ContinuousSet(initialize=m.meas_time, bounds=(0,1))
+
+m.a = pyo.Var(m.time, bounds=(0,1))
+m.b = pyo.Var(m.time, bounds=(0,1))
+
+m.dadt = DerivativeVar(m.a)
+m.dbdt = DerivativeVar(m.b)
+
+m.k1 = pyo.Var()
+m.k2 = pyo.Var()
+
+def _a_diffeq(m,t):
+ return m.dadt[t] == -m.k1*m.a[t]
+m.a_diffeq = pyo.Constraint(m.time, rule=_a_diffeq)
+
+def _b_diffeq(m,t):
+ return m.dbdt[t] == m.k1*m.a[t] - m.k2*m.b[t]
+m.b_diffeq = pyo.Constraint(m.time, rule=_b_diffeq)
+
+m.ainit = pyo.Constraint(expr=m.a[0]==1)
+m.binit = pyo.Constraint(expr=m.b[0]==0)
+
+def _obj(m):
+ return sum((m.a[t]-m.ameas[t])**2+(m.b[t]-m.bmeas[t])**2 for t in m.meas_time)
+m.obj = pyo.Objective(rule=_obj)
+
+discretizer = pyo.TransformationFactory('dae.collocation')
+discretizer.apply_to(m,nfe=10,ncp=3,scheme='LAGRANGE-RADAU')
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(m, tee=True)
+
+print('k1= '+str(pyo.value(m.k1)))
+print('k2= '+str(pyo.value(m.k2)))
+
+meas_time = list(m.meas_time)
+a_meas = [pyo.value(m.ameas[i]) for i in m.meas_time]
+b_meas = [pyo.value(m.bmeas[i]) for i in m.meas_time]
+
+t = list(m.time)
+a = [pyo.value(m.a[i]) for i in m.time]
+b = [pyo.value(m.b[i]) for i in m.time]
+
+import matplotlib.pyplot as plt
+
+plt.plot(t,a,label='A')
+plt.plot(t,b,label='B')
+plt.plot(meas_time,a_meas,'o')
+plt.plot(meas_time,b_meas,'o')
+plt.legend(loc='best')
+plt.xlabel('t')
+plt.ylabel('concentration')
+plt.title('Kinetic Parameter Estimation')
+plt.show()
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[2], line 47
+ 45 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 46 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 47 solver.solve(m, tee=True)
+ 49 print('k1= '+str(pyo.value(m.k1)))
+ 50 print('k2= '+str(pyo.value(m.k2)))
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
import pyomo.environ as pyo
+from pyomo.dae import ContinuousSet, DerivativeVar
+
+a_conc = {0.1:0.606, 0.2:0.368, 0.3:0.223, 0.4:0.135, 0.5:0.082,
+ 0.6:0.05, 0.7:0.03, 0.8:0.018, 0.9:0.011, 1.0:0.007}
+
+b_conc = {0.1:0.373, 0.2:0.564, 0.3:0.647, 0.4:0.669, 0.5:0.656,
+ 0.6:0.624, 0.7:0.583, 0.8:0.539, 0.9:0.494, 1.0:0.451}
+
+m = pyo.ConcreteModel()
+
+m.meas_time = pyo.Set(initialize=sorted(a_conc.keys()),ordered=True)
+m.ameas = pyo.Param(m.meas_time, initialize=a_conc)
+m.bmeas = pyo.Param(m.meas_time, initialize=b_conc)
+
+m.time = ContinuousSet(initialize=m.meas_time, bounds=(0,1))
+
+m.a = pyo.Var(m.time, bounds=(0,1))
+m.b = pyo.Var(m.time, bounds=(0,1))
+
+m.dadt = DerivativeVar(m.a)
+m.dbdt = DerivativeVar(m.b)
+
+m.k1 = pyo.Var()
+m.k2 = pyo.Var()
+
+def _a_diffeq(m,t):
+ return m.dadt[t] == -m.k1*m.a[t]
+m.a_diffeq = pyo.Constraint(m.time, rule=_a_diffeq)
+
+def _b_diffeq(m,t):
+ return m.dbdt[t] == m.k1*m.a[t] - m.k2*m.b[t]
+m.b_diffeq = pyo.Constraint(m.time, rule=_b_diffeq)
+
+m.ainit = pyo.Constraint(expr=m.a[0]==1)
+m.binit = pyo.Constraint(expr=m.b[0]==0)
+
+def _obj(m):
+ return sum((m.a[t]-m.ameas[t])**2+(m.b[t]-m.bmeas[t])**2 for t in m.meas_time)
+m.obj = pyo.Objective(rule=_obj)
+
+discretizer = pyo.TransformationFactory('dae.collocation')
+discretizer.apply_to(m,nfe=10,ncp=3,scheme='LAGRANGE-RADAU')
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(m, tee=True)
+
+print('k1= '+str(pyo.value(m.k1)))
+print('k2= '+str(pyo.value(m.k2)))
+
+meas_time = list(m.meas_time)
+a_meas = [pyo.value(m.ameas[i]) for i in m.meas_time]
+b_meas = [pyo.value(m.bmeas[i]) for i in m.meas_time]
+
+t = list(m.time)
+a = [pyo.value(m.a[i]) for i in m.time]
+b = [pyo.value(m.b[i]) for i in m.time]
+
+import matplotlib.pyplot as plt
+
+plt.plot(t,a,label='A')
+plt.plot(t,b,label='B')
+plt.plot(meas_time,a_meas,'o')
+plt.plot(meas_time,b_meas,'o')
+plt.legend(loc='best')
+plt.xlabel('t')
+plt.ylabel('concentration')
+plt.title('Kinetic Parameter Estimation')
+plt.show()
+
Ipopt 3.9.1:
+
+******************************************************************************
+This program contains Ipopt, a library for large-scale nonlinear optimization.
+ Ipopt is released as open source code under the Common Public License (CPL).
+ For more information visit http://projects.coin-or.org/Ipopt
+******************************************************************************
+
+NOTE: You are using Ipopt by default with the MUMPS linear solver.
+ Other linear solvers might be more efficient (see Ipopt documentation).
+
+
+This is Ipopt version 3.9.1, running with linear solver mumps.
+
+Number of nonzeros in equality constraint Jacobian...: 550
+Number of nonzeros in inequality constraint Jacobian.: 0
+Number of nonzeros in Lagrangian Hessian.............: 82
+
+Total number of variables............................: 126
+ variables with only lower bounds: 0
+ variables with lower and upper bounds: 62
+ variables with only upper bounds: 0
+Total number of equality constraints.................: 124
+Total number of inequality constraints...............: 0
+ inequality constraints with only lower bounds: 0
+ inequality constraints with lower and upper bounds: 0
+ inequality constraints with only upper bounds: 0
+
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 0 3.6615861e+000 9.90e-001 5.94e-002 -1.0 0.00e+000 - 0.00e+000 0.00e+000 0
+ 1 3.6629897e+000 9.88e-001 7.45e-001 -1.7 1.87e+002 - 1.01e-002 2.51e-003h 4
+ 2 3.6603131e+000 9.75e-001 1.30e+000 -1.7 1.72e+002 - 1.69e-002 1.30e-002f 2
+ 3 3.6608441e+000 9.74e-001 1.33e+001 -1.7 2.68e+002 - 5.93e-002 3.38e-004h 6
+ 4 3.5037068e+000 8.92e-001 1.43e+001 -1.7 1.09e+002 - 4.56e-002 8.43e-002f 1
+ 5 3.4924703e+000 8.73e-001 3.43e+002 -1.7 1.49e+002 - 5.89e-001 2.12e-002h 3
+ 6 3.3768345e+000 7.61e-001 6.01e+002 -1.7 8.52e+001 - 7.87e-002 1.29e-001h 2
+ 7 3.3421277e+000 7.11e-001 6.56e+002 -1.7 6.92e+001 - 4.48e-001 6.53e-002H 1
+ 8 3.3131009e+000 6.49e-001 7.61e+002 -1.7 9.22e+001 - 3.90e-002 8.81e-002h 3
+ 9 3.2866091e+000 5.80e-001 7.80e+002 -1.7 1.21e+002 - 2.37e-001 1.06e-001h 3
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 10 3.0889266e+000 7.63e-001 1.80e+002 -1.7 6.41e+001 - 5.95e-001 9.90e-001H 1
+ 11 3.1019027e+000 2.49e-001 2.25e+002 -1.7 2.44e+001 - 3.31e-001 9.90e-001h 1
+ 12 2.6900557e+000 1.11e+001 2.08e+004 -1.7 8.92e+001 - 3.72e-001 9.90e-001h 1
+ 13 2.5940881e+000 1.04e+001 2.15e+004 -1.7 2.48e+002 - 3.77e-002 3.89e-002h 1
+ 14 2.5828123e+000 1.03e+001 1.94e+004 -1.7 7.45e+001 -2.0 7.81e-003 6.23e-003h 1
+ 15 2.6632291e+000 1.26e+001 3.37e+005 -1.7 1.21e+002 - 9.94e-003 2.69e-001f 1
+ 16 2.7587278e+000 1.19e+001 3.93e+005 -1.7 3.75e+001 -0.7 9.59e-003 6.72e-002h 1
+ 17 2.7634022e+000 1.19e+001 3.32e+005 -1.7 4.07e+001 -1.1 4.56e-002 1.84e-003h 1
+ 18 2.9029379e+000 1.15e+001 2.76e+005 -1.7 1.45e+002 -1.6 5.70e-002 2.07e-002h 1
+ 19 2.9064212e+000 1.15e+001 1.94e+005 -1.7 1.46e+001 - 3.65e-001 1.98e-003h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 20 2.9777819e+000 1.09e+001 2.62e+005 -1.7 9.65e+000 - 1.39e-001 5.63e-002h 1
+ 21 2.9781801e+000 1.08e+001 2.63e+005 -1.7 8.00e+000 - 2.31e-003 3.28e-004h 2
+ 22 3.0173374e+000 1.05e+001 2.25e+005 -1.7 6.47e+000 - 4.77e-004 3.45e-002f 2
+ 23 3.0623458e+000 1.01e+001 4.69e+005 -1.7 6.66e+000 - 3.29e-001 3.84e-002h 3
+ 24 3.0978406e+000 9.78e+000 4.85e+005 -1.7 6.78e+000 - 7.44e-002 2.96e-002h 3
+ 25 3.1115858e+000 9.67e+000 6.90e+005 -1.7 6.84e+000 - 3.48e-001 1.13e-002h 4
+ 26 3.2162760e+000 8.90e+000 6.63e+005 -1.7 6.85e+000 - 1.40e-001 8.01e-002h 1
+ 27 3.2173913e+000 8.89e+000 6.66e+005 -1.7 7.20e+000 - 8.13e-003 8.57e-004h 1
+ 28 3.2202040e+000 8.83e+000 6.59e+005 -1.7 3.29e+001 - 5.29e-005 6.29e-003f 1
+ 29 3.2628294e+000 8.10e+000 5.89e+005 -1.7 3.17e+001 - 4.70e-002 8.35e-002h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 30 3.2633851e+000 8.09e+000 5.96e+005 -1.7 2.40e+001 - 1.97e-002 7.38e-004h 1
+ 31 3.2630525e+000 8.08e+000 5.94e+005 -1.7 4.97e+001 - 1.43e-005 1.45e-003f 1
+ 32 3.2712218e+000 7.58e+000 5.52e+005 -1.7 4.12e+001 - 4.76e-002 6.18e-002f 1
+ 33 3.2713560e+000 7.57e+000 5.54e+005 -1.7 3.50e+001 - 7.06e-003 4.92e-004h 1
+ 34 3.1338693e+000 3.99e+000 4.64e+005 -1.7 3.06e+002 - 1.22e-004 9.56e-002h 1
+ 35 3.1335676e+000 3.89e+000 4.55e+005 -1.7 6.09e+001 - 2.86e-002 2.32e-002h 1
+ 36 3.1335214e+000 3.89e+000 4.55e+005 -1.7 6.01e+001 - 4.94e-004 3.26e-004h 1
+ 37 3.1335183e+000 3.89e+000 4.76e+005 -1.7 4.48e+001 - 5.28e-002 6.27e-005h 1
+ 38 3.1241874e+000 3.74e+000 4.43e+005 -1.7 5.23e+001 - 1.60e-004 3.83e-002f 1
+ 39 3.1171869e+000 3.55e+000 4.16e+005 -1.7 4.84e+001 - 3.90e-002 5.14e-002f 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 40 3.1151200e+000 3.38e+000 3.77e+005 -1.7 4.54e+001 - 5.65e-004 4.92e-002h 1
+ 41 3.1151686e+000 3.38e+000 3.78e+005 -1.7 4.23e+001 - 3.53e-003 4.13e-004h 1
+ 42 3.1154084e+000 3.15e+000 3.28e+005 -1.7 4.45e+001 - 2.27e-004 6.71e-002f 1
+ 43 3.1155587e+000 3.15e+000 3.32e+005 -1.7 4.14e+001 - 1.13e-002 4.63e-004h 1
+ 44 3.1167299e+000 3.12e+000 3.26e+005 -1.7 4.37e+001 - 4.19e-005 8.91e-003h 1
+ 45 3.1215632e+000 3.05e+000 3.27e+005 -1.7 4.35e+001 - 4.96e-002 2.54e-002f 1
+ 46 3.1220781e+000 3.04e+000 3.26e+005 -1.7 4.41e+001 - 6.82e-005 1.62e-003h 1
+ 47 3.1288284e+000 2.98e+000 3.15e+005 -1.7 4.42e+001 - 1.02e-002 2.09e-002f 1
+ 48 3.1399760e+000 2.89e+000 2.93e+005 -1.7 4.64e+001 - 1.14e-004 3.23e-002f 1
+ 49 3.1401932e+000 2.89e+000 2.93e+005 -1.7 5.09e+001 - 7.52e-004 3.18e-004h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 50 3.1487231e+000 2.84e+000 2.81e+005 -1.7 5.06e+001 - 5.58e-004 1.93e-002f 1
+ 51 3.1489225e+000 2.83e+000 2.81e+005 -1.7 5.54e+001 - 7.21e-004 2.82e-004h 1
+ 52 3.1573389e+000 2.80e+000 2.75e+005 -1.7 5.50e+001 - 5.16e-003 1.31e-002f 1
+ 53 3.1707023e+000 2.74e+000 2.61e+005 -1.7 5.78e+001 - 1.59e-004 2.25e-002f 1
+ 54 3.1715876e+000 2.74e+000 2.60e+005 -1.7 6.38e+001 - 1.14e-003 1.30e-003h 1
+ 55 3.1802329e+000 2.71e+000 2.53e+005 -1.7 6.32e+001 - 4.01e-003 1.37e-002f 1
+ 56 3.1895650e+000 2.68e+000 2.54e+005 -1.7 6.82e+001 - 2.39e-002 1.21e-002f 1
+ 57 3.1914476e+000 2.67e+000 2.53e+005 -1.7 6.84e+001 - 8.69e-004 2.81e-003h 1
+ 58 3.2055746e+000 2.63e+000 2.44e+005 -1.7 6.96e+001 - 7.23e-003 1.96e-002f 1
+ 59 3.2058102e+000 2.63e+000 2.44e+005 -1.7 8.39e+001 - 1.44e-003 2.15e-004h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 60 3.2174999e+000 2.58e+000 2.32e+005 -1.7 6.77e+001 - 5.37e-004 2.05e-002f 1
+ 61 3.2177165e+000 2.58e+000 2.33e+005 -1.7 7.99e+001 - 1.92e-003 2.46e-004h 1
+ 62 3.2318343e+000 2.54e+000 2.36e+005 -1.7 7.45e+001 - 4.31e-002 1.91e-002f 1
+ 63 3.2320440e+000 2.54e+000 2.37e+005 -1.7 9.03e+001 - 2.93e-003 2.01e-004h 1
+ 64 3.2606037e+000 2.46e+000 2.13e+005 -1.7 7.38e+001 - 1.53e-004 4.35e-002f 1
+ 65 3.2611656e+000 2.46e+000 2.16e+005 -1.7 1.13e+002 - 1.09e-002 4.56e-004h 1
+ 66 3.2892835e+000 2.39e+000 1.92e+005 -1.7 8.25e+001 - 9.69e-005 4.37e-002f 1
+ 67 3.2898347e+000 2.38e+000 1.93e+005 -1.7 1.22e+002 - 3.86e-003 5.56e-004h 1
+ 68 3.3218210e+000 2.32e+000 1.75e+005 -1.7 1.10e+002 - 6.16e-003 3.84e-002f 1
+ 69 3.3922188e+000 2.04e+000 6.58e+004 -1.7 7.35e+001 - 4.35e-004 4.10e-001h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 70 3.4493028e+000 2.03e+000 6.62e+004 -1.7 6.28e+002 - 3.15e-004 2.43e-003f 1
+ 71 3.4499691e+000 2.03e+000 6.52e+004 -1.7 6.07e+002 - 4.27e-003 2.53e-005h 1
+ 72 4.0787075e+000 1.50e+000 8.45e+004 -1.7 1.33e+002 - 2.05e-001 3.93e-001H 1
+ 73 4.2275282e+000 1.40e+000 6.95e+004 -1.7 5.28e+000 -1.2 4.86e-001 6.24e-002h 1
+ 74 4.3150405e+000 1.35e+000 5.45e+004 -1.7 1.62e+002 - 1.10e-003 3.82e-002h 1
+ 75 4.6039256e+000 1.20e+000 3.54e+005 -1.7 2.98e+001 -1.7 1.00e+000 1.13e-001h 1
+ 76 5.1023120e+000 9.80e-001 2.41e+005 -1.7 4.42e+001 - 1.24e-002 1.78e-001h 1
+ 77 5.1959724e+000 9.48e-001 4.30e+005 -1.7 4.30e+000 -1.3 6.01e-001 3.24e-002h 1
+ 78 1.0205454e+001 2.11e-001 2.63e+005 -1.7 2.83e+001 - 8.94e-002 9.89e-001H 1
+ 79 1.0641258e+001 1.43e-002 6.48e+005 -1.7 6.71e+000 -1.7 3.07e-001 9.10e-001h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 80 9.9053759e+000 1.41e-002 6.94e+005 -1.7 6.90e+000 -2.2 7.04e-002 1.00e+000f 1
+ 81 9.0481510e+000 3.86e-002 2.57e+005 -1.7 2.28e+001 -2.7 6.32e-001 1.00e+000f 1
+ 82 6.8695692e+000 8.43e-002 1.62e+005 -1.7 1.20e+001 -2.3 3.70e-001 1.00e+000f 1
+ 83 4.9135344e+000 1.26e-001 4.96e+004 -1.7 2.61e+000 -1.8 6.93e-001 1.00e+000f 1
+ 84 3.3176443e+000 2.91e-001 1.59e+004 -1.7 5.18e+000 -2.3 6.79e-001 1.00e+000f 1
+ 85 7.0764337e-001 1.99e+002 1.47e+004 -1.7 3.21e+002 -2.8 7.98e-002 1.00e+000f 1
+ 86 1.6164858e+000 5.02e+001 2.50e+001 -1.7 1.49e+002 - 1.00e+000 1.00e+000h 1
+ 87 2.3671166e+000 1.31e+001 6.69e+000 -1.7 7.72e+001 - 1.00e+000 1.00e+000h 1
+ 88 2.6628977e+000 8.11e+000 1.11e+001 -1.7 5.83e+001 - 8.81e-002 4.02e-001h 1
+ 89 3.1543854e+000 2.97e+001 1.28e+001 -1.7 4.63e+001 - 5.33e-002 8.42e-001h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 90 2.4677809e+000 7.78e+000 7.95e+000 -1.7 5.16e+001 - 2.10e-002 8.17e-001h 1
+ 91 1.1019642e+000 2.28e+001 9.86e+000 -1.7 3.84e+001 - 2.40e-001 1.00e+000f 1
+ 92 5.0737316e-001 2.22e+001 2.91e+001 -1.7 3.95e+001 - 1.00e+000 4.43e-001h 1
+ 93 4.0587600e-001 1.82e+001 2.31e+001 -1.7 2.21e+001 - 1.00e+000 1.82e-001h 1
+ 94 2.4201589e-001 3.80e+000 7.77e+000 -1.7 1.82e+001 - 1.00e+000 1.00e+000h 1
+ 95 8.6749139e-001 7.43e-001 5.29e+000 -1.7 3.69e+000 - 4.13e-001 1.00e+000h 1
+ 96 2.0694723e-001 1.22e-001 9.01e+000 -1.7 1.03e+000 - 1.41e-001 1.00e+000h 1
+ 97 1.2151856e-002 1.33e-001 6.41e+005 -2.5 7.32e-001 - 6.27e-001 1.00e+000h 1
+ 98 1.0517863e-002 2.10e-003 9.55e-004 -2.5 1.17e-001 - 1.00e+000 1.00e+000h 1
+ 99 4.3023769e-004 1.31e-002 8.05e+003 -3.8 3.96e-001 - 9.70e-001 1.00e+000h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 100 2.9477653e-005 7.36e-004 1.33e-003 -3.8 1.07e-001 - 1.00e+000 1.00e+000h 1
+ 101 1.2003375e-006 6.52e-005 7.43e-005 -5.7 3.02e-002 - 1.00e+000 1.00e+000h 1
+ 102 1.1912249e-006 1.26e-008 2.88e-008 -5.7 4.56e-004 - 1.00e+000 1.00e+000h 1
+ 103 1.1862889e-006 1.14e-008 1.25e-008 -8.6 3.94e-004 - 1.00e+000 1.00e+000h 1
+ 104 1.1862894e-006 1.22e-014 1.59e-014 -9.0 4.16e-007 - 1.00e+000 1.00e+000h 1
+
+Number of Iterations....: 104
+
+ (scaled) (unscaled)
+Objective...............: 1.1862894024317902e-006 1.1862894024317902e-006
+Dual infeasibility......: 1.5938798298139044e-014 1.5938798298139044e-014
+Constraint violation....: 1.2212453270876722e-014 1.2212453270876722e-014
+Complementarity.........: 9.0909169535204519e-010 9.0909169535204519e-010
+Overall NLP error.......: 9.0909169535204519e-010 9.0909169535204519e-010
+
+
+Number of objective function evaluations = 142
+Number of objective gradient evaluations = 105
+Number of equality constraint evaluations = 142
+Number of inequality constraint evaluations = 0
+Number of equality constraint Jacobian evaluations = 105
+Number of inequality constraint Jacobian evaluations = 0
+Number of Lagrangian Hessian evaluations = 104
+Total CPU secs in IPOPT (w/o function evaluations) = 0.396
+Total CPU secs in NLP function evaluations = 0.006
+
+EXIT: Optimal Solution Found.
+k1= 5.00350934848808
+k2= 0.9999977260457735
+
import pyomo.environ as pyo
+
+numcollocation = 4
+numfinelems = 2
+
+model = m = pyo.ConcreteModel()
+m.colloc = pyo.RangeSet(0,numcollocation-1)
+m.fe = pyo.RangeSet(0,numfinelems-1)
+m.h = pyo.Param(initialize=1.0/numfinelems)
+
+m.z = pyo.Var(m.fe,m.colloc)
+m.dzdt = pyo.Var(m.fe,m.colloc)
+m.time = pyo.Var(m.fe,m.colloc)
+
+# Collocation matrix for Radau points [0, 0.155051, 0.644949, 1]
+adot=[
+[-9.000001008080126, -4.1393887736243791, 1.7393879671602779, -3.0000002520200333],
+[10.048810106494384, 3.2247461916839306, -3.5678400771209411, 5.5319724150606273],
+[-1.3821424037453669, 1.1678398419022438, 0.77525464838285485, -7.5319723310539404],
+[0.33333330533110994, -0.25319725996179565, 1.0531974615778044, 5.000000168013341],
+]
+
+m.obj = pyo.Objective(expr=1) # Dummy Objective
+
+def _zdot(m, i, j):
+ return m.dzdt[i,j] == m.z[i,j]**2 - 2*m.z[i,j] +1
+m.zdot = pyo.Constraint(m.fe,m.colloc,rule=_zdot)
+
+# Collocation Equations
+def _colloc_eq(m,i,j):
+ if j == 0:
+ return pyo.Constraint.Skip
+ return m.h*(m.dzdt[i,j]) == sum(m.z[i,k]*adot[k][j] for k in range(0,numcollocation))
+m.colloc_eq = pyo.Constraint(m.fe,m.colloc,rule=_colloc_eq)
+
+def _colloc_eq_t(m,i,j):
+ if j == 0:
+ return pyo.Constraint.Skip
+ return m.h == sum(m.time[i,k]*adot[k][j] for k in range(0,numcollocation))
+m.colloc_eq_t = pyo.Constraint(m.fe,m.colloc,rule=_colloc_eq_t)
+
+
+# Continuity Equations
+def _cont_z(m,i):
+ if i == 0:
+ return pyo.Constraint.Skip
+ return m.z[i,0] == m.z[i-1,numcollocation-1]
+m.cont_z = pyo.Constraint(m.fe,rule=_cont_z)
+
+def _cont_t(m,i):
+ if i == 0:
+ return pyo.Constraint.Skip
+ return m.time[i,0] == m.time[i-1,numcollocation-1]
+m.cont_t = pyo.Constraint(m.fe,rule=_cont_t)
+
+# Initial Conditions
+def _init_con(m):
+ return m.z[0,0] == -3
+m.init_con = pyo.Constraint(rule=_init_con)
+
+def _init_con_t(m):
+ return m.time[0,0] == 0
+m.init_con_t = pyo.Constraint(rule=_init_con_t)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(m,tee=True)
+
+import matplotlib.pyplot as plt
+
+analytical_t = [0.01*i for i in range(0,101)]
+analytical_z = [(4*t-3)/(4*t+1) for t in analytical_t]
+
+findiff_t = []
+findiff_z = []
+
+for i in range(0,numfinelems):
+ for j in range(0,numcollocation):
+ if i != 0 and j == 0:
+ continue
+ findiff_t.append(pyo.value(m.time[i,j]))
+ findiff_z.append(pyo.value(m.z[i,j]))
+
+plt.plot(analytical_t,analytical_z,'b',label='analytical solution')
+plt.plot(findiff_t,findiff_z,'ro--',label='collocation solution')
+plt.legend(loc='best')
+plt.xlabel("t")
+plt.show()
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 67
+ 65 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 66 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 67 solver.solve(m,tee=True)
+ 69 import matplotlib.pyplot as plt
+ 71 analytical_t = [0.01*i for i in range(0,101)]
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
import pyomo.environ as pyo
+from pyomo.dae import DerivativeVar, ContinuousSet
+
+model = m = pyo.ConcreteModel()
+
+m.t = ContinuousSet(bounds=(0,1))
+
+m.z = pyo.Var(m.t)
+m.dzdt = DerivativeVar(m.z)
+
+m.obj = pyo.Objective(expr=1) # Dummy Objective
+
+def _zdot(m, i):
+ return m.dzdt[i] == m.z[i]**2 - 2*m.z[i] +1
+m.zdot = pyo.Constraint(m.t,rule=_zdot)
+
+def _init_con(m):
+ return m.z[0] == -3
+m.init_con = pyo.Constraint(rule=_init_con)
+
+# Discretize using backward finite difference
+#discretizer = pyo.TransformationFactory('dae.finite_difference')
+#discretizer.apply_to(m, nfe=50, scheme='BACKWARD')
+
+# Discretize using collocation
+discretizer = pyo.TransformationFactory('dae.collocation')
+discretizer.apply_to(m, nfe=2, ncp=3 , scheme='LAGRANGE-RADAU')
+
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(m,tee=True)
+
+import matplotlib.pyplot as plt
+
+analytical_t = [0.01*i for i in range(0,101)]
+analytical_z = [(4*t-3)/(4*t+1) for t in analytical_t]
+
+findiff_t = list(m.t)
+findiff_z = [pyo.value(m.z[i]) for i in m.t]
+
+plt.plot(analytical_t,analytical_z,'b',label='analytical solution')
+plt.plot(findiff_t,findiff_z,'ro--',label='pyomo.dae discretization solution')
+plt.legend(loc='best')
+plt.xlabel('t')
+plt.show()
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 32
+ 30 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 31 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 32 solver.solve(m,tee=True)
+ 34 import matplotlib.pyplot as plt
+ 36 analytical_t = [0.01*i for i in range(0,101)]
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
import pyomo.environ as pyo
+
+numpoints = 5
+model = m = pyo.ConcreteModel()
+m.points = pyo.RangeSet(0,numpoints-1)
+m.h = pyo.Param(initialize=1.0/(numpoints-1))
+
+m.z = pyo.Var(m.points)
+m.dzdt = pyo.Var(m.points)
+
+m.obj = pyo.Objective(expr=1) # Dummy Objective
+
+def _zdot(m, i):
+ return m.dzdt[i] == m.z[i]**2 - 2*m.z[i] +1
+m.zdot = pyo.Constraint(m.points,rule=_zdot)
+
+def _back_diff(m,i):
+ if i == 0:
+ return pyo.Constraint.Skip
+ return m.dzdt[i] == (m.z[i]-m.z[i-1])/m.h
+m.back_diff = pyo.Constraint(m.points,rule=_back_diff)
+
+def _init_con(m):
+ return m.z[0] == -3
+m.init_con = pyo.Constraint(rule=_init_con)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(m,tee=True)
+
+import matplotlib.pyplot as plt
+
+analytical_t = [0.01*i for i in range(0,101)]
+analytical_z = [(4*t-3)/(4*t+1) for t in analytical_t]
+
+findiff_t = [m.h*i for i in m.points]
+findiff_z = [pyo.value(m.z[i]) for i in m.points]
+
+plt.plot(analytical_t,analytical_z,'b',label='analytical solution')
+plt.plot(findiff_t,findiff_z,'ro--',label='finite difference solution')
+plt.legend(loc='best')
+plt.xlabel('t')
+plt.show()
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 29
+ 27 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 28 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 29 solver.solve(m,tee=True)
+ 31 import matplotlib.pyplot as plt
+ 33 analytical_t = [0.01*i for i in range(0,101)]
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
This model packs a set of rectangles without rotation or overlap within a strip of a given width, while minimizing the length of the strip.
+This is a Strip-packing example from http://minlp.org/library/lib.php?lib=GDP
+import pyomo.environ as pyo
+from pyomo.gdp import Disjunct, Disjunction
+
+model = pyo.ConcreteModel()
+
+model.RECTANGLES = pyo.Set(ordered=True, initialize=[0,1,2,3])
+
+# Width and Lenght of each rectangle
+model.Width = pyo.Param(model.RECTANGLES, initialize={0:6, 1:3, 2:4, 3:2})
+model.Length = pyo.Param(model.RECTANGLES, initialize={0:6, 1:8, 2:5, 3:3})
+
+model.StripWidth = pyo.Param(initialize=10, doc="Width of the strip" )
+
+# upperbound on length (default is sum of lengths of rectangles)
+model.LengthUB = pyo.Param(initialize=sum(model.Length[i] for i in
+ model.RECTANGLES))
+
+# x (length) and y (width) coordinates of each of the rectangles
+model.x = pyo.Var(model.RECTANGLES, bounds=(0, model.LengthUB),
+ doc="rectangle corner x-position (position down length)")
+def y_bounds(m, i):
+ return (0, m.StripWidth-m.Width[i])
+model.y = pyo.Var(model.RECTANGLES,
+ bounds=y_bounds,
+ doc="rectangle corner y-position (position across width)")
+
+# length of strip (this will be the objective)
+model.MaxLength = pyo.Var(within=pyo.NonNegativeReals)
+
+# generate the list of possible rectangle conflicts (which are any pair)
+def rec_pairs_filter(model, i, j):
+ return i < j
+model.OVERLAP_PAIRS = pyo.Set(initialize=model.RECTANGLES * model.RECTANGLES,
+ dimen=2, filter=rec_pairs_filter)
+
+# strip length constraint
+@model.Constraint(model.RECTANGLES)
+def strip_ends_after_last_rec(model, i):
+ return model.MaxLength >= model.x[i] + model.Length[i]
+
+# minimize length
+model.total_length = pyo.Objective(expr=model.MaxLength)
+
+#
+# Insert the no-overlap disjunctions here!
+#
+@model.Disjunction(model.OVERLAP_PAIRS)
+def noOverlap(m,i,j):
+ return [
+ m.x[i] + m.Length[i] <= m.x[j],
+ m.x[j] + m.Length[j] <= m.x[i],
+ m.y[i] + m.Width[i] <= m.y[j],
+ m.y[j] + m.Width[j] <= m.y[i],
+ ]
+#
+# Transform the model using the BigM relaxation
+#
+pyo.TransformationFactory('gdp.bigm').apply_to(model)
+
+#
+# Solve and print the solution
+#
+pyo.SolverFactory('glpk').solve(model, tee=True)
+model.pprint()
+for i in model.RECTANGLES:
+ print("Rectangle %s: (%s, %s)" % (i, pyo.value(model.x[i]), pyo.value(model.y[i])))
+model.total_length.display()
+
WARNING: DEPRECATED: OrderedScalarSet OVERLAP_PAIRS: 'filter=' callback
+signature matched (block, *value). Please update the callback to match the
+signature (block, value). (deprecated in 6.8.0) (called from
+/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-
+packages/pyomo/core/base/disable_methods.py:124)
+
WARNING: Could not locate the 'glpsol' executable, which is required for
+solver 'glpk'
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 63
+ 58 pyo.TransformationFactory('gdp.bigm').apply_to(model)
+ 60 #
+ 61 # Solve and print the solution
+ 62 #
+---> 63 pyo.SolverFactory('glpk').solve(model, tee=True)
+ 64 model.pprint()
+ 65 for i in model.RECTANGLES:
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'glpk'
+
Effective initialization can be critical for solving nonlinear problems, since they can have several local solutions +and numerical difficulties. Below we solve the Rosenbrock example using different initial values for the x variables. We write a loop that varies the initial value from 2.0 to 6.0, solves the problem, and prints the solution for each iteration of the loop.
+# rosenbrock_script_loop.py: A Pyomo model for the Rosenbrock problem
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var()
+model.y = pyo.Var()
+
+def rosenbrock(m):
+ return (1.0-m.x)**2 + 100.0*(m.y - m.x**2)**2
+model.obj = pyo.Objective(rule=rosenbrock, sense=pyo.minimize)
+
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+
+print('x_init, y_init, x_soln, y_soln')
+y_init = 5.0
+for x_init in range(2, 6):
+ model.x = x_init
+ model.y = 5.0
+
+ solver.solve(model)
+
+ print("{0:6.2f} {1:6.2f} {2:6.2f} {3:6.2f}".format(x_init, \
+ y_init, pyo.value(model.x), pyo.value(model.y)))
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
x_init, y_init, x_soln, y_soln
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 22
+ 19 model.x = x_init
+ 20 model.y = 5.0
+---> 22 solver.solve(model)
+ 24 print("{0:6.2f} {1:6.2f} {2:6.2f} {3:6.2f}".format(x_init, \
+ 25 y_init, pyo.value(model.x), pyo.value(model.y)))
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
Consider the following problem with initial values \(x=5, y=5\).
+(a) Below we formulate this Pyomo model and solve using Ipopt. We then get a list of +errors from the solver. What did you discover? How might you fix this? (Hint: error output might be ordered strangely, look up in the console output.)
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+
+model.x = pyo.Var(initialize=5.0)
+model.y = pyo.Var(initialize=5.0)
+
+def obj_rule(m):
+ return (m.x-1.01)**2 + m.y**2
+model.obj = pyo.Objective(rule=obj_rule)
+
+def con_rule(m):
+ return m.y == pyo.sqrt(m.x - 1.0)
+model.con = pyo.Constraint(rule=con_rule)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.options['halt_on_ampl_error'] = 'yes'
+solver.solve(model, tee=True)
+
+print(pyo.value(model.x))
+print(pyo.value(model.y))
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 19
+ 17 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+ 18 solver.options['halt_on_ampl_error'] = 'yes'
+---> 19 solver.solve(model, tee=True)
+ 21 print(pyo.value(model.x))
+ 22 print(pyo.value(model.y))
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {'halt_on_ampl_error': 'yes'}
+
(b) Add bounds \(x\geq 1\) to fix this problem. Resolve the problem. Comment on the number of iterations and the quality of solution. +(Note: The problem still occurs because \(x \geq 1\) is not enforced exactly, and small numerical values still cause the error.)
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+
+model.x = pyo.Var(initialize=5.0, bounds=(1,None))
+model.y = pyo.Var(initialize=5.0)
+
+def obj_rule(m):
+ return (m.x-1.01)**2 + m.y**2
+model.obj = pyo.Objective(rule=obj_rule)
+
+def con_rule(m):
+ return m.y == pyo.sqrt(m.x - 1.0)
+model.con = pyo.Constraint(rule=con_rule)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.options['halt_on_ampl_error'] = 'yes'
+solver.solve(model, tee=True)
+
+print(pyo.value(model.x))
+print(pyo.value(model.y))
+
Ipopt 3.9.1: halt_on_ampl_error=yes
+
+
+******************************************************************************
+This program contains Ipopt, a library for large-scale nonlinear optimization.
+ Ipopt is released as open source code under the Common Public License (CPL).
+ For more information visit http://projects.coin-or.org/Ipopt
+******************************************************************************
+
+NOTE: You are using Ipopt by default with the MUMPS linear solver.
+ Other linear solvers might be more efficient (see Ipopt documentation).
+
+
+This is Ipopt version 3.9.1, running with linear solver mumps.
+
+Number of nonzeros in equality constraint Jacobian...: 2
+Number of nonzeros in inequality constraint Jacobian.: 0
+Number of nonzeros in Lagrangian Hessian.............: 2
+
+Total number of variables............................: 2
+ variables with only lower bounds: 1
+ variables with lower and upper bounds: 0
+ variables with only upper bounds: 0
+Total number of equality constraints.................: 1
+Total number of inequality constraints...............: 0
+ inequality constraints with only lower bounds: 0
+ inequality constraints with lower and upper bounds: 0
+ inequality constraints with only upper bounds: 0
+
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 0 4.0920100e+001 3.00e+000 8.92e+000 -1.0 0.00e+000 - 0.00e+000 0.00e+000 0
+ 1 1.3964766e+000 9.81e-001 4.57e+000 -1.0 4.20e+000 - 1.00e+000 9.43e-001f 1
+ 2 1.3265288e+000 4.58e-001 9.56e+000 -1.0 3.54e-001 2.0 1.31e-001 1.00e+000f 1
+ 3 3.2528786e-001 1.23e-002 1.25e+000 -1.0 5.70e-001 - 1.00e+000 1.00e+000f 1
+ 4 4.9701812e-003 7.82e-002 1.36e-001 -1.0 3.78e-001 - 1.00e+000 1.00e+000F 1
+ 5 6.0628408e-003 4.53e-002 1.66e+000 -2.5 2.08e-002 - 1.00e+000 1.00e+000h 1
+ 6 6.7063949e-003 4.53e-002 2.24e+000 -2.5 1.05e+000 - 1.53e-002 3.91e-003h 9
+ 7 7.6973110e-003 1.67e-002 5.10e-001 -2.5 6.16e-003 1.5 1.00e+000 1.00e+000h 1
+ 8 3.5855462e-003 1.09e-003 2.51e-001 -2.5 2.81e-002 - 1.00e+000 1.00e+000h 1
+ 9 3.0456986e-003 1.24e-004 1.10e-003 -2.5 4.78e-003 - 1.00e+000 1.00e+000h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 10 9.2960387e-004 1.58e-002 1.21e+000 -3.8 2.59e-002 - 1.00e+000 1.00e+000h 1
+ 11 2.2722219e-004 1.18e-004 1.42e-001 -3.8 1.75e-002 - 1.00e+000 1.00e+000h 1
+ 12 2.4804811e-004 4.21e-005 4.38e-003 -3.8 8.99e-004 - 1.00e+000 1.00e+000h 1
+ 13 2.5041988e-004 8.02e-007 1.04e-004 -3.8 9.89e-005 - 1.00e+000 1.00e+000h 1
+ 14 1.3928326e-004 4.89e-003 3.54e+000 -5.7 6.12e-003 - 1.00e+000 1.00e+000h 1
+ 15 1.6721345e-004 3.66e-003 4.16e+000 -5.7 1.95e-003 1.0 1.01e-001 1.00e+000h 1
+ 16 1.7756299e-004 1.12e-003 2.28e+000 -5.7 6.51e-004 1.5 1.00e+000 1.00e+000h 1
+ 17 1.5169810e-004 1.68e-005 1.58e-001 -5.7 1.61e-003 1.0 1.00e+000 1.00e+000h 1
+Error evaluating constraint 1: can't evaluate sqrt(-9.90312e-09).
+ERROR: Solver (ipopt) returned non-zero return code (1)
+ERROR: See the solver log above for diagnostic information.
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 18
+ 16 solver = pyo.SolverFactory('ipopt')
+ 17 solver.options['halt_on_ampl_error'] = 'yes'
+---> 18 solver.solve(model, tee=True)
+ 20 print(pyo.value(model.x))
+ 21 print(pyo.value(model.y))
+
+File c:\Users\bmurr\CHE 498\.venv\Lib\site-packages\pyomo\opt\base\solvers.py:628, in OptSolver.solve(self, *args, **kwds)
+ 626 elif hasattr(_status, 'log') and _status.log:
+ 627 logger.error("Solver log:\n" + str(_status.log))
+--> 628 raise ApplicationError("Solver (%s) did not exit normally" % self.name)
+ 629 solve_completion_time = time.time()
+ 630 if self._report_timing:
+
+ApplicationError: Solver (ipopt) did not exit normally
+
(c) Think about other solutions for this problem. (e.g., \(x \geq 1.001\)).
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+
+model.x = pyo.Var(initialize=5.0, bounds=(1.001,None))
+model.y = pyo.Var(initialize=5.0)
+
+def obj_rule(m):
+ return (m.x-1.01)**2 + m.y**2
+model.obj = pyo.Objective(rule=obj_rule)
+
+def con_rule(m):
+ return m.y == pyo.sqrt(m.x - 1.0)
+model.con = pyo.Constraint(rule=con_rule)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.options['halt_on_ampl_error'] = 'yes'
+solver.solve(model, tee=True)
+
+print(pyo.value(model.x))
+print(pyo.value(model.y))
+
Ipopt 3.9.1: halt_on_ampl_error=yes
+
+
+******************************************************************************
+This program contains Ipopt, a library for large-scale nonlinear optimization.
+ Ipopt is released as open source code under the Common Public License (CPL).
+ For more information visit http://projects.coin-or.org/Ipopt
+******************************************************************************
+
+NOTE: You are using Ipopt by default with the MUMPS linear solver.
+ Other linear solvers might be more efficient (see Ipopt documentation).
+
+
+This is Ipopt version 3.9.1, running with linear solver mumps.
+
+Number of nonzeros in equality constraint Jacobian...: 2
+Number of nonzeros in inequality constraint Jacobian.: 0
+Number of nonzeros in Lagrangian Hessian.............: 2
+
+Total number of variables............................: 2
+ variables with only lower bounds: 1
+ variables with lower and upper bounds: 0
+ variables with only upper bounds: 0
+Total number of equality constraints.................: 1
+Total number of inequality constraints...............: 0
+ inequality constraints with only lower bounds: 0
+ inequality constraints with lower and upper bounds: 0
+ inequality constraints with only upper bounds: 0
+
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 0 4.0920100e+001 3.00e+000 8.92e+000 -1.0 0.00e+000 - 0.00e+000 0.00e+000 0
+ 1 1.3985928e+000 9.80e-001 4.51e+000 -1.0 4.20e+000 - 1.00e+000 9.43e-001f 1
+ 2 1.3200328e+000 4.52e-001 1.00e+001 -1.0 3.56e-001 2.0 1.31e-001 1.00e+000f 1
+ 3 3.3527706e-001 1.13e-002 1.27e+000 -1.0 5.60e-001 - 1.00e+000 1.00e+000f 1
+ 4 4.9066403e-003 4.74e-002 2.52e-002 -1.0 3.83e-001 - 1.00e+000 1.00e+000F 1
+ 5 4.4928608e-003 2.36e-002 7.26e-001 -2.5 1.19e-002 - 1.00e+000 1.00e+000h 1
+ 6 5.9528153e-003 7.95e-003 5.53e-001 -2.5 1.04e-002 - 1.00e+000 1.00e+000h 1
+ 7 3.2290130e-003 1.43e-003 4.99e-003 -2.5 2.06e-002 - 1.00e+000 1.00e+000h 1
+ 8 1.5403307e-003 3.85e-003 1.04e-001 -3.8 1.82e-002 - 1.00e+000 1.00e+000h 1
+ 9 1.2315611e-003 2.80e-006 1.34e-003 -3.8 4.28e-003 - 1.00e+000 1.00e+000h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 10 1.0880355e-003 7.80e-005 2.46e-003 -5.7 2.23e-003 - 1.00e+000 1.00e+000h 1
+ 11 1.0828351e-003 2.74e-010 3.15e-007 -5.7 8.21e-005 - 1.00e+000 1.00e+000h 1
+ 12 1.0809936e-003 1.39e-008 4.39e-007 -8.6 2.96e-005 - 1.00e+000 1.00e+000h 1
+ 13 1.0809927e-003 1.34e-015 6.88e-014 -8.6 1.40e-008 - 1.00e+000 1.00e+000h 1
+
+Number of Iterations....: 13
+
+ (scaled) (unscaled)
+Objective...............: 1.0809926760836025e-003 1.0809926760836025e-003
+Dual infeasibility......: 6.8833827526759706e-014 6.8833827526759706e-014
+Constraint violation....: 1.3392065234540951e-015 1.3392065234540951e-015
+Complementarity.........: 2.5059036424968433e-009 2.5059036424968433e-009
+Overall NLP error.......: 2.5059036424968433e-009 2.5059036424968433e-009
+
+
+Number of objective function evaluations = 15
+Number of objective gradient evaluations = 14
+Number of equality constraint evaluations = 15
+Number of inequality constraint evaluations = 0
+Number of equality constraint Jacobian evaluations = 14
+Number of inequality constraint Jacobian evaluations = 0
+Number of Lagrangian Hessian evaluations = 13
+Total CPU secs in IPOPT (w/o function evaluations) = 0.005
+Total CPU secs in NLP function evaluations = 0.000
+
+EXIT: Optimal Solution Found.
+1.001
+0.0316226586775465
+
Consider the following problem with ini- +tial values x=5, y=5.
+Note that the solution to this problem is \(x=1.005\) and \(y=0.005\). There +are several ways that the problem above can be reformulated. Some examples are shown below. Which ones do you expect to be better? Why? Note the number of iterations and quality of solutions. What can you learn +about problem formulation from these examples?
+(a)
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+
+model.x = pyo.Var(initialize=5.0)
+model.y = pyo.Var(initialize=5.0)
+
+def obj_rule(m):
+ return (m.x-1.01)**2 + m.y**2
+model.obj = pyo.Objective(rule=obj_rule)
+
+def con_rule(m):
+ return (m.x - 1.0) / m.y == 1.0
+model.con = pyo.Constraint(rule=con_rule)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(model, tee=True)
+
+print(pyo.value(model.x))
+print(pyo.value(model.y))
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 18
+ 16 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 17 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 18 solver.solve(model, tee=True)
+ 20 print(pyo.value(model.x))
+ 21 print(pyo.value(model.y))
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
(b)
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+
+model.x = pyo.Var(initialize=5.0)
+model.y = pyo.Var(initialize=5.0)
+
+def obj_rule(m):
+ return (m.x-1.01)**2 + m.y**2
+model.obj = pyo.Objective(rule=obj_rule)
+
+def con_rule(m):
+ return m.x / (m.y + 1.0) == 1.0
+model.con = pyo.Constraint(rule=con_rule)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(model, tee=True)
+
+print(pyo.value(model.x))
+print(pyo.value(model.y))
+
Ipopt 3.9.1:
+
+******************************************************************************
+This program contains Ipopt, a library for large-scale nonlinear optimization.
+ Ipopt is released as open source code under the Common Public License (CPL).
+ For more information visit http://projects.coin-or.org/Ipopt
+******************************************************************************
+
+NOTE: You are using Ipopt by default with the MUMPS linear solver.
+ Other linear solvers might be more efficient (see Ipopt documentation).
+
+
+This is Ipopt version 3.9.1, running with linear solver mumps.
+
+Number of nonzeros in equality constraint Jacobian...: 2
+Number of nonzeros in inequality constraint Jacobian.: 0
+Number of nonzeros in Lagrangian Hessian.............: 3
+
+Total number of variables............................: 2
+ variables with only lower bounds: 0
+ variables with lower and upper bounds: 0
+ variables with only upper bounds: 0
+Total number of equality constraints.................: 1
+Total number of inequality constraints...............: 0
+ inequality constraints with only lower bounds: 0
+ inequality constraints with lower and upper bounds: 0
+ inequality constraints with only upper bounds: 0
+
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 0 4.0920100e+001 1.67e-001 9.83e+000 -1.0 0.00e+000 - 0.00e+000 0.00e+000 0
+ 1 4.0023722e-001 1.49e+000 2.82e+001 -1.0 5.39e+000 - 1.00e+000 1.00e+000f 1
+ 2 1.0494629e+001 1.04e+000 2.24e+001 -1.0 2.58e+000 - 1.00e+000 1.00e+000h 1
+ 3 5.4394796e+000 1.78e-001 8.48e+000 -1.0 1.23e+000 - 1.00e+000 1.00e+000f 1
+ 4 1.0538196e-001 1.52e-001 3.90e+000 -1.0 1.75e+000 - 1.00e+000 1.00e+000f 1
+ 5 4.6918851e-002 2.17e-002 1.20e+000 -1.0 1.63e-001 - 1.00e+000 1.00e+000h 1
+ 6 1.3071752e-004 2.88e-003 1.19e-001 -1.0 1.62e-001 - 1.00e+000 1.00e+000h 1
+ 7 4.9833353e-005 1.79e-005 1.02e-003 -2.5 6.25e-003 - 1.00e+000 1.00e+000h 1
+ 8 5.0000013e-005 1.28e-009 6.30e-008 -5.7 9.00e-005 - 1.00e+000 1.00e+000h 1
+ 9 5.0000000e-005 2.22e-016 4.77e-016 -8.6 4.58e-009 - 1.00e+000 1.00e+000h 1
+
+Number of Iterations....: 9
+
+ (scaled) (unscaled)
+Objective...............: 5.0000000000001568e-005 5.0000000000001568e-005
+Dual infeasibility......: 4.7704895589362195e-016 4.7704895589362195e-016
+Constraint violation....: 2.2204460492503131e-016 2.2204460492503131e-016
+Complementarity.........: 0.0000000000000000e+000 0.0000000000000000e+000
+Overall NLP error.......: 4.7704895589362195e-016 4.7704895589362195e-016
+
+
+Number of objective function evaluations = 10
+Number of objective gradient evaluations = 10
+Number of equality constraint evaluations = 10
+Number of inequality constraint evaluations = 0
+Number of equality constraint Jacobian evaluations = 10
+Number of inequality constraint Jacobian evaluations = 0
+Number of Lagrangian Hessian evaluations = 9
+Total CPU secs in IPOPT (w/o function evaluations) = 0.003
+Total CPU secs in NLP function evaluations = 0.000
+
+EXIT: Optimal Solution Found.
+1.005
+0.005000000000000042
+
(c)
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+
+model.x = pyo.Var(initialize=5.0)
+model.y = pyo.Var(initialize=5.0)
+
+def obj_rule(m):
+ return (m.x-1.01)**2 + m.y**2
+model.obj = pyo.Objective(rule=obj_rule)
+
+def con_rule(m):
+ return m.y == m.x - 1.0
+model.con = pyo.Constraint(rule=con_rule)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(model, tee=True)
+
+print(pyo.value(model.x))
+print(pyo.value(model.y))
+
Ipopt 3.9.1:
+
+******************************************************************************
+This program contains Ipopt, a library for large-scale nonlinear optimization.
+ Ipopt is released as open source code under the Common Public License (CPL).
+ For more information visit http://projects.coin-or.org/Ipopt
+******************************************************************************
+
+NOTE: You are using Ipopt by default with the MUMPS linear solver.
+ Other linear solvers might be more efficient (see Ipopt documentation).
+
+
+This is Ipopt version 3.9.1, running with linear solver mumps.
+
+Number of nonzeros in equality constraint Jacobian...: 2
+Number of nonzeros in inequality constraint Jacobian.: 0
+Number of nonzeros in Lagrangian Hessian.............: 2
+
+Total number of variables............................: 2
+ variables with only lower bounds: 0
+ variables with lower and upper bounds: 0
+ variables with only upper bounds: 0
+Total number of equality constraints.................: 1
+Total number of inequality constraints...............: 0
+ inequality constraints with only lower bounds: 0
+ inequality constraints with lower and upper bounds: 0
+ inequality constraints with only upper bounds: 0
+
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 0 4.0920100e+001 1.00e+000 8.99e+000 -1.0 0.00e+000 - 0.00e+000 0.00e+000 0
+ 1 5.0000000e-005 0.00e+000 4.44e-016 -1.0 5.00e+000 - 1.00e+000 1.00e+000f 1
+
+Number of Iterations....: 1
+
+ (scaled) (unscaled)
+Objective...............: 5.0000000000000090e-005 5.0000000000000090e-005
+Dual infeasibility......: 4.4408920985006262e-016 4.4408920985006262e-016
+Constraint violation....: 0.0000000000000000e+000 0.0000000000000000e+000
+Complementarity.........: 0.0000000000000000e+000 0.0000000000000000e+000
+Overall NLP error.......: 4.4408920985006262e-016 4.4408920985006262e-016
+
+
+Number of objective function evaluations = 2
+Number of objective gradient evaluations = 2
+Number of equality constraint evaluations = 2
+Number of inequality constraint evaluations = 0
+Number of equality constraint Jacobian evaluations = 2
+Number of inequality constraint Jacobian evaluations = 0
+Number of Lagrangian Hessian evaluations = 1
+Total CPU secs in IPOPT (w/o function evaluations) = 0.001
+Total CPU secs in NLP function evaluations = 0.000
+
+EXIT: Optimal Solution Found.
+1.005
+0.004999999999999893
+
(d) Bounds and initialization can be very helpful when solving nonlinear optimization problems. Starting with the code below, resolve the original problem, but add bounds, \(y \geq 0\). Note the +number of iterations and quality of solution, and compare with what you found in 1.2 (a).
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+
+model.x = pyo.Var(initialize=5.0)
+model.y = pyo.Var(initialize=5.0, bounds=(0,None))
+
+def obj_rule(m):
+ return (m.x-1.01)**2 + m.y**2
+model.obj = pyo.Objective(rule=obj_rule)
+
+def con_rule(m):
+ return (m.x - 1.0) / m.y == 1.0
+model.con = pyo.Constraint(rule=con_rule)
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+solver.solve(model, tee=True)
+
+print(pyo.value(model.x))
+print(pyo.value(model.y))
+
Ipopt 3.9.1:
+
+******************************************************************************
+This program contains Ipopt, a library for large-scale nonlinear optimization.
+ Ipopt is released as open source code under the Common Public License (CPL).
+ For more information visit http://projects.coin-or.org/Ipopt
+******************************************************************************
+
+NOTE: You are using Ipopt by default with the MUMPS linear solver.
+ Other linear solvers might be more efficient (see Ipopt documentation).
+
+
+This is Ipopt version 3.9.1, running with linear solver mumps.
+
+Number of nonzeros in equality constraint Jacobian...: 2
+Number of nonzeros in inequality constraint Jacobian.: 0
+Number of nonzeros in Lagrangian Hessian.............: 3
+
+Total number of variables............................: 2
+ variables with only lower bounds: 1
+ variables with lower and upper bounds: 0
+ variables with only upper bounds: 0
+Total number of equality constraints.................: 1
+Total number of inequality constraints...............: 0
+ inequality constraints with only lower bounds: 0
+ inequality constraints with lower and upper bounds: 0
+ inequality constraints with only upper bounds: 0
+
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 0 4.0920100e+001 2.00e-001 9.38e+000 -1.0 0.00e+000 - 0.00e+000 0.00e+000 0
+ 1 9.7049410e-001 1.89e+001 2.29e+003 -1.0 5.19e+000 - 1.00e+000 9.54e-001f 1
+ 2 2.8303563e+003 1.85e+001 2.25e+003 -1.0 5.21e+001 - 1.88e-002 1.00e+000h 1
+ 3 2.9704435e+003 9.12e+000 1.14e+003 -1.0 2.64e+000 - 1.00e+000 1.00e+000h 1
+ 4 2.5293245e+003 4.09e+000 5.51e+002 -1.0 4.89e+000 - 8.94e-001 1.00e+000f 1
+ 5 1.7547126e+003 1.52e+000 2.52e+002 -1.0 1.04e+001 - 1.00e+000 1.00e+000f 1
+ 6 6.8047428e+002 1.49e-001 8.49e+001 -1.0 1.93e+001 - 1.00e+000 1.00e+000f 1
+ 7 7.4721920e+000 8.01e-001 2.32e+002 -1.0 1.91e+001 - 1.00e+000 1.00e+000f 1
+ 8 8.1969347e+003 7.77e-001 2.62e+002 -1.0 8.57e+001 - 3.37e-002 1.00e+000h 1
+ 9 1.1605265e+004 2.36e-001 4.89e+002 -1.0 6.40e+001 - 1.00e+000 1.00e+000h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 10 5.5411085e+002 5.19e-001 5.83e+002 -1.0 7.36e+001 - 1.00e+000 1.00e+000f 1
+ 11 1.7377623e+004 4.22e-001 5.65e+002 -1.0 9.29e+001 - 3.00e-001 1.00e+000h 1
+ 12 1.1573362e+004 1.25e-001 1.63e+002 -1.0 6.64e+001 - 1.00e+000 5.00e-001f 2
+ 13 3.3128549e+003 8.55e-003 9.20e+001 -1.0 8.52e+001 - 1.00e+000 4.70e-001f 2
+ 14 7.1443870e-001 8.34e-001 1.80e+003 -1.0 4.11e+001 - 1.00e+000 9.85e-001f 1
+ 15 3.2462198e-005 4.75e-001 1.05e+003 -1.0 1.73e+002 - 1.00e+000 4.30e-003f 1
+ 16 9.8963008e-005 2.74e-001 8.52e+002 -1.0 1.41e+000 - 1.00e+000 4.23e-003h 1
+ 17 9.2105755e-005 2.40e-001 5.57e+002 -1.0 3.56e-004 - 1.00e+000 1.00e+000f 1
+ 18 7.9772743e-005 1.58e-001 3.60e+002 -1.0 7.13e-004 - 1.00e+000 1.00e+000h 1
+ 19 6.9741224e-005 6.86e-002 1.47e+002 -1.0 7.40e-004 - 1.00e+000 1.00e+000h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 20 4.9888137e-005 3.97e-002 6.88e+001 -1.0 2.39e-003 - 1.00e+000 1.00e+000h 1
+ 21 3.3950490e-004 3.02e-002 4.89e+001 -1.0 1.32e-002 - 1.00e+000 1.00e+000f 1
+ 22 3.7536170e-003 1.95e-002 3.11e+001 -1.0 3.12e-002 - 1.00e+000 1.00e+000h 1
+ 23 1.2981580e-002 8.58e-003 1.36e+001 -1.0 3.74e-002 - 1.00e+000 1.00e+000h 1
+ 24 3.4681398e-002 3.23e-003 5.01e+000 -1.0 5.13e-002 - 1.00e+000 1.00e+000h 1
+ 25 4.7179466e-002 4.50e-004 7.03e-001 -1.0 2.21e-002 - 1.00e+000 1.00e+000h 1
+ 26 1.7082443e-002 2.83e-004 3.55e-001 -1.7 6.13e-002 - 1.00e+000 1.00e+000f 1
+ 27 1.0216180e-002 7.79e-005 1.09e-001 -1.7 2.10e-002 - 1.00e+000 1.00e+000h 1
+ 28 3.1289054e-003 5.64e-005 3.27e-002 -2.5 3.21e-002 - 1.00e+000 1.00e+000h 1
+ 29 1.4987215e-003 2.18e-005 2.21e-002 -2.5 1.23e-002 - 1.00e+000 1.00e+000h 1
+iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
+ 30 3.8554063e-004 1.69e-005 4.50e-003 -3.8 1.40e-002 - 1.00e+000 1.00e+000h 1
+ 31 1.3832051e-004 9.18e-006 4.39e-003 -3.8 6.31e-003 - 1.00e+000 1.00e+000h 1
+ 32 8.9968997e-005 2.11e-006 9.99e-006 -3.8 2.18e-003 - 1.00e+000 1.00e+000h 1
+ 33 5.4301800e-005 9.79e-007 2.80e-003 -5.7 3.00e-003 - 1.00e+000 1.00e+000h 1
+ 34 5.0216846e-005 2.09e-007 1.11e-004 -5.7 1.14e-003 - 1.00e+000 1.00e+000h 1
+ 35 5.0020268e-005 9.37e-009 2.55e-005 -5.7 2.29e-004 - 1.00e+000 1.00e+000h 1
+ 36 5.0016425e-005 1.85e-011 1.06e-008 -5.7 1.00e-005 - 1.00e+000 1.00e+000h 1
+ 37 5.0000006e-005 3.39e-013 3.16e-006 -8.6 8.89e-005 - 1.00e+000 1.00e+000h 1
+ 38 5.0000000e-005 5.55e-015 4.02e-013 -8.6 1.58e-006 - 1.00e+000 1.00e+000h 1
+
+Number of Iterations....: 38
+
+ (scaled) (unscaled)
+Objective...............: 5.0000000031647193e-005 5.0000000031647193e-005
+Dual infeasibility......: 4.0225288377992996e-013 4.0225288377992996e-013
+Constraint violation....: 5.5511151231257827e-015 5.5511151231257827e-015
+Complementarity.........: 2.5158913589264014e-009 2.5158913589264014e-009
+Overall NLP error.......: 2.5158913589264014e-009 2.5158913589264014e-009
+
+
+Number of objective function evaluations = 44
+Number of objective gradient evaluations = 39
+Number of equality constraint evaluations = 44
+Number of inequality constraint evaluations = 0
+Number of equality constraint Jacobian evaluations = 39
+Number of inequality constraint Jacobian evaluations = 0
+Number of Lagrangian Hessian evaluations = 38
+Total CPU secs in IPOPT (w/o function evaluations) = 0.012
+Total CPU secs in NLP function evaluations = 0.001
+
+EXIT: Optimal Solution Found.
+1.0050001257911454
+0.005000125791145421
+
In this example, we will consider a chemical reactor designed to produce +product B from reactant A using a reaction scheme known as the Van +de Vusse reaction:
+Under appropriate assumptions, \(F\) is the volumetric flowrate through the tank. The concentation of component \(A\) in the feed is \(c_{Af}\) , and the concentrations in the reactor are equivalent to the concentrations of each component flowing out of the reactor, given by \(c_{A}, c_{B}, c_{C}, c_{D}\)
+If the reactor is too small, we will not produce sufficient quantity of \(B\), and if the reactor is too large, much of \(B\) will be further reacted to form the undesired product \(C\). Therefore, our goal is to solve for the reactor volume that maximizes the outlet concentration for product \(B\).
+The steady-state mole balances for each of the four components are given by,
+The known parameters for the system are,
+Below we formulate and solve this optimization problem using Pyomo. Since the +volumetric flowrate \(F\) always appears as the numerator over the reactor +volume \(V\) , it is common to consider this ratio as a single variable, called +the space-velocity \(SV\).
+import pyomo.environ as pyo
+
+# create the concrete model
+model = pyo.ConcreteModel()
+
+# set the data (native python data)
+k1 = 5.0/6.0 # min^-1
+k2 = 5.0/3.0 # min^-1
+k3 = 1.0/6000.0 # m^3/(gmol min)
+caf = 10000.0 # gmol/m^3
+
+# create the variables
+model.sv = pyo.Var(initialize = 1.0, within=pyo.PositiveReals)
+model.ca = pyo.Var(initialize = 5000.0, within=pyo.PositiveReals)
+model.cb = pyo.Var(initialize = 2000.0, within=pyo.PositiveReals)
+model.cc = pyo.Var(initialize = 2000.0, within=pyo.PositiveReals)
+model.cd = pyo.Var(initialize = 1000.0, within=pyo.PositiveReals)
+
+# create the objective
+model.obj = pyo.Objective(expr = model.cb, sense=pyo.maximize)
+
+# create the constraints
+model.ca_bal = pyo.Constraint(expr = (0 == model.sv * caf \
+ - model.sv * model.ca - k1 * model.ca \
+ - 2.0 * k3 * model.ca ** 2.0))
+
+model.cb_bal = pyo.Constraint(expr=(0 == -model.sv * model.cb \
+ + k1 * model.ca - k2 * model.cb))
+
+model.cc_bal = pyo.Constraint(expr=(0 == -model.sv * model.cc \
+ + k2 * model.cb))
+
+model.cd_bal = pyo.Constraint(expr=(0 == -model.sv * model.cd \
+ + k3 * model.ca ** 2.0))
+
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+
+solver.solve(model)
+model.pprint()
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 39
+ 36 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 37 solver = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 39 solver.solve(model)
+ 40 model.pprint()
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
Below is the knapsack problem. Which items are acquired in the optimal solution? What is the value of the selected items?
+# knapsack.py
+import pyomo.environ as pyo
+
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+
+model.obj = pyo.Objective(
+ expr = sum( b[i]*model.x[i] for i in A ),
+ sense = pyo.maximize )
+
+model.weight_con = pyo.Constraint(
+ expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+
+opt = pyo.SolverFactory('glpk')
+opt_success = opt.solve(model)
+
+model.pprint()
+
WARNING: Could not locate the 'glpsol' executable, which is required for
+solver 'glpk'
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 20
+ 16 model.weight_con = pyo.Constraint(
+ 17 expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+ 19 opt = pyo.SolverFactory('glpk')
+---> 20 opt_success = opt.solve(model)
+ 22 model.pprint()
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'glpk'
+
The knapsack.py example shown
+in the tutorial uses model.pprint()
to see the value of the solution
+variables. Note that the Pyomo value function should be used to get the floating point value of Pyomo modeling components (e.g., print(value(model.x[i])
). We can also
+print the value of the items selected (the objective), and the total
+weight.
import pyomo.environ as pyo
+
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+
+model.obj = pyo.Objective(
+ expr = sum( b[i]*model.x[i] for i in A ),
+ sense = pyo.maximize )
+
+model.weight_con = pyo.Constraint(
+ expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+
+opt = pyo.SolverFactory('cbc')
+opt_success = opt.solve(model)
+
+total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+print('Total Weight:', total_weight)
+print('Total Benefit:', pyo.value(model.obj))
+
+print('%12s %12s' % ('Item', 'Selected'))
+print('=========================')
+for i in A:
+ acquired = 'No'
+ if pyo.value(model.x[i]) >= 0.5:
+ acquired = 'Yes'
+ print('%12s %12s' % (i, acquired))
+print('-------------------------')
+
WARNING: Could not locate the 'cbc' executable, which is required for solver
+cbc
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 19
+ 15 model.weight_con = pyo.Constraint(
+ 16 expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+ 18 opt = pyo.SolverFactory('cbc')
+---> 19 opt_success = opt.solve(model)
+ 21 total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+ 22 print('Total Weight:', total_weight)
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'cbc'
+
When we increase the value of the wrench, at what point would it become selected as part of the optimal solution?
+import pyomo.environ as pyo
+
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':8, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+
+model.obj = pyo.Objective(
+ expr = sum( b[i]*model.x[i] for i in A ),
+ sense = pyo.maximize )
+
+model.weight_con = pyo.Constraint(
+ expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+
+opt = pyo.SolverFactory('cbc')
+opt_success = opt.solve(model)
+
+total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+print('Total Weight:', total_weight)
+print('Total Benefit:', pyo.value(model.obj))
+
+print('%12s %12s' % ('Item', 'Selected'))
+print('=========================')
+for i in A:
+ acquired = 'No'
+ if pyo.value(model.x[i]) >= 0.5:
+ acquired = 'Yes'
+ print('%12s %12s' % (i, acquired))
+print('-------------------------')
+
WARNING: Could not locate the 'cbc' executable, which is required for solver
+cbc
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 19
+ 15 model.weight_con = pyo.Constraint(
+ 16 expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+ 18 opt = pyo.SolverFactory('cbc')
+---> 19 opt_success = opt.solve(model)
+ 21 total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+ 22 print('Total Weight:', total_weight)
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'cbc'
+
In the knapsack example shown in the tutorial slides, the data is hardcoded at the top of the file. Instead of hard-coding the data, we can Python to load the data from a different source.
+import pandas as pd
+import pyomo.environ as pyo
+import os
+import openpyxl
+path = os.path.abspath('knapsack_data.xlsx')
+df_items = pd.read_excel(path, sheet_name='data', header=0, index_col=0)
+W_max = 14
+
+A = df_items.index.tolist()
+b = df_items['Benefit'].to_dict()
+w = df_items['Weight'].to_dict()
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+
+model.obj = pyo.Objective(
+ expr = sum( b[i]*model.x[i] for i in A ),
+ sense = pyo.maximize )
+
+model.weight_con = pyo.Constraint(
+ expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+
+opt = pyo.SolverFactory('cbc')
+opt_success = opt.solve(model)
+
+total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+print('Total Weight:', total_weight)
+print('Total Benefit:', pyo.value(model.obj))
+
+print('%12s %12s' % ('Item', 'Selected'))
+print('=========================')
+for i in A:
+ acquired = 'No'
+ if pyo.value(model.x[i]) >= 0.5:
+ acquired = 'Yes'
+ print('%12s %12s' % (i, acquired))
+print('-------------------------')
+
WARNING: Could not locate the 'cbc' executable, which is required for solver
+cbc
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 24
+ 20 model.weight_con = pyo.Constraint(
+ 21 expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+ 23 opt = pyo.SolverFactory('cbc')
+---> 24 opt_success = opt.solve(model)
+ 26 total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+ 27 print('Total Weight:', total_weight)
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'cbc'
+
Here we solve the knapsack problem with Ipopt instead of cbc. What happened? Why?
+import pyomo.environ as pyo
+import os
+os.environ['PATH'] += ':solvers'
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+
+model.obj = pyo.Objective(
+ expr = sum( b[i]*model.x[i] for i in A ),
+ sense = pyo.maximize )
+
+model.weight_con = pyo.Constraint(
+ expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
+ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+opt = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+opt_success = opt.solve(model)
+
+model.pprint()
+
WARNING: Failed to create solver with name 'ipopt': Failed to set executable
+for solver ipopt. File with
+name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+either does not exist or it is not executable. To skip this validation, call
+set_executable with validate=False.
+Traceback (most recent call last):
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py", line 148, in __call__
+ opt = self._cls[_name](**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/solvers/plugins/solvers/IPOPT.py", line 44, in __init__
+ super(IPOPT, self).__init__(**kwds)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 66, in __init__
+ self.set_executable(name=executable, validate=validate)
+ File "/home/murraybj/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py", line 115, in set_executable
+ raise ValueError(
+ValueError: Failed to set executable for solver ipopt. File with name=/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt either does not exist or it is not executable. To skip this validation, call set_executable with validate=False.
+
---------------------------------------------------------------------------
+RuntimeError Traceback (most recent call last)
+Cell In[1], line 20
+ 18 ipopt_runner_path = "/home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt"
+ 19 opt = pyo.SolverFactory('ipopt', executable=ipopt_runner_path)
+---> 20 opt_success = opt.solve(model)
+ 22 model.pprint()
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:99, in UnknownSolver.solve(self, *args, **kwds)
+ 97 def solve(self, *args, **kwds):
+ 98 """Perform optimization and return an SolverResults object."""
+---> 99 self._solver_error('solve')
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:116, in UnknownSolver._solver_error(self, method_name)
+ 115 def _solver_error(self, method_name):
+--> 116 raise RuntimeError(
+ 117 """Attempting to use an unavailable solver.
+ 118
+ 119 The SolverFactory was unable to create the solver "%s"
+ 120 and returned an UnknownSolver object. This error is raised at the point
+ 121 where the UnknownSolver object was used as if it were valid (by calling
+ 122 method "%s").
+ 123
+ 124 The original solver was created with the following parameters:
+ 125 \t"""
+ 126 % (self.type, method_name)
+ 127 + "\n\t".join("%s: %s" % i for i in sorted(self._kwds.items()))
+ 128 + "\n\t_args: %s" % (self._args,)
+ 129 + "\n\toptions: %s" % (self.options,)
+ 130 )
+
+RuntimeError: Attempting to use an unavailable solver.
+
+The SolverFactory was unable to create the solver "ipopt"
+and returned an UnknownSolver object. This error is raised at the point
+where the UnknownSolver object was used as if it were valid (by calling
+method "solve").
+
+The original solver was created with the following parameters:
+ executable: /home/runner/work/pyomo_jupyter_book/pyomo_jupyter_book/solvers/ipopt
+ type: ipopt
+ _args: ()
+ options: {}
+
Rules are important for defining indexed constraints, however, they can also be used for single (i.e. scalar) constraints. Here we reimplement the model using +rules for the objective and the constraints.
+import pyomo.environ as pyo
+
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+
+def obj_rule(m):
+ return sum( b[i]*m.x[i] for i in A )
+model.obj = pyo.Objective(rule=obj_rule, sense = pyo.maximize )
+
+def weight_con_rule(m):
+ return sum( w[i]*m.x[i] for i in A ) <= W_max
+model.weight_con = pyo.Constraint(rule=weight_con_rule)
+
+opt = pyo.SolverFactory('cbc')
+opt_success = opt.solve(model)
+
+model.pprint()
+
WARNING: Could not locate the 'cbc' executable, which is required for solver
+cbc
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 20
+ 17 model.weight_con = pyo.Constraint(rule=weight_con_rule)
+ 19 opt = pyo.SolverFactory('cbc')
+---> 20 opt_success = opt.solve(model)
+ 22 model.pprint()
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'cbc'
+
Consider again, the +knapsack problem. Assume now that we can acquire multiple items of +the same type. In this new formulation, \(x_{i}\) is now an integer variable +instead of a binary variable. One way to formulate this problem is as +follows:
+Below we implement this new formulation and solve. Is the solution surprising?
+import pyomo.environ as pyo
+
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+N = range(6) # create a list from 0-5
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A )
+model.q = pyo.Var( A, N, within=pyo.Binary )
+
+def obj_rule(m):
+ return sum( b[i]*m.x[i] for i in A )
+model.obj = pyo.Objective(rule=obj_rule, sense = pyo.maximize )
+
+def weight_con_rule(m):
+ return sum( w[i]*m.x[i] for i in A ) <= W_max
+model.weight_con = pyo.Constraint(rule=weight_con_rule)
+
+def x_integer_rule(m, i):
+ return m.x[i] == sum( j*m.q[i,j] for j in N )
+model.x_integer = pyo.Constraint(A, rule=x_integer_rule)
+
+opt = pyo.SolverFactory('glpk')
+result_obj = opt.solve(model)
+
+total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+print('Total Weight:', total_weight)
+print('Total Benefit:', pyo.value(model.obj))
+
+print('%12s %12s' % ('Item', '# Selected'))
+print('=========================')
+for i in A:
+ print('%12s %12s' % (i, pyo.value(model.x[i])))
+print('-------------------------')
+
WARNING: Could not locate the 'glpsol' executable, which is required for
+solver 'glpk'
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 26
+ 23 model.x_integer = pyo.Constraint(A, rule=x_integer_rule)
+ 25 opt = pyo.SolverFactory('glpk')
+---> 26 result_obj = opt.solve(model)
+ 28 total_weight = sum( w[i]*pyo.value(model.x[i]) for i in A )
+ 29 print('Total Weight:', total_weight)
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'glpk'
+
In the slides, we saw an alternative notation for declaring and defining Pyomo components using decorators. Below we change the model to use the decorator notation.
+# Warehouse location determination problem using decorator notation
+import pyomo.environ as pyo
+
+model = pyo.ConcreteModel(name="(WL)")
+
+W = ['Harlingen', 'Memphis', 'Ashland']
+C = ['NYC', 'LA', 'Chicago', 'Houston']
+d = {('Harlingen', 'NYC'): 1956, \
+ ('Harlingen', 'LA'): 1606, \
+ ('Harlingen', 'Chicago'): 1410, \
+ ('Harlingen', 'Houston'): 330, \
+ ('Memphis', 'NYC'): 1096, \
+ ('Memphis', 'LA'): 1792, \
+ ('Memphis', 'Chicago'): 531, \
+ ('Memphis', 'Houston'): 567, \
+ ('Ashland', 'NYC'): 485, \
+ ('Ashland', 'LA'): 2322, \
+ ('Ashland', 'Chicago'): 324, \
+ ('Ashland', 'Houston'): 1236 }
+P = 2
+
+model.x = pyo.Var(W, C, bounds=(0,1))
+model.y = pyo.Var(W, within=pyo.Binary)
+
+@model.Objective()
+def obj(m):
+ return sum(d[w,c]*m.x[w,c] for w in W for c in C)
+
+@model.Constraint(C)
+def one_per_cust(m, c):
+ return sum(m.x[w,c] for w in W) == 1
+
+@model.Constraint(W,C)
+def warehouse_active(m, w, c):
+ return m.x[w,c] <= m.y[w]
+
+@model.Constraint()
+def num_warehouses(m):
+ return sum(m.y[w] for w in W) <= P
+
+pyo.SolverFactory('glpk').solve(model)
+
+model.y.pprint()
+model.x.pprint()
+
WARNING: Could not locate the 'glpsol' executable, which is required for
+solver 'glpk'
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 41
+ 37 @model.Constraint()
+ 38 def num_warehouses(m):
+ 39 return sum(m.y[w] for w in W) <= P
+---> 41 pyo.SolverFactory('glpk').solve(model)
+ 43 model.y.pprint()
+ 44 model.x.pprint()
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'glpk'
+
In the tutorial slides, we saw that a parameter could be specified to be mutable. This tells Pyomo that the value of the parameter may change in the future, and allows the user to change the parameter value and resolve the problem without the need to rebuild the entire model each time. We will use this functionality +to find a better solution to an earlier exercise. Considering again the knapsack problem, we would like to find when the wrench becomes valuable enough to be a part of the optimal solution. Below we create a Pyomo Parameter for the value of the items, make it mutable, and then write a loop that prints the solution for different wrench values.
+import pyomo.environ as pyo
+
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+model.item_benefit = pyo.Param( A, within=pyo.NonNegativeReals, initialize=b, mutable=True)
+
+def obj_rule(m):
+ return sum( m.item_benefit[i]*m.x[i] for i in A )
+model.obj = pyo.Objective(rule=obj_rule, sense = pyo.maximize )
+
+def weight_rule(m):
+ return sum( w[i]*m.x[i] for i in A ) <= W_max
+model.weight = pyo.Constraint(rule=weight_rule)
+
+opt = pyo.SolverFactory('glpk')
+
+for wrench_benefit in range(1,11):
+ model.item_benefit['wrench'] = wrench_benefit
+ result_obj = opt.solve(model)
+
+ print('Wrench benefit:', wrench_benefit, "x['wrench']:", pyo.value(model.x['wrench']))
+
WARNING: Could not locate the 'glpsol' executable, which is required for
+solver 'glpk'
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 24
+ 22 for wrench_benefit in range(1,11):
+ 23 model.item_benefit['wrench'] = wrench_benefit
+---> 24 result_obj = opt.solve(model)
+ 26 print('Wrench benefit:', wrench_benefit, "x['wrench']:", pyo.value(model.x['wrench']))
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'glpk'
+
Often, it can be important to find not only the “best” solution, but a number of solutions that are equally optimal, or close to optimal. For discrete optimization problems, this can be done using something known as an integer cut. Consider again the knapsack problem where the choice of which items to select is a discrete variable \(x_{i} \forall i \in A\). Let \(x_{i}^{*}\) be a particular set of x values we want to remove from the feasible solution space. We define an integer cut using two sets. The first set \(S_{0}\) contains the indices for those variables whose current solution is 0, and the second set \(S_{1}\) consists of indices for those variables whose current solution is 1. Given these two sets, an integer cut constraint that would prevent such a solution from appearing again +is defined by,
+Below, we write a loop that solves the problem 5 times, adding an integer cut to remove the previous solution, and printing the value of the objective function and the solution at each iteration of the loop.
+import pyomo.environ as pyo
+
+A = ['hammer', 'wrench', 'screwdriver', 'towel']
+b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
+w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
+W_max = 14
+
+model = pyo.ConcreteModel()
+model.x = pyo.Var( A, within=pyo.Binary )
+
+def obj_rule(m):
+ return sum( b[i]*m.x[i] for i in A )
+model.obj = pyo.Objective(rule=obj_rule, sense = pyo.maximize )
+
+def weight_con_rule(m):
+ return sum( w[i]*m.x[i] for i in A ) <= W_max
+model.weight_con = pyo.Constraint(rule=weight_con_rule)
+
+opt = pyo.SolverFactory('glpk')
+
+
+# create the ConstraintList to hold the integer cuts
+model.int_cuts = pyo.ConstraintList()
+
+# loop 5 times
+for l in range(5):
+ # solve the problem
+ result_obj = opt.solve(model)
+
+ # print the solution
+ output_str = 'Obj: ' + str(pyo.value(model.obj))
+ for i in A:
+ output_str += " x[%s]: %f" % (str(i), pyo.value(model.x[i]))
+ print(output_str)
+
+ # add the integer cut based on the current solution
+ cut_expr = 0
+ for i in A:
+ if pyo.value(model.x[i]) < 0.5:
+ cut_expr += model.x[i]
+ else:
+ cut_expr += (1.0 - model.x[i])
+ model.int_cuts.add(cut_expr >= 1)
+
WARNING: Could not locate the 'glpsol' executable, which is required for
+solver 'glpk'
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 28
+ 25 # loop 5 times
+ 26 for l in range(5):
+ 27 # solve the problem
+---> 28 result_obj = opt.solve(model)
+ 30 # print the solution
+ 31 output_str = 'Obj: ' + str(pyo.value(model.obj))
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'glpk'
+
We will now write a complete model from scratch using a well-known multi-period optimization problem for optimal lot-sizing adapted from +Hagen et al. (2001) shown below.
+Our goal is to find the optimal production \(X_{t}\) given known demands \(d_{t}\), fixed cost \(c_{t}\) associated with active production in a particular time +period, an inventory holding cost \(h_{t}^{+}\) and a shortage cost \(h_{t}^{-}\) (cost of keeping a backlog) of orders. The variable \(y_{t}\) (binary) determines if we produce in time \(t\) or not, and \(I_{t}^{+}\) represents inventory that we are storing +across time period \(t\), while \(h_{t}^{-}\) represents the magnitude of the backlog. +Note that equation (4) is a constraint that only allows production in time period t if the indicator variable \(y_{t}=1\). Below we write a Pyomo model for this problem and solve it using glpk using the data provided below.
+Parameter |
+Description |
+Value |
+
---|---|---|
\(c\) |
+fixed cost of production |
+4.6 |
+
\(I_{0}^{+}\) |
+initial value of positive inventory |
+5.0 |
+
\(I_{0}^{-}\) |
+initial value of backlogged orders |
+0.0 |
+
\(h^{+}\) |
+cost (per unit) of holding inventory |
+0.7 |
+
\(h^{-}\) |
+shortage cost (per unit) |
+1.2 |
+
\(P\) |
+maximum production amount (big-M value) |
+5 |
+
\(d\) |
+demand |
+[5,7,6.2,3.1,1.7] |
+
import pyomo.environ as pyo
+
+model = pyo.ConcreteModel()
+model.T = pyo.RangeSet(5) # time periods
+
+i0 = 5.0 # initial inventory
+c = 4.6 # setup cost
+h_pos = 0.7 # inventory holding cost
+h_neg = 1.2 # shortage cost
+P = 5.0 # maximum production amount
+
+# demand during period t
+d = {1: 5.0, 2:7.0, 3:6.2, 4:3.1, 5:1.7}
+
+# define the variables
+model.y = pyo.Var(model.T, domain=pyo.Binary)
+model.x = pyo.Var(model.T, domain=pyo.NonNegativeReals)
+model.i = pyo.Var(model.T)
+model.i_pos = pyo.Var(model.T, domain=pyo.NonNegativeReals)
+model.i_neg = pyo.Var(model.T, domain=pyo.NonNegativeReals)
+
+# define the inventory relationships
+def inventory_rule(m, t):
+ if t == m.T.first():
+ return m.i[t] == i0 + m.x[t] - d[t]
+ return m.i[t] == m.i[t-1] + m.x[t] - d[t]
+model.inventory = pyo.Constraint(model.T, rule=inventory_rule)
+
+def pos_neg_rule(m, t):
+ return m.i[t] == m.i_pos[t] - m.i_neg[t]
+model.pos_neg = pyo.Constraint(model.T, rule=pos_neg_rule)
+
+# create the big-M constraint for the production indicator variable
+def prod_indicator_rule(m,t):
+ return m.x[t] <= P*m.y[t]
+model.prod_indicator = pyo.Constraint(model.T, rule=prod_indicator_rule)
+
+# define the cost function
+def obj_rule(m):
+ return sum(c*m.y[t] + h_pos*m.i_pos[t] + h_neg*m.i_neg[t] for t in m.T)
+model.obj = pyo.Objective(rule=obj_rule)
+
+# solve the problem
+solver = pyo.SolverFactory('glpk')
+solver.solve(model)
+
+# print the results
+for t in model.T:
+ print('Period: {0}, Prod. Amount: {1}'.format(t, pyo.value(model.x[t])))
+
WARNING: Could not locate the 'glpsol' executable, which is required for
+solver 'glpk'
+
---------------------------------------------------------------------------
+ApplicationError Traceback (most recent call last)
+Cell In[1], line 45
+ 43 # solve the problem
+ 44 solver = pyo.SolverFactory('glpk')
+---> 45 solver.solve(model)
+ 47 # print the results
+ 48 for t in model.T:
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/base/solvers.py:534, in OptSolver.solve(self, *args, **kwds)
+ 531 def solve(self, *args, **kwds):
+ 532 """Solve the problem"""
+--> 534 self.available(exception_flag=True)
+ 535 #
+ 536 # If the inputs are models, then validate that they have been
+ 537 # constructed! Collect suffix names to try and import from solution.
+ 538 #
+ 539 from pyomo.core.base.block import BlockData
+
+File ~/CHE498/pyomo_jupyter_book/.venv/lib/python3.10/site-packages/pyomo/opt/solver/shellcmd.py:140, in SystemCallSolver.available(self, exception_flag)
+ 138 if exception_flag:
+ 139 msg = "No executable found for solver '%s'"
+--> 140 raise ApplicationError(msg % self.name)
+ 141 return False
+ 142 return True
+
+ApplicationError: No executable found for solver 'glpk'
+
Hart, W. E., Laird, C. D., Watson, J. P., Woodruff, D. L., Hackebeil, G.A., Nicholson, B. L., and Siirola, J. D. Pyomo: Optimization Modeling in Python (Second Edition), Vol (67), Springer Verlag, 2017.
+Kjetil K. Haugen, Arne Lkketangen,and David L. Woodruff. Progressive hedging as a meta-heuristic applied to stochastic lot-sizing. European Journal of Operational Research, 132(1):116 122, 2001
+B.W. Bequette. Process control: modeling, design, and simulation. Prentice Hall 2003.
+A conversion of the Pyomo workshop into a jupyter book
+Find the companion website here
+Ensure you’ve opened the directory of the jupyter-book as the working directory. You should have a _config.yml and _toc.yml file in this directory. Make sure you’re in a virtual environment. Install jupyter-book is using:
+pip install jupyter-book
+then
+jupyter-book build ./
+to build the current working directory into a jupyter-book.
The html is in the folder _build\html\
and you can preview the book by opening the file _build\html\index.html