# source:coopr.doc/trunk/GettingStarted/current/pyomo.txt@5779

Last change on this file since 5779 was 5779, checked in by dlwoodr, 22 months ago

added info about getting solution status in a script; did a temporary fix of some formatting problems in pysp

File size: 37.7 KB
Line
1== Pyomo Overview  ==
2
3=== Mathematical Modeling ===
4
5This chapter provides an introduction to Pyomo: Python Optimization Modeling Objects.
6A more complete description is contained in <<PyomoBook>>. Pyomo
7supports the formulation and analysis of mathematical models for complex
8optimization applications.  This capability is commonly associated with
9algebraic modeling languages (AMLs) such as AMPL <<AMPL>> AIMMS <<AIMMS>>
10and GAMS <<GAMS>>.  Pyomo's modeling objects are embedded within Python, a
11full-featured high-level programming language that contains a rich set of
12supporting libraries.
13
14Modeling is a fundamental process in many aspects of scientific research,
15engineering and business.  Modeling involves the formulation of a simplified
16representation of a system or real-world object.  Thus, modeling tools like
17Pyomo can be used in a variety of ways:
18
19- *Explain phenomena* that arise in a system,
20
21- *Make predictions* about future states of a system,
22
23- *Assess key factors* that influence phenomena in a system,
24
25- *Identify extreme states* in a system, that might represent worst-case scenarios or
26 minimal cost plans, and
27
28- *Analyze trade-offs* to support human decision makers.
29
30Mathematical models represent system knowledge with a formalized
31mathematical language.
32The following mathematical concepts are central to modern
33modeling activities:
34
35variables::
36    Variables represent unknown or changing parts of a model (e.g. whether or not to make a decision, or the characteristic of a system outcome). The values taken by the variables are often referred to as a _solution_ and are usually an output of the optimization process.
37
38parameters::
39    Parameters represents the data that must be supplied to perform the optimization. In fact, in some settings the word _data_ is used in place of the word _parameters_.
40
41relations::
42    These are equations, inequalities or other mathematical relationships that define how different parts of a model are connected to each other.
43
44goals::
45    These are functions that reflect goals and objectives for the system being modeled.
46
48numerical analysis of mathematical models a commonplace activity.
49Without a modeling language, the process of setting up input files,
50executing a solver and extracting the final results from the solver
51output is tedious and error prone.  This difficulty is compounded
52in complex, large-scale real-world applications which are difficult
53to debug when errors occur.  Additionally, there are many different
54formats used by optimization software packages, and few formats are
55recognized by many optimizers.  Thus the application of multiple
56optimization solvers to analyze a model introduces additional
57complexities.
58
59Pyomo is an AML that extends Python to include objects for mathematical modeling.
60Hart et al. <<PyomoBook>>, <<PyomoJournal>> compare Pyomo with other AMLs.  Although many
61good AMLs have been developed for optimization models, the following are motivating
62factors for the development of Pyomo:
63
64Open Source::
65  Pyomo is developed within Coopr's open source project to promote transparency of the modeling framework and encourage community development of Pyomo capabilities.
66
67Customizable Capability::
68  Pyomo supports a customizable capability through the extensive use of plug-ins to modularize software components.
69
70Solver Integration::
71  Pyomo models can be optimized with solvers that are written either in Python or in compiled, low-level languages.
72
73Programming Language::
74  Pyomo leverages a high-level programming language, which has several advantages over custom AMLs:  a very robust language, extensive documentation, a rich set of standard libraries, support for modern programming features like classes and functions, and portability to many platforms.
75
76
77=== Overview of Modeling Components and Processes ===
78
79Pyomo supports an object-oriented design for the definition of
80optimization models.  The basic steps of a simple modeling process
81are:
82
83* Create model and declare components
84* Instantiate the model
85* Apply solver
86* Interrogate solver results
87
88In practice, these steps may be applied repeatedly with different
89data or with different constraints applied to the model.  However,
90we focus on this simple modeling process to illustrate different
91strategies for modeling with Pyomo.
92
93A Pyomo _model_ consists of a collection of
94modeling _components_ that define different aspects of the model.
95Pyomo includes the modeling components that are commonly
96supported by modern AMLs:  index sets, symbolic parameters, decision
97variables, objectives, and constraints.
98These modeling components are defined in Pyomo through the following Python classes:
99
100Set::
101  set data that is used to define a model instance
102
103Param::
104  parameter data that is used to define a model instance
105
106Var::
107  decision variables in a model
108
109Objective::
110  expressions that are minimized or maximized in a model
111
112Constraint::
113  constraint expressions that impose restrictions on variable values in a model
114
115=== Abstract Versus Concrete Models ===
116
117A mathematical model can be defined using symbols that represent data values.
118For example, the following equations represent a linear program
119(LP) to find optimal values for the vector latexmath:[$x$] with parameters latexmath:[$n$] and latexmath:[$b$], and parameter vectors latexmath:[$a$] and latexmath:[$c$]:
120[latexmath]
121++++++++++++++
122\begin{array}{lll}
123\min       & \sum_{j=1}^n c_j x_j &\\
124\mathrm{s.t.} & \sum_{j=1}^n a_{ij} x_j \geq b_i & \forall i = 1 \ldots m\\
125           & x_j \geq 0 & \forall j = 1 \ldots n
126\end{array}
127++++++++++++++
128NOTE: As a convenience, we use the symbol latexmath:[$\forall$] to mean for all'' or for each.''
129
130We call this an _abstract_ or _symbolic_ mathematical model since it relies on
131unspecified parameter values.  Data values can be used to specify a _model instance_.
132The +AbstractModel+ class provides a context for defining and initializing abstract
133optimization models in Pyomo when the data values will be supplied at the time a solution
134is to be obtained.
135
136In some contexts a mathematical model can be directly defined
137with the data values supplied at the time of the model definition and built into the model.
138We call these _concrete_ mathematical models.
139For example, the following LP model is a concrete instance of the previous abstract model:
140[latexmath]
141++++++++++++++
142\begin{array}{ll}
143\min       & 2 x_1 + 3 x_2\\
144\mathrm{s.t.} & 3 x_1 + 4 x_2 \geq 1\\
145           & x_1, x_2 \geq 0
146\end{array}
147++++++++++++++
148The +ConcreteModel+ class is used to define concrete
149optimization models in Pyomo.
150
151=== A Simple Abstract Pyomo Model ===
152
153We repeat the abstract model already given:
154[latexmath]
155++++++++++++++
156\begin{array}{lll}
157\min       & \sum_{j=1}^n c_j x_j &\\
158\mathrm{s.t.} & \sum_{j=1}^n a_{ij} x_j \geq b_i & \forall i = 1 \ldots m\\
159           & x_j \geq 0 & \forall j = 1 \ldots n
160\end{array}
161++++++++++++++
162
163One way to implement this in Pyomo is as follows:
164----
165include::examples/CooprGettingStarted/abstract1.py[]
166----
167
168NOTE: Python is interpreted one line at a time and if statements need to span a line
169for some reason then a line continuation character, which is backslash, must be used. In Python, indentation has meaning and must
170be consistent. Lines inside a function definition, for example, must be indented and the end of the indentation is used by Python
171to signal the end of the definition.
172
173We will now examine the lines in this example beginning with the import line
174that is required in every Pyomo model. Its purpose is to make the symbols used by Pyomo known to Python.
175----
176from coopr.pyomo import *
177----
178
179The 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.
180----
181model = AbstractModel()
182----
183
184We declare the parameters latexmath:[$m$] and latexmath:[$n$] using the Pyomo +Param+ function. This function can take a
185variety of arguments; this example illustrates use of the +within+ option that is used by Pyomo to validate the
186data value that is assigned to the parameter. If this option were not given, then Pyomo would not object to any type of data being
187assigned to these parameters. As it is, assignment of a value that is not a non-negative integer will result in an error.
188----
189model.m = Param(within=NonNegativeIntegers)
190model.n = Param(within=NonNegativeIntegers)
191----
192
193Although not required, it is convenient to define index sets. In this example we use the +RangeSet+ function to
194declare that the sets will be a sequence of integers starting at 1 and ending at a value specified by the the parameters
195+model.m+ and +model.n+.
196----
197model.I = RangeSet(1, model.m)
198model.J = RangeSet(1, model.n)
199----
200
201The coefficient and right-hand-side data are defined as indexed parameters. When sets are given as arguments to the
202+Param+ function, they indicate that the set will index the parameter.
203----
204model.a = Param(model.I, model.J)
205model.b = Param(model.I)
206model.c = Param(model.J)
207----
208
209NOTE: In Python, and therefore in Pyomo, any text after pound sign is considered to be a comment.
210
211The next line
212interpreted by Python as part of the model declares the variable latexmath:[$x$]. The first argument to the
213+Var+ function is a set, so it is defined as an index set for the variable. In this case the variable
214has only one index set, but multiple sets could be used as was the case for the declaration of the
215parameter +model.a+. The second argument specifies a domain for the variable. This information is part of the model
216and will passed to the solver when data is provided and the model is solved. Specification of the
217+NonNegativeReals+ domain implements the requirement that the variables be greater than or equal to zero.
218----
219# the next line declares a variable indexed by the set J
220model.x = Var(model.J, domain=NonNegativeReals)
221----
222
223In abstract models, Pyomo expressions are usually provided to objective function and constraint declarations via a function
224defined with a
225Python +def+ statement. The +def+ statement establishes a name for a function along with its arguments. When
226Pyomo uses a function to get objective function or constraint expressions, it always passes in the model (i.e., itself) as the
227the first argument so the model is always the first formal argument when declaring such functions in Pyomo. Additional arguments,
228if needed, follow. Since summation is an extremely common part of optimization models, Pyomo provides a flexible function to
229accommodate 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
230only works, of course, if the two arguments have the same indexes. If it is given only one argument it returns an expression for
231the 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 latexmath:[$\sum_{j=1}^{n}c_{j} x_{j}$].
232----
233def obj_expression(model):
234    return summation(model.c, model.x)
235----
236
237To declare an objective function, the Pyomo function called +Objective+ is used. The +rule+ argument
238gives the name of a function that returns the expression to be used. The default _sense_ is minimization. For
239maximization, the +sense=maximize+ argument must be used. The name that is declared, which is +OBJ+ in this
240case, appears in some reports and can be almost any name.
241----
242model.OBJ = Objective(rule=obj_expression)
243----
244
245Declaration of constraints is similar. A function is declared to deliver the constraint expression. In this case, there can be
246multiple constraints of the same form because we index the constraints by latexmath:[$i$] in the expression
247latexmath:[$\sum_{j=1}^n a_{ij} x_j \geq b_i \;\;\forall i = 1 \ldots m$], which states that we need a constraint
248for each value of latexmath:[$i$] from one to latexmath:[$m$]. In order to parametrize the expression by latexmath:[$i$] we
249include it as a formal parameter to the function that declares the constraint expression. Technically, we could have used anything for
250this argument, but that might be confusing. Using an +i+ for an latexmath:[$i$] seems sensible in this situation.
251----
252def ax_constraint_rule(model, i):
253    # return the expression for the constraint for i
254    return sum(model.a[i,j] * model.x[j] for j in model.J) >= model.b[i]
255----
256NOTE: In Python, indexes are in square brackets and function arguments are in parentheses.
257
258In order to declare constraints that use this expression, we use the Pyomo +Constraint+ function
259that takes a variety of arguments. In this case, our model specifies that we can have more than one constraint
260of the same form and we have created a set, +model.I+, over which these constraints can be indexed so
261that is the first argument to the constraint declaration function. The next argument gives the rule that will be used to generate
262expressions for the constraints. Taken as a whole, this constraint declaration says that a list of constraints indexed
263by the set +model.I+ will be created and for each member of +model.I+, the function +ax_constraint_rule+ will be
264called and it will be passed the model object as well as the member of +model.I+.
265----
266# the next line creates one constraint for each member of the set model.I
267model.AxbConstraint = Constraint(model.I, rule=ax_constraint_rule)
268----
269
270In 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
271+Set+ object that is contained by this model.
272Many modeling components in Pyomo can be optionally specified as _indexed_ _components_:
273collections of components that are referenced using one or more values.
274In this example, the parameter +model.c+ is indexed
275with set +model.J+.
276
277In order to use this model, data must be given for the values of the parameters. Here is one file that
278provides data.
279----
280include::examples/CooprGettingStarted/abstract1.dat[]
281----
282
283There are multiple formats that can be used to provide data to a Pyomo model, but the AMPL format works well
284for our purposes because it contains the names of the data elements together with the data. In AMPL data files,
285text after a pound sign is treated as a comment. Lines generally do not matter, but statements must be terminated
286with a semi-colon.
287
288For this particular data file, there is one constraint, so the value of +model.m+ will be one and there are two
289variables (i.e., the vector +model.x+ is two elements long) so the value of +model.n+ will be two. These
290two assignments are accomplished with standard assignments. Notice that in AMPL format input, the name of the model is
291omitted.
292----
293param m := 1 ;
294param n := 2 ;
295----
296
297There is only one constraint, so only two values are needed for +model.a+. When assigning values to arrays and vectors in
298AMPL 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
2994. 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
300get 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
301+model.b+ is given on one line since that is easy to read.
302----
303param a :=
3041 1 3
3051 2 4
306;
307
308param c:=
3091 2
3102 3
311;
312
313param b := 1 1 ;
314----
315// vim:set syntax=asciidoc:
316
317When working with Pyomo (or any other AML), it is convenient to write abstract models in a somewhat more
318abstract way by using index sets that contain strings rather than index sets that are implied by
319latexmath:[$1,\ldots,m$] or the summation from 1 to latexmath:[$n$]. When this is done, the size of the set
320is implied by the input, rather than specified directly. Furthermore, the index entries may have no real order.
321Often, a mixture of integers and indexes and strings as indexes is needed in the same model. To start with
322an illustration of general indexes, consider a slightly different Pyomo implementation of the model we just presented.
323----
324include::examples/CooprGettingStarted/abstract2.py[]
325----
326
327To get the same instantiated model, the following data file can be used.
328----
329include::examples/CooprGettingStarted/abstract2a.dat[]
330----
331
332However, this model can also be fed different data for problems of the same general form using meaningful indexes.
333----
334include::examples/CooprGettingStarted/abstract2.dat[]
335----
336
337=== A Simple Concrete Pyomo Model ===
338
339It is possible to get nearly the same flexible behavior from models declared to be abstract and models
340declared to be concrete in Pyomo; however, we will focus on a straightforward concrete example here where
341the data is hard-wired into the model file. Python programmers will quickly realize that the
342data could have come from other sources.
343
344We repeat the concrete model already given:
345[latexmath]
346++++++++++++++
347\begin{array}{ll}
348\min       & 2 x_1 + 3 x_2\\
349\mathrm{s.t.} & 3 x_1 + 4 x_2 \geq 1\\
350           & x_1, x_2 \geq 0
351\end{array}
352++++++++++++++
353
354This is implemented as a concrete model as follows:
355----
356include::examples/CooprGettingStarted/concrete1.py[]
357----
358
359Although 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.
360
361=== Solving the Simple Examples ===
362
363Pyomo supports modeling and scripting but does not install a solver
364automatically. In order to solve a model, there must be a solver installed
365on the computer to be used. If there is a solver, then the +pyomo+
366command can be used to solve a problem instance.
367
368Suppose 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:
369----
370pyomo abstract1.py abstract1.dat --solver=glpk
371----
372Since glpk is the default solver, there really is no need specify it so the
373+--solver+ option can be dropped.
374
375NOTE: There are two dashes before the command line option names such as
376+solver+.
377
378To continue the example, if CPLEX is installed then it can be listed as the solver. The command to solve with
379CPLEX is
380----
381pyomo abstract1.py abstract1.dat --solver=cplex
382----
383This yields the following output on the screen:
384----
385[    0.00] Setting up Pyomo environment
386[    0.00] Applying Pyomo preprocessing actions
387[    0.07] Creating model
388[    0.15] Applying solver
389[    0.37] Processing results
390    Number of solutions: 1
391    Solution Information
392      Gap: 0.0
393      Status: optimal
394      Function Value: 0.666666666667
395    Solver results file: results.json
396[    0.39] Applying Pyomo postprocessing actions
397[    0.39] Pyomo Finished
398----
399The numbers is square brackets indicate how much time was required for each step. Results are written to the file named +results.json+, which
400has a special structure that makes it useful for post-processing. To see a summary of results written to the screen, use the
401+--summary+ option:
402----
403pyomo abstract1.py abstract1.dat --solver=cplex --summary
404----
405To see a list of Pyomo command line options, use:
406----
407pyomo --help
408----
409NOTE: There are two dashes before +help+.
410
411For a concrete model, no data file is specified on the Pyomo command line.
412
413== Sets ==
414
415=== Declaration ===
416
417Sets can be declared using the +Set+ and +RangeSet+ functions or by
418assigning set expressions.  The simplest set declaration creates
419a set and postpones creation of its members:
420----
421model.A = Set()
422----
423
424The +Set+ function takes optional arguments such as:
425
426* doc = String describing the set
427* dimen = Dimension of the members of the set
428* filter = A boolean function used during construction to indicate if a potential new member should be assigned to the set
429* initialize = A function that returns the members to initialize the set.
430ordered = A boolean indicator that the set is ordered; the default is +False+
431* validate = A boolean function that validates new member data
432* virtual = A boolean indicator that the set will never have elements; it is unusual for a modeler to create a virtual set; they are typically used as domains for sets, parameters and variables
433* within = Set used for validation; it is a super-set of the set being declared.
434
435One way to create a set whose members will be two dimensional is to use
436the +dimen+ argument:
437----
438model.B = Set(dimen=2)
439----
440
441To create a set of all the numbers in set +model.A+ doubled, one could use
442----
443def doubleA_init(model):
444    return (i*2 for i in model.A)
445model.C = Set(initialize=DoubleA_init)
446----
447As an aside we note that as always in Python, there are lot
448of ways to accomplish the same thing. Also, note that this
449will generate an error if +model.A+ contains elements for
450which multiplication times two is not defined.
451
452The +initialize+ option can refer to a Python set, which can be returned by a function or given directly as in
453----
454model.D = Set(initialize=['red', 'green', 'blue'])
455----
456
457The +initialize+ option can also specify a
458function that is applied sequentially to generate set members. Consider the case of
459a simple set. In this case, the initialization
460function accepts a set element number and model and
461returns the set element associated with that number:
462----
463def Z_init(model, i):
464    if i > 10:
465        return Set.End
466    return 2*i+1
467model.Z = Set(initialize=Z_init)
468----
469The +Set.End+ return value terminates input to the set. Additional information about iterators for set initialization is
470in <<PyomoBook>>.
471
472NOTE: Data specified in an input file will override the data specified by the initialize options.
473
474If sets are given as arguments to +Set+ without keywords, they are interpreted as indexes for an array of sets. For example, to create an array of sets
475that is indexed by the members of the set +model.A+, use
476----
477model.E = Set(model.A)
478----
479
480Arguments can be combined. For example, to create an array of sets with three dimensional members indexed by set +model.A+, use
481----
482model.F = Set(model.A, dimen=3)
483----
484
485The +initialize+ option can be used to
486create a set that contains a sequence of numbers, but
487the +RangeSet+ function provides a concise mechanism for simple
488sequences. This function
489takes as its arguments a start value, a final value, and a
490step size. If the +RangeSet+ has only a single argument, then that value defines the final value in the sequence; the first value and step size default to one. If two values given, they are the first and last value in the sequence and the step size defaults to one. For
491example, the following declaration creates a set with the
492numbers 1.5, 5 and 8.5:
493----
494model.G = RangeSet(1.5, 10, 3.5)
495----
496
497=== Operations ===
498
499Sets may also be created by assigning other Pyomo sets as in these examples that also
500illustrate the set operators union, intersection, difference, and exclusive-or:
501----
502model.H = model.A
503model.I = model.A | model.D # union
504model.J = model.A & model.D # intersection
505model.K = model.A - model.D # difference
506model.L = model.A ^ model.D # exclusive-or
507----
508The cross-product operator is the asterisk (*). For example, to assign
509a set the cross product of two other sets, one could use
510----
511model.K = model.B * model.c
512----
513or to indicate the the members of a set are restricted to be
514in the cross product of two other sets, one could use
515----
516model.K = Set(within=model.B * model.C)
517----
518
519The cross-product operator is the asterisk (*).
520For example, to create a set that contains the cross-product
521of sets A and B, use
522----
523model.C = Set(model.A * model.B)
524----
525to instead create a set that can contain a subset of the members of this
526cross-product, use
527----
528model.C = Set(within=model.A * model.B)
529----
530
531
532=== Predefined Virtual Sets ===
533
534For use in specifying domains for sets, parameters and variables, Pyomo
535provides the following pre-defined virtual sets:
536
537* Any:  all possible values
538* Reals :  floating point values
539* PositiveReals:  strictly positive floating point values
540* NonPositiveReals:  non-positive floating point values
541* NegativeReals:  strictly negative floating point values
542* NonNegativeReals:  non-negative floating point values
543* PercentFraction:  floating point values in the interval [0,1]
544* Integers:  integer values
545* PositiveIntegers:  positive integer values
546* NonPositiveIntegers:  non-positive integer values
547* NegativeIntegers:  negative integer values
548* NonNegativeIntegers:  non-negative integer values
549* Boolean:  boolean values, which can be represented as False/True, 0/1, âFalseâ/âTrueâ and âFâ/âTâ
550* Binary: same as boolean
551
552For example, if the set +model.M+ is declared to be within the virtual set +NegativeIntegers+ then
553an attempt to add anything other than a negative integer will result in an error. Here
554is the declaration:
555----
556model.M = Set(within=NegativeIntegers)
557----
558
559=== Sparse Index Sets ===
560
561It is common for an index set to be used to index variables
562and parameters in a constraint as well as to index other index
563sets. For example, one may want to have a constraint that holds
564----
565for i in model.I, k in model.K, v in model.V[k]
566----
567
568There are many ways to accomplish this, but one good way
569is to create a set of tuples composed of all of +model.k, model.V[k]+ pairs.
570This can be done as follows:
571----
572def kv_init(model):
573    return ((k,v) for k in model.K for v in model.V[k])
574model.KV=Set(dimen=2, initialize=kv_init)
575----
576So then if there was a constraint defining rule such as
577----
578def MyC_rule(model, i, k, v):
579   return ...
580----
581Then a constraint could be declared using
582----
583model.MyConstraint = Constraint(model.I,model.KV,rule=c1Rule)
584----
585
586Here is the first few lines of a model that illustrates this:
587
588----
589from coopr.pyomo import *
590
591model = AbstractModel()
592
593model.I=Set()
594model.K=Set()
595model.V=Set(model.K)
596
597def kv_init(model):
598    return ((k,v) for k in model.K for v in model.V[k])
599model.KV=Set(dimen=2, initialize=kv_init)
600
601model.a = Param(model.I, model.K)
602
603model.y = Var(model.I)
604model.x = Var(model.I, model.KV)
605
606#include a constraint
607#x[i,k,v] <= a[i,k]*y[i], for i in model.I, k in model.K, v in model.V[k]
608
609def c1Rule(model,i,k,v):
610   return model.x[i,k,v] <= model.a[i,k]*model.y[i]
611model.c1 = Constraint(model.I,model.KV,rule=c1Rule)
612----
613
614== Parameters ==
615
616The word "parameters" is used in many settings. When discussing a Pyomo model, we use the word
617to refer to data that must be provided in order to find an optimal (or good) assignment of values
618to the decision variables. Parameters are declared with the +Param+ function, which takes arguments
619that are very similar to the +Set+ function. For example, the following code snippet declares sets
620+model.A+, +model.B+ and then a parameter array +model.P+ that is indexed by +model.A+:
621----
622model.A = Set()
623model.B = Set()
624model.P = Param(model.A, model.B)
625----
626
627In addition to sets that serve as indexes, the +Param+ function takes
628the following command options:
629
630* default = The value absent any other specification.
631* doc = String describing the parameter
632* initialize = A function (or Python object) that returns the members to initialize the parameter values.
633* rule = (this is a synonym for +initilize+)
634* validate = A boolean function with arguments that are the prospective parameter value, the parameter indices and the model.
635* within = Set used for validation; it specifies the domain of the parameter values.
636
637These options perform in the same way as they do for +Set+. For example,
638suppose 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:
639----
640v={}
641v[1,1] = 9
642v[2,2] = 16
643v[3,3] = 25
644model.S = Param(model.A, model.A, initialize=v, default=0)
645----
646And now using an initialization rule that is automatically called once for
647each index tuple (remember that we are assuming that +model.A+ contains
6481,2,3)
649----
650def s_init(model, i, j):
651    if i == j:
652        return i*i
653    else:
654        return 0.0
655model.S = Param(model.A, model.A, rule=s_init)
656----
657In this example, the index set contained integers, but index sets need not be numeric. It is very common to use strings.
658
659NOTE: Data specified in an input file will override the data specified by the initialize options.
660
661
662
663== Variables ==
664
665Variables are intended to ultimately be given values by an optimization package. The are
666declared and optionally bounded, given initial values, and documented using
667the Pyomo +Var+ function. If index sets are given as arguments to this function
668they are used to index the variable, other optional directives include:
669
670* bounds = A function (or Python object) that gives a (lower,upper) bound pair for the variable
671* domain = A set that is a super-set of the values the variable can take on.
672* initialize = A function (or Python object) that gives a starting value for the variable; this is particularly important for non-linear models
673* within = (synonym for +domain+)
674
675The following code snippet illustrates some aspects of these options by declaring a _singleton_ (i.e. unindexed) variable named +model.LumberJack+
676that will take on real values between zero and 6 and it initialized to be 1.5:
677----
678model.LumberJack = Var(within=NonNegativeReals, bounds=(0,6), initialize=1.5)
679----
680Instead of the +initialize+ option, initialization is sometimes done with a Python assignment statement
681as in
682----
683model.LumberJack = 1.5
684----
685
686For indexed variables, bounds and initial values are often specified by a rule (a Python function) that
687itself may make reference to parameters or other data. The formal arguments to these rules begins
688with the model followed by the indexes. This is illustrated in the following code snippet that
689makes use of Python dictionaries declared as lb and ub that are used by a function
690to provide bounds:
691----
692model.A = Set(initialize=['Scones', 'Tea']
693lb = {'Scones':2, 'Tea':4}
694ub = {'Scones':5, 'Tea':7}
695def fb(model, i):
696   return (lower[i], upper[i])
697model.PriceToCharge = Var(model.A, domain=PositiveInteger, bounds=fb)
698----
699
700NOTE: Many of the pre-defined virtual sets that are used as domains imply bounds. A strong
701example is the set +Boolean+ that implies bounds of zero and one.
702
703== Objectives ==
704
705An objective is a function of variables that returns a value that an optimization package
706attempts to maximize or minimize. The +Objective+ function in Pyomo declares
707an objective. Although other mechanisms are possible, this function is typically
708passed the name of another function that gives the expression.
709Here is a very simple version of such a function that assumes +model.x+ has
710previously been declared as a +Var+:
711----
712def ObjRule(model):
713    return 2*model.x[1] + 3*model.x[2]
714model.g = Objective(rule=ObjRule)
715----
716
717It is more common for an objective function to refer to parameters as in this example
718that assumes that +model.p+ has been declared as a parameters and that +model.x+ has been declared with
719the same index set, while +model.y+ has been declared as a singleton:
720----
721def profrul(model):
722   return summation(model.p, model.x) + model.y
723model.Obj = Objective(rule=ObjRule, sense=maximize)
724----
725This example uses the +sense+ option to specify maximization. The default sense is
726+minimize+.
727
728== Constraints ==
729
730Most constraints are specified using equality or inequality expressions
731that are created using a rule, which is a Python function. For example, if the variable
732+model.x+ has the indexes 'butter' and 'scones', then this constraint limits
733the sum for them to be exactly three:
734----
735def teaOKrule(model):
736    return(model.x['butter'] + model.x['scones'] == 3)
737model.TeaConst = Constraint, rule=teaOKrule)
738----
739
740Instead of expressions involving equality (==) or inequalities (<= or >=),
741constraints can also be expressed using a 3-tuple if the form (lb, expr, ub)
742where lb and ub can be +None+, which is interpreted as
743lb <= expr <= ub. Variables can appear only in the middle expr. For example,
744the following two constraint declarations have the same meaning:
745----
746model.x = Var()
747
748def aRule(model):
749   return model.x >= 2
750Boundx = Constraint(rule=aRule)
751
752def bRule(model):
753   return (2, model.x, None)
754Boundx = Constraint(rule=bRule)
755----
756For this simple example, it would also be possible to declare
757+model.x+ with a +bound+ option to accomplish the same thing.
758
759Constraints (and objectives) can be indexed by lists or sets. When
760the declaration contains lists or sets as arguments, the elements are iteratively
761passed to the rule function. If there is more than one, then the cross product
762is sent. For example the following constraint could be interpreted as
763placing a budget of latexmath:[$i$] on the latexmath:[$i^{\mbox{th}}$] item
764to buy where the cost per item is given by the parameter +model.a+:
765----
766model.A = RangeSet(1,10)
767model.a = Param(model.A, within=PostiveReals)
769def bud_rule(model, i):
771aBudget = Constraint(model.A)
772----
773
774NOTE: Python and Pyomo are case sensitive so +model.a+ is not the same
775as +model.A+.
776
777== Rules to Generate Expressions ==
778
779Both objectives and constraints make use of rules to generate
780expressions. These are Python functions that return the appropriate
781expression. These are first-class functions that can access
782global data as well as data passed in, including the model object.
783
784Operations on model elements results in expressions, which seems
785natural in expression like the constraints we have seen so far. It is also
786possible to build up expressions. The following example illustrates this along
787with a reference to global Pyton data in the form of a Python variable called +switch+:
788----
789switch = 3
790
791model.A = RangeSet(1, 10)
792model.c = Param(model.A)
793model.d = Param()
794model.x = Var(model.A, domain=Boolean)
795
796def pi_rule(model)
797    accexpr = summation(model.c, model.x)
798    if switch >= 2:
799        accexpr = accexpr - model.d
800    return accexpr >= 0.5
801PieSlice = Constraint(rule=pi_rule)
802----
803In this example, the constraint that is generated depends on the value
804of the Python variable called +switch+. If the value is 2 or greater, then
805the constraint is +summation(model.c, model.x) - model.d >= 0.5+; otherwise,
806the +model.d+ term is not present.
807
808CAUTION: Because model elements result in expressions, not values, the following
809does not work as expected in an abstract model!
810----
811model.A = RangeSet(1, 10)
812model.c = Param(model.A)
813model.d = Param()
814model.x = Var(model.A, domain=Boolean)
815
816def pi_rule(model)
817    accexpr = summation(model.c, model.x)
818    if model.d >= 2:  # NOT in an abstract model!!
819        accexpr = accexpr - model.d
820    return accexpr >= 0.5
821PieSlice = Constraint(rule=pi_rule)
822----
823The trouble is that +model.d >= 2+ results in an expression, not its evaluated value. Instead use +if value(model.d) >= 2+
824
825== Non-linear Expressions ==
826
827Pyomo supports non-linear expressions and can call non-linear solvers such as Ipopt.
828
829== Data Input ==
830
831For abstract models, Pyomo supports data input from a data command file or using ModelData object.
832
833=== Data Command Files ===
834The syntax of a data command files is based on AMPLâs data commands. Often, however, the data command
835file refers to files in other formats.
836
837Here are the commands of interest to us that can be used in data command files:
838
839â¢ +set+ declares set data.
840â¢ +param+ declares a table of parameter data, which can also
841include the declaration of the set data used to index parameter data.
842â¢ +import+ defines import
843from external data sources such as ASCII table files, CSV files, ranges in
845â¢ +include+ specifies a data command file that is to be pro-
846cessed immediately.
847â¢ The +data+ and +end+ commands do not perform any actions, but they provide
848compatibility with AMPL scripts that define data commands.
849
850The +namespace+ declaration allows data commands to be organized into named
851groups that can be enabled or disabled during model construction.
852
853NOTE: Apart from the +set+ and +param+ commands, Pyomoâs data commands do not exactly correspond to AMPL data
854commands. In particular, the syntax of
855the AMPL table command allows the user to specify complex mappings from
856table data values to corresponding model parameters and sets. The corresponding
857Pyomo import command supports much simpler mappings. Complex mappings
858are accomplished in Pyomo via scripting.
859
860=== ModelData Objects ===
861
862The ModelData object reads in data
863sequentially. Any data previously read is overwritten.
864
865Here is an excerpt from an example in <<PyomoBook>> that illustrates
866the use of ModelData objects:
867----
868from coopr.pyomo import ModelData
869from coopr.opt import SolverFactory
870from DiseaseEstimation import model
871
872modeldata = ModelData()
876instance = model.create(modeldata)
877----
878
879== The +pyomo+ Command ==
880
881The +pyomo+ command is issued to the DOS prompt or a Unix shell.
882To see a list of Pyomo command line options, use:
883----
884pyomo --help
885----
886NOTE: There are two dashes before +help+.
887
888In this section we will detail some of the options.
889
890=== Passing Options to a Solver ===
891
892To pass arguments to a solver, use the Pyomo argument
893+--solver-option=+ followed by
894an argument that is a string to be sent to the solver (perhaps with
896So for most MIP solvers, the mip gap can be set using
897----
898--ef-solver-options= "mipgap=0.01 "
899----
900
901Multiple options are separated by a space.
902For example, to specify that the solver is GLPK, then to specify a
903mipgap of two percent and the GLPK  cuts  option, use
904----
905--solver=glpk --solver-options="mipgap=0.02 cuts"
906----
907
908If there are multiple "levels" to the keyword, as is the case for some
909Gurobi and CPLEX options,
910the tokens are separated by underscore.
911For example, +mip cuts all+ would be specified as +mip_cuts_all+.
912For another example, to set the solver to be CPLEX, then to set a mip
913gap of one percent
914and to specify 'y' for the sub-option +numerical+ to the option +emphasis+ use
915----
916--solver=cplex --solver-options="mipgap=0.001 emphasis_numerical=y"
917----
918
919
920// vim: set syntax=asciidoc:
Note: See TracBrowser for help on using the repository browser.