Pyomo online Documentation 3.5. Pyomo online Documentation 3.5

Size: px
Start display at page:

Download "Pyomo online Documentation 3.5. Pyomo online Documentation 3.5"

Transcription

1 Pyomo online Documentation 3.5 i Pyomo online Documentation 3.5

2 Pyomo online Documentation 3.5 ii COLLABORATORS TITLE : Pyomo online Documentation 3.5 ACTION NAME DATE SIGNATURE WRITTEN BY William E. Hart and David L. Woodruff October 15, 2014

3 Pyomo online Documentation 3.5 iii Contents 1 Release Notes Highlights Determining Your Version of Coopr Pyomo Overview Mathematical Modeling Overview of Modeling Components and Processes Abstract Versus Concrete Models A Simple Abstract Pyomo Model A Simple Concrete Pyomo Model Solving the Simple Examples Sets Declaration Operations Predefined Virtual Sets Sparse Index Sets Sparse Index Sets Example Parameters 18 5 Variables 20 6 Objectives 21 7 Constraints 22 8 Expressions Rules to Generate Expressions Piecewise Linear Expressions Expression Objects

4 Pyomo online Documentation 3.5 iv 9 Data Input Data Command Files table namespace DataPortal Objects Loading Data The pyomo Command Passing Options to a Solver Troubleshooting Direct Interfaces to Solvers PySP Overview Overview of Modeling Components and Processes Birge and Louveaux s Farmer Problem ReferenceModel.py ReferenceModel.dat ScenarioStructure.dat Scenario data specification Finding Solutions for Stochastic Models runef runph Solution Output Control Summary of PySP File Names Solving Sub-problems in Parallel and/or Remotely Suffixes Suffix Notation and the Pyomo NL File Interface Declaration Operations Importing Suffix Data Exporting Suffix Data Using Suffixes With an AbstractModel Scripts Python Scripts Iterative Example Changing the Model or Data and Re-solving Fixing Variables and Re-solving Pyomo Callbacks

5 Pyomo online Documentation 3.5 v pyomo_preprocess pyomo_create_model pyomo_create_modeldata pyomo_print_model pyomo_modify_instance pyomo_print_instance pyomo_save_instance pyomo_print_results pyomo_save_results pyomo_postprocess Accessing Variable Values Primal Variable Values One Variable from a Python Script All Variables from a Python Script All Variables from Workflow Callbacks Accessing Parameter Values Accessing Duals Access Duals in a Python Script All Duals from Workflow Callbacks Accessing Solver Status Display of Solver Output Sending Options to the Solver Warm Starts BuildAction Solving Multiple Instances in Parallel Changing the temporary directory Coopr Solver Interfaces Using Black-Box Optimizers with Coopr.Opt Defining and Optimizing Simple Black-Box Applications Defining an Optimization Problem Optimizating with Coliny Solvers Diving Deeper Distributed Optimization with Pyro Step 1: Starting a Name Server Step 2: Starting a Dispatch Server Step 3: Starting a MIP server Step 4: Running a Client Moving from Multi-Core to Distributed Computation Cleaning Up After Yourself

6 Pyomo online Documentation 3.5 vi Preface This book provides a quick introduction to Coopr, which includes a collection of Python software packages that supports a diverse set of optimization capabilities for formulating and analyzing optimization models. A central component of Coopr is Pyomo, which supports the formulation and analysis of mathematical models for complex optimization applications. This capability is commonly associated with algebraic modeling languages (AMLs), which support the description and analysis of mathematical models with a high-level language. Although most AMLs are implemented in custom modeling languages, Pyomo s modeling objects are embedded within Python, a full-featured high-level programming language that contains a rich set of supporting libraries. Pyomo has also proven an effective framework for developing high-level optimization and analysis tools. For example, the PySP package provides generic solvers for stochastic programming. PySP leverages the fact that Pyomo s modeling objects are embedded within a full-featured high-level programming language, which allows for transparent parallelization of subproblems using Python parallel communication libraries. Goals of the Book This book provides a broad overview of different components of the Pyomo software. There are roughly two main goals for this book: 1. Help users get started with different Pyomo capabilities. Our goal is not to provide a comprehensive reference, but rather to provide a tutorial with simple and illustrative examples. Also, we aim to provide explanations behind the design and philosophy of Coopr. 2. Provide preliminary documentation of new features and capabilities. We know that a new feature or capability probably will not be used unless it is documented. As Coopr evolves, we plan to use this book to document these features. This provides users some context concerning the focus of Coopr development, and it also provides an opportunity to get early feedback on new features before they are documented in other contexts. Who Should Read This Book This book is intended to be a reference for students, academic researchers and practitioners. Pyomo has been effectively used in the classroom with undergraduate and graduate students. However, we assume that the reader is generally familiar with optimization and mathematical modeling. Although this book does not contain a glossary, we recommend the Mathematical Programming Glossary [MPG] as a reference for the reader. We also assume that the reader is generally familiar with the Python programming language. There are a variety of books describing Python, as well as excellent documentation of the Python language and the software packages bundled with Python distributions. Comments and Questions Further information about Pyomo and Coopr is available on the Coopr wiki:

7 Pyomo online Documentation 3.5 vii Coopr is also hosted at COIN-OR: We strongly encourage feedback from readers about the software on the Coopr Forum: We hope this will include feedback on typos and errors in our examples. Additionally, we welcome comments on the presentation of this material, and suggestions for material that we should develop in the other book chapters. Good Luck!

8 Pyomo online Documentation / 78 Chapter 1 Release Notes 1.1 Highlights The following are highlights of Coopr 3.5: Solvers Updates for CBC, Cplex and Gurobi solvers Added support for NEOS solvers (using Kestrel interface) Added preliminary support for persistent solvers Modeling Can now model bilevel programs Can now model mathematical programs with equillibrium constraints Added explicit support for model transformations Other Added the coopr.environ package, which initializes Coopr plugins The coopr command contains better documentation of installed capabilities Renamed coopr.plugins to coopr.solvers Cleanup and code reviews of core coopr.pyomo components Many bug fixes The coopr.environ package consolidates the management of plugins in Coopr. We now recommend using the following import when defining Coopr models: import coopr.environ This import line should be at the top of the Pyomo model, since it initializes plugins that may be used elsewhere during model generation. Models developed for earlier versions of Coopr should continue to work for now. However, after Coopr 4.0 these imports will be required. 1.2 Determining Your Version of Coopr To determine your current version of Coopr, use the command coopr version

9 Pyomo online Documentation / 78 Chapter 2 Pyomo Overview 2.1 Mathematical Modeling This chapter provides an introduction to Pyomo: Python Optimization Modeling Objects. A more complete description is contained in the Pyomo book. 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 [AMPL] AIMMS [AIMMS] and GAMS [GAMS]. Pyomo s modeling objects are embedded within Python, a full-featured high-level programming language that contains a rich set of supporting libraries. 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: Explain phenomena that arise in a system, Make predictions about future states of a system, Assess key factors that influence phenomena in a system, Identify extreme states in a system, that might represent worst-case scenarios or minimal cost plans, and Analyze trade-offs to support human decision makers. Mathematical models represent system knowledge with a formalized mathematical language. The following mathematical concepts are central to modern modeling activities: variables 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. parameters 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. relations These are equations, inequalities or other mathematical relationships that define how different parts of a model are connected to each other. goals These are functions that reflect goals and objectives for the system being modeled.

10 Pyomo online Documentation / 78 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. Pyomo is an AML that extends Python to include objects for mathematical modeling. Hart et al. Pyomo, [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: Open Source Pyomo is developed within Coopr s open source project to promote transparency of the modeling framework and encourage community development of Pyomo capabilities. Customizable Capability Pyomo supports a customizable capability through the extensive use of plug-ins to modularize software components. Solver Integration Pyomo models can be optimized with solvers that are written either in Python or in compiled, low-level languages. Programming Language 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. 2.2 Overview of Modeling Components and Processes Pyomo supports an object-oriented design for the definition of optimization models. The basic steps of a simple modeling process are: Create model and declare components Instantiate the model Apply solver Interrogate solver results 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. 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: Set set data that is used to define a model instance Param parameter data that is used to define a model instance Var decision variables in a model Objective expressions that are minimized or maximized in a model Constraint constraint expressions that impose restrictions on variable values in a model

11 Pyomo online Documentation / Abstract Versus Concrete Models 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: min n j=1 c jx j s.t. n j=1 a i jx j b i i = 1...m x j 0 j = 1...n Note As a convenience, we use the symbol to mean for all or for each. 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. 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: min 2x 1 + 3x 2 s.t. 3x 1 + 4x 2 1 x 1,x 2 0 The ConcreteModel class is used to define concrete optimization models in Pyomo. 2.4 A Simple Abstract Pyomo Model We repeat the abstract model already given: One way to implement this in Pyomo is as follows: from future import division from pyomo.environ import * model = AbstractModel() model.m = Param(within=NonNegativeIntegers) model.n = Param(within=NonNegativeIntegers) model.i = RangeSet(1, model.m) model.j = RangeSet(1, model.n) model.a = Param(model.I, model.j) model.b = Param(model.I) model.c = Param(model.J) min n j=1 c jx j s.t. n j=1 a i jx j b i i = 1...m x j 0 j = 1...n # the next line declares a variable indexed by the set J model.x = Var(model.J, domain=nonnegativereals) def obj_expression(model): return summation(model.c, model.x) model.obj = Objective(rule=obj_expression)

12 Pyomo online Documentation / 78 def ax_constraint_rule(model, i): # return the expression for the constraint for i return sum(model.a[i,j] * model.x[j] for j in model.j) >= model.b[i] # the next line creates one constraint for each member of the set model.i model.axbconstraint = Constraint(model.I, rule=ax_constraint_rule) Note 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. 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. from future import division 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. The next import line that is required in every Pyomo model. Its purpose is to make the symbols used by Pyomo known to Python. from coopr.pyomo import * 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. model = AbstractModel() 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. model.m = Param(within=NonNegativeIntegers) model.n = Param(within=NonNegativeIntegers) 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. model.i = RangeSet(1, model.m) model.j = RangeSet(1, model.n) 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. model.a = Param(model.I, model.j) model.b = Param(model.I) model.c = Param(model.J) Note In Python, and therefore in Pyomo, any text after pound sign is considered to be a comment.

13 Pyomo online Documentation / 78 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. # the next line declares a variable indexed by the set J model.x = Var(model.J, domain=nonnegativereals) 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 n j=1 c jx j. def obj_expression(model): return summation(model.c, model.x) 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. model.obj = Objective(rule=obj_expression) 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 n j=1 a i jx j b i i = 1...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. def ax_constraint_rule(model, i): # return the expression for the constraint for i return sum(model.a[i,j] * model.x[j] for j in model.j) >= model.b[i] Note In Python, indexes are in square brackets and function arguments are in parentheses. 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. # the next line creates one constraint for each member of the set model.i model.axbconstraint = Constraint(model.I, rule=ax_constraint_rule) 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. In order to use this model, data must be given for the values of the parameters. Here is one file that provides data.

14 Pyomo online Documentation / 78 # one way to input the data in AMPL format # for indexed parameters, the indexes are given before the value param m := 1 ; param n := 2 ; param a := ; param c:= ; param b := 1 1 ; 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. 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. param m := 1 ; param n := 2 ; 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 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. param a := ; param c:= ; param b := 1 1 ; 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. # abstract2.py from future import division from pyomo.environ import * model = AbstractModel() model.i = Set()

15 Pyomo online Documentation / 78 model.j = Set() model.a = Param(model.I, model.j) model.b = Param(model.I) model.c = Param(model.J) # the next line declares a variable indexed by the set J model.x = Var(model.J, domain=nonnegativereals) def obj_expression(model): return summation(model.c, model.x) model.obj = Objective(rule=obj_expression) def ax_constraint_rule(model, i): # return the expression for the constraint for i return sum(model.a[i,j] * model.x[j] for j in model.j) >= model.b[i] # the next line creates one constraint for each member of the set model.i model.axbconstraint = Constraint(model.I, rule=ax_constraint_rule) To get the same instantiated model, the following data file can be used. # abstract2a.dat AMPL format set I := 1 ; set J := 1 2 ; param a := ; param c:= ; param b := 1 1 ; However, this model can also be fed different data for problems of the same general form using meaningful indexes. # abstract2.dat AMPL data format set I := TV Film ; set J := Graham John Carol ; param a := TV Graham 3 TV John 4.4 TV Carol 4.9 Film Graham 1 Film John 2.4 Film Carol 1.1 ; param c := [*] Graham 2.2 John Carol 3 ;

16 Pyomo online Documentation / 78 param b := TV 1 Film 1 ; 2.5 A Simple Concrete Pyomo Model 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. We repeat the concrete model already given: This is implemented as a concrete model as follows: from future import division from pyomo.environ import * model = ConcreteModel() model.x = Var([1,2], domain=nonnegativereals) min 2x 1 + 3x 2 s.t. 3x 1 + 4x 2 1 x 1,x 2 0 model.obj = Objective(expr = 2*model.x[1] + 3*model.x[2]) model.constraint1 = Constraint(expr = 3*model.x[1] + 4*model.x[2] >= 1) 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. 2.6 Solving the Simple Examples 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. 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: pyomo abstract1.py abstract1.dat --solver=glpk Since glpk is the default solver, there really is no need specify it so the --solver option can be dropped. Note There are two dashes before the command line option names such as solver. To continue the example, if CPLEX is installed then it can be listed as the solver. The command to solve with CPLEX is pyomo abstract1.py abstract1.dat --solver=cplex This yields the following output on the screen:

17 Pyomo online Documentation / 78 [ 0.00] Setting up Pyomo environment [ 0.00] Applying Pyomo preprocessing actions [ 0.07] Creating model [ 0.15] Applying solver [ 0.37] Processing results Number of solutions: 1 Solution Information Gap: 0.0 Status: optimal Function Value: Solver results file: results.json [ 0.39] Applying Pyomo postprocessing actions [ 0.39] Pyomo Finished 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: pyomo abstract1.py abstract1.dat --solver=cplex --summary To see a list of Pyomo command line options, use: pyomo --help Note There are two dashes before help. For a concrete model, no data file is specified on the Pyomo command line.

18 Pyomo online Documentation / 78 Chapter 3 Sets 3.1 Declaration Sets can be declared using the Set and RangeSet functions or by assigning set expressions. The simplest set declaration creates a set and postpones creation of its members: model.a = Set() The Set function takes optional arguments such as: doc = String describing the set dimen = Dimension of the members of the set filter = A boolean function used during construction to indicate if a potential new member should be assigned to the set initialize = A function that returns the members to initialize the set. ordered = A boolean indicator that the set is ordered; the default is False validate = A boolean function that validates new member data 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 within = Set used for validation; it is a super-set of the set being declared. One way to create a set whose members will be two dimensional is to use the dimen argument: model.b = Set(dimen=2) To create a set of all the numbers in set model.a doubled, one could use def doublea_init(model): return (i*2 for i in model.a) model.c = Set(initialize=DoubleA_init) As an aside we note that as always in Python, there are lot of ways to accomplish the same thing. Also, note that this will generate an error if model.a contains elements for which multiplication times two is not defined. The initialize option can refer to a Python set, which can be returned by a function or given directly as in model.d = Set(initialize=[ red, green, blue ])

19 Pyomo online Documentation / 78 The initialize option can also specify a function that is applied sequentially to generate set members. Consider the case of a simple set. In this case, the initialization function accepts a set element number and model and returns the set element associated with that number: def Z_init(model, i): if i > 10: return Set.End return 2*i+1 model.z = Set(initialize=Z_init) The Set.End return value terminates input to the set. Additional information about iterators for set initialization is in the Pyomo book. Note Data specified in an input file will override the data specified by the initialize options. If 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 that is indexed by the members of the set model.a, use model.e = Set(model.A) Arguments can be combined. For example, to create an array of sets with three dimensional members indexed by set model.a, use model.f = Set(model.A, dimen=3) The initialize option can be used to create a set that contains a sequence of numbers, but the RangeSet function provides a concise mechanism for simple sequences. This function takes as its arguments a start value, a final value, and a step 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 example, the following declaration creates a set with the numbers 1.5, 5 and 8.5: model.g = RangeSet(1.5, 10, 3.5) 3.2 Operations Sets may also be created by assigning other Pyomo sets as in these examples that also illustrate the set operators union, intersection, difference, and exclusive-or: model.h = model.a model.i = model.a model.d # union model.j = model.a & model.d # intersection model.k = model.a - model.d # difference model.l = model.a ^ model.d # exclusive-or The cross-product operator is the asterisk (*). For example, to assign a set the cross product of two other sets, one could use model.k = model.b * model.c or to indicate the the members of a set are restricted to be in the cross product of two other sets, one could use model.k = Set(within=model.B * model.c) The cross-product operator is the asterisk (*). For example, to create a set that contains the cross-product of sets A and B, use model.c = Set(model.A * model.b) to instead create a set that can contain a subset of the members of this cross-product, use model.c = Set(within=model.A * model.b)

20 Pyomo online Documentation / Predefined Virtual Sets For use in specifying domains for sets, parameters and variables, Pyomo provides the following pre-defined virtual sets: Any: all possible values Reals : floating point values PositiveReals: strictly positive floating point values NonPositiveReals: non-positive floating point values NegativeReals: strictly negative floating point values NonNegativeReals: non-negative floating point values PercentFraction: floating point values in the interval [0,1] Integers: integer values PositiveIntegers: positive integer values NonPositiveIntegers: non-positive integer values NegativeIntegers: negative integer values NonNegativeIntegers: non-negative integer values Boolean: boolean values, which can be represented as False/True, 0/1, False / True and F / T Binary: same as boolean For example, if the set model.m is declared to be within the virtual set NegativeIntegers then an attempt to add anything other than a negative integer will result in an error. Here is the declaration: model.m = Set(within=NegativeIntegers) 3.4 Sparse Index Sets Sets provide indexes for parameters, variables and other sets. Index set issues are important for modelers in part because of efficiency considerations, but primarily because the right choice of index sets can result in very natural formulations that are condusive to understanding and maintenance. Pyomo leverages Python to provide a rich collection of options for index set creation and use. The choice of how to represent indexes often depends on the application and the nature of the instance data that are expected. To illustrate some of the options and issues, we will consider problems involving networks. In many network applications, it is useful to declare a set of nodes, such as model.nodes = Set() and then a set of arcs can be created with reference to the nodes. Consider the following simple version of minimum cost flow problem: minimize subject to: a A c a x a S n + (i,n) A x (i,n) D n (n, j) A x (n, j) x a 0, n N a A where

21 Pyomo online Documentation / 78 Set: Nodes N Set: Arcs A N N Var: Flow on arc (i, j): x i, j, (i, j) A Param: Flow Cost on arc (i, j): c i, j, (i, j) A Param: Demand at node i: D i, i N Param: Supply at node i: S i, i N In the simplest case, the arcs can just be the cross product of the nodes, which is accomplished by the definition model.arcs = model.nodes * model.nodes that creates a set with two dimensional members. For applications where all nodes are always connected to all other nodes this may suffice. However, issues can arise when the network is not fully dense. For example, the burden of avoiding flow on arcs that do not exist falls on the data file where high-enough costs must be provided for those arcs. Such a scheme is not very elegant or robust. For many network flow applications, it might be better to declare the arcs using model.arcs = Set(within=model.Nodes*model.Nodes) or model.arcs = Set(dimen=2) where the difference is that the first version will provide error checking as data is assigned to the set elements. This would enable specification of a sparse network in a natural way. But this results in a need to change the FlowBalance constraint because as it was written in the simple example, it sums over the entire set of nodes for each node. One way to remedy this is to sum only over the members of the set model.arcs as in def FlowBalance_rule(model, node): return model.supply[node] \ + sum(model.flow[i, node] for i in model.nodes if (i,node) in model.arcs) \ - model.demand[node] \ - sum(model.flow[node, j] for j in model.nodes if (j,node) in model.arcs) \ == 0 This will be OK unless the number of nodes becomes very large for a sparse network, then the time to generate this constraint might become an issue (admittely, only for very large networks, but such networks do exist). Another method, which comes in handy in many netowrk applications, is to have a set for each node that contain the nodes at the other end of arcs going to the node at hand and another set giving the nodes on out-going arcs. If these sets are called model. NodesIn and model.nodesout respectively, then the flow balance rule can be re-written as def FlowBalance_rule(model, node): return model.supply[node] \ + sum(model.flow[i, node] for i in model.nodesin[node]) \ - model.demand[node] \ - sum(model.flow[node, j] for j in model.nodesout[node]) \ == 0 The data for NodesIn and NodesOut could be added to the input file, and this may be the most efficient option. For all but the largest networks, rather than reading Arcs, NodesIn and NodesOut from a data file, it might be more elegant to read only Arcs from a data file and declare model.nodesin with an initialize option specifying the creation as follows:

22 Pyomo online Documentation / 78 def NodesIn_init(model, node): retval = [] for (i,j) in model.arcs: if j == node: retval.append(i) return retval model.nodesin = Set(model.Nodes, initialize=nodesin_init) with a similar definition for model.nodesout. This code creates a list of sets for NodesIn, one set of nodes for each node. The full model is: # Isinglecomm.py # NodesIn and NodesOut are intialized using the Arcs from pyomo.environ import * model = AbstractModel() model.nodes = Set() model.arcs = Set(dimen=2) def NodesOut_init(model, node): retval = [] for (i,j) in model.arcs: if i == node: retval.append(j) return retval model.nodesout = Set(model.Nodes, initialize=nodesout_init) def NodesIn_init(model, node): retval = [] for (i,j) in model.arcs: if j == node: retval.append(i) return retval model.nodesin = Set(model.Nodes, initialize=nodesin_init) model.flow = Var(model.Arcs, domain=nonnegativereals) model.flowcost = Param(model.Arcs) model.demand = Param(model.Nodes) model.supply = Param(model.Nodes) def Obj_rule(model): return summation(model.flowcost, model.flow) model.obj = Objective(rule=Obj_rule, sense=minimize) def FlowBalance_rule(model, node): return model.supply[node] \ + sum(model.flow[i, node] for i in model.nodesin[node]) \ - model.demand[node] \ - sum(model.flow[node, j] for j in model.nodesout[node]) \ == 0 model.flowbalance = Constraint(model.Nodes, rule=flowbalance_rule) for this model, a toy data file would be: # Isinglecomm.dat: data for Isinglecomm.py set Nodes := CityA CityB CityC ; set Arcs :=

23 Pyomo online Documentation / 78 CityA CityB CityA CityC CityC CityB ; param : FlowCost := CityA CityB 1.4 CityA CityC 2.7 CityC CityB 1.6 ; param Demand := CityA 0 CityB 1 CityC 1 ; param Supply := CityA 2 CityB 0 CityC 0 ; Sparse Index Sets Example One may want to have a constraint that holds for i in model.i, k in model.k, v in model.v[k] There are many ways to accomplish this, but one good way is to create a set of tuples composed of all of model.k, model. V[k] pairs. This can be done as follows: def kv_init(model): return ((k,v) for k in model.k for v in model.v[k]) model.kv=set(dimen=2, initialize=kv_init) So then if there was a constraint defining rule such as def MyC_rule(model, i, k, v): return... Then a constraint could be declared using model.myconstraint = Constraint(model.I,model.KV,rule=c1Rule) Here is the first few lines of a model that illustrates this: from coopr.pyomo import * model = AbstractModel() model.i=set() model.k=set() model.v=set(model.k) def kv_init(model): return ((k,v) for k in model.k for v in model.v[k]) model.kv=set(dimen=2, initialize=kv_init) model.a = Param(model.I, model.k)

24 Pyomo online Documentation / 78 model.y = Var(model.I) model.x = Var(model.I, model.kv) #include a constraint #x[i,k,v] <= a[i,k]*y[i], for i in model.i, k in model.k, v in model.v[k] def c1rule(model,i,k,v): return model.x[i,k,v] <= model.a[i,k]*model.y[i] model.c1 = Constraint(model.I,model.KV,rule=c1Rule)

25 Pyomo online Documentation / 78 Chapter 4 Parameters 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 very 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: model.a = Set() model.b = Set() model.p = Param(model.A, model.b) In addition to sets that serve as indexes, the Param function takes the following command options: default = The value absent any other specification. doc = String describing the parameter initialize = A function (or Python object) that returns the members to initialize the parameter values. rule = (this is a synonym for initilize) validate = A boolean function with arguments that are the prospective parameter value, the parameter indices and the model. within = Set used for validation; it specifies the domain of the parameter values. 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: v={} v[1,1] = 9 v[2,2] = 16 v[3,3] = 25 model.s = Param(model.A, model.a, initialize=v, default=0) And now using an initialization rule that is automatically called once for each index tuple (remember that we are assuming that model.a contains 1,2,3) def s_init(model, i, j): if i == j: return i*i else: return 0.0 model.s = Param(model.A, model.a, rule=s_init) In this example, the index set contained integers, but index sets need not be numeric. It is very common to use strings.

26 Pyomo online Documentation / 78 Note Data specified in an input file will override the data specified by the initialize options. 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 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. def s_validate(model, v, i): return v > model.s = Param(model.A, validate=s_validate)

27 Pyomo online Documentation / 78 Chapter 5 Variables Variables are intended to ultimately be given values by an optimization package. The 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: bounds = A function (or Python object) that gives a (lower,upper) bound pair for the variable domain = A set that is a super-set of the values the variable can take on. initialize = A function (or Python object) that gives a starting value for the variable; this is particularly important for non-linear models within = (synonym for domain) 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: model.lumberjack = Var(within=NonNegativeReals, bounds=(0,6), initialize=1.5) Instead of the initialize option, initialization is sometimes done with a Python assignment statement as in model.lumberjack = 1.5 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: model.a = Set(initialize=[ Scones, Tea ] lb = { Scones :2, Tea :4} ub = { Scones :5, Tea :7} def fb(model, i): return (lb[i], ub[i]) model.pricetocharge = Var(model.A, domain=positiveinteger, bounds=fb) Note 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.

28 Pyomo online Documentation / 78 Chapter 6 Objectives 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: def ObjRule(model): return 2*model.x[1] + 3*model.x[2] model.g = Objective(rule=ObjRule) 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: def profrul(model): return summation(model.p, model.x) + model.y model.obj = Objective(rule=ObjRule, sense=maximize) This example uses the sense option to specify maximization. The default sense is minimize.

29 Pyomo online Documentation / 78 Chapter 7 Constraints 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: def teaokrule(model): return(model.x[ butter ] + model.x[ scones ] == 3) model.teaconst = Constraint, rule=teaokrule) 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: model.x = Var() def arule(model): return model.x >= 2 Boundx = Constraint(rule=aRule) def brule(model): return (2, model.x, None) Boundx = Constraint(rule=bRule) For this simple example, it would also be possible to declare model.x with a bound option to accomplish the same thing. 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: model.a = RangeSet(1,10) model.a = Param(model.A, within=postivereals) model.tobuy = Var(model.A) def bud_rule(model, i): return model.a[i]*model.tobuy[i] <= i abudget = Constraint(model.A) Note Python and Pyomo are case sensitive so model.a is not the same as model.a.

30 Pyomo online Documentation / 78 Chapter 8 Expressions 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. 8.1 Rules to Generate Expressions 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. 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: switch = 3 model.a = RangeSet(1, 10) model.c = Param(model.A) model.d = Param() model.x = Var(model.A, domain=boolean) def pi_rule(model) accexpr = summation(model.c, model.x) if switch >= 2: accexpr = accexpr - model.d return accexpr >= 0.5 PieSlice = Constraint(rule=pi_rule) 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. Caution Because model elements result in expressions, not values, the following does not work as expected in an abstract model! model.a = RangeSet(1, 10) model.c = Param(model.A) model.d = Param() model.x = Var(model.A, domain=boolean)

31 Pyomo online Documentation / 78 def pi_rule(model) accexpr = summation(model.c, model.x) if model.d >= 2: # NOT in an abstract model!! accexpr = accexpr - model.d return accexpr >= 0.5 PieSlice = Constraint(rule=pi_rule) The trouble is that model.d >=2 results in an expression, not its evaluated value. Instead use if value(model.d) >=2 8.2 Piecewise Linear Expressions Pyomo has facilities to add piecewise constraints of the form y=f(x) for a variety of forms of the function f. The piecewise types other than SOS2, BIGM_SOS1, BIGM_BIN are implement as described in the paper [Vielma_et_al]. There are two basic forms for the declaration of the constraint: model.pwconst = Piecewise(index_1,...,index_n,yvar,xvar,**Keywords) model.pwconst = Piecewise(yvar,xvar,**Keywords) 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. KEYWORDS: 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). pw_repn=<option> Indicates the type of piecewise representation to use. This can have a major impact on solver performance. Options: (Default SOS2 ) SOS2 - Standard representation using sos2 constraints. BIGM_BIN - BigM constraints with binary variables. The theoretically tightest M values are automatically determined. BIGM_SOS1 - BigM constraints with sos1 variables. The theoretically tightest M values are automatically determined. DCC - Disaggregated convex combination model. DLOG - Logarithmic disaggregated convex combination model. CC - Convex combination model. LOG - Logarithmic branching convex combination. MC - Multiple choice model. INC - Incremental (delta) method. NOTE: Step functions are supported for all but the two BIGM options. Refer to the force_pw option. pw_constr_type= <Option> Indicates the bound type of the piecewise function. Options: UB - y variable is bounded above by piecewise function LB - y variable is bounded below by piecewise function EQ - y variable is equal to the piecewise function f_rule=f(model,i,j,...,x), {}, [], () An object that returns a numeric value that is the range value corresponding to each piecewise domain point. For functions, the first argument must be a Pyomo model. The last argument is the domain value at which the function evaluates (Not a Pyomo Var). Intermediate arguments are the corresponding indices of the Piecewise component (if any). Otherwise, the object can be a dictionary of lists/tuples (with keys the same as the indexing set) or a singe list/tuple (when no indexing set is used or when all indices use an identical piecewise function). Examples:

32 Pyomo online Documentation / 78 # A function that changes with index def f(model,j,x): if (j == 2): return x** else: return x** # A nonlinear function f = lambda model,x: return exp(x) + value(model.p) (model.p is a Pyomo Param) # A step function f = [0,0,1,1,2,2] force_pw=true/false Using the given function rule and pw_pts, a check for convexity/concavity is implemented. If (1) the function is convex and the piecewise constraints are lower bounds or if (2) the function is concave and the piecewise constraints are upper bounds then the piecewise constraints will be substituted for linear constraints. Setting force_pw=true will force the use of the original piecewise constraints even when one of these two cases applies. warning_tol=<float> To aid in debugging, a warning is printed when consecutive slopes of piecewise segments are within <warning_tol> of each other. Default=1e-8 warn_domain_coverage=true/false Print a warning when the feasible region of the domain variable is not completely covered by the piecewise breakpoints. Default=True unbounded_domain_var=true/false Allow an unbounded or partially bounded Pyomo Var to be used as the domain variable. Default=False NOTE: This does not imply unbounded piecewise segments will be constructed. The outermost piecwise breakpoints will bound the domain variable at each index. However, the Var attributes.lb and.ub will not be modified. Here is an example of an assignment to a Python dictionary variable that has keywords for a picewise constraint: kwds = { pw_constr_type : EQ, pw_repn : SOS2, sense :maximize, force_pw :True} Here is a simple example based on the abstract2.py example given early. In this new example, the objective function is the sum of c times x to the fourth. In this example, the keywords are passed directly to the Piecewise function without being assigned to a dictionary variable. The upper bound on the x variables was chosen whimsically just to make the example. The important thing to note is that variables that are going to appear as the independent variable in a piecewise constraint must have bounds. # abstract2piece.py # Similar to abstract2.py, but the objective is now c times x to the fourth power from future import division from pyomo.environ import * model = AbstractModel() model.i = Set() model.j = Set() model.a = Param(model.I, model.j) model.b = Param(model.I) model.c = Param(model.J) model.topx = Param(default=6.1) # range of x variables

33 Pyomo online Documentation / 78 # the next line declares a variable indexed by the set J model.x = Var(model.J, domain=nonnegativereals, bounds=(0,model.topx)) model.y = Var(model.J, domain=nonnegativereals) # to avoid warnings, we set breakpoints at or beyond the bounds PieceCnt = 100 bpts = [] for i in range(0,piececnt*model.topx+2): bpts.append(float(i/piececnt)) def f4(model, j, xp): # we not need j, but it is passed as the index for the constraint return xp**4 model.computeobj = Piecewise(model.J, model.y, model.x, pw_pts=bpts, f_rule=f4, pw_constr_type= EQ ) def obj_expression(model): return summation(model.c, model.y) model.obj = Objective(rule=obj_expression) def ax_constraint_rule(model, i): # return the expression for the constraint for i return sum(model.a[i,j] * model.x[j] for j in model.j) >= model.b[i] # the next line creates one constraint for each member of the set model.i model.axbconstraint = Constraint(model.I, rule=ax_constraint_rule) A more advanced example is provided as abstract2piecebuild.py. 8.3 Expression Objects Pyomo Expression objects are very similar to the Param component (with mutable=true) except that the underlying values can be numeric constants or Pyomo expressions. Here s an example in the context of an AbstractModel: model = AbstractModel() model.x = Var(initialize=1.0) def _e(m,i): return m.x*i model.e = Expression([1,2,3],initialize=_e) instance = model.create() print value(instance.e[1]) # -> 1.0 print instance.e[1]() # -> 1.0 print instance.e[1].value # -> a pyomo expression object # Change the underlying expression instance.e[1].value = instance.x**2 # This requires re-preprocessing instance.preprocess()... solve... load results # print the value of the expression given the loaded optimal solution print value(instance.e[1])

34 Pyomo online Documentation / 78 Chapter 9 Data Input Pyomo can initialize models in two general ways. When executing the pyomo command, one or more data command files can be specified to declare data and load data from other data sources (e.g. spreadsheets and CSV files). When initializing a model within a Python script, a DataPortal object can be used to load data from one or more data sources. 9.1 Data Command Files The following commands can be used in data command files: set declares set data, param declares a table of parameter data, which can also include the declaration of the set data used to index parameter data, import loads set and parameter data from an external data source such as ASCII table files, CSV files, ranges in spreadsheets, and database tables, table loads set and parameter data from a table, include specifies a data command file that is to be processed immediately, the data and end commands do not perform any actions, but they provide compatibility with AMPL scripts that define data commands, and namespace defines groupings of data commands. The syntax of the set and param data commands are adapted from AMPL s data commands. However, other Pyomo data commands do not directly correspond to AMPL data commands. In particular, Pyomo s table command was introduced to work around semantic ambiguities in the param command. Pyomo s table command does not correspond to AMPL s table command. Instead, the import command supports a simplified syntax that mimics AMPL s table command. Warning The data command file was initially developed to provide compatability in data formats between Pyomo and AMPL. However, these data formats continue to diverge in their syntax and semantics. Simple examples using set and param data commands are likely to work for both AMPL and Pyomo, particularly with abstract Pyomo models. But in general a user should expect to need to adapt their AMPL data command files for use with Pyomo. See the Pyomo book for detailed descriptions of these commands. The following sections provide additional details, particularly for new data commands that are not described in the Pyomo book: table.

35 Pyomo online Documentation / table The table data command was developed to provide a more flexible and complete data declaration than is possible with the param declaration. This command has a similar syntax to the import command, but it includes a complete specification of the table data. The following example illustrates a simple table command that declares data for a single parameter: table M(A) : A B M N := A1 B A2 B A3 B ; The parameter M is indexed by column A. The column labels are provided after the colon and before the :=. Subsequently, the table data is provided. Note that the syntax is not sensitive to whitespace. Thus, the following is an equivalent table command: table M(A) : A B M N := A1 B A2 B A3 B ; Multiple parameters can be declared by simply including additional parameter names. For example: table M(A) N(A,B) : A B M N := A1 B A2 B A3 B ; This example declares data for the M and N parameters. As this example illustrates, these parameters may have different indexing columns. The indexing columns represent set data, which is specified separately. For example: table A={A} Z={A,B} M(A) N(A,B) : A B M N := A1 B A2 B A3 B ; This examples declares data for the M and N parameters, along with the A and Z indexing sets. The correspondence between the index set Z and the indices of parameter N can be made more explicit by indexing N by Z: table A={A} Z={A,B} M(A) N(Z) : A B M N := A1 B A2 B A3 B ; Set data can also be specified independent of parameter data: table Z={A,B} Y={M,N} : A B M N := A1 B A2 B A3 B ;

36 Pyomo online Documentation / 78 Finally, singleton parameter values can be specified with a simple table command: table pi := ; The previous examples considered examples of the table command where column labels are provided. The table command can also be used without column labels. For example, the file table0.dat can be revised to omit column labels as follows: table columns=4 M(1)={3} := A1 B A2 B A3 B ; The columns=4 is a keyword-value pair that defines the number of columns in this table; this must be explicitly specified in unlabeled tables. The default column labels are integers starting from 1; the labels are columns 1, 2, 3, and 4 in this example. The M parameter is indexed by column 1. The braces syntax declares the column where the M data is provided. Similarly, set data can be declared referencing the integer column labels: table A={1} Z={1,2} M(1) N(1,2) := A1 B A2 B A3 B ; Declared set names can also be used to index parameters: table A={1} Z={1,2} M(A) N(Z) := A1 B A2 B A3 B ; Finally, we compare and contrast the table and param commands: Both commands can be used to declare parameter and set data. The param command can declare a single set that is used to index one or more parameters. The table command can declare data for any number of sets, independent of whether they are used to index parameter data. The param command can declare data for multiple parameters only if they share the same index set. The table command can declare data for any number of parameters that are may be indexed separately. Both commands can be used to declare a singleton parameter. The table syntax unambiguously describes the dimensionality of indexing sets. The param command must be interpreted with a model that provides the dimension of the indexing set. This last point provides a key motivation for the table command. Specifically, the table command can be used to reliably initialize concrete models using a DataPortal object. By contrast, the param command can only be used to initialize concrete models with parameters that are indexed by a single column (i.e. a simple set). See the discussion of DataPortal objects below for an example namespace The namespace command allows data commands to be organized into named groups that can be enabled from the pyomo command line. For example, consider again the abstract2.py example. Suppose that the cost data shown in abstract2.dat were valid only under certain circumstances that we will label as "TerryG" and that there would be different cost data under circumstances that we will label "JohnD." This could be represented using the following data file:

37 Pyomo online Documentation / 78 # abs2nspace.dat AMPL format with namespaces set I := TV Film ; set J := Graham John Carol ; param a := TV Graham 3 TV John 4.4 TV Carol 4.9 Film Graham 1 Film John 2.4 Film Carol 1.1 ; namespace TerryG { param c := [*] Graham 2.2 John Carol 3 ; } namespace JohnD { param c := [*] Graham 2.7 John 3 Carol 2.1 ; } param b := TV 1 Film 1 ; To use this data file with abstract2.py, a namespace must be indicated on the command line. specification, --namespace TerryG would be added to the command line. For example: pyomo abstract2.py abs2nspace.dat --namespace TerryG --solver=cplex To select the "TerryG" data If the --namespace option is omitted, then no data will be given for model.c (and no default was given for model.c). In other words, there is no default namespace selection. The option -ns (with one dash) is an alias for --namespace (which needs two dashes) Multiple namespaces can be selected by giving multiple --namespace or -ns arguments on the Pyomo command line. 9.2 DataPortal Objects The import and export Pyomo data commands can be used to load set and table data from a variety of data sources. Pyomo s DataPortal object provides this same functionality for users who work with Python scripts. A DataPortal object manages the process of loading data from different data sources, and it is used to construct model instances in a standard manner. Similarly, a DataPortal object can be used to store model data externally in a standard manner. Note Pyomo also supports the ModelData object, which provides a narrow set of capabilities than is supported by the DataPor tal object. The use of ModelData objects is deprecated.

38 Pyomo online Documentation / 78 Note The Pyomo data commands import and export correspond to the DataPortal methods load and store. This discrepancy is due to the fact that import is a reserved word in Python. Thus, we cannot define an import method in the DataPortal class. (TODO: we need to create load and store data commands, and deprecated the import and export data commands.) Loading Data The load method can be used to load data into Pyomo models from a variety of sources and formats. The most common format is a table representation of set and parameter data. For example, consider the file A.tab, which defines a simple set: A A1 A2 A3 The following example illustrates how a DataPortal object can be used to load this data into a model: model = AbstractModel() model.a = Set() data = DataPortal() data.load(filename= tab/a.tab, set=model.a) instance = model.create(data) The load method opens the data file, processes it, and loads the data in a format that is then used to construct a model instance. The load method can be called multiple times to load data for different sets or parameters, or to override data processed earlier. Note Subsequent examples omit the model declaration and instance creation. In the previous example, the set option is used to define the model component that is loaded with the set data. If the data source defines a table of data, then this option is used to specify data for a multi-dimensional set. For example, consider the file D.tab: A B A1 1 A1 2 A1 3 A2 1 A2 2 A2 3 A3 1 A3 2 A3 3 If a two-dimensional set is declared, then it can be loaded with the same syntax: model.a = Set(dimen=2) data.load(filename= tab/c.tab, set=model.a) This example also illustrates that the column titles do not directly impact the process of loading data. Column titles are only used to select columns that are included in the table that is loaded (see below). The param option is used to define the a parameter component that is loaded with data. The simplest parameter is a singleton. For example, consider the file Z.tab:

39 Pyomo online Documentation / This data is loaded with the following syntax: model.z = Param() data.load(filename= tab/z.tab, param=model.z) Indexed parameters can be defined from table data. For example, consider the file Y.tab: A Y A1 3.3 A2 3.4 A3 3.5 The parameter y is loaded with the following syntax: model.a = Set(initialize=[ A1, A2, A3, A4 ]) model.y = Param(model.A) data.load(filename= tab/y.tab, param=model.y) Pyomo assumes that the parameter values are defined on the rightmost column; the column names are not used to specify the index and parameter data (see below). In this file, the A column contains the index values, and the Y column contains the parameter values. Similarly, multiple parameters can be initialized at once by specifying a list (or tuple) of component parameters. For example, consider the file XW.tab: A X W A A A The parameters x and w are loaded with the following syntax: model.a = Set(initialize=[ A1, A2, A3, A4 ]) model.x = Param(model.A) model.w = Param(model.A) data.load(filename= tab/xw.tab, param=(model.x,model.w)) Note that the data for set A is predefined in this example. The index set can be loaded with the parameter data using the index option: model.a = Set() model.x = Param(model.A) model.w = Param(model.A) data.load(filename= tab/xw.tab, param=(model.x,model.w), index=model.a) We have previously noted that the column names are not used to define the set and parameter data. The select option is used to define the columns in the table that are used to load data. This option specifies a list (or tuple) of column names that are used, in that order, to form the table that defines the component data. For example, consider the following load declaration: model.a = Set() model.w = Param(model.A) data.load(filename= tab/xw.tab, select=( A, W ), param=model.w, index=model.a)

40 Pyomo online Documentation / 78 The columns A and W are selected from the file XW.tab, and a single parameter is defined. Note The load method allows for a variety of other options that are supported by the add method for ModelData objects. See the Pyomo book for a detailed description of these options.

41 Pyomo online Documentation / 78 Chapter 10 The pyomo Command The pyomo command is issued to the DOS prompt or a Unix shell. To see a list of Pyomo command line options, use: pyomo --help Note There are two dashes before help. In this section we will detail some of the options Passing Options to a Solver To pass arguments to a solver, use the Pyomo argument --solver-options= followed by an argument that is a string to be sent to the solver (perhaps with dashes added by Coopr). So for most MIP solvers, the mip gap can be set using --solver-options= "mipgap=0.01 " Multiple options are separated by a space. For example, to specify that the solver is GLPK, then to specify a mipgap of two percent and the GLPK cuts option, use --solver=glpk --solver-options="mipgap=0.02 cuts" If there are multiple "levels" to the keyword, as is the case for some Gurobi and CPLEX options, the tokens are separated by underscore. For example, mip cuts all would be specified as mip_cuts_all. For another example, to set the solver to be CPLEX, then to set a mip gap of one percent and to specify y for the sub-option numerical to the option emphasis use --solver=cplex --solver-options="mipgap=0.001 emphasis_numerical=y" See Solver Options for a discusion of passing options in a script Troubleshooting Many of things that can go wrong are covered by error messages, but sometimes they can be confusing or do not provide enough information. Depending on what the troubles are, there might be ways to get a little additional information. If there are syntax errors in the model file, for example, it can occasionally be helpful to get error messages directly from the Python interpreter rather than through Pyomo. Suppose the name of the model file is scuc.py, then

42 Pyomo online Documentation / 78 python scuc.py can sometimes give useful information for fixing syntax errors. When there are no syntax errors, but there troubles reading the data or generating the information to pass to a solver, then the - -verbose option provides a trace of the execution of Pyomo. The user should be aware that for some models this option can generate a lot of output. If there are troubles with solver (i.e., after Pyomo has output "Applying Solver"), it is often helpful to use the option --streamsolver that causes the solver output to be displayed rather than trapped. (See Solver Display for information about getting this output in a script). Advanced users may wish to examine the files that are generated to be passed to a solver. The type of file generated is controlled by the --solver-io option and the --keepfiles option instructs pyomo to keep the files and output their names. However, the --symbolic-solver-labels option should usually also be specified so that meaningful names are used in these files. When there seem to be troubles expressing the model, it is often useful to embed print commands in the model in places that will yield helpful information. Consider the following snippet: def ax_constraint_rule(model, i): # return the expression for the constraint for i print "ax_constraint_rule was called for i=",i return sum(model.a[i,j] * model.x[j] for j in model.j) >= model.b[i] # the next line creates one constraint for each member of the set model.i model.axbconstraint = Constraint(model.I, rule=ax_constraint_rule) The effect will be to output every member of the set model.i at the time the constraint named model.axbconstraint is constructed Direct Interfaces to Solvers In many applications, the default solver interface works well. However, in some cases it is useful to specify the interface using the solver-io option. For example, if the solver supports a direct Python interface, then the option would be specified on the command line as --solver-io=python Here are some of the choices: lp: generate a standard linear programming format file with filename extension lp nlp: generate a file with a standard format that supports linear and nonlinear optimization with filename extension n1lp os: generate an OSiL format XML file. python: use the direct Python interface. Note that not all solvers support all interfaces.

43 Pyomo online Documentation / 78 Chapter 11 PySP Overview This chapter describes PySP: (Pyomo Stochastic Programming), where parameters are allowed to be uncertain Overview of Modeling Components and Processes The sequence of activities is typically the following: Create a deterministic model and declare components Develop base-case data for the deterministic model Test, verify and validate the deterministic model Model the stochastic processes Develop a way to generate scenarios (in the form of a tree if there are more than two stages) Create the data files need to describe the stochastics Use PySP to solve stochastic problem When viewed from the standpoint of file creation, the process is Create an abstract model for the deterministic problem in a file called ReferenceModel.py Specify data for this model in a file called ReferenceModel.dat Specify the stochastics in a file called ScenarioStructure.dat Specify scenario data 11.2 Birge and Louveaux s Farmer Problem Birge and Louveaux [BirgeLouveauxBook] make use of the example of a farmer who has 500 acres that can be planted in wheat, corn or sugar beets, at a per acre cost of 150, 230 and 260 (Euros, presumably), respectively. The farmer needs to have at least 200 tons of wheat and 240 tons of corn to use as feed, but if enough is not grown, those crops can be purchased for 238 and 210, respectively. Corn and wheat grown in excess of the feed requirements can be sold for 170 and 150, respectively. A price of 36 per ton is guaranteed for the first 6000 tons grown by any farmer, but beets in excess of that are sold for 10 per ton. The yield is 2.5, 3, and 20 tons per acre for wheat, corn and sugar beets, respectively.

44 Pyomo online Documentation / ReferenceModel.py So far, this is a deterministic problem because we are assuming that we know all the data. The Pyomo model for this problem shown here is in the file ReferenceModel.py in the sub-directory examples/pysp/farmer/models that is distributed with Coopr. # Farmer: rent out version has a scalar root node var # note: this will minimize # # Imports # from future import division from pyomo.environ import * # # Model # model = AbstractModel() # # Parameters # model.crops = Set() model.total_acreage = Param(within=PositiveReals) model.pricequota = Param(model.CROPS, within=positivereals) model.subquotasellingprice = Param(model.CROPS, within=positivereals) def super_quota_selling_price_validate (model, value, i): return model.subquotasellingprice[i] >= model.superquotasellingprice[i] model.superquotasellingprice = Param(model.CROPS, validate= super_quota_selling_price_validate) model.cattlefeedrequirement = Param(model.CROPS, within=nonnegativereals) model.purchaseprice = Param(model.CROPS, within=positivereals) model.plantingcostperacre = Param(model.CROPS, within=positivereals) model.yield = Param(model.CROPS, within=nonnegativereals) # # Variables # model.devotedacreage = Var(model.CROPS, bounds=(0.0, model.total_acreage)) model.quantitysubquotasold = Var(model.CROPS, bounds=(0.0, None)) model.quantitysuperquotasold = Var(model.CROPS, bounds=(0.0, None)) model.quantitypurchased = Var(model.CROPS, bounds=(0.0, None)) model.firststagecost = Var() model.secondstagecost = Var() #

45 Pyomo online Documentation / 78 # Constraints # def ConstrainTotalAcreage_rule(model): return summation(model.devotedacreage) <= model.total_acreage model.constraintotalacreage = Constraint(rule=ConstrainTotalAcreage_rule) def EnforceCattleFeedRequirement_rule(model, i): return model.cattlefeedrequirement[i] <= (model.yield[i] * model.devotedacreage[i]) + model.quantitypurchased[i] - model.quantitysubquotasold[i] - model. QuantitySuperQuotaSold[i] model.enforcecattlefeedrequirement = Constraint(model.CROPS) def LimitAmountSold_rule(model, i): return model.quantitysubquotasold[i] + model.quantitysuperquotasold[i] - (model.yield[i ] * model.devotedacreage[i]) <= 0.0 model.limitamountsold = Constraint(model.CROPS) def EnforceQuotas_rule(model, i): return (0.0, model.quantitysubquotasold[i], model.pricequota[i]) model.enforcequotas = Constraint(model.CROPS) # # Stage-specific cost computations # def ComputeFirstStageCost_rule(model): return model.firststagecost - summation(model.plantingcostperacre, model.devotedacreage ) == 0.0 model.computefirststagecost = Constraint() def ComputeSecondStageCost_rule(model): expr = summation(model.purchaseprice, model.quantitypurchased) expr -= summation(model.subquotasellingprice, model.quantitysubquotasold) expr -= summation(model.superquotasellingprice, model.quantitysuperquotasold) return (model.secondstagecost - expr) == 0.0 model.computesecondstagecost = Constraint() # # Objective # def Total_Cost_Objective_rule(model): return model.firststagecost + model.secondstagecost model.total_cost_objective = Objective(sense=minimize) ReferenceModel.dat The data introduced here are in the file ReferenceModel.dat in the sub-directory examples/pysp/farmer/scenariodata that is distributed with Coopr. set CROPS := WHEAT CORN SUGAR_BEETS ;

46 Pyomo online Documentation / 78 param TOTAL_ACREAGE := 500 ; # no quotas on wheat or corn param PriceQuota := WHEAT CORN SUGAR_BEETS 6000 ; param SubQuotaSellingPrice := WHEAT 170 CORN 150 SUGAR_BEETS 36 ; param SuperQuotaSellingPrice := WHEAT 0 CORN 0 SUGAR_BEETS 10 ; param CattleFeedRequirement := WHEAT 200 CORN 240 SUGAR_BEETS 0 ; # can t purchase beets (no need, as cattle don t eat them) param PurchasePrice := WHEAT 238 CORN 210 SUGAR_BEETS ; param PlantingCostPerAcre := WHEAT 150 CORN 230 SUGAR_BEETS 260 ; param Yield := WHEAT 3.0 CORN 3.6 SUGAR_BEETS 24 ; Any of these data could be modeled as uncertain, but we will consider only the possibility that the yield per acre could be higher or lower than expected. Assume that there is a probability of 1/3 that the yields will be the average values that were given (i.e., wheat 2.5; corn 3; and beets 20). Assume that there is a 1/3 probability that they will be lower (2, 2.4, 16) and 1/3 probability they will be higher (3, 3.6, 24). We refer to each full set of data as a scenario and collectively we call them a scenario tree. In this case the scenario tree is very simple: there is a root node and three leaf nodes: one corresponding to each scenario. The acreage-to-plant decisions are root node decisions because they must be made without knowing what the yield will be. The other variables are so-called second stage decisions, because they will depend on which scenario is realized ScenarioStructure.dat PySP requires that users describe the scenario tree using specific constructs in a file named ScenarioStructure.dat; for the farmer problem, this file can be found in the coopr sub-directory examples/pysp/farmer/scenariodata that is distributed with Coopr. # IMPORTANT - THE STAGES ARE ASSUMED TO BE IN TIME-ORDER. set Stages := FirstStage SecondStage ; set Nodes := RootNode BelowAverageNode AverageNode AboveAverageNode ; param NodeStage := RootNode FirstStage BelowAverageNode SecondStage AverageNode SecondStage AboveAverageNode SecondStage ; set Children[RootNode] := BelowAverageNode AverageNode AboveAverageNode ; param ConditionalProbability := RootNode 1.0 BelowAverageNode AverageNode AboveAverageNode ;

47 Pyomo online Documentation / 78 set Scenarios := BelowAverageScenario AverageScenario AboveAverageScenario ; param ScenarioLeafNode := BelowAverageScenario BelowAverageNode AverageScenario AverageNode AboveAverageScenario AboveAverageNode ; set StageVariables[FirstStage] := DevotedAcreage[*] ; set StageVariables[SecondStage] := QuantitySubQuotaSold[*] QuantitySuperQuotaSold[*] QuantityPurchased[*] ; param StageCostVariable := FirstStage FirstStageCost SecondStage SecondStageCost ; This data file is verbose and somewhat redundant, but in most applications it is generated by software rather than by a person, so this is not an issue. Generally, the left-most part of each expression (e.g. set Stages := ) is required and uses reserved words (e.g., Stages) and the other names are supplied by the user (e.g., FirstStage could be any name). Every assignment is terminated with a semi-colon. We will now consider the assignments in this file one at a time. The first assignments provides names for the stages and the words "set Stages" are required, as are the := symbols. Any names can be used. In this example, we used "FirstStage" and "SecondStage" but we could have used "EtapPrimero" and "ZweiteEtage" if we had wanted to. Whatever names are given here will continue to be used to refer to the stages in the rest of the file. The order of the names is important. A simple way to think of it is that generally, the names must be in time order (technically, they need to be in order of information discovery, but that is usually time-order). Stages refers to decision stages, which may, or may not, correspond directly with time stages. In the farmer example, decisions about how much to plant are made in the first stage and "decisions" (which are pretty obvious, but which are decision variables nonetheless) about how much to sell at each price and how much needs to be bought are second stage decisions because they are made after the yield is known. set Stages := FirstStage SecondStage ; Node names are constructed next. The words "set Nodes" are required, but any names may be assigned to the nodes. In two stage stochastic problems there is a root node, which we chose to name "RootNode" and then there is a node for each scenario. set Nodes := RootNode BelowAverageNode AverageNode AboveAverageNode ; Nodes are associated with time stages with an assignment beginning with the required words "param Nodestage." The assignments must make use of previously defined node and stage names. Every node must be assigned a stage. param NodeStage := RootNode FirstStage BelowAverageNode SecondStage AverageNode SecondStage AboveAverageNode SecondStage ; The structure of the scenario tree is defined using assignment of children to each node that has them. Since this is a two stage problem, only the root node has children. The words "param Children" are required for every node that has children and the name of the node is in square brackets before the colon-equals assignment symbols. A list of children is assigned. set Children[RootNode] := BelowAverageNode AverageNode AboveAverageNode ; The probability for each node, conditional on observing the parent node is given in an assignment that begins with the required words "param ConditionalProbability." The root node always has a conditional probability of 1, but it must always be given anyway. In this example, the second stage nodes are equally likely.

48 Pyomo online Documentation / 78 param ConditionalProbability := RootNode 1.0 BelowAverageNode AverageNode AboveAverageNode ; Scenario names are given in an assignment that begins with the required words "set Scenarios" and provides a list of the names of the scenarios. Any names may be given. In many applications they are given unimaginative names generated by software such as "Scen1" and the like. In this example, there are three scenarios and the names reflect the relative values of the yields. set Scenarios := BelowAverageScenario AverageScenario AboveAverageScenario ; Leaf nodes, which are nodes with no children, are associated with scenarios. This assignment must be one-to-one and it is initiated with the words "param ScenarioLeafNode" followed by the colon-equals assignment characters. param ScenarioLeafNode := BelowAverageScenario BelowAverageNode AverageScenario AverageNode AboveAverageScenario AboveAverageNode ; Variables are associated with stages using an assignment that begins with the required words "set StageVariables" and the name of a stage in square brackets followed by the colon-equals assignment characters. Variable names that have been defined in the file ReferenceModel.py can be assigned to stages. Any variables that are not assigned are assumed to be in the last stage. Variable indexes can be given explicitly and/or wildcards can be used. Note that the variable names appear without the prefix "model." In the farmer example, DevotedAcreage is the only first stage variable. set StageVariables[FirstStage] := DevotedAcreage[*] ; set StageVariables[SecondStage] := QuantitySubQuotaSold[*] QuantitySuperQuotaSold[*] QuantityPurchased[*] ; For reporting purposes, it is useful to define auxiliary variables in ReferenceModel.py that will be assigned the cost associated with each stage. This variables do not impact algorithms, but the values are output by some software during execution as well as upon completion. The names of the variables are assigned to stages using the "param StageCostVariable" assignment. The stages are previously defined in ScenarioStructure.dat and the variables are previously defined in ReferenceModel. py. Note that the variable names appear without the prefix "model." param StageCostVariable := FirstStage FirstStageCost SecondStage SecondStageCost ; Scenario data specification So far, we have given a model in the file named ReferenceModel.py, a set of deterministic data in the file named Referen cemodel.py, and a description of the stochastics in the file named ScenarioStructure.dat. All that remains is to give the data for each scenario. There are two ways to do that in PySP: scenario-based and node-based. The default is scenario-based so we will describe that first. For scenario-based data, the full data for each scenario is given in a.dat file with the root name that is the name of the scenario. So, for example, the file named AverageScenario.dat must contain all the data for the model for the scenario named "AvererageScenario." It turns out that this file can be created by simply copying the file ReferenceModel.dat as shown above because it contains a full set of data for the "AverageScenario" scenario. The files BelowAverageScenario. dat and AboveAverageScenario.dat will differ from this file and from each other only in their last line, where the yield is specified. These three files are distributed with Coopr and are in the coopr sub-directory examples/pysp/farmer/ scenariodata along with ScenarioStructure.dat and ReferenceModel.dat. Scenario-based data wastes resources by specifying the same thing over and over again. In many cases, that does not matter and it is convenient to have full scenario data files available (for one thing, the scenarios can easily be run independently using

49 Pyomo online Documentation / 78 the pyomo command). However, in many other settings, it is better to use a node-based specification where the data that is unique to each node is specified in a.dat file with a root name that matches the node name. In the farmer example, the file RootNode.dat will be the same as ReferenceModel.dat except that it will lack the last line that specifies the yield. The files BelowAverageNode.dat, AverageNode.dat, and AboveAverageNode.dat will contain only one line each to specify the yield. If node-based data is to be used, then the ScenarioStructure.dat file must contain the following line: param ScenarioBasedData := False ; An entire set of files for node-based data for the farmer problem are distributed with Coopr in the sub-directory examples/ pysp/farmer/nodedata 11.3 Finding Solutions for Stochastic Models PySP provides a variety of tools for finding solutions to stochastic programs runef The runef command puts together the so-called extensive form version of the model. It creates a large model that has constraints to ensure that variables at a node have the same value. For example, in the farmer problem, all of the DevotedAcres variables must have the same value regardless of which scenario is ultimately realized. The objective can be the expected value of the objective function, or the CVaR, or a weighted combination of the two. Expected value is the default. A full set of options for runef can be obtained using the command: runef --help The coopr distribution contains the files need to run the farmer example in the sub-directories to the sub-directory examples/ pysp/farmer so if this is the current directory and if CPLEX is installed, the following command will cause formation of the EF and its solution using CPLEX. runef -m models -i nodedata --solver=cplex --solve The option -m models has one dash and is short-hand for the option --model-directory=models and note that the full option uses two dashes. The -i is equivalent to --instance-directory= in the same fashion. The default solver is CPLEX, so the solver option is not really needed. With the --solve option, runef would simply write an.lp data file that could be passed to a solver runph The runph command executes an implementation of Progressive Hedging (PH) that is intended to support scripting and extension. The coopr distribution contains the files need to run the farmer example in the sub-directories to the sub-directory examples/pysp/- farmer so if this is the current directory and if CPLEX is installed, the following command will cause PH to execute using the default sub-problem solver, which is CPLEX. runph -m models -i nodedata The option -m models has one dash and is short-hand for the option --model-directory=models and note that the full option uses two dashes. The -i is equivalent to --instance-directory= in the same fashion. After about 33 iterations, the algorithm will achieve the default level of convergence and terminate. A lot of output is generated and among the output is the following solution information: Variable=DevotedAcreage Index: [CORN] (Scenarios: BelowAverageScenario AverageScenario AboveAverageScenario ) Values: Max-Min= Avg=

50 Pyomo online Documentation / 78 Index: [SUGAR_BEETS] (Scenarios: BelowAverageScenario AverageScenario AboveAverageScenario ) Values: Max-Min= Avg= Index: [WHEAT] (Scenarios: BelowAverageScenario AverageScenario AboveAverageScenario ) Values: Max-Min= Avg= Cost Variable=FirstStageCost Tree Node=RootNode (Scenarios: BelowAverageScenario AverageScenario AboveAverageScenario ) Values: Max-Min= Avg= For problems with no, or few, integer variables, the default level of convergence leaves root-node variables almost converged. Since the acreage to be planted cannot depend on the scenario that will be realized in the future, the average, which is labeled "Avg" in this output, would be used. A farmer would probably interpret acreages of , , and to be 80, 250, and 170. In real-world applications, PH is embedded in scripts that produce output in a format desired by a decision maker. But in real-world applications, the default settings for PH seldom work well enough. In addition to post-processing the output, a number of parameters need to be adjusted and sometimes scripting to extend or augment the algorithm is needed to improve convergence rates. A full set of options can be obtained with the command: runph --help Note that there are two dashes before help. By default, PH uses quadratic objective functions after iteration zero; in some settings it may be desirable to linearize the quadratic terms. This is required to use a solver such as glpk for MIPs because it does not support quadratic MIPs. The directive --linearize-nonbinary-penalty-terms=n causes linearization of the penalty terms using n pieces. For example, to use glpk on the farmer, assuming glpk is installed and the command is given when the current directory is the examples/ pysp/farmer, the following command will use default settings for most parameters and four pieces to approximate quadratic terms in sub-problems: runph -i nodedata -m models --solver=glpk --linearize-nonbinary-penalty-terms=4 Use of the linearize-nonbinary-penalty-terms option requires that all variables not in the final stage have bounds Solution Output Control To get the full solution, including leaf node solution values, use the runph --output-scenario-tree-solution option. In both runph and runef the solution can be written in csv format using the --solution-writer=coopr.pysp. csvsolutionwriter option Summary of PySP File Names PySP scripts such as runef and runph require files that specify the model and data using files with specific names. All files can be in the current directory, but typically, the file ReferenceModel.py is in a directory that is specified using --modeldirectory= option (the short version of this option is -i +) and the data files are in a directory spe cified in the +--instance-directory= option (the short version of this option is +-m +). ReferenceModel.py: A full Pyomo model for a singe scenario. There should be no scenario indexes in this model because they are implicit. ReferenceModel.dat: A full set of data for an arbitrary scenario. This will not be used during solution, but just used to define indexes.

51 Pyomo online Documentation / 78 ScenarioStructure.dat: Specifies the nature of the stochastics. It also specifies whether the rest of the data is nodebased or scenario-based. It is scenario-based unless ScenarioStructure.dat contains the line param ScenarioBasedData := False ; If scenario-based, then there is a data file for each scenario that specifies a full set of data for the scenario. The name of the file is the name of the scenario with.dat appended. The names of the scenarios are given in the ScenarioStructure.dat file. If node-based, then there is a file with data for each node that specifies only that data that is unique for the node. The name of the file is the name of the node with.dat appended. The names of the nodes are given in the ScenarioStructure.dat file Solving Sub-problems in Parallel and/or Remotely The Python package called Pyro provides capalities that are used to enable PH to make use of multiple solver processes for sub-problems and allows both runef and runph to make use remote solvers. We will focus on PH in our discussion here. There are two solver management systems available for runph, one is based on a pyro_mip_server and the other is based on a phsolverserver. Regardless of which is used, a name server and a dispatch server must be running and accessible to the runph process. The name server is launched using the command coopr_ns and then the dispatch server is launched with dispatch_srvr. Note that both commands contain an underscore. Both programs keep running until terminated by an external signal, so it is common to pipe their output to a file. Solvers are controlled by solver servers. The pyro mip solver server is launched with the command pyro_mip_server. This command may be repeated to launch as many solvers as are desired. The runph then needs a --solver-manager=pyro option to signal that runph should not launch its own solver, but should send subproblems to be dispatched to parallel solvers. To summarize the commands: Once: coopr_ns Once: dispatch_srvr Multiple times: pyro_mip_server Once: runph... --solver-manager=pyro... Note The runph option --shutdown-pryo will cause a shutdown signal to be sent to coopr_ns, dispatch_srvr and all pyro_mip_server programs upon termination of runph. Instead of using pyro_mip_server, one can use phsolverserver in its place. You can get a list of arguments using pyrosolverserver --help, which does not launch a solver server (it just displays help and terminates). If you use the phsolversover, then use --solver-manager=phpyro as an argument to runph rather than --solver-manager=pyro. Warning Unlike the normal pyro_mip_server, there must be one phsolverserver for each sub-problem.

52 Pyomo online Documentation / 78 Chapter 12 Suffixes Suffixes provide a mechanism for declaring extraneous model data, which can be used in a number of contexts. Most commonly, suffixes are used by solver plugins to store extra information about the solution of a model. This and other suffix functionality is made available to the modeler through the use of the Suffix component class. Uses of Suffix include: Importing extra information from a solver about the solution of a mathematical program (e.g., constraint duals, variable reduced costs, basis information). Exporting information to a solver or algorithm to aid in solving a mathematical program (e.g., warm-starting information, variable branching priorities). Tagging modeling components with local data for later use in advanced scripting algorithms Suffix Notation and the Pyomo NL File Interface The Suffix component used in Pyomo has been adapted from the suffix notation used in the modeling language AMPL [AMPL]. Therefore, it follows naturally that AMPL style suffix functionality is fully available using Pyomo s NL file interface. For information on AMPL style suffixes the reader is referred to the AMPL website: A number of scripting examples that highlight the use AMPL style suffix functionality are available in the examples/pyomo/ suffixes directory distributed with Coopr Declaration The effects of declaring a Suffix component on a Pyomo model are determined by the following traits: direction: This trait defines the direction of information flow for the suffix. A suffix direction can be assigned one of four possible values: LOCAL - suffix data stays local to the modeling framework and will not be imported or exported by a solver plugin (default) IMPORT - suffix data will be imported from the solver by its respective solver plugin EXPORT - suffix data will be exported to a solver by its respective solver plugin IMPORT_EXPORT - suffix data flows in both directions between the model and the solver or algorithm datatype: This trait advertises the type of data held on the suffix for those interfaces where it matters (e.g., the NL file interface). A suffix datatype can be assigned one of three possible values:

53 Pyomo online Documentation / 78 FLOAT - the suffix stores floating point data (default) INT - the suffix stores integer data None - the suffix stores any type of data Note Exporting suffix data through Pyomo s NL file interface requires all active export suffixes have a strict datatype (i.e., datat ype=none is not allowed). The following code snippet shows examples of declaring a Suffix component on a Pyomo model: from coopr.pyomo import * model = ConcreteModel() # Export integer data model.priority = Suffix(direction=Suffix.EXPORT, datatype=suffix.int) # Export and import floating point data model.dual = Suffix(direction=Suffix.IMPORT_EXPORT) # Store floating point data model.junk = Suffix() Declaring a Suffix with a non-local direction on a model is not guaranteed to be compatible with all solver plugins in Coopr. Whether a given Suffix is acceptable or not depends on both the solver and solver interface being used. In some cases, a solver plugin will raise an exception if it encounters a Suffix type that it does not handle, but this is not true in every situation. For instance, the NL file interface is generic to all AMPL-compatible solvers, so there is no way to validate that a Suffix of a given name, direction, and datatype is appropriate for a solver. One should be careful in verifying that Suffix declarations are being handled as expected when switching to a different solver or solver interface Operations The Suffix component class provides a dictionary interface for mapping Coopr modeling components to arbitrary data. This mapping functionality is captured within the ComponentMap base class, which is also available within Pyomo s modeling environment. The ComponentMap can be used as a more lightweight replacement for Suffix in cases where a simple mapping from Coopr modeling components to arbitrary data values is required. Note ComponentMap and Suffix use the built-in id() function for hashing entry keys. This design decision arises from the fact that most of the modeling components found in Coopr are either not hashable or use a hash based on a mutable numeric value, making them unacceptable for use as keys with the built-in dict class. Warning The use of the built-in id() function for hashing entry keys in ComponentMap and Suffix makes them inappropriate for use in situations where built-in object types must be used as keys. It is strongly recommended that only Coopr modeling components be used as keys in these mapping containers (Var, Constraint, etc.). Warning Do not attempt to pickle or deepcopy instances of ComponentMap or Suffix unless doing so along with the components for which they hold mapping entries. As an example, placing one of these objects on a model and then cloning or pickling that model is an acceptable scenario.

54 Pyomo online Documentation / 78 In addition to the dictionary interface provided through the ComponentMap base class, the Suffix component class also provides a number of methods whose default semantics are more convenient for working with indexed modeling components. The easiest way to highlight this functionality is through the use of an example. from coopr.pyomo import * model = ConcreteModel() model.x = Var() model.y = Var([1,2,3]) model.foo = Suffix() In this example we have a concrete Pyomo model with two different types of variable components (indexed and non-indexed) as well as a Suffix declaration (foo). The next code snippet shows examples of adding entries to the suffix foo. # Assign a suffix value of 1.0 to model.x model.foo.setvalue(model.x, 1.0) # Same as above with dict interface model.foo[model.x] = 1.0 # Assign a suffix value of 0.0 to all indices of model.y # By default this expands so that entries are created for # every index (y[1], y[2], y[3]) and not model.y itself model.foo.setvalue(model.y, 0.0) # The same operation using the dict interface results in an entry only # for the parent component model.y model.foo[model.y] = 50.0 # Assign a suffix value of -1.0 to model.y[1] model.foo.setvalue(model.y[1], -1.0) # Same as above with the dict interface model.foo[model.y[1]] = -1.0 In this example we highlight the fact that the setitem and setvalue entry methods can be used interchangeably except in the case where indexed components are used (model.y). In the indexed case, the setitem approach creates a single entry for the parent indexed component itself, whereas the setvalue approach by default creates an entry for each index of the component. This behavior can be controlled using the optional keyword expand, where assigning it a value of False results in the same behavior as setitem. Other operations like accessing or removing entries in our mapping can performed as if the built-in dict class is in use. print(model.foo.get(model.x)) # -> 1.0 print(model.foo[model.x]) # -> 1.0 print(model.foo.get(model.y[1])) # -> -1.0 print(model.foo[model.y[1]]) # -> -1.0 print(model.foo.get(model.y[2])) # -> 0.0 print(model.foo[model.y[2]]) # -> 0.0 print(model.foo.get(model.y)) # -> 50.0 print(model.foo[model.y]) # -> 50.0 del model.foo[model.y] print(model.foo.get(model.y)) print(model.foo[model.y]) # -> None # -> raise KeyError

55 Pyomo online Documentation / 78 The non-dict method clearvalue can be used in place of delitem to remove entries, where it inherits the same default behavior as setvalue for indexed components and does not raise a KeyError when the argument does not exist as a key in the mapping. model.foo.clearvalue(model.y) print(model.foo[model.y[1]]) del model.foo[model.y[1]] model.foo.clearvalue(model.y[1]) # -> raise KeyError # -> raise KeyError # -> does nothing A summary non-dict Suffix methods is provided here: clearallvalues() Clears all suffix data. clearvalue(component, expand=true) Clears suffix information for a component. setallvalues(value) Sets the value of this suffix on all components. setvalue(component, value, expand=true) Sets the value of this suffix on the specified component. updatevalues(data_buffer, expand=true) Updates the suffix data given a list of component,value tuples. Provides an improvement in efficiency over calling setvalue on every component. getdatatype() Return the suffix datatype. setdatatype(datatype) Set the suffix datatype. getdirection() Return the suffix direction. setdirection(direction) Set the suffix direction. importenabled() Returns True when this suffix is enabled for import from solutions. exportenabled() Returns True when this suffix is enabled for export to solvers Importing Suffix Data Importing suffix information from a solver solution is achieved by declaring a Suffix component with the appropriate name and direction. Suffix names available for import may be specific to third-party solvers as well as individual solver interfaces within Coopr. The most common of these, available with most solvers and solver interfaces, is constraint dual multipliers. Requesting that duals be imported into suffix data can be accomplished by declaring a Suffix component on the model. from coopr.pyomo import *

56 Pyomo online Documentation / 78 model = ConcreteModel() model.dual = Suffix(direction=Suffix.IMPORT) model.x = Var() model.obj = Objective(expr=model.x) model.con = Constraint(expr=model.x>=1.0) The existence of an active suffix with the name dual that has an import style suffix direction will cause constraint dual information to be collected into the solver results (assuming the solver supplies dual information). In addition to this, after loading solver results into a problem instance (using a python script or Pyomo callback functions in conjunction with the pyomo command), one can access the dual values associated with constraints using the dual Suffix component. print(instance.dual[instance.con]) # -> 1.0 Alternatively, the pyomo option --solver-suffixes can be used to request suffix information from a solver. In the event that suffix names are provided via this command-line option, the pyomo script will automatically declare these Suffix components on the constructed instance making these suffixes available for import Exporting Suffix Data Exporting suffix data is accomplished in a similar manner as to that of importing suffix data. One simply needs to declare a Suffix component on the model with an export style suffix direction and associate modeling component values with it. The following example shows how one can declare a special ordered set of type 1 using AMPL-style suffix notation in conjunction with Pyomo s NL file interface. from coopr.pyomo import * model = ConcreteModel() model.y = Var([1,2,3],within=NonNegativeReals) model.sosno = Suffix(direction=Suffix.EXPORT) model.ref = Suffix(direction=Suffix.EXPORT) # Add entry for each index of model.y model.sosno.setvalue(model.y,1) model.ref[model.y[1]] = 0 model.ref[model.y[2]] = 1 model.ref[model.y[3]] = 2 Most AMPL-compatible solvers will recognize the suffix names sosno and ref as declaring a special ordered set, where a positive value for sosno indicates a special ordered set of type 1 and a negative value indicates a special ordered set of type 2. Note Pyomo provides the SOSConstraint component for declaring special ordered sets, which is recognized by all solver interface, including the NL file interface. Pyomo s NL file interface will recognize an EXPORT style Suffix component with the name dual as supplying initializations for constraint multipliers. As such it will be treated separately than all other EXPORT style suffixes encountered in the NL writer, which are treated as AMPL-style suffixes. The following example script shows how one can warmstart the interior-point solver Ipopt by supplying both primal (variable values) and dual (suffixes) solution information. This dual suffix information can be both imported and exported using a single Suffix component with an IMPORT_EXPORT direction. from pyomo.environ import * ### Create the ipopt solver plugin using the ASL interface solver = ipopt

57 Pyomo online Documentation / 78 solver_io = nl stream_solver = True # True prints solver output to screen keepfiles = False # True prints intermediate file names (.nl,.sol,...) opt = SolverFactory(solver,solver_io=solver_io) if opt is None: print("") print("error: Unable to create solver plugin for %s "\ "using the %s interface" % (solver, solver_io)) print("") exit(1) ### ### Create the example model model = ConcreteModel() model.x1 = Var(bounds=(1,5),initialize=1.0) model.x2 = Var(bounds=(1,5),initialize=5.0) model.x3 = Var(bounds=(1,5),initialize=5.0) model.x4 = Var(bounds=(1,5),initialize=1.0) model.obj = Objective(expr=model.x1*model.x4*(model.x1+model.x2+model.x3) + model.x3) model.inequality = Constraint(expr=model.x1*model.x2*model.x3*model.x4 >= 25.0) model.equality = Constraint(expr=model.x1**2 + model.x2**2 + model.x3**2 + model.x4**2 == 40.0) ### ### Declare all suffixes # Ipopt bound multipliers (obtained from solution) model.ipopt_zl_out = Suffix(direction=Suffix.IMPORT) model.ipopt_zu_out = Suffix(direction=Suffix.IMPORT) # Ipopt bound multipliers (sent to solver) model.ipopt_zl_in = Suffix(direction=Suffix.EXPORT) model.ipopt_zu_in = Suffix(direction=Suffix.EXPORT) # Obtain dual solutions from first solve and send to warm start model.dual = Suffix(direction=Suffix.IMPORT_EXPORT) ### # Build the expression trees for the model objectives and constraints model.preprocess() ### Send the model to ipopt and collect the solution print("") print("initial SOLVE") results = opt.solve(model,keepfiles=keepfiles,tee=stream_solver) # load the results (including any values for previously declared # IMPORT / IMPORT_EXPORT Suffix components) model.load(results) ### ### Set Ipopt options for warm-start # The current values on the ipopt_zu_out and # ipopt_zl_out suffixes will be used as initial # conditions for the bound multipliers to solve # the new problem model.ipopt_zl_in.update(model.ipopt_zl_out) model.ipopt_zu_in.update(model.ipopt_zu_out) opt.options[ warm_start_init_point ] = yes opt.options[ warm_start_bound_push ] = 1e-6 opt.options[ warm_start_mult_bound_push ] = 1e-6 opt.options[ mu_init ] = 1e-6 ### ### Send the model and suffix information to ipopt and collect the solution

58 Pyomo online Documentation / 78 print("") print("warm-started SOLVE") # The solver plugin will scan the model for all active suffixes # valid for importing, which it will store into the results object results = opt.solve(model,keepfiles=keepfiles,tee=stream_solver) # load the results (including any values for previously declared # IMPORT / IMPORT_EXPORT Suffix components) model.load(results) ### The difference in performance can be seen by examining Ipopt s iteration log with and without warm starting: Without Warmstart: iter objective inf_pr inf_du lg(mu) d lg(rg) alpha_du alpha_pr ls e e e e e e e e e e e e+00f e e e e e e+00h e e e e e e+00h e e e e e e+00h e e e e e e-01h e e e e e e+00h e e e e e e+00h e e e e e e+00h 1 Number of Iterations...: 8 With Warmstart: iter objective inf_pr inf_du lg(mu) d lg(rg) alpha_du alpha_pr ls e e e e e e e e e e e e+00h e e e e e e+00h 1 Number of Iterations...: Using Suffixes With an AbstractModel In order to allow the declaration of suffix data within the framework of an AbstractModel, the Suffix component can be initialized with an optional construction rule. As with constraint rules, this function will be executed at the time of model construction. The following simple example highlights the use of the rule keyword in suffix initialization. Suffix rules are expected to return an iterable of (component, value) tuples, where the expand=true semantics are applied for indexed components. from coopr.pyomo import * model = AbstractModel() model.x = Var() model.c = Constraint(expr= model.x >= 1) def foo_rule(m): return ((m.x, 2.0), (m.c, 3.0)) model.foo = Suffix(rule=foo_rule) # Instantiate the model inst = model.create() print(inst.foo[model.x]) # -> raise KeyError print(inst.foo[inst.x]) # -> 2.0 print(inst.foo[inst.c]) # -> 3.0

59 Pyomo online Documentation / 78 The next example shows an abstract model where suffixes are attached only to the variables: from pyomo.environ import * model = AbstractModel() model.i = RangeSet(1,4) model.x = Var(model.I) def c_rule(m, i): return m.x[i] >= i model.c = Constraint(model.I, rule=c_rule) def foo_rule(m): return ((m.x[i], 3.0*i) for i in m.i) model.foo = Suffix(rule=foo_rule) # instantiate the model inst = model.create() for i in inst.i: print i, inst.foo[inst.x[i]]

60 Pyomo online Documentation / 78 Chapter 13 Scripts There are two main ways to add scripting for Pyomo models: using Python scripts and using callbacks for the pyomo command that alter or supplement its workflow Python Scripts Iterative Example To illustrate Python scripts for Pyomo we consider an example that is in the file iterative1.py and is executed using the command python iterative1.py Note This is a Python script that contains elements of Pyomo, so it is executed using the python command. The pyomo command can be used, but then there will be some strange messages at the end when Pyomo finishes the script and attempts to send the results to a solver, which is what the pyomo command does. This script creates a model, solves it, and then adds a constraint to preclude the solution just found. This process is repeated, so the script finds and prints multiple solutions. The particular model it creates is just the sum of four binary variables. One does not need a computer to solve the problem or even to iterate over solutions. This example is provided just to illustrate some elementary aspects of scripting. Note The built-in code for printing solutions prints only non-zero variable values. So if you run this code, no variable values will be output for the first solution found because all of the variables are zero. However, other information about the solution, such as the objective value, will be displayed. # iterative1.py from future import division from pyomo.environ import * # Create a solver opt = SolverFactory( glpk ) #

61 Pyomo online Documentation / 78 # A simple model with binary variables and # an empty constraint list. # model = AbstractModel() model.n = Param(default=4) model.x = Var(RangeSet(model.n), within=binary) def o_rule(model): return summation(model.x) model.o = Objective(rule=o_rule) model.c = ConstraintList() # Create a model instance and optimize instance = model.create() results = opt.solve(instance) print results # Iterate to eliminate the previously found solution for i in range(5): instance.load(results) expr = 0 for j in instance.x: if instance.x[j].value == 0: expr += instance.x[j] else: expr += (1-instance.x[j]) instance.c.add( expr >= 1 ) instance.preprocess() results = opt.solve(instance) print results Let us now analyze this script. The first line is a comment that happens to give the name of the file. This is followed by two lines that import symbols for Pyomo: # iterative1.py from coopr.pyomo import * from coopr.opt import SolverFactory An object to perform optimization is created by calling SolverFactory with an argument giving the name of the solver.t The argument would be gurobi if, e.g., Gurobi was desired instead of glpk: # Create a solver opt = SolverFactory( glpk ) The next lines after a comment create a model. For our discussion here, we will refer to this as the base model because it will be extended by adding constraints later. (The words "base model" are not reserved words, they are just being introduced for the discussion of this example). There are no constraints in the base model, but that is just to keep it simple. Constraints could be present in the base model. Even though it is an abstract model, the base model is fully specified by these commands because it requires no external data: model = AbstractModel() model.n = Param(default=4) model.x = Var(RangeSet(model.n), within=binary) def o_rule(model): return summation(model.x) model.o = Objective(rule=o_rule) The next line is not part of the base model specification. It creates an empty constraint list that the script will use to add constraints.

62 Pyomo online Documentation / 78 model.c = ConstraintList() The next non-comment line creates the instantiated model and refers to the instance object with a Python variable instance. Models run using the pyomo script do not typically contain this line because model instantiation is done by the pyomo script. In this example, the create function is called without arguments because none are needed; however, the name of a file with data commands is given as an argument in many scripts. instance = model.create() The next line invokes the solver and refers to the object contain results with the Python variable results. results = opt.solve(instance) The print method of the results object is invoked by the Python print command: print results The next non-comment line is a Python iteration command that will successively assign the integers from 0 to 4 to the Python variable i, although that variable is not used in script. This loop is what causes the script to generate five more solutions: for i in range(5): The next line associates the results obtained with the instance. This then enables direct queries of solution values in subsequent lines using variable names contained in the instance: instance.load(results) An expression is built up in the Python variable named expr. The Python variable j will be iteratively assigned all of the indexes of the variable x. For each index, the value of the variable (which was loaded by the load method just described) is tested to see if it is zero and the expression in expr is augmented accordingly. Although expr is initialized to 0 (an integer), its type will change to be a Pyomo expression when it is assigned expressions involving Pyomo variable objects: expr = 0 for j in instance.x: if instance.x[j].value == 0: expr += instance.x[j] else: expr += (1-instance.x[j]) During the first iteration (when i is 0), we know that all values of x will be 0, so we can anticipate what the expression will look like. We know that x is indexed by the integers from 1 to 4 so we know that j will take on the values from 1 to 4 and we also know that all value of x will be zero for all indexes so we know that the value of expr will be something like 0 + instance.x[1] + instance.x[2] + instance.x[3] + instance.x[4] The value of j will be evaluated because it is a Python variable; however, because it is a Pyomo variable, the value of inst ance.x[j] not be used, instead the variable object will appear in the expression. That is exactly what we want in this case. When we wanted to use the current value in the if statement, we used the value method to get it. The next line adds to the constaint list called c the requirement that the expression be greater than or equal to one: instance.c.add( expr >= 1 ) The proof that this precludes the last solution is left as an exerise for the reader. When the model is modified, such as when constraints are added, the preprocess method must be called or the changes will not be passed to the solver: instance.preprocess() The final lines in the outer for loop find a solution and display it: results = opt.solve(instance) print results

63 Pyomo online Documentation / Changing the Model or Data and Re-solving The iterative1.py example illustrates how a model can be changed and then re-solved. In that example, the model is changed by adding a constraint, but the model could also be changed by altering the values of parameters. Note, however, that in these examples, we make the changes to the instance object rather than the model object so that we do not have to create a new model object. Here is the basic idea: 1. Create an AbstractModel (suppose it is called model) 2. Call model.create() to create an instance (suppose it is called instance) 3. Solve instance 4. Change someting in instance 5. Call presolve 6. Solve instance again If instance has a parameter whose name is in ParamName with an index that is in idx, the the value in NewVal can be assigned to it using getattr(instance, ParamName)[idx] = NewVal For a singleton parameter named ParamName (i.e., if it is not indexed), the assignment can be made using either getattr(instance, ParamName)[None] = NewVal or else getattr(instance, ParamName).set_value(NewVal) The function getattr is provided by Python. For more information about access to Pyomo parameters, see the section in this document on Param Access Fixing Variables and Re-solving Instead of changing model data, scripts are often used to fix variable values. The following example illustrates this. # iterative2.py from future import division from pyomo.environ import * # Create a solver opt = SolverFactory( cplex ) # # A simple model with binary variables and # an empty constraint list. # model = AbstractModel() model.n = Param(default=4) model.x = Var(RangeSet(model.n), within=binary) def o_rule(model): return summation(model.x) model.o = Objective(rule=o_rule) model.c = ConstraintList() # Create a model instance and optimize

64 Pyomo online Documentation / 78 instance = model.create() results = opt.solve(instance) print results # "flip" the value of x[2] (it is binary) # then solve again instance.load(results) if instance.x[2] == 0: instance.x[2] = 1 else: instance.x[2] = 0 instance.x[2].fixed = True instance.preprocess() results = opt.solve(instance) print results In this example, the variables are binary. The model is solved and then the value of model.x[2] is flipped to the opposite value before solving the model again. The main lines of interest are: instance.load(results) if instance.x[2] == 0: instance.x[2] = 1 else: instance.x[2] = 0 instance.x[2].fixed = True instance.preprocess() results = opt.solve(instance) This could also have been accomplished by setting the upper and lower bounds: instance.load(results) if instance.x[2] == 0: instance.x[2].setlb(1) instance.x[2].setub(1) else: instance.x[2].setlb(0) instance.x[2].setub(0) instance.preprocess() results = opt.solve(instance) Notice that when using the bounds, we do not set fixed to True because that would fix the variable at whatever value it presently has and then the bounds would be ignored by the solver. For more information about access to Pyomo variables, see the section in this document on Variable Access Pyomo Callbacks Pyomo enables altering or extending its workflow through the use of callbacks that are defined in the model file. Taken together, the callbacks allow for consruction of a rich set of workflows. However, many users might be interesting in making use of only one or two of the callbacks. They are executable Python functions with pre-defined names: pyomo_preprocess: Preprocessing before model construction pyomo_create_model: Constructs and returns the model object pyomo_create_modeldata: Constructs and returns a ModelData object

65 Pyomo online Documentation / 78 pyomo_print_model: Display model information pyomo_modify_instance: Modify the model instance pyomo_print_instance: Display instance information pyomo_save_instance: Write the model instance to a file pyomo_print_results: Display the results of optimization pyomo_save_results: Store the optimization results pyomo_postprocess: Postprocessing after optimization Many of these functions have arguments, which must be declared when the functions are declared. This can be done either by listing the arguments, as we will show below, or by providing a dictionary for arbitrary keyword arguments in the form **kwds. If the abritrary keywords are used, then the arguments are access using the get method. For example the preprocess function takes one argument (as will be described below) so the following two function will produce the same output: def pyomo_preprocess(options=none): if options == None: print "No command line options were given." else: print "Command line arguments were: %s" % options def pyomo_preprocess(**kwds): options = kwds.get( options,none) if options == None: print "No command line options were given." else: print "Command line arguments were: %s" % options To access the various arguments using the **kwds argument, use the following strings: options for the command line arguments dictionary model-options for the --model-options dictionary model for a model object instance for an instance object results for a results object pyomo_preprocess This function has one argument, which is an enhanced Python dictionary containing the command line options given to launch Pyomo. It is called before model construction so it augments the workflow. It is defined in the model file as follows: def pyomo_preprocess(options=none): pyomo_create_model This function is for experts who want to replace the model creation functionality provided by the pyomo script with their own. It takes two arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo and a dictionary with the options given in the --model-options argument to the pyomo command. The function must return the model object that has been created.

66 Pyomo online Documentation / pyomo_create_modeldata Users who employ ModelData objects may want to give their own method for populating the object. This function returns returns a ModelData object that will be used to instantiate the model to form an instance. It takes two arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo and a model object pyomo_print_model This callback is executed between model creation and instance creation. It takes two arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo and a model object pyomo_modify_instance This callback is executed after instance creation. It takes three arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo, a model object, and an instance object pyomo_print_instance This callback is executed after instance creation (and after the pyomo_modify_instance callback). It takes two arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo and an instance object pyomo_save_instance This callback also takes place after instance creation and takes It takes two arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo and an instance object pyomo_print_results This callback is executed after optimization. It takes three arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo, an instance object, and a results object. Note that the --print-results option provides a way to print results; this callback is intended for users who want to customize the display pyomo_save_results This callback is executed after optimization. It takes three arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo, an instance object, and a results object. Note that the --save-results option provides a way to store results; this callback is intended for users who want to customize the format or contents pyomo_postprocess This callback is also executed after optimization. It also takes three arguments: an enhanced Python dictionary containing the command line options given to launch Pyomo, an instance object, and a results object Accessing Variable Values Primal Variable Values Often, the point of optimization is to get optimal values of variables. The pyomo script automatically outputs the values to a file and optionally displays the non-zero values on the standard output device (usually the computer screen). Some user may want to process the values in a script. We will describe how to access a particular variable from a Python script as well as how to access all variables from a Python script and from a callback. This should enable the reader to understand how to get the access that they desire. The Iterative example given above also illustrates access to variable values.

67 Pyomo online Documentation / One Variable from a Python Script Assuming the model has been instantiated and solved and the results have been loded back into the instance object, then we can make use of the fact that the variable is a member of the instance object and its value can be accessed using its value member. For example, suppose the model contains a variable named quant that is a singleton (has no indexes) and suppose further that the name of the instance object is instance. Then the value of this variable can be accessed using instance.quant. value. Variables with indexes can be referenced by supplying the index. Consider the following very simple example, which is similar to the iterative example. This is a very simple model and there are no parameter values to be read from a data file, so the model.create() call does not specify a file name. In this example, the value of x[2] is accessed. # noiteration1.py from future import division from pyomo.environ import * # Create a solver opt = SolverFactory( glpk ) # # A simple model with binary variables and # an empty constraint list. # model = AbstractModel() model.n = Param(default=4) model.x = Var(RangeSet(model.n), within=binary) def o_rule(model): return summation(model.x) model.o = Objective(rule=o_rule) model.c = ConstraintList() # Create a model instance and optimize instance = model.create() results = opt.solve(instance) instance.load(results) if instance.x[2].value == 0: print "The second index has a zero" else: print "x[2]=",instance.x[2].value All Variables from a Python Script As with one variable, we assume that the model has been instantiated and solved and the results have been loded back into the instance object using instance.load(results) and the code includes the line from coopr.pyomo import Var, then we can make use of the fact that the variable is a member of the instance object and its value can be accessed using its value member. Assuming the instance object has the name instance, the following code snippet displays all variables and their values: for v in instance.active_components(var): print "Variable",v varobject = getattr(instance, v) for index in varobject: print " ",index, varobject[index].value This code could be improved by checking to see if the variable is not indexed (i.e., the only index value is None), then the code could print the value without the word None next to it. Assuming again that the model has been instantiated and solved and the results have been loded back into the instance object using instance.load(results) and that the code includes the line from coopr.pyomo import Var here is a code snippet for fixing all integers at their current value:

68 Pyomo online Documentation / 78 for v in instance.active_components(var): varobject = getattr(instance, v) if isinstance(varobject.domain, IntegerSet) or isinstance(varobject.domain, BooleanSet) : print "fixing",v for index in varobject: varobject[index].fixed = True # fix the current value Warning In order for changes to the model such as fixing a variable to affect subsequent solves, preprocessing must be invoked. In this example, instance.preprocess() would be used All Variables from Workflow Callbacks The pyomo_print_results, pyomo_save_results, and pyomo_postprocess callbacks from the pyomo script take the instance as one of their arguments and the instance has the solver results at the time of the callback so the body of the callback matches the code snipped given for a Python script. For example, if the following defintion were included in the model file, then the pyomo command would output all variables and their values (including those variables with a value of zero): def pyomo_print_results(options, instance, results): from coopr.pyomo import Var for v in instance.active_components(var): print "Variable",v varobject = getattr(instance, v) for index in varobject: print " ",index, varobject[index].value 13.6 Accessing Parameter Values Access to paramaters is completely analgous to access to variables. For example, here is a code snippet to print the name and value of every Parameter: from coopr.pyomo import Param for p in instance.active_components(param): print "Parameter",p parmobject = getattr(instance, p) for index in parmobject: print " ",index, parmobject[index].value NOTE:The value of a Param can be returned as None+ if no data was specified for it. This will be true even if a default value was given. To inspect the default value of a Param, replace.value with.default() but note that the default might be a function Accessing Duals Access to dual values in scripts is similar to accessing primal variable values, except that dual values are not captured by default so additional directives are needed before optimization to signal that duals are desired. To get duals without a script, use the pyomo option --solver-suffixes=dual which will cause dual values to be included in output. Note: In addition to duals (dual), reduced costs (rc) and slack values (slack) can be requested. All suffixes can be requested using the pyomo option --solver-suffixes=.*

69 Pyomo online Documentation / 78 Warning Some of the duals may have the value None, rather than Access Duals in a Python Script To signal that duals are desired, declare a Suffix component with the name "dual" on the model or instance with an IMPORT or IMPORT_EXPORT direction. # Create a dual suffix component on the instance # so the solver plugin will know which suffixes to collect instance.dual = Suffix(direction=Suffix.IMPORT) See the section on [?simpara] for more information on Pyomo s Suffix component. After the results are obtained and loaded into an instance, duals can be accessed in the following fashion. # display all duals print "Duals" from coopr.pyomo import Constraint for c in instance.active_components(constraint): print " Constraint",c cobject = getattr(instance, c) for index in cobject: print " ", index, instance.dual[cobject[index]] The following snippet will only work, of course, if there is a constraint with the name AxbConstraint that has and index, which is the string Film. # access (display, this case) one dual print "Dual for Film=", instance.dual[instance.axbconstraint[ Film ]] Here is a complete example that relies on the file abstract2.py to provide the model and the file abstract2.dat to provide the data. Note that the model in abstract2.py does contain a constraint named AxbConstraint and abstra ct2.dat does specify an index for it named Film. # driveabs2.py from future import division from pyomo.environ import * # Create a solver opt = SolverFactory( cplex ) # get the model from another file from abstract2 import model # Create a model instance and optimize instance = model.create( abstract2.dat ) # Create a dual suffix component on the instance # so the solver plugin will know which suffixes to collect instance.dual = Suffix(direction=Suffix.IMPORT) results = opt.solve(instance) # get the results back into the instance for easy access instance.load(results) # display all duals

70 Pyomo online Documentation / 78 print "Duals" for c in instance.active_components(constraint): print " Constraint",c cobject = getattr(instance, c) for index in cobject: print " ", index, instance.dual[cobject[index]] # access (display, this case) one dual print "Dual for Film=", instance.dual[instance.axbconstraint[ Film ]] All Duals from Workflow Callbacks The pyomo script needs to be instructed to obtain duals, either by using a command line option such as --solver-suffi xes=dual or by adding code in the pyomo_preprocess callback to add solver-suffixes to the list of command line arguments if it is not there and to add dual to its list of arguments if it is there, but dual is not. If a suffix with the name dual has been declared on the model the use of the command line option or pyomo_preprocess callback is not required. The pyomo_print_results, pyomo_save_results, and pyomo_postprocess callbacks from the pyomo script take the instance as one of their arguments and the instance has the solver results at the time of the callback so the body of the callback matches the code snipped given for a Python script. For example, if the following definition were included in the model file, then the pyomo command would output all constraints and their duals. def pyomo_print_results(options, instance, results): # display all duals print "Duals" from coopr.pyomo import Constraint for c in instance.active_components(constraint): print " Constraint",c cobject = getattr(instance, c) for index in cobject: print " ", index, instance.dual[cobject[index]] Note If the --solver-suffixes command line option is used to request constraint duals, an IMPORT style Suffix component will be added to the model by the pyomo command Accessing Solver Status After a solve, the results object has a member Solution.Status that contains the solver status. The following snippet shows an example of access via a print statement: instance = model.create() results = opt.solve(instance) print "The solver returned a status of:"+str(results.solution.status) The use of the Python str function to cast the value to a be string makes it easy to test it. In particular, the value optimal indicates that the solver succeeded. It is also possible to access Pyomo data that can be compared with the solver status as in the following code snippet: from coopr.opt import SolverStatus, TerminationCondition...

71 Pyomo online Documentation / 78 if (results.solver.status == SolverStatus.ok) and (results.solver.termination_condition == TerminationCondition.optimal): # this is feasible and optimal elif results.solver.termination_condition == TerminationCondition.infeasible: # do something else: # something else is wrong print results.solver 13.9 Display of Solver Output To see the output of the solver, use the option tee=true as in results = opt.solve(instance, tee=true) This can be useful for troubleshooting solver difficulties Sending Options to the Solver Most solvers accept options and Pyomo can pass options through to a solver. In scripts or callbacks, the options can be attached to the solver object by adding to its options dictionary as illustrated by this snippet: opt = SolverFactory[ cbc ] opt.options["threads"] = 4 If multiple options are needed, then multiple dictionary entries should be added. Sometime it is desirable to pass options as part of the call to the solve function as in this snippet: results = opt.solve(instance, options="threads=4", tee=true) The quoted string is passed directly to the solver. If multiple options need to be passed to the solver in this way, they should be separated by a space within the quoted string. Notice that tee is a Pyomo option and is solver-independent, while the string argument to options is passed to the solver without very little processing by Pyomo. If the solver does not have a "threads" option, it will probably complain, but Pyomo will not Warm Starts Some solvers support a warm start based on current values of variables. To use this feature, set the values of variables in the instance and pass warmstart=true to the solve() method. E.g., instance = model.create() instance.y[0] = 1 instance.y[1] = 0 opt = SolverFactory("cplex") results = opt.solve(instance, warmstart=true) Note The Cplex and Gurobi LP file (and Python) interfaces will generate an MST file with the variable data and hand this off to the solver in addition to the LP file.

72 Pyomo online Documentation / 78 Warning Solvers using the NL file interface (e.g., "gurobi_ampl", "cplexamp") do not accept warmstart as a keyword to the solve() method as the NL file format, by default, includes variable initialization data (drawn from the current value of all variables) BuildAction This is a somewhat advanced topic. In some cases, it is desirable to trigger actions to be done as part of the model building process. The BuildAction function provides this capability in a Pyomo model. It takes as arguments optional index sets and a function to peform the action. For example, model.buildbpts = BuildAction(model.J, rule=bpts_build) calls the function bpts_build for each member of model.j. The function bpts_build should have the model and a variable for the members of model.j as formal arguments. In this example, the following would be a valid declaration for the function: def bpts_build(model, j): A full example, which extends the abstract2.py and [?] examples, is # abstract2piecebuild.py # Similar to abstract2piece.py, but the breakpoints are created using a build action from future import division from pyomo.environ import * model = AbstractModel() model.i = Set() model.j = Set() model.a = Param(model.I, model.j) model.b = Param(model.I) model.c = Param(model.J) model.topx = Param(default=6.1) # range of x variables # the next line declares a variable indexed by the set J model.x = Var(model.J, domain=nonnegativereals, bounds=(0,model.topx)) model.y = Var(model.J, domain=nonnegativereals) # to avoid warnings, we set breakpoints beyond the bounds # we are using a dictionary so that we can have different # breakpoints for each index. But we won t. model.bpts = {} def bpts_build(model, j): model.bpts[j] = [] for i in range(0,int(m.topx+2)): model.bpts[j].append(i) # The object model.buildbpts is not refered to again; # the only goal is to trigger the action at build time model.buildbpts = BuildAction(model.J, rule=bpts_build) def f4(model, j, xp): # we not need j in this example, but it is passed as the index for the constraint return xp**4

73 Pyomo online Documentation / 78 model.computeobj = Piecewise(model.J, model.y, model.x, pw_pts=model.bpts, f_rule=f4, pw_constr_type= EQ ) def obj_expression(model): return summation(model.c, model.y) model.obj = Objective(rule=obj_expression) def ax_constraint_rule(model, i): # return the expression for the constraint for i return sum(model.a[i,j] * model.x[j] for j in model.j) >= model.b[i] # the next line creates one constraint for each member of the set model.i model.axbconstraint = Constraint(model.I, rule=ax_constraint_rule) This example uses the build action to create a model component with breakpoints for a piecewise function. The BuildAction is triggered by the assignment to model.buildbpts. This object is not reference again, the only goal is to cause the execution of bpts_build, which places data in the model.bpts dictionary. Note that if model.bpts had been a Set, then it could have been created with an initialize argument to the Set declaration. Since it is a special-purpose dictionary to support the piecewise functionality in Pyomo, we use a BuildAction Solving Multiple Instances in Parallel Use of parallel solvers for PySP is discussed in the section on Parallel PySP. Solvers are controlled by solver servers. The pyro mip solver server is launched with the command pyro_mip_server. This command may be repeated to launch as many solvers as are desired. A name server and a dispatch server must be running and accessible to the process that runs the script that will use the mip servers as well as to the mip servers. The name server is launched using the command coopr_ns and then the dispatch server is launched with dispatch_srvr. Note that both commands contain an underscore. Both programs keep running until terminated by an external signal, so it is common to pipe their output to a file. The commands are: Once: coopr_ns Once: dispatch_srvr Multiple times: pyro_mip_server This example demonstrates how to use these services to solve two instances in parallel. # parallel.py from future import division import sys from pyomo.environ import * action_handle_map = {} # maps action handles to instances # Create a solver optsolver = SolverFactory( cplex ) # create a solver manager # pyro could be replaced with serial solver_manager = SolverManagerFactory( pyro ) if solver_manager is None: print "Failed to create solver manager." sys.exit(1) #

74 Pyomo online Documentation / 78 # A simple model with binary variables and # an empty constraint list. # model = AbstractModel() model.n = Param(default=4) model.x = Var(RangeSet(model.n), within=binary) def o_rule(model): return summation(model.x) model.o = Objective(rule=o_rule) model.c = ConstraintList() # Create two model instances instance1 = model.create() instance2 = model.create() instance2.x[1] = 1 instance2.x[1].fixed = True instance2.preprocess() # send them to the solver(s) action_handle = solver_manager.queue(instance1, opt=optsolver, warmstart=false, tee=true, verbose=false) action_handle_map[action_handle] = "Original" action_handle = solver_manager.queue(instance2, opt=optsolver, warmstart=false, tee=true, verbose=false) action_handle_map[action_handle] = "One Var Fixed" # retrieve the solutions for i in range(2): # we know there are two instances this_action_handle = solver_manager.wait_any() solved_name = action_handle_map[this_action_handle] results = solver_manager.get_results(this_action_handle) print "Results for",solved_name print results This example creates two instances that are very similar and then sends them to be dispatched to solvers. If there are two solvers, then these problems could be solved in parallel (we say "could" because for such trivial problems to be actually solved in parallel, the solvers would have to be very, very slow). This example is non-sensical; the goal is simply to show solver_manager. queue to submit jobs to a name server for dispatch to solver servers and solver_manager.wait_any to recover the results. The wait_all function is similar, but it takes a list of action handles (returned by queue) as an argument and returns all of the results at once Changing the temporary directory A "temporary" directory is used for many intermediate files. Normally, the name of the directory for temporary files is provided by the operating system, but the user can specify their own directory name. The pyomo command-line "--tempdir" option propagates through to the TempFileManager service. One can accomplish the same through the following few lines of code in a script: from pyutilib.services import TempFileManager TempfileManager.tempdir = YourDirectoryNameGoesHere

75 Pyomo online Documentation / 78 Chapter 14 Coopr Solver Interfaces This chapter describes how Coopr interfaces with different solvers.

76 Pyomo online Documentation / 78 Chapter 15 Using Black-Box Optimizers with Coopr.Opt Many optimization software packages contain black-box optimizers, which perform optimization without using detailed knowledge of the structure of an optimization problem. Thus, black-box optimizers require a generic interface for optimization problems that defines key features of problems, like objectives and constraints. The coopr.opt package contains the coopr.opt.blackbox subpackage, which provides facilities for (a) integrating Coopr solvers with blackbox optimization applications and (b) wrapping Pyomo models for use by external blackbox optimizers. We illustrate these capabilities in this chapter with simple examples that illustrate the use of coopr.opt.blackbox Defining and Optimizing Simple Black-Box Applications Many black-box optimizers interact with an optimization problem by executing a separate process that computes properties of the optimization problem. This process typically reads an input file that defines the requested properties and writes an output file that contains the computed values. Unfortunately, no standards have emerged for black-box optimizers that interact with problems in this manner. Thus, different file formats are used by different optimizer software packages Defining an Optimization Problem The coopr.opt.blackbox package provides several Python classes for optimization problems that coordinates file I/O for the user and simplifies the definition of simple black-box problems. The RealOptProblem class provides a generic interface for continuous optimization problems (i.e. with real variables). The following example defines a simple continuous optimization problem: class RealProblem1(RealOptProblem): def init (self): RealOptProblem. init (self) self.lower=[0.0, -1.0, 1.0, None] self.upper=[none, 0.0, 2.0, -1.0] self.nvars=4 def function_value(self, point): self.validate(point) return point.vars[0] - point.vars[1] + (point.vars[2]-1.5)**2 + (point.vars[3]+2) **4 This problem is equivalent to the following problem definition: min x 0 x 1 + (x 2 1.5) 2 + (x 3 + 2) 4 s.t. 0 x 0 1 x x 2 2 x 3 1

77 Pyomo online Documentation / 78 Note that the problem class does not specify the sense of the optimization problem. These problem classes are not a complete specification of an optimization problem. Rather, an instance of a problem class can compute information about the problem that is used during optimization. Similarly, the MixedIntOptProblem class provides a generic interface for mixed-integer optimization problems, which may contain real variables, integer variables and binary variables. The following example defines a simple mixed-integer optimization problem: class MixedIntProblem1(MixedIntOptProblem): def init (self): MixedIntOptProblem. init (self) self.real_lower=[0.0]*4 self.real_upper=[2.0]*4 self.int_lower=[-2]*3 self.int_upper=[0]*3 self.nreal=4 self.nint=3 self.nbinary=2 def function_value(self, point): self.validate(point) return sum((x-1)**2 for x in self.reals) + \ sum((y+1)**2 for y in self.ints) + \ sum(b for b in self.bits) This problem is equivalent to the following problem definition: min 4 i=1 (x i 1) i=1 (y i + 1) i=1 z i s.t. 0 x i 2 2 y i 0 z i {0,1} Optimizating with Coliny Solvers The Coliny software library supports interfaces to a variety of black-box optimizers <Coliny>. The coliny executable reads an XML specification of the optimization problem and solver, as well as a specification of how the optimizer is applied. Consider the following XML specification: <!--- RealProblem1.xml This Coliny XML specification illustrates the execution of the colin:ls solver on the RealProblem1 problem. ---> <ColinInput> <Problem type="minlp0"> <Domain> <RealVars num="4"> <Lower index="1" value="0.0"/> <Lower index="2" value="-1.0"/> <Lower index="3" value="1.0"/> <Upper index="2" value="0.0"/> <Upper index="3" value="2.0"/> <Upper index="4" value="-1.0"/> </RealVars> </Domain> <Driver>

78 Pyomo online Documentation / 78 <Command>RealProblem1.py</Command> </Driver> </Problem> <Solver type="colin:ls"> <InitialPoint> </InitialPoint> <Options> <Option name="min_function_value">-1.0</option> </Options> </Solver> </ColinInput> This XML specification defines a MINLP0 problem, which indicated that this is a mixed-integer problem that supports zero-order derivatives (i.e. no derivatives). This problem has four real variables with lower and upper bounds specified. The problem values are computed with the RealProblem1.py command-line, which defines and uses the RealProblem1 class defined above: #!/usr/bin/env python # # RealProblem1.py import sys from pyomo.opt.blackbox import RealOptProblem class RealProblem1(RealOptProblem): def init (self): RealOptProblem. init (self) self.lower=[0.0, -1.0, 1.0, None] self.upper=[none, 0.0, 2.0, -1.0] self.nvars=4 def function_value(self, point): self.validate(point) return point.vars[0] - point.vars[1] + (point.vars[2]-1.5)**2 + (point.vars[3]+2) **4 problem = RealProblem1() problem.main(sys.argv) Note that this command is a Python script that includes the shebang character sequence on the first line. On Linux and Unix systems, this line indicates that this is a script that is executed using the python command that is found in the user environment. Thus, this example assumes that the python command has coopr.opt installed. Since multiple versions of Python can be installed on a single computer, the XML Command element may need to be defined with an explicitly Python version. For example, if Python 2.6 is installed in /usr/local with coopr.opt, then the Command element would look like: <Command>/usr/local/bin/python26 RealProblem1.py</Command> Additionally, the duplication of bounds information between RealProblem1.py and RealProblem1.xml is not strictly necessary in this example. The bounds information in RealProblem1.py is used in the validate method to verify that the point being evaluated is consistent with the bounds information. We can generally assume that the Coliny solver will only evaluate feasible points, so a simpler problem definition can be used: #!/usr/bin/env python # # RealProblem2.py import sys from pyomo.opt.blackbox import RealOptProblem

79 Pyomo online Documentation / 78 class RealProblem2(RealOptProblem): def init (self): RealOptProblem. init (self) self.nvars=4 def function_value(self, point): return point.vars[0] - point.vars[1] + (point.vars[2]-1.5)**2 + (point.vars[3]+2) **4 problem = RealProblem2() problem.main(sys.argv) The last two lines of RealProblem1.py create a problem instance and then call the main method to parse the command-line arguments. This script has the following command-line syntax: RealProblem1.py <input-file> <output-file> The first argument is the name of an XML input file, and the second argument is the name of an XML output file. The optimization problem class manages the parsing of the input and generation of the output file. For example, consider the following input file: <ColinRequest> <Parameters> <Real size="4"> 0.1e </Real> </Parameters> <Requests> <FunctionValue/> </Requests> </ColinRequest> The RealProblem1.py script creates the following output file: <?xml version="1.0" encoding="utf-8"?> <ColinResponse> <FunctionValue> </FunctionValue> </ColinResponse> 15.2 Diving Deeper The previous section provided an overview of the how the coopr.opt.blackbox package supports the definition of optimization problems that are solved with black-box optimizers. In this section we provide more detail about how the Python problem class can be customized, as well as details about the XML file format used to communicate with Coliny optimizers. The Dakota User Manual <Dakota> provides documentation of the file format of the input and output files used with Dakota optimizers. Table Table 15.1 summarizes the methods of the OptProblem class that a user is likely to either use or redefine when declaring a subclass. The MixedIntOptProblem class is a convenient base class for the problems solved by most black-box optimizers, and this class provides the definition of the main, create_point and validate methods. However, any of the remaining methods may need to be defined, depending on the problem. Table 15.1: Methods in the OptProblem class. Method _init_ Description The constructor, which may be redefined to specify problem properties.

80 Pyomo online Documentation / 78 Table 15.1: (continued) main create_point function_value function_values gradient hessian nonlinear_constraint_values jacobian validate Method that processes command-line options to create a results file from an input file. Create an instances of the class that defines a point in the search domain. Returns the value of the objective function. Returns a list of objective function values. Returns a list that represents the gradient vector at the given point. Returns a Hessian matrix. Returns a list of values for the constraint functions. Returns a Jacobian matrix. Returns True if the given point is feasible, and False otherwise. The following detailed example illustrates the use of all of these methods in a simple application: class RealProblem3(RealOptProblem): def init (self): RealOptProblem. init (self) self.nvars=4 self.ncons=4 self.response_types = [response_enum.functionvalue, response_enum.gradient, response_enum.hessian, response_enum.nonlinearconstraintvalues, response_enum.jacobian] def function_value(self, point): return point.vars[0] - point.vars[1] + (point.vars[2]-1.5)**2 + (point.vars[3]+2) **4 def gradient(self, point): return [1, -1, 2*(point.vars[2]-1.5), 4*(point.vars[3]+2)**3] def hessian(self, point): H = [] H.append( (2,2,2) ) H.append( (3,3,12*(point.vars[3]+2)**2) ) return H def nonlinear_constraint_values(self, point): C = [] C.append( sum(point.vars) ) C.append( sum(x**2 for x in point.vars) ) return C def jacobian(self, point): J = [] for j in range(self.nvars): J.append( (0,j,1) ) for j in range(self.nvars): J.append( (1,j,2*point.vars[j]) ) return J The response_types attribute defined in the constructor specifies the type of information that this class can compute. For example, consider the following input XML file:

81 Pyomo online Documentation / 78 <ColinRequest> <Parameters> <Real size="4"> 0.1e </Real> </Parameters> <Requests> <FunctionValue/> <Gradient/> <Hessian/> <NonlinearConstraintValues/> <Jacobian/> </Requests> </ColinRequest> This input file requests that the class compute all of the response values, and thus the following output is generated: <?xml version="1.0" encoding="utf-8"?> <ColinResponse> <Gradient> </Gradient> <NonlinearConstraintValues> </NonlinearConstraintValues> <FunctionValue> </FunctionValue> <Hessian> (2, 2, 2) (3, 3, ) </Hessian> <Jacobian> (0, 0, 1) (0, 1, 1) (0, 2, 1) (0, 3, 1) (1, 0, 0.02) (1, 1, ) (1, 2, ) (1, 3, ) </Jacobian> </ColinResponse> Note that the values for Jacobian and Hessian matrices are represented in a sparse manner. Currently, these are represented with a list of tuple values, though a sparse matrix representation might be supported in the future.

82 Pyomo online Documentation / 78 Chapter 16 Distributed Optimization with Pyro Coopr supports distributed computing via the Python "PYRO" package. PYRO stands for PYthon Remote Objects. Full documentation of PYRO is available from: The following describes a "quick-start" process for creating and using a client and multiple solvers on a single, presumably multi-core compute server. For example, an institution may have an 8-core workstation with numerous CPLEX licenses. With distributed solves under PYRO, Coopr algorithms can take advantage of the full set of resources on a machine. The following example assumes a unix/linux platform. The steps for Windows are qualitatively identical - the sole difference is that you can t (or at least we haven t figured out how to) put processes in the background on Windows. The work-around is simply (albeit painfully) to launch the various processes in distinct shells Step 1: Starting a Name Server All PYRO objects communicate via a name server, which provides a well-defined point of contact through which distributed objects can interact. You can think of the name server as a phone directory. To start the name server, type: coopr-ns In general, we suggest that the output be redirected to a file, with the entire process being placed in the background: coopr-ns >& ns.out & 16.2 Step 2: Starting a Dispatch Server With the name server up and running, the next step is to create a dispatch server. The function of the dispatch server is to route work from clients to servers - both of the latter will be established in the immediately following steps. We again assume the process is executed in the background, with the output redirected: dispatch_srvr >& dispatch_srvr.out & 16.3 Step 3: Starting a MIP server With the work dispatcher up, the next step is to create servers to do real work! Coopr ships with a pyro_mip_server script, which launches a server capable of solving a single MIP at a time. This server can be invoked as follows:

83 Pyomo online Documentation / 78 pyro_mip_server >& pyro_mip_server1.out & We can also create multiple instances of the pyro_mip_server, e.g., to take advantage of multiple solver licenses: pyro_mip_server >& pyro_mip_server2.out & With this configuration, the dispatch server "sees" two mip servers, and can route work to both Step 4: Running a Client To take advantage of the distributed MIP servers, a Coopr user only needs to change the type of the solver manager supplied to the various solver scripts. For example, one can run pyomo as follows, considering the PySP example found in: coopr/examples/pysp/farmer: pyomo --solver=cplex --solver-manager=pyro farmer_lp.py farmer_lp.dat This will execute the LP solve using one of the two mip servers established in Step 3, which might be useful if they are on remote servers. To take advantage of parallelism, we can solve the farmer example using progressive hedging, as follows: runph --solver=cplex --solver-manager=pyro --model-directory=models --instance-directory= scenariodata 16.5 Moving from Multi-Core to Distributed Computation Truly distributed computation, i.e., with the client and server components on different hosts, is only incrementally more difficult than what is outlined above. If multiple hosts are involved in the computation, the only real issue is making sure the various hosts can all find a common nameserver. After starting coopr-ns on some host (presumably a server-class machine), the other components (dispatch_srvr and the pyro_mip_server) can be pointed to the nameserver by simply setting the environment variable PYRO_NS_HOSTNAME to the name (or IP address) of the host running the nameserver. The same process should be followed on the client prior to executing either pyomo, runph, or some other client solver script. We have tested this on linux clusters with success. The only issues encountered involve overly aggressive firewalls on the host running the nameserver, which was easily corrected. In theory, Pyro should also work on Windows clusters, and linux-window hybrid clusters via the same mechanism Cleaning Up After Yourself It is important to remember that the name server, the dispatch server, and the mip server processes are persistent, and need to be terminated when a user has completed computational experiments. Actually, that is not entirely correct - the server processes can live forever, and continue to receive work. The only issue is when multiple users are attempting to use the same compute platform, are running their own servers, etc. While this may work, we have not tested it fully yet!

84 Pyomo online Documentation / 78 Bibliography [AIMMS] [AMPL] [GAMS] [Coliny] Hart and Siirola. Coliny Technical Report. Sandia National Labs. [Dakota] Eldred et al. Dakota Technical Report. Sandia National Labs. [MPG] Mathematical Programming Glossary, Ed. Allen Holder, [] Hart, W.E., Laird, C., Watson, J.-P., Woodruff, D.L., Pyomo Optimization Modeling in Python, Springer, [PyomoJournal] William E. Hart, Jean-Paul Watson, David L. Woodruff, "Pyomo: modeling and solving mathematical programs in Python," Mathematical Programming Computation, Volume 3, Number 3, August 2011 [BirgeLouveauxBook] Introduction to Stochastic Programming; J.R. Birge and F. Louveaux; Springer Series in Operations Research; New York: Springer, [Vielma_et_al] Vielma, J.P, Ahmed, S., Nemhauser, G., "Mixed-Integer Models for Non-separable Piecewise Linear Optimization: Unifying framework and Extensions," Operations Research 58, pp

85 Pyomo online Documentation / 78 Colophon This book was created using asciidoc software. The Sandia National Laboratories Laboratory-Directed Research and Development Program and the U.S. Department of Energy Office of Science Advanced Scientific Computing Research Program funded portions of this work. Sandia National Laboratories is a multi-program laboratory managed and operated by Sandia Corporation, a wholly owned subsidiary of Lockheed Martin Corporation, for the U.S. Department of Energy s National Nuclear Security Administration under contract DE-AC04-94AL SAND P.

Pyomo Documentation. Release 5.1. Pyomo

Pyomo Documentation. Release 5.1. Pyomo Pyomo Documentation Release 5.1 Pyomo Dec 19, 2018 Contents 1 Installation 3 1.1 Using CONDA.............................................. 3 1.2 Using PIP.................................................

More information

3. Pyomo Fundamentals

3. Pyomo Fundamentals 3. Pyomo Fundamentals John D. Siirola Discrete Math & Optimization (1464) Center for Computing Research Sandia National Laboratories Albuquerque, NM USA Sandia National Laboratories is a

More information

Coopr User Manual: Getting Started with the Pyomo Modeling Language

Coopr User Manual: Getting Started with the Pyomo Modeling Language Coopr User Manual: Getting Started with the Pyomo Modeling Language William E. Hart 1 Jean-Paul Watson 2 David L. Woodruff 3 November 7, 2009 1 Sandia National Laboratories, Discrete Math and Complex Systems

More information

6 Initializing Abstract Models with Data Command Files Model Data The set Command Simple Sets... 68

6 Initializing Abstract Models with Data Command Files Model Data The set Command Simple Sets... 68 Contents 1 Introduction 1 1.1 Mathematical Modeling........................ 1 1.2 Modeling Languages for Optimization................ 3 1.3 Modeling Graph Coloring....................... 4 1.4 Motivating

More information

Python Optimization Modeling Objects (Pyomo)

Python Optimization Modeling Objects (Pyomo) Noname manuscript No. (will be inserted by the editor) Python Optimization Modeling Objects (Pyomo) William E. Hart Jean-Paul Watson David L. Woodruff Received: December 29, 2009. Abstract We describe

More information

SENSITIVITY. CS4491 Introduction to Computational Models with Python

SENSITIVITY. CS4491 Introduction to Computational Models with Python SENSITIVITY CS4491 Introduction to Computational Models with Python José M Garrido Department of Computer Science January 2016 College of Computing and Software Engineering Kennesaw State University Sensitivity

More information

8. Solving Stochastic Programs

8. Solving Stochastic Programs 8. Solving Stochastic Programs Sandia National Laboratories is a multi-program laboratory managed and operated by Sandia Corporation, a wholly owned subsidiary of Lockheed Martin Corporation, for the U.S.

More information

NOTATION AND TERMINOLOGY

NOTATION AND TERMINOLOGY 15.053x, Optimization Methods in Business Analytics Fall, 2016 October 4, 2016 A glossary of notation and terms used in 15.053x Weeks 1, 2, 3, 4 and 5. (The most recent week's terms are in blue). NOTATION

More information

CPS122 Lecture: From Python to Java last revised January 4, Objectives:

CPS122 Lecture: From Python to Java last revised January 4, Objectives: Objectives: CPS122 Lecture: From Python to Java last revised January 4, 2017 1. To introduce the notion of a compiled language 2. To introduce the notions of data type and a statically typed language 3.

More information

Student Performance Q&A:

Student Performance Q&A: Student Performance Q&A: 2016 AP Computer Science A Free-Response Questions The following comments on the 2016 free-response questions for AP Computer Science A were written by the Chief Reader, Elizabeth

More information

CPS122 Lecture: From Python to Java

CPS122 Lecture: From Python to Java Objectives: CPS122 Lecture: From Python to Java last revised January 7, 2013 1. To introduce the notion of a compiled language 2. To introduce the notions of data type and a statically typed language 3.

More information

Chapter 2 Basic Elements of C++

Chapter 2 Basic Elements of C++ C++ Programming: From Problem Analysis to Program Design, Fifth Edition 2-1 Chapter 2 Basic Elements of C++ At a Glance Instructor s Manual Table of Contents Overview Objectives s Quick Quizzes Class Discussion

More information

LP-Modelling. dr.ir. C.A.J. Hurkens Technische Universiteit Eindhoven. January 30, 2008

LP-Modelling. dr.ir. C.A.J. Hurkens Technische Universiteit Eindhoven. January 30, 2008 LP-Modelling dr.ir. C.A.J. Hurkens Technische Universiteit Eindhoven January 30, 2008 1 Linear and Integer Programming After a brief check with the backgrounds of the participants it seems that the following

More information

Pace University. Fundamental Concepts of CS121 1

Pace University. Fundamental Concepts of CS121 1 Pace University Fundamental Concepts of CS121 1 Dr. Lixin Tao http://csis.pace.edu/~lixin Computer Science Department Pace University October 12, 2005 This document complements my tutorial Introduction

More information

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #43. Multidimensional Arrays

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #43. Multidimensional Arrays Introduction to Programming in C Department of Computer Science and Engineering Lecture No. #43 Multidimensional Arrays In this video will look at multi-dimensional arrays. (Refer Slide Time: 00:03) In

More information

SPARK-PL: Introduction

SPARK-PL: Introduction Alexey Solovyev Abstract All basic elements of SPARK-PL are introduced. Table of Contents 1. Introduction to SPARK-PL... 1 2. Alphabet of SPARK-PL... 3 3. Types and variables... 3 4. SPARK-PL basic commands...

More information

Chapter 1 Summary. Chapter 2 Summary. end of a string, in which case the string can span multiple lines.

Chapter 1 Summary. Chapter 2 Summary. end of a string, in which case the string can span multiple lines. Chapter 1 Summary Comments are indicated by a hash sign # (also known as the pound or number sign). Text to the right of the hash sign is ignored. (But, hash loses its special meaning if it is part of

More information

The Dynamic Typing Interlude

The Dynamic Typing Interlude CHAPTER 6 The Dynamic Typing Interlude In the prior chapter, we began exploring Python s core object types in depth with a look at Python numbers. We ll resume our object type tour in the next chapter,

More information

Week - 01 Lecture - 04 Downloading and installing Python

Week - 01 Lecture - 04 Downloading and installing Python Programming, Data Structures and Algorithms in Python Prof. Madhavan Mukund Department of Computer Science and Engineering Indian Institute of Technology, Madras Week - 01 Lecture - 04 Downloading and

More information

3 No-Wait Job Shops with Variable Processing Times

3 No-Wait Job Shops with Variable Processing Times 3 No-Wait Job Shops with Variable Processing Times In this chapter we assume that, on top of the classical no-wait job shop setting, we are given a set of processing times for each operation. We may select

More information

II. Linear Programming

II. Linear Programming II. Linear Programming A Quick Example Suppose we own and manage a small manufacturing facility that produced television sets. - What would be our organization s immediate goal? - On what would our relative

More information

\n is used in a string to indicate the newline character. An expression produces data. The simplest expression

\n is used in a string to indicate the newline character. An expression produces data. The simplest expression Chapter 1 Summary Comments are indicated by a hash sign # (also known as the pound or number sign). Text to the right of the hash sign is ignored. (But, hash loses its special meaning if it is part of

More information

A Survey of Software Packages for Teaching Linear and Integer Programming

A Survey of Software Packages for Teaching Linear and Integer Programming A Survey of Software Packages for Teaching Linear and Integer Programming By Sergio Toledo Spring 2018 In Partial Fulfillment of Math (or Stat) 4395-Senior Project Department of Mathematics and Statistics

More information

Financial Optimization ISE 347/447. Lecture 13. Dr. Ted Ralphs

Financial Optimization ISE 347/447. Lecture 13. Dr. Ted Ralphs Financial Optimization ISE 347/447 Lecture 13 Dr. Ted Ralphs ISE 347/447 Lecture 13 1 Reading for This Lecture C&T Chapter 11 ISE 347/447 Lecture 13 2 Integer Linear Optimization An integer linear optimization

More information

6.001 Notes: Section 15.1

6.001 Notes: Section 15.1 6.001 Notes: Section 15.1 Slide 15.1.1 Our goal over the next few lectures is to build an interpreter, which in a very basic sense is the ultimate in programming, since doing so will allow us to define

More information

Statements 2. a operator= b a = a operator b

Statements 2. a operator= b a = a operator b Statements 2 Outline Note: i=i+1 is a valid statement. Don t confuse it with an equation i==i+1 which is always false for normal numbers. The statement i=i+1 is a very common idiom: it just increments

More information

Type Checking and Type Equality

Type Checking and Type Equality Type Checking and Type Equality Type systems are the biggest point of variation across programming languages. Even languages that look similar are often greatly different when it comes to their type systems.

More information

CS112 Lecture: Primitive Types, Operators, Strings

CS112 Lecture: Primitive Types, Operators, Strings CS112 Lecture: Primitive Types, Operators, Strings Last revised 1/24/06 Objectives: 1. To explain the fundamental distinction between primitive types and reference types, and to introduce the Java primitive

More information

Turtle Blocks Python Export

Turtle Blocks Python Export Turtle Blocks Python Export A Report on my GSoC Project Marion Zepf October 7, 2013 1 Motivation Turtle Blocks teaches children an important skill in today s world: programming. Its block-based graphical

More information

The Python interpreter

The Python interpreter The Python interpreter Daniel Winklehner, Remi Lehe US Particle Accelerator School (USPAS) Summer Session Self-Consistent Simulations of Beam and Plasma Systems S. M. Lund, J.-L. Vay, D. Bruhwiler, R.

More information

This session will provide an overview of the research resources and strategies that can be used when conducting business research.

This session will provide an overview of the research resources and strategies that can be used when conducting business research. Welcome! This session will provide an overview of the research resources and strategies that can be used when conducting business research. Many of these research tips will also be applicable to courses

More information

PRG PROGRAMMING ESSENTIALS. Lecture 2 Program flow, Conditionals, Loops

PRG PROGRAMMING ESSENTIALS. Lecture 2 Program flow, Conditionals, Loops PRG PROGRAMMING ESSENTIALS 1 Lecture 2 Program flow, Conditionals, Loops https://cw.fel.cvut.cz/wiki/courses/be5b33prg/start Michal Reinštein Czech Technical University in Prague, Faculty of Electrical

More information

PLD Semester Exam Study Guide Dec. 2018

PLD Semester Exam Study Guide Dec. 2018 Covers material from Chapters 1-8. Semester Exam will be built from these questions and answers, though they will be re-ordered and re-numbered and possibly worded slightly differently than on this study

More information

Bits, Words, and Integers

Bits, Words, and Integers Computer Science 52 Bits, Words, and Integers Spring Semester, 2017 In this document, we look at how bits are organized into meaningful data. In particular, we will see the details of how integers are

More information

Full file at

Full file at Java Programming: From Problem Analysis to Program Design, 3 rd Edition 2-1 Chapter 2 Basic Elements of Java At a Glance Instructor s Manual Table of Contents Overview Objectives s Quick Quizzes Class

More information

Introduction to Programming, Aug-Dec 2008

Introduction to Programming, Aug-Dec 2008 Introduction to Programming, Aug-Dec 2008 Lecture 1, Monday 4 Aug 2008 Administrative matters Resource material Textbooks and other resource material for the course: The Craft of Functional Programming

More information

Lecture 2: Analyzing Algorithms: The 2-d Maxima Problem

Lecture 2: Analyzing Algorithms: The 2-d Maxima Problem Lecture 2: Analyzing Algorithms: The 2-d Maxima Problem (Thursday, Jan 29, 1998) Read: Chapter 1 in CLR. Analyzing Algorithms: In order to design good algorithms, we must first agree the criteria for measuring

More information

Department of Computer Science COMP The Programming Competency Test

Department of Computer Science COMP The Programming Competency Test The Australian National University Faculty of Engineering & Information Technology Department of Computer Science COMP1120-2003-01 The Programming Competency Test 1 Introduction The purpose of COMP1120

More information

EqualsEquals Language Reference Manual

EqualsEquals Language Reference Manual EqualsEquals Language Reference Manual name email role UNI Nam Nhat Hoang nam.hoang@columbia.edu System Architect nnh2110 Tianci Zhong tz2278@columbia.edu Manager tz2278 Ruicong Xie rx2119@columbia.edu

More information

Contents. Introduction

Contents. Introduction Contents Introduction xv Chapter 1. Production Models: Maximizing Profits 1 1.1 A two-variable linear program 2 1.2 The two-variable linear program in AMPL 5 1.3 A linear programming model 6 1.4 The linear

More information

6.001 Notes: Section 8.1

6.001 Notes: Section 8.1 6.001 Notes: Section 8.1 Slide 8.1.1 In this lecture we are going to introduce a new data type, specifically to deal with symbols. This may sound a bit odd, but if you step back, you may realize that everything

More information

Pyomo Documentation. Release 5.1. Pyomo

Pyomo Documentation. Release 5.1. Pyomo Pyomo Documentation Release 5.1 Pyomo Apr 26, 2018 Contents 1 Getting Started 3 2 Tutorial 5 3 Core Pyomo Components 9 4 Managing Data in Pyomo Models 11 5 Scripting 41 6 Modeling Extensions 43 7 Developer

More information

The PCAT Programming Language Reference Manual

The PCAT Programming Language Reference Manual The PCAT Programming Language Reference Manual Andrew Tolmach and Jingke Li Dept. of Computer Science Portland State University September 27, 1995 (revised October 15, 2002) 1 Introduction The PCAT language

More information

Tools for Modeling Optimization Problems A Short Course. Algebraic Modeling Systems. Dr. Ted Ralphs

Tools for Modeling Optimization Problems A Short Course. Algebraic Modeling Systems. Dr. Ted Ralphs Tools for Modeling Optimization Problems A Short Course Algebraic Modeling Systems Dr. Ted Ralphs Algebraic Modeling Systems 1 The Modeling Process Generally speaking, we follow a four-step process in

More information

Contents. Jairo Pava COMS W4115 June 28, 2013 LEARN: Language Reference Manual

Contents. Jairo Pava COMS W4115 June 28, 2013 LEARN: Language Reference Manual Jairo Pava COMS W4115 June 28, 2013 LEARN: Language Reference Manual Contents 1 Introduction...2 2 Lexical Conventions...2 3 Types...3 4 Syntax...3 5 Expressions...4 6 Declarations...8 7 Statements...9

More information

PySP: modeling and solving stochastic programs in Python

PySP: modeling and solving stochastic programs in Python Math. Prog. Comp. (2012) 4:109 149 DOI 10.1007/s12532-012-0036-1 FULL LENGTH PAPER PySP: modeling and solving stochastic programs in Python Jean-Paul Watson David L. Woodruff William E. Hart Received:

More information

Operators. Java operators are classified into three categories:

Operators. Java operators are classified into three categories: Operators Operators are symbols that perform arithmetic and logical operations on operands and provide a meaningful result. Operands are data values (variables or constants) which are involved in operations.

More information

CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square)

CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square) CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square) Introduction This semester, through a project split into 3 phases, we are going

More information

PySP: Modeling and Solving Stochastic Programs in Python

PySP: Modeling and Solving Stochastic Programs in Python Noname manuscript No. (will be inserted by the editor) PySP: Modeling and Solving Stochastic Programs in Python Jean-Paul Watson David L. Woodruff William E. Hart Received: September 6, 2010. Abstract

More information

Linear Programming. Slides by Carl Kingsford. Apr. 14, 2014

Linear Programming. Slides by Carl Kingsford. Apr. 14, 2014 Linear Programming Slides by Carl Kingsford Apr. 14, 2014 Linear Programming Suppose you are given: A matrix A with m rows and n columns. A vector b of length m. A vector c of length n. Find a length-n

More information

Introduction to Mathematical Programming IE406. Lecture 9. Dr. Ted Ralphs

Introduction to Mathematical Programming IE406. Lecture 9. Dr. Ted Ralphs Introduction to Mathematical Programming IE406 Lecture 9 Dr. Ted Ralphs IE406 Lecture 9 1 Reading for This Lecture AMPL Book: Chapter 1 AMPL: A Mathematical Programming Language GMPL User s Guide ZIMPL

More information

Integrating Optimization Modeling with General-Purpose Programming for Efficient and Reliable Application Deployment

Integrating Optimization Modeling with General-Purpose Programming for Efficient and Reliable Application Deployment Integrating Optimization Modeling with General-Purpose Programming for Efficient and Reliable Application Deployment Robert Fourer, Filipe Brandão AMPL Optimization {4er,fdabrandao}@ampl.com Christian

More information

Section Notes 5. Review of Linear Programming. Applied Math / Engineering Sciences 121. Week of October 15, 2017

Section Notes 5. Review of Linear Programming. Applied Math / Engineering Sciences 121. Week of October 15, 2017 Section Notes 5 Review of Linear Programming Applied Math / Engineering Sciences 121 Week of October 15, 2017 The following list of topics is an overview of the material that was covered in the lectures

More information

Appendix: Generic PbO programming language extension

Appendix: Generic PbO programming language extension Holger H. Hoos: Programming by Optimization Appendix: Generic PbO programming language extension As explained in the main text, we propose three fundamental mechanisms to be covered by a generic PbO programming

More information

The SPL Programming Language Reference Manual

The SPL Programming Language Reference Manual The SPL Programming Language Reference Manual Leonidas Fegaras University of Texas at Arlington Arlington, TX 76019 fegaras@cse.uta.edu February 27, 2018 1 Introduction The SPL language is a Small Programming

More information

CS2900 Introductory Programming with Python and C++ Kevin Squire LtCol Joel Young Fall 2007

CS2900 Introductory Programming with Python and C++ Kevin Squire LtCol Joel Young Fall 2007 CS2900 Introductory Programming with Python and C++ Kevin Squire LtCol Joel Young Fall 2007 Course Web Site http://www.nps.navy.mil/cs/facultypages/squire/cs2900 All course related materials will be posted

More information

CMSC 451: Linear Programming

CMSC 451: Linear Programming CMSC 451: Linear Programming Slides By: Carl Kingsford Department of Computer Science University of Maryland, College Park Linear Programming Suppose you are given: A matrix A with m rows and n columns.

More information

Table of Contents EVALUATION COPY

Table of Contents EVALUATION COPY Table of Contents Introduction... 1-2 A Brief History of Python... 1-3 Python Versions... 1-4 Installing Python... 1-5 Environment Variables... 1-6 Executing Python from the Command Line... 1-7 IDLE...

More information

1 2 (3 + x 3) x 2 = 1 3 (3 + x 1 2x 3 ) 1. 3 ( 1 x 2) (3 + x(0) 3 ) = 1 2 (3 + 0) = 3. 2 (3 + x(0) 1 2x (0) ( ) = 1 ( 1 x(0) 2 ) = 1 3 ) = 1 3

1 2 (3 + x 3) x 2 = 1 3 (3 + x 1 2x 3 ) 1. 3 ( 1 x 2) (3 + x(0) 3 ) = 1 2 (3 + 0) = 3. 2 (3 + x(0) 1 2x (0) ( ) = 1 ( 1 x(0) 2 ) = 1 3 ) = 1 3 6 Iterative Solvers Lab Objective: Many real-world problems of the form Ax = b have tens of thousands of parameters Solving such systems with Gaussian elimination or matrix factorizations could require

More information

Types and Static Type Checking (Introducing Micro-Haskell)

Types and Static Type Checking (Introducing Micro-Haskell) Types and Static (Introducing Micro-Haskell) Informatics 2A: Lecture 14 John Longley School of Informatics University of Edinburgh jrl@inf.ed.ac.uk 17 October 2017 1 / 21 1 Types 2 3 4 2 / 21 So far in

More information

9/21/17. Outline. Expression Evaluation and Control Flow. Arithmetic Expressions. Operators. Operators. Notation & Placement

9/21/17. Outline. Expression Evaluation and Control Flow. Arithmetic Expressions. Operators. Operators. Notation & Placement Outline Expression Evaluation and Control Flow In Text: Chapter 6 Notation Operator evaluation order Operand evaluation order Overloaded operators Type conversions Short-circuit evaluation of conditions

More information

egrapher Language Reference Manual

egrapher Language Reference Manual egrapher Language Reference Manual Long Long: ll3078@columbia.edu Xinli Jia: xj2191@columbia.edu Jiefu Ying: jy2799@columbia.edu Linnan Wang: lw2645@columbia.edu Darren Chen: dsc2155@columbia.edu 1. Introduction

More information

Intro to Programming. Unit 7. What is Programming? What is Programming? Intro to Programming

Intro to Programming. Unit 7. What is Programming? What is Programming? Intro to Programming Intro to Programming Unit 7 Intro to Programming 1 What is Programming? 1. Programming Languages 2. Markup vs. Programming 1. Introduction 2. Print Statement 3. Strings 4. Types and Values 5. Math Externals

More information

Java Bytecode (binary file)

Java Bytecode (binary file) Java is Compiled Unlike Python, which is an interpreted langauge, Java code is compiled. In Java, a compiler reads in a Java source file (the code that we write), and it translates that code into bytecode.

More information

Unit E Step-by-Step: Programming with Python

Unit E Step-by-Step: Programming with Python Unit E Step-by-Step: Programming with Python Computer Concepts 2016 ENHANCED EDITION 1 Unit Contents Section A: Hello World! Python Style Section B: The Wacky Word Game Section C: Build Your Own Calculator

More information

CircuitPython 101: Working with Lists, Iterators and Generators

CircuitPython 101: Working with Lists, Iterators and Generators CircuitPython 101: Working with Lists, Iterators and Generators Created by Dave Astels Last updated on 2018-11-01 12:06:56 PM UTC Guide Contents Guide Contents Overview List Functions Slicing Filtering

More information

JME Language Reference Manual

JME Language Reference Manual JME Language Reference Manual 1 Introduction JME (pronounced jay+me) is a lightweight language that allows programmers to easily perform statistic computations on tabular data as part of data analysis.

More information

Al al-bayt University Prince Hussein Bin Abdullah College for Information Technology Computer Science Department

Al al-bayt University Prince Hussein Bin Abdullah College for Information Technology Computer Science Department Al al-bayt University Prince Hussein Bin Abdullah College for Information Technology Computer Science Department 0901212 Python Programming 1 st Semester 2014/2015 Course Catalog This course introduces

More information

Control Structures. Lecture 4 COP 3014 Fall September 18, 2017

Control Structures. Lecture 4 COP 3014 Fall September 18, 2017 Control Structures Lecture 4 COP 3014 Fall 2017 September 18, 2017 Control Flow Control flow refers to the specification of the order in which the individual statements, instructions or function calls

More information

Language Basics. /* The NUMBER GAME - User tries to guess a number between 1 and 10 */ /* Generate a random number between 1 and 10 */

Language Basics. /* The NUMBER GAME - User tries to guess a number between 1 and 10 */ /* Generate a random number between 1 and 10 */ Overview Language Basics This chapter describes the basic elements of Rexx. It discusses the simple components that make up the language. These include script structure, elements of the language, operators,

More information

Introduction to AMPL (Math 464, Spring 2018)

Introduction to AMPL (Math 464, Spring 2018) Math464 - AMPL Handout 1 Introduction to AMPL (Math 464, Spring 2018) Details of how to download and start up the demo version of AMPL are given in http://www.ampl.com. Download and install AMPL in your

More information

MATLAB COURSE FALL 2004 SESSION 1 GETTING STARTED. Christian Daude 1

MATLAB COURSE FALL 2004 SESSION 1 GETTING STARTED. Christian Daude 1 MATLAB COURSE FALL 2004 SESSION 1 GETTING STARTED Christian Daude 1 Introduction MATLAB is a software package designed to handle a broad range of mathematical needs one may encounter when doing scientific

More information

Computational Integer Programming. Lecture 12: Branch and Cut. Dr. Ted Ralphs

Computational Integer Programming. Lecture 12: Branch and Cut. Dr. Ted Ralphs Computational Integer Programming Lecture 12: Branch and Cut Dr. Ted Ralphs Computational MILP Lecture 12 1 Reading for This Lecture Wolsey Section 9.6 Nemhauser and Wolsey Section II.6 Martin Computational

More information

Hardware versus software

Hardware versus software Logic 1 Hardware versus software 2 In hardware such as chip design or architecture, designs are usually proven to be correct using proof tools In software, a program is very rarely proved correct Why?

More information

DaMPL. Language Reference Manual. Henrique Grando

DaMPL. Language Reference Manual. Henrique Grando DaMPL Language Reference Manual Bernardo Abreu Felipe Rocha Henrique Grando Hugo Sousa bd2440 flt2107 hp2409 ha2398 Contents 1. Getting Started... 4 2. Syntax Notations... 4 3. Lexical Conventions... 4

More information

5 The Control Structure Diagram (CSD)

5 The Control Structure Diagram (CSD) 5 The Control Structure Diagram (CSD) The Control Structure Diagram (CSD) is an algorithmic level diagram intended to improve the comprehensibility of source code by clearly depicting control constructs,

More information

n! = 1 * 2 * 3 * 4 * * (n-1) * n

n! = 1 * 2 * 3 * 4 * * (n-1) * n The Beauty and Joy of Computing 1 Lab Exercise 9: Problem self-similarity and recursion Objectives By completing this lab exercise, you should learn to Recognize simple self-similar problems which are

More information

CS 315 Software Design Homework 3 Preconditions, Postconditions, Invariants Due: Sept. 29, 11:30 PM

CS 315 Software Design Homework 3 Preconditions, Postconditions, Invariants Due: Sept. 29, 11:30 PM CS 315 Software Design Homework 3 Preconditions, Postconditions, Invariants Due: Sept. 29, 11:30 PM Objectives Defining a wellformed method to check class invariants Using assert statements to check preconditions,

More information

Programming for Engineers Iteration

Programming for Engineers Iteration Programming for Engineers Iteration ICEN 200 Spring 2018 Prof. Dola Saha 1 Data type conversions Grade average example,-./0 class average = 23450-67 893/0298 Grade and number of students can be integers

More information

Metaheuristic Optimization with Evolver, Genocop and OptQuest

Metaheuristic Optimization with Evolver, Genocop and OptQuest Metaheuristic Optimization with Evolver, Genocop and OptQuest MANUEL LAGUNA Graduate School of Business Administration University of Colorado, Boulder, CO 80309-0419 Manuel.Laguna@Colorado.EDU Last revision:

More information

lpsymphony - Integer Linear Programming in R

lpsymphony - Integer Linear Programming in R lpsymphony - Integer Linear Programming in R Vladislav Kim October 30, 2017 Contents 1 Introduction 2 2 lpsymphony: Quick Start 2 3 Integer Linear Programming 5 31 Equivalent and Dual Formulations 5 32

More information

The Three Rules. Program. What is a Computer Program? 5/30/2018. Interpreted. Your First Program QuickStart 1. Chapter 1

The Three Rules. Program. What is a Computer Program? 5/30/2018. Interpreted. Your First Program QuickStart 1. Chapter 1 The Three Rules Chapter 1 Beginnings Rule 1: Think before you program Rule 2: A program is a human-readable essay on problem solving that also executes on a computer Rule 3: The best way to improve your

More information

Metaheuristic Development Methodology. Fall 2009 Instructor: Dr. Masoud Yaghini

Metaheuristic Development Methodology. Fall 2009 Instructor: Dr. Masoud Yaghini Metaheuristic Development Methodology Fall 2009 Instructor: Dr. Masoud Yaghini Phases and Steps Phases and Steps Phase 1: Understanding Problem Step 1: State the Problem Step 2: Review of Existing Solution

More information

Ohio Tutorials are designed specifically for the Ohio Learning Standards to prepare students for the Ohio State Tests and end-ofcourse

Ohio Tutorials are designed specifically for the Ohio Learning Standards to prepare students for the Ohio State Tests and end-ofcourse Tutorial Outline Ohio Tutorials are designed specifically for the Ohio Learning Standards to prepare students for the Ohio State Tests and end-ofcourse exams. Math Tutorials offer targeted instruction,

More information

Introduction to: Computers & Programming: Review prior to 1 st Midterm

Introduction to: Computers & Programming: Review prior to 1 st Midterm Introduction to: Computers & Programming: Review prior to 1 st Midterm Adam Meyers New York University Summary Some Procedural Matters Summary of what you need to Know For the Test and To Go Further in

More information

9. Elementary Algebraic and Transcendental Scalar Functions

9. Elementary Algebraic and Transcendental Scalar Functions Scalar Functions Summary. Introduction 2. Constants 2a. Numeric Constants 2b. Character Constants 2c. Symbol Constants 2d. Nested Constants 3. Scalar Functions 4. Arithmetic Scalar Functions 5. Operators

More information

SECTION 1: INTRODUCTION. ENGR 112 Introduction to Engineering Computing

SECTION 1: INTRODUCTION. ENGR 112 Introduction to Engineering Computing SECTION 1: INTRODUCTION ENGR 112 Introduction to Engineering Computing 2 Course Overview What is Programming? 3 Programming The implementation of algorithms in a particular computer programming language

More information

Table : IEEE Single Format ± a a 2 a 3 :::a 8 b b 2 b 3 :::b 23 If exponent bitstring a :::a 8 is Then numerical value represented is ( ) 2 = (

Table : IEEE Single Format ± a a 2 a 3 :::a 8 b b 2 b 3 :::b 23 If exponent bitstring a :::a 8 is Then numerical value represented is ( ) 2 = ( Floating Point Numbers in Java by Michael L. Overton Virtually all modern computers follow the IEEE 2 floating point standard in their representation of floating point numbers. The Java programming language

More information

CS1114: Matlab Introduction

CS1114: Matlab Introduction CS1114: Matlab Introduction 1 Introduction The purpose of this introduction is to provide you a brief introduction to the features of Matlab that will be most relevant to your work in this course. Even

More information

Chapter 3. More Flow of Control. Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

Chapter 3. More Flow of Control. Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 3 More Flow of Control Overview 3.1 Using Boolean Expressions 3.2 Multiway Branches 3.3 More about C++ Loop Statements 3.4 Designing Loops Slide 3-3 Flow Of Control Flow of control refers to the

More information

Fundamentals of Operations Research. Prof. G. Srinivasan. Department of Management Studies. Indian Institute of Technology Madras.

Fundamentals of Operations Research. Prof. G. Srinivasan. Department of Management Studies. Indian Institute of Technology Madras. Fundamentals of Operations Research Prof. G. Srinivasan Department of Management Studies Indian Institute of Technology Madras Lecture No # 06 Simplex Algorithm Initialization and Iteration (Refer Slide

More information

structure syntax different levels of abstraction

structure syntax different levels of abstraction This and the next lectures are about Verilog HDL, which, together with another language VHDL, are the most popular hardware languages used in industry. Verilog is only a tool; this course is about digital

More information

Here is a list of lecture objectives. They are provided for you to reflect on what you are supposed to learn, rather than an introduction to this

Here is a list of lecture objectives. They are provided for you to reflect on what you are supposed to learn, rather than an introduction to this This and the next lectures are about Verilog HDL, which, together with another language VHDL, are the most popular hardware languages used in industry. Verilog is only a tool; this course is about digital

More information

BACK TO MATH LET S START EASY.

BACK TO MATH LET S START EASY. BACK TO MATH LET S START EASY. Of all rectangles of the same perimeter, which one has the largest area? (Yes, you have all solved this problem before, in Calc I. Apologies if this insults your intelligence.

More information

1. Lecture notes on bipartite matching February 4th,

1. Lecture notes on bipartite matching February 4th, 1. Lecture notes on bipartite matching February 4th, 2015 6 1.1.1 Hall s Theorem Hall s theorem gives a necessary and sufficient condition for a bipartite graph to have a matching which saturates (or matches)

More information

CSE Theory of Computing Fall 2017 Project 4-Combinator Project

CSE Theory of Computing Fall 2017 Project 4-Combinator Project CSE 30151 Theory of Computing Fall 2017 Project 4-Combinator Project Version 1: Nov. 20, 2017 1 Overview At this point you understand computations that happen as planned series of individual steps where

More information

Notes on AMPL for and (Adapted from notes by Sommer Gentry)

Notes on AMPL for and (Adapted from notes by Sommer Gentry) Notes on AMPL for 16.410 and 16.413 (Adapted from notes by Sommer Gentry) User Guides for MS-Dos and UNIX: http://www.ampl.com/refs/index.html#os_links About AMPL/CPLEX AMPL stands for A Mathematical Programming

More information

Modelling. Christina Burt, Stephen J. Maher, Jakob Witzig. 29th September Zuse Institute Berlin Berlin, Germany

Modelling. Christina Burt, Stephen J. Maher, Jakob Witzig. 29th September Zuse Institute Berlin Berlin, Germany Modelling Christina Burt, Stephen J. Maher, Jakob Witzig Zuse Institute Berlin Berlin, Germany 29th September 2015 Modelling Languages Jakob Witzig Burt, Maher, Witzig Modelling 1 / 22 Modelling Languages:

More information

CS201 - Introduction to Programming Glossary By

CS201 - Introduction to Programming Glossary By CS201 - Introduction to Programming Glossary By #include : The #include directive instructs the preprocessor to read and include a file into a source code file. The file name is typically enclosed with

More information

Types and Static Type Checking (Introducing Micro-Haskell)

Types and Static Type Checking (Introducing Micro-Haskell) Types and Static (Introducing Micro-Haskell) Informatics 2A: Lecture 13 Alex Simpson School of Informatics University of Edinburgh als@inf.ed.ac.uk 16 October, 2012 1 / 21 1 Types 2 3 4 2 / 21 Thus far

More information