├── 01_PyomoOverview.ipynb
├── 02_Sets.ipynb
├── 03_Parameters.ipynb
├── 04_Variables.ipynb
├── 05_Objectives.ipynb
├── 06_Constraints.ipynb
├── 07_Expressions.ipynb
├── 08_DataInput.ipynb
├── 09_BuildActionAndBuildCheck.ipynb
├── 10_PyomoCommand.ipynb
├── 11_PySPOverview.ipynb
├── 12_Suffixes.ipynb
├── 13_DAEToolbox.ipynb
├── 14_Scripts.ipynb
├── README.md
├── abstract1.dat
├── abstract1.py
├── abstract2.dat
├── abstract2.py
└── examples
└── README.md
/01_PyomoOverview.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "#1. Pyomo Overview"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "##1.1 Mathematical Modeling"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {},
20 | "source": [
21 | "\n",
22 | "This chapter provides an introduction to Pyomo: Python Optimization Modeling Objects. A more complete description is contained in [Pyomo - Optimization Modeling in Python](http://www.springer.com/us/book/9781461432258). Pyomo supports the formulation and analysis of mathematical models for complex optimization applications. This capability is commonly associated with algebraic modeling languages (AMLs) such as [AMPL](http://www.ampl.com), [AIMMS](http://www.aimms.com/), and [GAMS](http://www.gams.com). Pyomo’s modeling objects are embedded within Python, a full-featured high-level programming language that contains a rich set of supporting libraries.\n",
23 | "Modeling is a fundamental process in many aspects of scientific research, engineering and business. Modeling involves the formulation of a simplified representation of a system or real-world object. Thus, modeling tools like Pyomo can be used in a variety of ways:\n",
24 | "\n",
25 | "- **Explain** phenomena that arise in a system,\n",
26 | "\n",
27 | "- **Make predictions** about future states of a system,\n",
28 | "\n",
29 | "- **Assess key factors** that influence phenomena in a system,\n",
30 | "\n",
31 | "- **Identify extreme states** in a system, that might represent worst-case scenarios or minimal cost plans, and\n",
32 | "\n",
33 | "- **Analyze trade-offs** to support human decision makers.\n",
34 | "\n",
35 | "Mathematical models represent system knowledge with a formalized mathematical language. The following mathematical concepts are central to modern modeling activities:\n",
36 | "\n",
37 | " ####variables\n",
38 | "- **Variables**Variables represent unknown or changing parts of a model\n",
39 | " (e.g. whether or not to make a decision, or the characteristic of \n",
40 | " a system outcome).The values taken by the variables are often\n",
41 | " referred to as a *solution* and are usually an output of the\n",
42 | " optimization process.\n",
43 | "\n",
44 | "####parameters\n",
45 | "- Parameters represents the data that must be supplied to perform\n",
46 | " theoptimization. In fact, in some settings the word *data* is used in\n",
47 | " place of the word *parameters*.\n",
48 | "\n",
49 | "####relations\n",
50 | "- These are equations, inequalities or other mathematical relationships\n",
51 | " that define how different parts of a model are connected to each\n",
52 | " other.\n",
53 | "\n",
54 | "####goals\n",
55 | "- These are functions that reflect goals and objectives for the system\n",
56 | " being modeled.\n",
57 | "\n",
58 | "The widespread availability of computing resources has made the numerical analysis of mathematical models a commonplace activity. Without a modeling language, the process of setting up input files, executing a solver and extracting the final results from the solver output is tedious and error prone. This difficulty is compounded in complex, large-scale real-world applications which are difficult to debug when errors occur. Additionally, there are many different formats used by optimization software packages, and few formats are recognized by many optimizers. Thus the application of multiple optimization solvers to analyze a model introduces additional complexities.\n",
59 | "\n",
60 | "Pyomo is an AML that extends Python to include objects for mathematical modeling. Hart et al. [PyomoBook](https://software.sandia.gov/downloads/pub/pyomo/PyomoOnlineDocs.html#PyomoBook), [PyomoJournal](https://software.sandia.gov/downloads/pub/pyomo/PyomoOnlineDocs.html#PyomoJournal) compare Pyomo with other AMLs. Although many good AMLs have been developed for optimization models, the following are motivating factors for the development of Pyomo:\n",
61 | "\n",
62 | "####Open Source\n",
63 | "- Pyomo is developed within Pyomo’s open source project to promote\n",
64 | " transparency of the modeling framework and encourage community\n",
65 | " development of Pyomo capabilities.\n",
66 | "\n",
67 | "####Customizable Capability\n",
68 | "- Pyomo supports a customizable capability through the extensive use \n",
69 | " of plug-ins to modularize software components.\n",
70 | "\n",
71 | "####Solver Integration\n",
72 | "- Pyomo models can be optimized with solvers that are written either in\n",
73 | " Python or in compiled, low-level languages.\n",
74 | "\n",
75 | "####Programming Language\n",
76 | "- Pyomo leverages a high-level programming language, which has several\n",
77 | " advantages over custom AMLs: a very robust language, extensive\n",
78 | " documentation, a rich set of standard libraries, support for modern\n",
79 | " programming features like classes and functions, and portability to\n",
80 | " many platforms."
81 | ]
82 | },
83 | {
84 | "cell_type": "markdown",
85 | "metadata": {},
86 | "source": [
87 | "##1.2 Overview of Modeling Components and Processes"
88 | ]
89 | },
90 | {
91 | "cell_type": "markdown",
92 | "metadata": {},
93 | "source": [
94 | "Pyomo supports an object-oriented design for the definition of optimization models. The basic steps of a simple modeling process are:\n",
95 | "\n",
96 | "- Create model and declare components\n",
97 | "\n",
98 | "- Instantiate the model\n",
99 | "\n",
100 | "- Apply solver\n",
101 | "\n",
102 | "- Interrogate solver results\n",
103 | "\n",
104 | "In practice, these steps may be applied repeatedly with different data or with different constraints applied to the model. However, we focus on this simple modeling process to illustrate different strategies for modeling with Pyomo.\n",
105 | "\n",
106 | "A Pyomo *model* consists of a collection of modeling *components* that define different aspects of the model. Pyomo includes the modeling components that are commonly supported by modern AMLs: index sets, symbolic parameters, decision variables, objectives, and constraints. These modeling components are defined in Pyomo through the following Python classes:\n",
107 | "\n",
108 | "####Set\n",
109 | "- set data that is used to define a model instance\n",
110 | "\n",
111 | "####Param\n",
112 | "- parameter data that is used to define a model instance\n",
113 | "\n",
114 | "####Var\n",
115 | "- decision variables in a model\n",
116 | "\n",
117 | "####Objective\n",
118 | "- expressions that are minimized or maximized in a model\n",
119 | "\n",
120 | "####Constraint\n",
121 | "- constraint expressions that impose restrictions on variable\n",
122 | " values in a model"
123 | ]
124 | },
125 | {
126 | "cell_type": "markdown",
127 | "metadata": {},
128 | "source": [
129 | "##1.3 Abstract Versus Concrete Models"
130 | ]
131 | },
132 | {
133 | "cell_type": "markdown",
134 | "metadata": {},
135 | "source": [
136 | "A mathematical model can be defined using symbols that represent data values. For example, the following equations represent a linear program (LP) to find optimal values for the vector $x$ with parameters $n$ and $b$, and parameter vectors $a$ and $c$:\n",
137 | "\n",
138 | "$$\n",
139 | "\\begin{array}{lll}\n",
140 | "\\min & \\sum_{j=1}^n c_j x_j & \\\\\n",
141 | "s.t. & \\sum_{j=1}^n a_ij x_j \\geq b_i & \\forall i = 1 \\ldots m\\\\\n",
142 | " & x_j \\geq 0 & \\forall j = 1 \\ldots n\n",
143 | "\\end{array}\n",
144 | "$$"
145 | ]
146 | },
147 | {
148 | "cell_type": "markdown",
149 | "metadata": {},
150 | "source": [
151 | ">#####Note:\n",
152 | ">As a convenience, we use the symbol $\\forall$\n",
153 | " to mean “for all” or “for each.”\n",
154 | " \n"
155 | ]
156 | },
157 | {
158 | "cell_type": "markdown",
159 | "metadata": {},
160 | "source": [
161 | "We call this an *abstract* or *symbolic* mathematical model since it relies on unspecified parameter values. Data values can be used to specify a *model instance*. The AbstractModel class provides a context for defining and initializing abstract optimization models in Pyomo when the data values will be supplied at the time a solution is to be obtained.\n",
162 | "\n",
163 | "In some contexts a mathematical model can be directly defined with the data values supplied at the time of the model definition and built into the model. We call these *concrete* mathematical models. For example, the following LP model is a concrete instance of the previous abstract model:\n",
164 | "\n",
165 | "$$\n",
166 | "\\begin{array}{ll}\n",
167 | "\\min & 2x_1 + 3x_2\\\\\n",
168 | "s.t. & 3x_1 + 4x_2 \\geq 1\\\\\n",
169 | " & x_1,x_2 \\geq 0 \n",
170 | "\\end{array}\n",
171 | "$$\n",
172 | "\n",
173 | "The ConcreteModel class is used to define concrete optimization models in Pyomo."
174 | ]
175 | },
176 | {
177 | "cell_type": "markdown",
178 | "metadata": {},
179 | "source": [
180 | "##1.4 A Simple Abstract Pyomo Model"
181 | ]
182 | },
183 | {
184 | "cell_type": "markdown",
185 | "metadata": {},
186 | "source": [
187 | "We repeat the abstract model already given:\n",
188 | "\n",
189 | "$$\n",
190 | "\\begin{array}{lll}\n",
191 | "\\min & \\sum_{j=1}^n c_j x_j & \\\\\n",
192 | "s.t. & \\sum_{j=1}^n a_ij x_j \\geq b_i & \\forall i = 1 \\ldots m\\\\\n",
193 | " & x_j \\geq 0 & \\forall j = 1 \\ldots n\n",
194 | "\\end{array}\n",
195 | "$$\n",
196 | "\n",
197 | "One way to implement this in Pyomo is as follows:"
198 | ]
199 | },
200 | {
201 | "cell_type": "code",
202 | "execution_count": 31,
203 | "metadata": {
204 | "collapsed": true
205 | },
206 | "outputs": [],
207 | "source": [
208 | "from __future__ import division\n",
209 | "from pyomo.environ import *\n",
210 | "\n",
211 | "model = AbstractModel()\n",
212 | "\n",
213 | "model.m = Param(within=NonNegativeIntegers)\n",
214 | "model.n = Param(within=NonNegativeIntegers)\n",
215 | "\n",
216 | "model.I = RangeSet(1, model.m)\n",
217 | "model.J = RangeSet(1, model.n)\n",
218 | "\n",
219 | "model.a = Param(model.I, model.J)\n",
220 | "model.b = Param(model.I)\n",
221 | "model.c = Param(model.J)\n",
222 | "\n",
223 | "# the next line declares a variable indexed by the set J\n",
224 | "model.x = Var(model.J, domain=NonNegativeReals)\n",
225 | "\n",
226 | "def obj_expression(model):\n",
227 | " return summation(model.c, model.x)\n",
228 | "\n",
229 | "model.OBJ = Objective(rule=obj_expression)\n",
230 | "\n",
231 | "def ax_constraint_rule(model, i):\n",
232 | " # return the expression for the constraint for i\n",
233 | " return sum(model.a[i,j] * model.x[j] for j in model.J) >= model.b[i]\n",
234 | "\n",
235 | "# the next line creates one constraint for each member of the set model.I\n",
236 | "model.AxbConstraint = Constraint(model.I, rule=ax_constraint_rule)"
237 | ]
238 | },
239 | {
240 | "cell_type": "markdown",
241 | "metadata": {},
242 | "source": [
243 | ">#####Note:\n",
244 | ">Python is interpreted one line at a time. A line continuation character, backslash, is used for Python statements that need to span multiple lines. In Python, indentation has meaning and must be consistent. For example, lines inside a function definition must be indented and the end of the indentation is used by Python to signal the end of the definition."
245 | ]
246 | },
247 | {
248 | "cell_type": "markdown",
249 | "metadata": {},
250 | "source": [
251 | "We will now examine the lines in this example. The first import line is used to ensure that int or long division arguments are converted to floating point values before division is performed."
252 | ]
253 | },
254 | {
255 | "cell_type": "code",
256 | "execution_count": 32,
257 | "metadata": {
258 | "collapsed": true
259 | },
260 | "outputs": [],
261 | "source": [
262 | "from __future__ import division"
263 | ]
264 | },
265 | {
266 | "cell_type": "markdown",
267 | "metadata": {},
268 | "source": [
269 | "In Python versions before 3.0, division returns the floor of the mathematical result of division if arguments are int or long. This import line avoids unexpected behavior when developing mathematical models with integer values.\n",
270 | "\n",
271 | "The next import line that is required in every Pyomo model. Its purpose is to make the symbols used by Pyomo known to Python."
272 | ]
273 | },
274 | {
275 | "cell_type": "code",
276 | "execution_count": 33,
277 | "metadata": {
278 | "collapsed": true
279 | },
280 | "outputs": [],
281 | "source": [
282 | "from pyomo.environ import *"
283 | ]
284 | },
285 | {
286 | "cell_type": "markdown",
287 | "metadata": {},
288 | "source": [
289 | "The declaration of a model is also required. The use of the name model is not required. Almost any name could be used, but we will use the name model most of the time in this book. In this example, we are declaring that it will be an abstract model."
290 | ]
291 | },
292 | {
293 | "cell_type": "code",
294 | "execution_count": 34,
295 | "metadata": {
296 | "collapsed": true
297 | },
298 | "outputs": [],
299 | "source": [
300 | "model = AbstractModel()"
301 | ]
302 | },
303 | {
304 | "cell_type": "markdown",
305 | "metadata": {},
306 | "source": [
307 | "We declare the parameters $m$ and $n$ using the Pyomo Param function. This function can take a variety of arguments; this example illustrates use of the within option that is used by Pyomo to validate the data value that is assigned to the parameter. If this option were not given, then Pyomo would not object to any type of data being assigned to these parameters. As it is, assignment of a value that is not a non-negative integer will result in an error."
308 | ]
309 | },
310 | {
311 | "cell_type": "code",
312 | "execution_count": 35,
313 | "metadata": {
314 | "collapsed": true
315 | },
316 | "outputs": [],
317 | "source": [
318 | "model.m = Param(within=NonNegativeIntegers)\n",
319 | "model.n = Param(within=NonNegativeIntegers)"
320 | ]
321 | },
322 | {
323 | "cell_type": "markdown",
324 | "metadata": {},
325 | "source": [
326 | "Although not required, it is convenient to define index sets. In this example we use the RangeSet function to declare that the sets will be a sequence of integers starting at 1 and ending at a value specified by the the parameters model.m and model.n."
327 | ]
328 | },
329 | {
330 | "cell_type": "code",
331 | "execution_count": 36,
332 | "metadata": {
333 | "collapsed": true
334 | },
335 | "outputs": [],
336 | "source": [
337 | "model.I = RangeSet(1, model.m)\n",
338 | "model.J = RangeSet(1, model.n)"
339 | ]
340 | },
341 | {
342 | "cell_type": "markdown",
343 | "metadata": {},
344 | "source": [
345 | "The coefficient and right-hand-side data are defined as indexed parameters. When sets are given as arguments to the Param function, they indicate that the set will index the parameter."
346 | ]
347 | },
348 | {
349 | "cell_type": "code",
350 | "execution_count": 37,
351 | "metadata": {
352 | "collapsed": true
353 | },
354 | "outputs": [],
355 | "source": [
356 | "model.a = Param(model.I, model.J)\n",
357 | "model.b = Param(model.I)\n",
358 | "model.c = Param(model.J)"
359 | ]
360 | },
361 | {
362 | "cell_type": "markdown",
363 | "metadata": {},
364 | "source": [
365 | ">#####Note:\n",
366 | ">In Python, and therefore in Pyomo, any text after pound sign is considered to be a comment.\n",
367 | "\n",
368 | "The next line interpreted by Python as part of the model declares the variable $x$. The first argument to the Var function is a set, so it is defined as an index set for the variable. In this case the variable has only one index set, but multiple sets could be used as was the case for the declaration of the parameter model.a. The second argument specifies a domain for the variable. This information is part of the model and will passed to the solver when data is provided and the model is solved. Specification of the NonNegativeReals domain implements the requirement that the variables be greater than or equal to zero."
369 | ]
370 | },
371 | {
372 | "cell_type": "code",
373 | "execution_count": 38,
374 | "metadata": {
375 | "collapsed": true
376 | },
377 | "outputs": [],
378 | "source": [
379 | "# the next line declares a variable indexed by the set J\n",
380 | "model.x = Var(model.J, domain=NonNegativeReals)"
381 | ]
382 | },
383 | {
384 | "cell_type": "markdown",
385 | "metadata": {},
386 | "source": [
387 | "In abstract models, Pyomo expressions are usually provided to objective function and constraint declarations via a function defined with a Python def statement. The def statement establishes a name for a function along with its arguments. When Pyomo uses a function to get objective function or constraint expressions, it always passes in the model (i.e., itself) as the the first argument so the model is always the first formal argument when declaring such functions in Pyomo. Additional arguments, if needed, follow. Since summation is an extremely common part of optimization models, Pyomo provides a flexible function to accommodate it. When given two arguments, the summation function returns an expression for the sum of the product of the two arguments over their indexes. This only works, of course, if the two arguments have the same indexes. If it is given only one argument it returns an expression for the sum over all indexes of that argument. So in this example, when summation is passed the arguments model.c, model.x it returns an internal representation of the expression $\\sum_{j=1}^n c_j x_j$."
388 | ]
389 | },
390 | {
391 | "cell_type": "code",
392 | "execution_count": 39,
393 | "metadata": {
394 | "collapsed": true
395 | },
396 | "outputs": [],
397 | "source": [
398 | "def obj_expression(model):\n",
399 | " return summation(model.c, model.x)"
400 | ]
401 | },
402 | {
403 | "cell_type": "markdown",
404 | "metadata": {},
405 | "source": [
406 | "To declare an objective function, the Pyomo function called Objective is used. The rule argument gives the name of a function that returns the expression to be used. The default *sense* is minimization. For maximization, the sense=maximize argument must be used. The name that is declared, which is OBJ in this case, appears in some reports and can be almost any name."
407 | ]
408 | },
409 | {
410 | "cell_type": "code",
411 | "execution_count": 40,
412 | "metadata": {
413 | "collapsed": true
414 | },
415 | "outputs": [],
416 | "source": [
417 | "model.OBJ = Objective(rule=obj_expression)"
418 | ]
419 | },
420 | {
421 | "cell_type": "markdown",
422 | "metadata": {},
423 | "source": [
424 | "Declaration of constraints is similar. A function is declared to deliver the constraint expression. In this case, there can be multiple constraints of the same form because we index the constraints by $i$ in the expression $ \\sum_{j=1}^n a_ij x_j \\geq b_i \\forall i = 1 \\ldots m$, which states that we need a constraint for each value of $i$ from one to $m$. In order to parametrize the expression by $i$ we include it as a formal parameter to the function that declares the constraint expression. Technically, we could have used anything for this argument, but that might be confusing. Using an i for an $i$ seems sensible in this situation."
425 | ]
426 | },
427 | {
428 | "cell_type": "code",
429 | "execution_count": 41,
430 | "metadata": {
431 | "collapsed": true
432 | },
433 | "outputs": [],
434 | "source": [
435 | "def ax_constraint_rule(model, i):\n",
436 | " # return the expression for the constraint for i\n",
437 | " return sum(model.a[i,j] * model.x[j] for j in model.J) >= model.b[i]"
438 | ]
439 | },
440 | {
441 | "cell_type": "markdown",
442 | "metadata": {},
443 | "source": [
444 | ">####Note:\n",
445 | ">In Python, indexes are in square brackets and function arguments are in parentheses.\n",
446 | "\n",
447 | "In order to declare constraints that use this expression, we use the Pyomo Constraint function that takes a variety of arguments. In this case, our model specifies that we can have more than one constraint of the same form and we have created a set, model.I, over which these constraints can be indexed so that is the first argument to the constraint declaration function. The next argument gives the rule that will be used to generate expressions for the constraints. Taken as a whole, this constraint declaration says that a list of constraints indexed by the set model.I will be created and for each member of model.I, the function ax_constraint_rule will be called and it will be passed the model object as well as the member of model.I."
448 | ]
449 | },
450 | {
451 | "cell_type": "code",
452 | "execution_count": 42,
453 | "metadata": {
454 | "collapsed": true
455 | },
456 | "outputs": [],
457 | "source": [
458 | "# the next line creates one constraint for each member of the set model.I\n",
459 | "model.AxbConstraint = Constraint(model.I, rule=ax_constraint_rule)"
460 | ]
461 | },
462 | {
463 | "cell_type": "markdown",
464 | "metadata": {},
465 | "source": [
466 | "In the object oriented view of all of this, we would say that model object is a class instance of the AbstractModel class, and model.J is a Set object that is contained by this model. Many modeling components in Pyomo can be optionally specified as *indexed components*: collections of components that are referenced using one or more values. In this example, the parameter model.c is indexed with set model.J.\n",
467 | "\n",
468 | "In order to use this model, data must be given for the values of the parameters. Here is one file that provides data."
469 | ]
470 | },
471 | {
472 | "cell_type": "code",
473 | "execution_count": 5,
474 | "metadata": {
475 | "collapsed": false
476 | },
477 | "outputs": [
478 | {
479 | "name": "stdout",
480 | "output_type": "stream",
481 | "text": [
482 | "# one way to input the data in AMPL format\r\n",
483 | "# for indexed parameters, the indexes are given before the value\r\n",
484 | "\r\n",
485 | "param m := 1 ;\r\n",
486 | "param n := 2 ;\r\n",
487 | "\r\n",
488 | "param a :=\r\n",
489 | "1 1 3\r\n",
490 | "1 2 4\r\n",
491 | ";\r\n",
492 | "\r\n",
493 | "param c:=\r\n",
494 | "1 2\r\n",
495 | "2 3\r\n",
496 | ";\r\n",
497 | "\r\n",
498 | "param b := 1 1 ;\r\n"
499 | ]
500 | }
501 | ],
502 | "source": [
503 | "!cat abstract1.dat"
504 | ]
505 | },
506 | {
507 | "cell_type": "markdown",
508 | "metadata": {},
509 | "source": [
510 | "There are multiple formats that can be used to provide data to a Pyomo model, but the AMPL format works well for our purposes because it contains the names of the data elements together with the data. In AMPL data files, text after a pound sign is treated as a comment. Lines generally do not matter, but statements must be terminated with a semi-colon.\n",
511 | "\n",
512 | "For this particular data file, there is one constraint, so the value of model.m will be one and there are two variables (i.e., the vector model.x is two elements long) so the value of model.n will be two. These two assignments are accomplished with standard assignments. Notice that in AMPL format input, the name of the model is omitted."
513 | ]
514 | },
515 | {
516 | "cell_type": "code",
517 | "execution_count": 7,
518 | "metadata": {
519 | "collapsed": false
520 | },
521 | "outputs": [
522 | {
523 | "name": "stdout",
524 | "output_type": "stream",
525 | "text": [
526 | "param m := 1 ;\r\n",
527 | "param n := 2 ;\r\n",
528 | "\r\n"
529 | ]
530 | }
531 | ],
532 | "source": [
533 | "!sed -n '4,6p' abstract1.dat"
534 | ]
535 | },
536 | {
537 | "cell_type": "markdown",
538 | "metadata": {},
539 | "source": [
540 | "There is only one constraint, so only two values are needed for model.a. When assigning values to arrays and vectors in AMPL format, one way to do it is to give the index(es) and the the value. The line 1 2 4 causes model.a[1,2] to get the value 4. Since model.c has only one index, only one index value is needed so, for example, the line 1 2 causes model.c[1] to get the value 2. Line breaks generally do not matter in AMPL format data files, so the assignment of the value for the single index of model.b is given on one line since that is easy to read."
541 | ]
542 | },
543 | {
544 | "cell_type": "code",
545 | "execution_count": 9,
546 | "metadata": {
547 | "collapsed": false
548 | },
549 | "outputs": [
550 | {
551 | "name": "stdout",
552 | "output_type": "stream",
553 | "text": [
554 | "param a :=\r\n",
555 | "1 1 3\r\n",
556 | "1 2 4\r\n",
557 | ";\r\n",
558 | "\r\n",
559 | "param c:=\r\n",
560 | "1 2\r\n",
561 | "2 3\r\n",
562 | ";\r\n",
563 | "\r\n",
564 | "param b := 1 1 ;\r\n"
565 | ]
566 | }
567 | ],
568 | "source": [
569 | "!sed -n '7,18p' abstract1.dat"
570 | ]
571 | },
572 | {
573 | "cell_type": "markdown",
574 | "metadata": {},
575 | "source": [
576 | "When working with Pyomo (or any other AML), it is convenient to write abstract models in a somewhat more abstract way by using index sets that contain strings rather than index sets that are implied by $1,...,m$ or the summation from 1 to $n$. When this is done, the size of the set is implied by the input, rather than specified directly. Furthermore, the index entries may have no real order. Often, a mixture of integers and indexes and strings as indexes is needed in the same model. To start with an illustration of general indexes, consider a slightly different Pyomo implementation of the model we just presented."
577 | ]
578 | },
579 | {
580 | "cell_type": "code",
581 | "execution_count": 43,
582 | "metadata": {
583 | "collapsed": true
584 | },
585 | "outputs": [],
586 | "source": [
587 | "# abstract2.py\n",
588 | "\n",
589 | "from __future__ import division\n",
590 | "from pyomo.environ import *\n",
591 | "\n",
592 | "model = AbstractModel()\n",
593 | "\n",
594 | "model.I = Set()\n",
595 | "model.J = Set()\n",
596 | "\n",
597 | "model.a = Param(model.I, model.J)\n",
598 | "model.b = Param(model.I)\n",
599 | "model.c = Param(model.J)\n",
600 | "\n",
601 | "# the next line declares a variable indexed by the set J\n",
602 | "model.x = Var(model.J, domain=NonNegativeReals)\n",
603 | "\n",
604 | "def obj_expression(model):\n",
605 | " return summation(model.c, model.x)\n",
606 | "\n",
607 | "model.OBJ = Objective(rule=obj_expression)\n",
608 | "\n",
609 | "def ax_constraint_rule(model, i):\n",
610 | " # return the expression for the constraint for i\n",
611 | " return sum(model.a[i,j] * model.x[j] for j in model.J) >= model.b[i]\n",
612 | "\n",
613 | "# the next line creates one constraint for each member of the set model.I\n",
614 | "model.AxbConstraint = Constraint(model.I, rule=ax_constraint_rule)\n"
615 | ]
616 | },
617 | {
618 | "cell_type": "markdown",
619 | "metadata": {},
620 | "source": [
621 | "However, this model can also be fed different data for problems of the same general form using meaningful indexes."
622 | ]
623 | },
624 | {
625 | "cell_type": "code",
626 | "execution_count": 4,
627 | "metadata": {
628 | "collapsed": false
629 | },
630 | "outputs": [
631 | {
632 | "name": "stdout",
633 | "output_type": "stream",
634 | "text": [
635 | "# abstract2.dat AMPL data format\r\n",
636 | "\r\n",
637 | "set I := TV Film ;\r\n",
638 | "set J := Graham John Carol ;\r\n",
639 | "\r\n",
640 | "param a :=\r\n",
641 | "TV Graham 3\r\n",
642 | "TV John 4.4\r\n",
643 | "TV Carol 4.9\r\n",
644 | "Film Graham 1\r\n",
645 | "Film John 2.4\r\n",
646 | "Film Carol 1.1\r\n",
647 | ";\r\n",
648 | "\r\n",
649 | "param c := [*]\r\n",
650 | " Graham 2.2\r\n",
651 | " John 3.1416\r\n",
652 | " Carol 3\r\n",
653 | ";\r\n",
654 | "\r\n",
655 | "param b := TV 1 Film 1 ;\r\n"
656 | ]
657 | }
658 | ],
659 | "source": [
660 | "! cat abstract2.dat"
661 | ]
662 | },
663 | {
664 | "cell_type": "markdown",
665 | "metadata": {},
666 | "source": [
667 | "##1.5 A Simple Concrete Pyomo Model"
668 | ]
669 | },
670 | {
671 | "cell_type": "markdown",
672 | "metadata": {},
673 | "source": [
674 | "It is possible to get nearly the same flexible behavior from models declared to be abstract and models declared to be concrete in Pyomo; however, we will focus on a straightforward concrete example here where the data is hard-wired into the model file. Python programmers will quickly realize that the data could have come from other sources.\n",
675 | "\n",
676 | "We repeat the concrete model already given:\n",
677 | "\n",
678 | "$$\\min \\quad 2x_1 + 3x_2$$\n",
679 | "$$s.t. \\quad 3x_1 + 4x_2 \\geq 1$$\n",
680 | "$$x_1,x_2 \\geq 0$$\n",
681 | "\n",
682 | "This is implemented as a concrete model as follows:"
683 | ]
684 | },
685 | {
686 | "cell_type": "code",
687 | "execution_count": 46,
688 | "metadata": {
689 | "collapsed": true
690 | },
691 | "outputs": [],
692 | "source": [
693 | "from __future__ import division\n",
694 | "from pyomo.environ import *\n",
695 | "\n",
696 | "model = ConcreteModel()\n",
697 | "\n",
698 | "model.x = Var([1,2], domain=NonNegativeReals)\n",
699 | "\n",
700 | "model.OBJ = Objective(expr = 2*model.x[1] + 3*model.x[2])\n",
701 | "\n",
702 | "model.Constraint1 = Constraint(expr = 3*model.x[1] + 4*model.x[2] >= 1)\n"
703 | ]
704 | },
705 | {
706 | "cell_type": "markdown",
707 | "metadata": {},
708 | "source": [
709 | "Although rule functions can also be used to specify constraints and objectives, in this example we use the expr option that is available only in concrete models. This option gives a direct specification of the expression."
710 | ]
711 | },
712 | {
713 | "cell_type": "markdown",
714 | "metadata": {},
715 | "source": [
716 | "##1.6 Solving the Simple Examples"
717 | ]
718 | },
719 | {
720 | "cell_type": "markdown",
721 | "metadata": {},
722 | "source": [
723 | "Pyomo supports modeling and scripting but does not install a solver automatically. In order to solve a model, there must be a solver installed on the computer to be used. If there is a solver, then the pyomo command can be used to solve a problem instance.\n",
724 | "\n",
725 | "Suppose that the solver named glpk (also known as glpsol) is installed on the computer. Suppose further that an abstract model is in the file named abstract1.py and a data file for it is in the file named abstract1.dat. From the command prompt, with both files in the current directory, a solution can be obtained with the command:"
726 | ]
727 | },
728 | {
729 | "cell_type": "code",
730 | "execution_count": 47,
731 | "metadata": {
732 | "collapsed": false
733 | },
734 | "outputs": [
735 | {
736 | "name": "stdout",
737 | "output_type": "stream",
738 | "text": [
739 | "[ 0.00] Setting up Pyomo environment\n",
740 | "[ 0.00] Applying Pyomo preprocessing actions\n",
741 | "[ 0.01] Creating model\n",
742 | "[ 0.15] Applying solver\n",
743 | "[ 0.24] Processing results\n",
744 | " Number of solutions: 1\n",
745 | " Solution Information\n",
746 | " Gap: 0.0\n",
747 | " Status: feasible\n",
748 | " Function Value: 0.666666666666667\n",
749 | " Solver results file: results.json\n",
750 | "[ 0.24] Applying Pyomo postprocessing actions\n",
751 | "[ 0.24] Pyomo Finished\n"
752 | ]
753 | }
754 | ],
755 | "source": [
756 | "!pyomo solve abstract1.py abstract1.dat --solver=glpk"
757 | ]
758 | },
759 | {
760 | "cell_type": "markdown",
761 | "metadata": {},
762 | "source": [
763 | "Since glpk is the default solver, there really is no need specify it so the --solver option can be dropped.\n",
764 | "\n",
765 | ">#####Note:\n",
766 | ">There are two dashes before the command line option names such as solver.\n",
767 | "\n",
768 | "To continue the example, if CPLEX is installed then it can be listed as the solver. The command to solve with CPLEX is"
769 | ]
770 | },
771 | {
772 | "cell_type": "code",
773 | "execution_count": 29,
774 | "metadata": {
775 | "collapsed": false
776 | },
777 | "outputs": [
778 | {
779 | "name": "stdout",
780 | "output_type": "stream",
781 | "text": [
782 | "[ 0.00] Setting up Pyomo environment\n",
783 | "[ 0.00] Applying Pyomo preprocessing actions\n",
784 | "[ 0.00] Creating model\n",
785 | "[ 0.24] Applying solver\n",
786 | "WARNING: \"[base]/pyomo/pyomo/solvers/plugins/solvers/CPLEX.py\", 207, executable\n",
787 | "\tCould not locate the 'cplex' executable, which is required for solver cplex\n",
788 | "[ 0.24] Pyomo Finished\n",
789 | "ERROR: Unexpected exception while running model:\n",
790 | "\tNo executable found for solver 'cplex'\n"
791 | ]
792 | }
793 | ],
794 | "source": [
795 | "!pyomo solve abstract1.py abstract1.dat --solver=cplex"
796 | ]
797 | },
798 | {
799 | "cell_type": "markdown",
800 | "metadata": {},
801 | "source": [
802 | "This yields the following output on the screen:"
803 | ]
804 | },
805 | {
806 | "cell_type": "markdown",
807 | "metadata": {},
808 | "source": [
809 | "The numbers is square brackets indicate how much time was required for each step. Results are written to the file named results.json, which has a special structure that makes it useful for post-processing. To see a summary of results written to the screen, use the --summary option:"
810 | ]
811 | },
812 | {
813 | "cell_type": "code",
814 | "execution_count": 27,
815 | "metadata": {
816 | "collapsed": false
817 | },
818 | "outputs": [
819 | {
820 | "name": "stdout",
821 | "output_type": "stream",
822 | "text": [
823 | "[ 0.00] Setting up Pyomo environment\n",
824 | "[ 0.00] Applying Pyomo preprocessing actions\n",
825 | "[ 0.05] Creating model\n",
826 | "[ 0.23] Applying solver\n",
827 | "WARNING: \"[base]/pyomo/pyomo/solvers/plugins/solvers/CPLEX.py\", 207, executable\n",
828 | "\tCould not locate the 'cplex' executable, which is required for solver cplex\n",
829 | "[ 0.23] Pyomo Finished\n",
830 | "ERROR: Unexpected exception while running model:\n",
831 | "\tNo executable found for solver 'cplex'\n"
832 | ]
833 | }
834 | ],
835 | "source": [
836 | "!pyomo solve abstract1.py abstract1.dat --solver=cplex --summary"
837 | ]
838 | },
839 | {
840 | "cell_type": "markdown",
841 | "metadata": {},
842 | "source": [
843 | "To see a list of Pyomo command line options, use:"
844 | ]
845 | },
846 | {
847 | "cell_type": "code",
848 | "execution_count": 26,
849 | "metadata": {
850 | "collapsed": false
851 | },
852 | "outputs": [
853 | {
854 | "name": "stdout",
855 | "output_type": "stream",
856 | "text": [
857 | "usage: pyomo solve [options] []\r\n",
858 | "\r\n",
859 | "positional arguments:\r\n",
860 | " model_or_config_file A Python module that defines a Pyomo model, or a\r\n",
861 | " configuration file that defines options for 'pyomo\r\n",
862 | " solve' (in either YAML or JSON format)\r\n",
863 | " data_files Pyomo data files that defined data used to initialize\r\n",
864 | " the model (specified in the first argument)\r\n",
865 | "\r\n",
866 | "optional arguments:\r\n",
867 | " -h, --help show this help message and exit\r\n",
868 | " --generate-config-template TEMPLATE\r\n",
869 | " Create a configuration template file in YAML or JSON\r\n",
870 | " and exit.\r\n",
871 | " --solver SOLVER Solver name. This option is required unless the solver\r\n",
872 | " name is specified in a configuration file.\r\n",
873 | "\r\n",
874 | "Description:\r\n",
875 | "\r\n",
876 | "The 'pyomo solve' subcommand optimizes a Pyomo model. The --solver option\r\n",
877 | "is required because the specific steps executed are solver dependent.\r\n",
878 | "The standard steps executed by this subcommand are:\r\n",
879 | "\r\n",
880 | " - Apply pre-solve operations (e.g. import Python packages)\r\n",
881 | " - Create the model\r\n",
882 | " - Apply model transformations\r\n",
883 | " - Perform optimization\r\n",
884 | " - Apply post-solve operations (e.g. save optimal solutions)\r\n",
885 | "\r\n",
886 | "This subcommand can be executed with or without a configuration file.\r\n",
887 | "The command-line options can be used to perform simple optimization steps.\r\n",
888 | "For example:\r\n",
889 | "\r\n",
890 | " pyomo solve --solver=glpk model.py model.dat\r\n",
891 | "\r\n",
892 | "This uses the 'glpk' solver to optimize the model define in 'model.py'\r\n",
893 | "using the Pyomo data file 'pyomo.dat'. Solver-specific command-line\r\n",
894 | "options can be listed by specifying the '--solver' option and the '--help'\r\n",
895 | "(or '-h') option:\r\n",
896 | "\r\n",
897 | " pyomo solve --solver=glpk --help\r\n",
898 | "\r\n",
899 | "A yaml or json configuration file can also be used to specify\r\n",
900 | "options used by the solver. For example:\r\n",
901 | "\r\n",
902 | " pyomo solve --solver=glpk config.yaml\r\n",
903 | "\r\n",
904 | "No other command-line options are required! Further, the '--solver'\r\n",
905 | "option can be omitted if the solver name is specified in the configuration\r\n",
906 | "file.\r\n",
907 | "\r\n",
908 | "Configuration options are also solver-specific; a template configuration\r\n",
909 | "file can be generated with the '--generate-config-template' option:\r\n",
910 | "\r\n",
911 | " pyomo solve --solver=glpk --generate-config-template=template.yaml\r\n",
912 | " pyomo solve --solver=glpk --generate-config-template=template.json\r\n",
913 | "\r\n",
914 | "Note that yaml template files contain comments that describe the\r\n",
915 | "configuration options. Also, configuration files will generally support\r\n",
916 | "more configuration options than are available with command-line options.\r\n"
917 | ]
918 | }
919 | ],
920 | "source": [
921 | "!pyomo solve --help"
922 | ]
923 | },
924 | {
925 | "cell_type": "markdown",
926 | "metadata": {},
927 | "source": [
928 | ">#####Note:\n",
929 | ">There are two dashes before help.\n",
930 | "\n",
931 | "For a concrete model, no data file is specified on the Pyomo command line."
932 | ]
933 | }
934 | ],
935 | "metadata": {
936 | "kernelspec": {
937 | "display_name": "Python 3",
938 | "language": "python",
939 | "name": "python3"
940 | },
941 | "language_info": {
942 | "codemirror_mode": {
943 | "name": "ipython",
944 | "version": 3
945 | },
946 | "file_extension": ".py",
947 | "mimetype": "text/x-python",
948 | "name": "python",
949 | "nbconvert_exporter": "python",
950 | "pygments_lexer": "ipython3",
951 | "version": "3.4.1"
952 | }
953 | },
954 | "nbformat": 4,
955 | "nbformat_minor": 0
956 | }
957 |
--------------------------------------------------------------------------------
/03_Parameters.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "#3. Parameters"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "The word \"parameters\" is used in many settings. When discussing a Pyomo model, we use the word to refer to data that must be provided in order to find an optimal (or good) assignment of values to the decision variables. Parameters are declared with the Param function, which takes arguments that are somewhat similar to the Set function. For example, the following code snippet declares sets model.A, model.B and then a parameter array model.P that is indexed by model.A:"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "metadata": {
21 | "collapsed": false
22 | },
23 | "outputs": [
24 | {
25 | "ename": "NameError",
26 | "evalue": "name 'Set' is not defined",
27 | "output_type": "error",
28 | "traceback": [
29 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
30 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
31 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mSet\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mB\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mSet\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mP\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mParam\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mB\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
32 | "\u001b[0;31mNameError\u001b[0m: name 'Set' is not defined"
33 | ]
34 | }
35 | ],
36 | "source": [
37 | "model.A = Set()\n",
38 | "model.B = Set()\n",
39 | "model.P = Param(model.A, model.B)"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {},
45 | "source": [
46 | "In addition to sets that serve as indexes, the Param function takes the following command options:\n",
47 | "\n",
48 | "- default = The value absent any other specification.\n",
49 | "\n",
50 | "- doc = String describing the parameter\n",
51 | "\n",
52 | "- initialize = A function (or Python object) that returns the members to initialize the parameter values.\n",
53 | "\n",
54 | "- validate = A boolean function with arguments that are the prospective parameter value, the parameter indices and the model.\n",
55 | "\n",
56 | "- within = Set used for validation; it specifies the domain of the parameter values.\n",
57 | "\n",
58 | "These options perform in the same way as they do for Set. For example, suppose that Model.A = RangeSet(1,3), then there are many ways to create a parameter that is a square matrix with 9, 16, 25 on the main diagonal zeros elsewhere, here are two ways to do it. First using a Python object to initialize:"
59 | ]
60 | },
61 | {
62 | "cell_type": "code",
63 | "execution_count": 3,
64 | "metadata": {
65 | "collapsed": false
66 | },
67 | "outputs": [
68 | {
69 | "ename": "NameError",
70 | "evalue": "name 'Param' is not defined",
71 | "output_type": "error",
72 | "traceback": [
73 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
74 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
75 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m16\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m25\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mS\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mParam\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minitialize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefault\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
76 | "\u001b[0;31mNameError\u001b[0m: name 'Param' is not defined"
77 | ]
78 | }
79 | ],
80 | "source": [
81 | "v={}\n",
82 | "v[1,1] = 9\n",
83 | "v[2,2] = 16\n",
84 | "v[3,3] = 25\n",
85 | "model.S = Param(model.A, model.A, initialize=v, default=0)"
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {},
91 | "source": [
92 | "And now using an initialization function that is automatically called once for each index tuple (remember that we are assuming that model.A contains 1,2,3)"
93 | ]
94 | },
95 | {
96 | "cell_type": "code",
97 | "execution_count": 4,
98 | "metadata": {
99 | "collapsed": false
100 | },
101 | "outputs": [
102 | {
103 | "ename": "NameError",
104 | "evalue": "name 'Param' is not defined",
105 | "output_type": "error",
106 | "traceback": [
107 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
108 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
109 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;36m0.0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mS\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mParam\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minitialize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0ms_init\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
110 | "\u001b[0;31mNameError\u001b[0m: name 'Param' is not defined"
111 | ]
112 | }
113 | ],
114 | "source": [
115 | "def s_init(model, i, j):\n",
116 | " if i == j:\n",
117 | " return i*i\n",
118 | " else:\n",
119 | " return 0.0\n",
120 | "model.S = Param(model.A, model.A, initialize=s_init)"
121 | ]
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "metadata": {},
126 | "source": [
127 | "In this example, the index set contained integers, but index sets need not be numeric. It is very common to use strings.\n",
128 | "\n",
129 | ">#####Note:\n",
130 | ">Data specified in an input file will override the data specified by the initialize options.\n",
131 | "\n",
132 | "Parameter values can be checked by a validation function. In the following example, the parameter S indexed by model.A and checked to be greater than 3.14159. If value is provided that is less than that, the model instantation would be terminated and an error message issued. The function used to validate should be written so as to return True if the data is valid and False otherwise."
133 | ]
134 | },
135 | {
136 | "cell_type": "code",
137 | "execution_count": 5,
138 | "metadata": {
139 | "collapsed": false
140 | },
141 | "outputs": [
142 | {
143 | "ename": "NameError",
144 | "evalue": "name 'Param' is not defined",
145 | "output_type": "error",
146 | "traceback": [
147 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
148 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
149 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0ms_validate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mv\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m3.14159\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mS\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mParam\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalidate\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0ms_validate\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
150 | "\u001b[0;31mNameError\u001b[0m: name 'Param' is not defined"
151 | ]
152 | }
153 | ],
154 | "source": [
155 | "def s_validate(model, v, i):\n",
156 | " return v > 3.14159\n",
157 | "model.S = Param(model.A, validate=s_validate)"
158 | ]
159 | }
160 | ],
161 | "metadata": {
162 | "kernelspec": {
163 | "display_name": "Python 3",
164 | "language": "python",
165 | "name": "python3"
166 | },
167 | "language_info": {
168 | "codemirror_mode": {
169 | "name": "ipython",
170 | "version": 3
171 | },
172 | "file_extension": ".py",
173 | "mimetype": "text/x-python",
174 | "name": "python",
175 | "nbconvert_exporter": "python",
176 | "pygments_lexer": "ipython3",
177 | "version": "3.4.3"
178 | }
179 | },
180 | "nbformat": 4,
181 | "nbformat_minor": 0
182 | }
183 |
--------------------------------------------------------------------------------
/04_Variables.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "#4. Variables"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "Variables are intended to ultimately be given values by an optimization package. They are declared and optionally bounded, given initial values, and documented using the Pyomo Var function. If index sets are given as arguments to this function they are used to index the variable, other optional directives include:\n",
15 | "\n",
16 | "- bounds = A function (or Python object) that gives a (lower,upper) bound pair for the variable\n",
17 | "\n",
18 | "- domain = A set that is a super-set of the values the variable can take on.\n",
19 | "\n",
20 | "- initialize = A function (or Python object) that gives a starting value for the variable; this is particularly important for non-linear models\n",
21 | "\n",
22 | "- within = (synonym for domain)\n",
23 | "\n",
24 | "The following code snippet illustrates some aspects of these options by declaring a *singleton* (i.e. unindexed) variable named model.LumberJack that will take on real values between zero and 6 and it initialized to be 1.5:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": 1,
30 | "metadata": {
31 | "collapsed": false
32 | },
33 | "outputs": [
34 | {
35 | "ename": "NameError",
36 | "evalue": "name 'Var' is not defined",
37 | "output_type": "error",
38 | "traceback": [
39 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
40 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
41 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mLumberJack\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mVar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwithin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mNonNegativeReals\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbounds\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minitialize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1.5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
42 | "\u001b[0;31mNameError\u001b[0m: name 'Var' is not defined"
43 | ]
44 | }
45 | ],
46 | "source": [
47 | "model.LumberJack = Var(within=NonNegativeReals, bounds=(0,6), initialize=1.5)\n"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "metadata": {},
53 | "source": [
54 | "Instead of the initialize option, initialization is sometimes done with a Python assignment statement as in"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": 2,
60 | "metadata": {
61 | "collapsed": false
62 | },
63 | "outputs": [
64 | {
65 | "ename": "NameError",
66 | "evalue": "name 'model' is not defined",
67 | "output_type": "error",
68 | "traceback": [
69 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
70 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
71 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mLumberJack\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1.5\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
72 | "\u001b[0;31mNameError\u001b[0m: name 'model' is not defined"
73 | ]
74 | }
75 | ],
76 | "source": [
77 | "model.LumberJack = 1.5"
78 | ]
79 | },
80 | {
81 | "cell_type": "markdown",
82 | "metadata": {},
83 | "source": [
84 | "For indexed variables, bounds and initial values are often specified by a rule (a Python function) that itself may make reference to parameters or other data. The formal arguments to these rules begins with the model followed by the indexes. This is illustrated in the following code snippet that makes use of Python dictionaries declared as lb and ub that are used by a function to provide bounds:"
85 | ]
86 | },
87 | {
88 | "cell_type": "code",
89 | "execution_count": 3,
90 | "metadata": {
91 | "collapsed": false
92 | },
93 | "outputs": [
94 | {
95 | "ename": "SyntaxError",
96 | "evalue": "invalid syntax (, line 2)",
97 | "output_type": "error",
98 | "traceback": [
99 | "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m lb = {'Scones':2, 'Tea':4}\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
100 | ]
101 | }
102 | ],
103 | "source": [
104 | "model.A = Set(initialize=['Scones', 'Tea']\n",
105 | "lb = {'Scones':2, 'Tea':4}\n",
106 | "ub = {'Scones':5, 'Tea':7}\n",
107 | "def fb(model, i):\n",
108 | " return (lb[i], ub[i])\n",
109 | "model.PriceToCharge = Var(model.A, domain=PositiveInteger, bounds=fb)"
110 | ]
111 | },
112 | {
113 | "cell_type": "markdown",
114 | "metadata": {},
115 | "source": [
116 | ">#####Note:\n",
117 | ">Many of the pre-defined virtual sets that are used as domains imply bounds. A strong example is the set Boolean that implies bounds of zero and one."
118 | ]
119 | }
120 | ],
121 | "metadata": {
122 | "kernelspec": {
123 | "display_name": "Python 3",
124 | "language": "python",
125 | "name": "python3"
126 | },
127 | "language_info": {
128 | "codemirror_mode": {
129 | "name": "ipython",
130 | "version": 3
131 | },
132 | "file_extension": ".py",
133 | "mimetype": "text/x-python",
134 | "name": "python",
135 | "nbconvert_exporter": "python",
136 | "pygments_lexer": "ipython3",
137 | "version": "3.4.3"
138 | }
139 | },
140 | "nbformat": 4,
141 | "nbformat_minor": 0
142 | }
143 |
--------------------------------------------------------------------------------
/05_Objectives.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "#8. Objectives"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "An objective is a function of variables that returns a value that an optimization package attempts to maximize or minimize. The Objective function in Pyomo declares an objective. Although other mechanisms are possible, this function is typically passed the name of another function that gives the expression. Here is a very simple version of such a function that assumes model.x has previously been declared as a Var:"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 1,
20 | "metadata": {
21 | "collapsed": false
22 | },
23 | "outputs": [
24 | {
25 | "ename": "NameError",
26 | "evalue": "name 'Objective' is not defined",
27 | "output_type": "error",
28 | "traceback": [
29 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
30 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
31 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mObjRule\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mObjective\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrule\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mObjRule\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
32 | "\u001b[0;31mNameError\u001b[0m: name 'Objective' is not defined"
33 | ]
34 | }
35 | ],
36 | "source": [
37 | "def ObjRule(model):\n",
38 | " return 2*model.x[1] + 3*model.x[2]\n",
39 | "model.g = Objective(rule=ObjRule)"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {},
45 | "source": [
46 | "It is more common for an objective function to refer to parameters as in this example that assumes that model.p has been declared as a parameters and that model.x has been declared with the same index set, while model.y has been declared as a singleton:"
47 | ]
48 | },
49 | {
50 | "cell_type": "code",
51 | "execution_count": 2,
52 | "metadata": {
53 | "collapsed": false
54 | },
55 | "outputs": [
56 | {
57 | "ename": "NameError",
58 | "evalue": "name 'Objective' is not defined",
59 | "output_type": "error",
60 | "traceback": [
61 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
62 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
63 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mprofrul\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msummation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mObj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mObjective\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrule\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mObjRule\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msense\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmaximize\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
64 | "\u001b[0;31mNameError\u001b[0m: name 'Objective' is not defined"
65 | ]
66 | }
67 | ],
68 | "source": [
69 | "def profrul(model):\n",
70 | " return summation(model.p, model.x) + model.y\n",
71 | "model.Obj = Objective(rule=ObjRule, sense=maximize)"
72 | ]
73 | },
74 | {
75 | "cell_type": "markdown",
76 | "metadata": {},
77 | "source": [
78 | "This example uses the sense option to specify maximization. The default sense is minimize."
79 | ]
80 | }
81 | ],
82 | "metadata": {
83 | "kernelspec": {
84 | "display_name": "Python 3",
85 | "language": "python",
86 | "name": "python3"
87 | },
88 | "language_info": {
89 | "codemirror_mode": {
90 | "name": "ipython",
91 | "version": 3
92 | },
93 | "file_extension": ".py",
94 | "mimetype": "text/x-python",
95 | "name": "python",
96 | "nbconvert_exporter": "python",
97 | "pygments_lexer": "ipython3",
98 | "version": "3.4.3"
99 | }
100 | },
101 | "nbformat": 4,
102 | "nbformat_minor": 0
103 | }
104 |
--------------------------------------------------------------------------------
/06_Constraints.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "#9. Constraints"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "Most constraints are specified using equality or inequality expressions that are created using a rule, which is a Python function. For example, if the variable model.x has the indexes *butter* and *scones*, then this constraint limits the sum for them to be exactly three:"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 5,
20 | "metadata": {
21 | "collapsed": false
22 | },
23 | "outputs": [
24 | {
25 | "ename": "SyntaxError",
26 | "evalue": "invalid syntax (, line 3)",
27 | "output_type": "error",
28 | "traceback": [
29 | "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m3\u001b[0m\n\u001b[0;31m model.TeaConst = Constraint, rule=teaOKrule)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
30 | ]
31 | }
32 | ],
33 | "source": [
34 | "def teaOKrule(model):\n",
35 | " return(model.x['butter'] + model.x['scones'] == 3)\n",
36 | "model.TeaConst = Constraint, rule=teaOKrule)"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {},
42 | "source": [
43 | "Instead of expressions involving equality (==) or inequalities (<= or >=), constraints can also be expressed using a 3-tuple if the form (lb, expr, ub) where lb and ub can be None, which is interpreted as lb <= expr <= ub. Variables can appear only in the middle expr. For example, the following two constraint declarations have the same meaning:"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 6,
49 | "metadata": {
50 | "collapsed": false
51 | },
52 | "outputs": [
53 | {
54 | "ename": "NameError",
55 | "evalue": "name 'Var' is not defined",
56 | "output_type": "error",
57 | "traceback": [
58 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
59 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
60 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mVar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0maRule\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mBoundx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mConstraint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrule\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0maRule\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
61 | "\u001b[0;31mNameError\u001b[0m: name 'Var' is not defined"
62 | ]
63 | }
64 | ],
65 | "source": [
66 | "model.x = Var()\n",
67 | "\n",
68 | "def aRule(model):\n",
69 | " return model.x >= 2\n",
70 | "Boundx = Constraint(rule=aRule)\n",
71 | "\n",
72 | "def bRule(model):\n",
73 | " return (2, model.x, None)\n",
74 | "Boundx = Constraint(rule=bRule)"
75 | ]
76 | },
77 | {
78 | "cell_type": "markdown",
79 | "metadata": {},
80 | "source": [
81 | "For this simple example, it would also be possible to declare model.x with a bound option to accomplish the same thing.\n",
82 | "\n",
83 | "Constraints (and objectives) can be indexed by lists or sets. When the declaration contains lists or sets as arguments, the elements are iteratively passed to the rule function. If there is more than one, then the cross product is sent. For example the following constraint could be interpreted as placing a budget of $i$ on the $i th$ item to buy where the cost per item is given by the parameter model.a:"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": 7,
89 | "metadata": {
90 | "collapsed": false
91 | },
92 | "outputs": [
93 | {
94 | "ename": "NameError",
95 | "evalue": "name 'RangeSet' is not defined",
96 | "output_type": "error",
97 | "traceback": [
98 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
99 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
100 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mRangeSet\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mParam\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwithin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mPostiveReals\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mToBuy\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mVar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mA\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mbud_rule\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mToBuy\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
101 | "\u001b[0;31mNameError\u001b[0m: name 'RangeSet' is not defined"
102 | ]
103 | }
104 | ],
105 | "source": [
106 | "model.A = RangeSet(1,10)\n",
107 | "model.a = Param(model.A, within=PostiveReals)\n",
108 | "model.ToBuy = Var(model.A)\n",
109 | "def bud_rule(model, i):\n",
110 | " return model.a[i]*model.ToBuy[i] <= i\n",
111 | "aBudget = Constraint(model.A)"
112 | ]
113 | },
114 | {
115 | "cell_type": "markdown",
116 | "metadata": {},
117 | "source": [
118 | ">#####Note:\n",
119 | ">Python and Pyomo are case sensitive so model.a is not the same as model.A."
120 | ]
121 | }
122 | ],
123 | "metadata": {
124 | "kernelspec": {
125 | "display_name": "Python 3",
126 | "language": "python",
127 | "name": "python3"
128 | },
129 | "language_info": {
130 | "codemirror_mode": {
131 | "name": "ipython",
132 | "version": 3
133 | },
134 | "file_extension": ".py",
135 | "mimetype": "text/x-python",
136 | "name": "python",
137 | "nbconvert_exporter": "python",
138 | "pygments_lexer": "ipython3",
139 | "version": "3.4.3"
140 | }
141 | },
142 | "nbformat": 4,
143 | "nbformat_minor": 0
144 | }
145 |
--------------------------------------------------------------------------------
/07_Expressions.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "#7. Expressions"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "In this chapter, we use the word “expression” is two ways: first in the general sense of the word and second to desribe a class of Pyomo objects that have the name expression as described in the subsection on expression objects.\n",
15 | "\n",
16 | "###7.1. Rules to Generate Expressions\n",
17 | "Both objectives and constraints make use of rules to generate expressions. These are Python functions that return the appropriate expression. These are first-class functions that can access global data as well as data passed in, including the model object.\n",
18 | "\n",
19 | "Operations on model elements results in expressions, which seems natural in expression like the constraints we have seen so far. It is also possible to build up expressions. The following example illustrates this along with a reference to global Pyton data in the form of a Python variable called switch:\n",
20 | "\n"
21 | ]
22 | },
23 | {
24 | "cell_type": "code",
25 | "execution_count": 1,
26 | "metadata": {
27 | "collapsed": false
28 | },
29 | "outputs": [
30 | {
31 | "ename": "SyntaxError",
32 | "evalue": "invalid syntax (, line 8)",
33 | "output_type": "error",
34 | "traceback": [
35 | "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m8\u001b[0m\n\u001b[0;31m def pi_rule(model)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
36 | ]
37 | }
38 | ],
39 | "source": [
40 | "switch = 3\n",
41 | "\n",
42 | "model.A = RangeSet(1, 10)\n",
43 | "model.c = Param(model.A)\n",
44 | "model.d = Param()\n",
45 | "model.x = Var(model.A, domain=Boolean)\n",
46 | "\n",
47 | "def pi_rule(model)\n",
48 | " accexpr = summation(model.c, model.x)\n",
49 | " if switch >= 2:\n",
50 | " accexpr = accexpr - model.d\n",
51 | " return accexpr >= 0.5\n",
52 | "PieSlice = Constraint(rule=pi_rule)"
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "metadata": {},
58 | "source": [
59 | "In this example, the constraint that is generated depends on the value of the Python variable called switch. If the value is 2 or greater, then the constraint is summation(model.c, model.x) - model.d >= 0.5; otherwise, the model.d term is not present.\n",
60 | "\n",
61 | ">####Caution:\n",
62 | ">Because model elements result in expressions, not values, the following does not work as expected in an abstract model!"
63 | ]
64 | },
65 | {
66 | "cell_type": "code",
67 | "execution_count": 2,
68 | "metadata": {
69 | "collapsed": false
70 | },
71 | "outputs": [
72 | {
73 | "ename": "SyntaxError",
74 | "evalue": "invalid syntax (, line 6)",
75 | "output_type": "error",
76 | "traceback": [
77 | "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m6\u001b[0m\n\u001b[0;31m def pi_rule(model)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
78 | ]
79 | }
80 | ],
81 | "source": [
82 | "model.A = RangeSet(1, 10)\n",
83 | "model.c = Param(model.A)\n",
84 | "model.d = Param()\n",
85 | "model.x = Var(model.A, domain=Boolean)\n",
86 | "\n",
87 | "def pi_rule(model)\n",
88 | " accexpr = summation(model.c, model.x)\n",
89 | " if model.d >= 2: # NOT in an abstract model!!\n",
90 | " accexpr = accexpr - model.d\n",
91 | " return accexpr >= 0.5\n",
92 | "PieSlice = Constraint(rule=pi_rule)"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {},
98 | "source": [
99 | "The trouble is that model.d >= 2 results in an expression, not its evaluated value. Instead use if value(model.d) >= 2\n",
100 | "\n",
101 | "##7.2 Piecewise Linear Expressions\n",
102 | "\n",
103 | "Pyomo has facilities to add piecewise constraints of the form y=f(x) for a variety of forms of the function f.\n",
104 | "\n",
105 | "The piecewise types other than SOS2, BIGM_SOS1, BIGM_BIN are implement as described in the paper [Vielma_et_al](https://software.sandia.gov/downloads/pub/pyomo/PyomoOnlineDocs.html#Vielma_et_al).\n",
106 | "\n",
107 | "There are two basic forms for the declaration of the constraint:"
108 | ]
109 | },
110 | {
111 | "cell_type": "code",
112 | "execution_count": 3,
113 | "metadata": {
114 | "collapsed": false
115 | },
116 | "outputs": [
117 | {
118 | "ename": "NameError",
119 | "evalue": "name 'Piecewise' is not defined",
120 | "output_type": "error",
121 | "traceback": [
122 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
123 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
124 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpwconst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPiecewise\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindexes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0myvar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxvar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mKeywords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpwconst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPiecewise\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0myvar\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mxvar\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mKeywords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
125 | "\u001b[0;31mNameError\u001b[0m: name 'Piecewise' is not defined"
126 | ]
127 | }
128 | ],
129 | "source": [
130 | "model.pwconst = Piecewise(indexes, yvar, xvar, **Keywords)\n",
131 | "model.pwconst = Piecewise(yvar,xvar,**Keywords)"
132 | ]
133 | },
134 | {
135 | "cell_type": "markdown",
136 | "metadata": {},
137 | "source": [
138 | "where pwconst can be replaced by a name appropriate for the application. The choice depends on whether the x and y variables are indexed. If so, they must have the same index sets and these sets are give as the first arguments.\n",
139 | "\n",
140 | "###Keywords:\n",
141 | "- pw_pts={},[],() A dictionary of lists (keys are index set) or a single list (for the non-indexed case or when an identical set of breakpoints is used across all indices) defining the set of domain breakpoints for the piecewise linear function. NOTE: pw_pts is always required. These give the breakpoints for the piecewise function and are expected to full span the bounds for the independent variable(s).\n",
142 | "\n",
143 | "- pw_repn=