@@ -8,42 +8,77 @@ Parameters
88 >>> import pyomo.environ as pyo
99 >>> model = pyo.ConcreteModel()
1010
11- The word "parameters" is used in many settings. When discussing a Pyomo
12- model, we use the word to refer to data that must be provided in order
13- to find an optimal (or good) assignment of values to the decision
14- variables. Parameters are declared as instances of a :class: `Param `
15- class, which
16- takes arguments that are somewhat similar to the :class: `Set ` class. For
17- example, the following code snippet declares sets ``model.A `` and
18- ``model.B ``, and then a parameter ``model.P `` that is indexed by
19- ``model.A `` and ``model.B ``:
11+ The word "parameters" is used in many settings. In Pyomo, a :class: `Param `
12+ represents the fixed data of an optimization model. Unlike variables
13+ (:class: `Var `), which the solver determines, parameters are inputs that define
14+ the specific instance of the problem you are solving.
15+
16+ Common examples of parameters include costs, demands, capacities, or physical
17+ constants. While you could use standard Python variables to store these values,
18+ using Pyomo :class: `Param ` components offers several advantages:
19+
20+ * **Index Management: ** Params can be indexed by Pyomo :class: `Set ` objects,
21+ ensuring consistency between your data and the model structure. In a
22+ :class: `ConcreteModel `, they can also be indexed by standard Python iterables
23+ like lists, tuples, or ranges.
24+ * **Validation: ** You can define rules to ensure that the data provided (e.g.,
25+ from an external file) is valid before solving.
26+ * **Symbolic Representation: ** In large or complex models, using Params allows
27+ Pyomo to maintain the structure of the model separately from the specific values.
28+
29+ .. note ::
30+
31+ When working with a :class: `ConcreteModel `, many modelers choose to use
32+ standard Python variables, lists, or dictionaries to store their data
33+ instead of Pyomo :class: `Param ` objects. This is a common and valid
34+ practice.
35+
36+ However, you must use a Pyomo :class: `Param ` if:
37+
38+ * You are using an :class: `AbstractModel ` (which requires components to be
39+ declared before data is loaded).
40+ * You need a **mutable ** parameter to change values and re-solve the model
41+ without the overhead of rebuilding it from scratch.
42+ * You want to leverage Pyomo's built-in data validation and index-checking
43+ capabilities.
44+
45+ Declaration and Options
46+ -----------------------
47+
48+ Parameters are declared as instances of the :class: `Param ` class. They can be
49+ scalar (single value) or indexed by one or more sets (Pyomo :class: `Set ` or
50+ other iterables). For example:
2051
2152.. testcode ::
2253
2354 model.A = pyo.RangeSet(1,3)
24- model.B = pyo.Set()
55+ model.B = pyo.Set(initialize=['dog', 'cat'])
56+ # Scalar parameter
57+ model.rho = pyo.Param(initialize=0.5)
58+ # Indexed parameter (by Set)
2559 model.P = pyo.Param(model.A, model.B)
60+ # Indexed parameter (by standard list)
61+ model.Q = pyo.Param(['a', 'b', 'c'], initialize={'a': 1, 'b': 2, 'c': 3})
2662
27- In addition to sets that serve as indexes, :class: `Param ` takes
28- the following options:
63+ If there are indexes for a :class: `Param `, they are provided as the first
64+ positional arguments and do not have a keyword label. In addition to these
65+ optional indexes, :class: `Param ` takes the following keyword arguments:
2966
30- - ``default `` = The parameter value absent any other specification .
67+ - ``default `` = The parameter value used if no other value is specified for an index .
3168- ``doc `` = A string describing the parameter.
32- - ``initialize `` = A function (or Python object) that returns data used to
33- initialize the parameter values.
34- - ``mutable `` = Boolean value indicating if the Param values are allowed
35- to change after the Param is initialized.
36- - ``validate `` = A callback function that takes the model, proposed
37- value, and indices of the proposed value; returning ``True `` if the value
38- is valid. Returning ``False `` will generate an exception.
39- - ``within `` = Set used for validation; it specifies the domain of
40- valid parameter values.
41-
42- These options perform in the same way as they do for :class: `Set `. For
43- example, given ``model.A `` with values ``{1, 2, 3} ``, then there are many
44- ways to create a parameter that represents a square matrix with 9, 16, 25 on the
45- main diagonal and zeros elsewhere, here are two ways to do it. First using a
46- Python object to initialize:
69+ - ``initialize `` = A function, dictionary, or other Python object used to
70+ provide initial data.
71+ - ``mutable `` = Boolean indicating if values can be changed after construction
72+ (see below).
73+ - ``validate `` = A callback function to verify data integrity.
74+ - ``within `` = A set (e.g., ``NonNegativeReals ``) used for domain validation.
75+
76+ Basic Initialization
77+ --------------------
78+
79+ There are many ways to provide data to a :class: `Param `. For example, given
80+ ``model.A `` with values ``{1, 2, 3} ``, here are two ways to create a diagonal
81+ matrix:
4782
4883.. testcode ::
4984
@@ -53,9 +88,7 @@ Python object to initialize:
5388 v[3,3] = 25
5489 model.S1 = pyo.Param(model.A, model.A, initialize=v, default=0)
5590
56- And now using an initialization function that is automatically called
57- once for each index tuple (remember that we are assuming that
58- ``model.A `` contains ``{1, 2, 3} ``)
91+ You can also use an initialization function that Pyomo calls for each index:
5992
6093.. testcode ::
6194
@@ -66,21 +99,17 @@ once for each index tuple (remember that we are assuming that
6699 return 0.0
67100 model.S2 = pyo.Param(model.A, model.A, initialize=s_init)
68101
69- In this example, the index set contained integers, but index sets need
70- not be numeric. It is very common to use strings.
71-
72102.. note ::
73103
74- Data specified in an input file will override the data specified by
75- the ``initialize `` option.
104+ In an :class: `AbstractModel `, data specified in an external input file (e.g.,
105+ a ``.dat `` file) will override the data specified by the ``initialize ``
106+ option.
76107
77- Parameter values can be checked by a validation function. In the
78- following example, the every value of the parameter ``T `` (indexed by
79- ``model.A ``) is checked
80- to be greater than 3.14159. If a value is provided that is less than
81- that, the model instantiation will be terminated and an error message
82- issued. The validation function should be written so as to return
83- ``True `` if the data is valid and ``False `` otherwise.
108+ Validation
109+ ----------
110+
111+ Parameter values can be checked by a validation function. In the following
112+ example, we ensure every value of ``model.T `` is greater than 3.14159:
84113
85114.. testcode ::
86115
@@ -91,12 +120,97 @@ issued. The validation function should be written so as to return
91120
92121 model.T = pyo.Param(model.A, validate=t_validate, initialize=t_data)
93122
94- This example will prodice the following error, indicating that the value
95- provided for ``T[2] `` failed validation:
123+ This example will produce the following error:
96124
97125.. testoutput ::
98126
99127 Traceback (most recent call last):
100128 ...
101129 ValueError: Invalid parameter value: T[2] = '3', value type=<class 'int'>.
102130 Value failed parameter validation rule
131+
132+ Performance vs. Flexibility: Mutable Parameters
133+ -----------------------------------------------
134+
135+ By default, Pyomo parameters are **immutable ** (``mutable=False ``). This choice
136+ is driven by performance:
137+
138+ * **Immutable (Default): ** Pyomo "pre-computes" these values into the algebraic
139+ expressions during model construction. This results in faster model generation
140+ and significantly lower memory usage, especially for large models. Key
141+ advantages include:
142+
143+ * **Memory Efficiency: ** For indexed parameters, Pyomo avoids creating
144+ individual component data objects, significantly reducing memory overhead.
145+ * **Expression Speed: ** Values are injected as constants directly into the
146+ expression tree. This allows Pyomo to optimize expression tree walking.
147+ * **Simplification: ** Pyomo can simplify constant sub-expressions during
148+ model construction (e.g., ``5 * model.p * model.q[i] `` is simplified to a
149+ single float if ``p `` and ``q `` are immutable), further accelerating
150+ subsequent processing.
151+ * **Mutable: ** Pyomo maintains the parameter as a symbolic object within
152+ expressions. This allows you to change the value and re-solve without
153+ rebuilding the entire model, but it adds computational overhead.
154+
155+ It is important to note that even immutable :class: `Param ` objects carry some
156+ overhead. For the fastest possible model instantiation in a
157+ :class: `ConcreteModel `, using native Python data structures (like dictionaries
158+ or lists) to provide values directly into expressions is usually faster than
159+ using :class: `Param ` components. However, as noted earlier, :class: `Param `
160+ provides benefits like validation and the ability to update values if declared
161+ as mutable.
162+
163+ When to use Mutable
164+ ~~~~~~~~~~~~~~~~~~~
165+
166+ **Use Immutable if: **
167+ * The data is static and never changes during the lifetime of the model.
168+ * You want to maximize performance and minimize memory usage for large models.
169+
170+ **Use Mutable if: **
171+ * You are running a loop (e.g., sensitivity analysis) where you change
172+ parameter values and re-solve.
173+ * You want to update values frequently without the "re-construction"
174+ bottleneck.
175+ * The parameter is part of a nonlinear expression that you need to update.
176+ * You want named constants to be preserved in the Pyomo expressions (e.g., for documentation of debugging purposes)
177+
178+ Comparison: Param vs. Var
179+ -------------------------
180+
181+ It is common to confuse mutable parameters with variables. The following table
182+ summarizes the key differences:
183+
184+ .. list-table ::
185+ :header-rows: 1
186+
187+ * - Feature
188+ - Param (Immutable)
189+ - Param (Mutable)
190+ - Var (fixed)
191+ - Var (free)
192+ * - Can change after model construction?
193+ - No
194+ - Yes
195+ - Yes
196+ - Yes
197+ * - Rebuilds model on change?
198+ - Yes (requires new Param)
199+ - No
200+ - No
201+ - No
202+ * - Solver sees it as:
203+ - A constant number
204+ - A constant number
205+ - A constant number
206+ - An optimization variable
207+
208+ .. note ::
209+
210+ **Should I use a mutable Param or a fixed Var? **
211+ While functionally similar, you should use a :class: `Param ` for data that
212+ defines the problem instance (like costs or demands) and a :class: `Var ` for
213+ the decisions the solver needs to make. Use `fix() ` on a :class: `Var ` when
214+ you want to temporarily hold a decision constant, and use a mutable
215+ :class: `Param ` when you need to update input data for sensitivity analysis
216+ or iterative algorithms.
0 commit comments