#### 21 September 2022 (1,571 words)

In this article we continue the Python Production mix series, using the Pyomo library. Specifically, we build Model 6, which changes Model 5 to:

• Declare the model as a Pyomo pyo.AbstractModel, rather than as a pyo.ConcreteModel.
• Read the data from a dat file rather than a json file.

These changes show that, contrary to how abstract and concrete models are portrayed in most blogs, there is actually little difference between abstract and concrete Pyomo models.

### Articles in this series

Articles in the Python Production mix series:

The Python code and data for this model are available in the following files:

The "Jupyter notebook" file contains a formatted combination of Python code and markdown code – this file should be opened and run in Jupyter Lab. We describe setting up our Python environment, including Jupyter Lab and various Python libraries, in the article Set up a Python modelling environment.

The "Python code" file is a plain text file containing only the Python code of this model. Download this file if you have a non-Jupyter environment for running Python programs.

The "Data" file is a plain text file containing the model's data, in Pyomo dat format.

The model files are also available on GitHub.

### Formulation for Model 6

For this model, we're using the same general formulation that we used for Model 5, as shown in Figure 1.

### Model 6 Python code

#### Import dependencies

The first task is to import the libraries that are needed for our program. As shown in Figure 2, we aren't using a json file, so we don't need the os and json libraries that we imported in Model 5.

#### Data file

The data for Model 6 is shown in Figure 3. Unlike Model 5, where we read json format data and assign it to Pyomo Param data structures, here we define the data directly in param data structures. Note the different capitalization of the two structures – uppercase for parameters defined in the model, and lowercase for parameters defined in a dat file. The same convention applies to sets.

Note that, unlike concrete models, we don't load the data at this stage. This is the essential difference between the two types of Pyomo model. That is:

• pyo.ConcreteModel. Data is loaded before the constraints and objective function are defined.
• pyo.AbstractModel. The constraints are objective function are defined first, with the data loaded only when we solve the model.

#### Declarations

We declare an pyo.AbstractModel, rather than a pyo.ConcreteModel. Because we have not loaded the data, the declarations are empty sets and parameters, as shown in Figure 4. Though we can declare the domains, such as pyo.NonNegativeReals.

#### Define the model

The model definition, as shown in Figure 5, is the same as for Model 5.

In a more complex model, the concrete and abstract model definitions may not be the same. Specifically, in a concrete mode, we may use the data to make decisions within the constraint and objective function rules. That is not possible in a pure abstract model – though we could read some data, to inform decision making, but there is typically little advantage in adopting a hybrid approach.

#### Solve model

As shown in Figure 6, we create an instance of an abstract model by loading the data just before we solve the model. Having created an instance, we need to refer to our Instance object rather than our Model object. In abstract models, a common error is to refer to the model definition rather than its instance.

#### Process results

The code for processing the solver result, as shown in Figure 7, is the same as for Model 5 except that we refer to Instance rather than Model.

#### Write output

The code for writing the output, as shown in Figure 8, is almost the same as for Model 5, except that, again, we refer to Instance rather than Model.

When we find an optimal solution, the output is shown in Figure 9. This output is the same as for Model 5.

### Evaluation of this model

Model 6 is our final Pyomo model in this series of articles. This model translates the concrete Model 5 into an abstract model.

Most blog articles about Pyomo models suggest that there is a substantial difference between concrete and abstract models. A model like our Model 1 is often used as a typical concrete model, while a model like our Model 6 is used as a typical abstract model. When presented that way, there is indeed a substantial difference between the two types of model.

However, a fairer comparison is between our Model 5 and Model 6. When presented this way, there is actually little difference between the two model types. As the Pyomo documentation says:

Python programmers will probably prefer to write concrete models, while users of some other algebraic modeling languages may tend to prefer to write abstract models. The choice is largely a matter of taste; some applications may be a little more straightforward using one or the other.

Abstract versus Concrete models

### Next steps

So far in this series, we've explored the Pyomo library quite extensively. Next, we'll continue our Production mix series by implementing the model using other Python modelling libraries. Specifically, we'll use the PuLP, OR Tools, Gekko, CVXPY, and SciPy libraries to implement the same model. By using different libraries, we'll get some insight into their similarities and differences, along with their relative strengths and weaknesses.

### Conclusion

This article completes the Pyomo part of this series. Compared with models 1 to 5, which use Pyomo's concrete model type, here we use Pyomo's abstract model type. It turns out that there isn't much difference between the two model types, with the choice between them being largely a matter of taste.

In the next article, we'll start using different libraries to build the same Production mix model.