amplpy setup & Quick Start

quickstart.ipynb Open In Colab Kaggle Gradient Open In SageMaker Studio Lab Hits

Description: amplpy setup and quick start

Tags: amplpy, example

Notebook author: Filipe Brandão <fdabrandao@gmail.com>

Model author: N/A

References: N/A

Setup

Install from the PiPY repository:

$ python -m pip install amplpy

Note: For Windows, Linux, and macOS, the amplpy package comes with 33 binary wheels for Python 2.7, 3.5, 3.6, 3.7, 3.8, and 3.9. Please make sure that you are using the latest version of pip before installing amplpy (upgrade using “python -m pip install pip --upgrade”). If a binary wheel for your platform is not available, a C++ compiler and python development libraries will be required.

Additional packages

In this tutorial, we will also use Pandas and Bokeh. You can install these packages using “pip install pandas bokeh” or “python -m pip install pandas bokeh”. Note that Bokeh is not mandatory for this tutorial.

We also recommend the use of Jupyter Notebook, which was used to create this tutorial. You can install Jupyter using “pip install jupyter” or “python -m pip install jupyter”.

# Install dependencies
%pip install -q amplpy pandas numpy bokeh
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook

ampl = ampl_notebook(
    modules=["gurobi"],  # modules to install
    license_uuid="default",  # license to use
)  # instantiate AMPL object and register magics

Quick start

Step 1: Import some packages that we will use

Import Pandas and NumPy:

import pandas as pd
import numpy as np

Import Bokeh (do not run if you do not have Bokeh installed):

from bokeh.layouts import row
from bokeh.plotting import figure, show

For Jupyter Notebooks only (do not run if you are not using Bokeh and Jupyter):

from bokeh.io import output_notebook

output_notebook()

Step 2: Import the amplpy components that we will use

from amplpy import AMPL, Environment

Step 3: Create an AMPL object

ampl = AMPL()
ampl.eval("option version;")
option version 'AMPL Development Version 20230830 (Linux-5.15.0-1042-azure, 64-bit)\
Licensed to AMPL Community Edition License for the AMPL Model Colaboratory (https://colab.ampl.com).\
Temporary license expires 20240331.\
Using license file "/tmp/tmpti35nze0.lic".\
';

If the AMPL installation directory is not in the system search path, you should create the AMPL object as follows instead:

ampl = AMPL(Environment('full path to the AMPL installation directory'))

Note that you may need to use raw strings (e.g., r'C:\ampl\ampl.mswin64') or escape the slashes (e.g., 'C:\\ampl\\ampl.mswin64') if the path includes backslashes.

Step 4: Select the solver

ampl.set_option("solver", "gurobi")

Step 5: Define the model

ampl.eval(
    """
set NUTR;
set FOOD;

param cost {FOOD} > 0;
param f_min {FOOD} >= 0;
param f_max {j in FOOD} >= f_min[j];

param n_min {NUTR} >= 0;
param n_max {i in NUTR} >= n_min[i];

param amt {NUTR,FOOD} >= 0;

var Buy {j in FOOD} >= f_min[j], <= f_max[j];

minimize Total_Cost:  sum {j in FOOD} cost[j] * Buy[j];

subject to Diet {i in NUTR}:
   n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
"""
)

Note: Alternatively you can read the model from a file using “ampl.read(filename)”.

Step 6: Define the initial data

foods = ["BEEF", "CHK", "FISH", "HAM", "MCH", "MTL", "SPG", "TUR"]
nutrients = ["A", "C", "B1", "B2", "NA", "CAL"]

Define AMPL sets fom python lists

ampl.get_set("FOOD").set_values(foods)
ampl.get_set("NUTR").set_values(nutrients)

Define data using an amplpy DataFrame

ampl.set_data(
    pd.DataFrame(
        {
            "cost": [3.59, 2.59, 2.29, 2.89, 1.89, 1.99, 1.99, 2.49],
            "f_min": [2, 2, 2, 2, 2, 2, 2, 2],
            "f_max": [10, 10, 10, 10, 10, 10, 10, 10],
        },
        index=foods,
    )
)

Define data using a Pandas DataFrame

ampl.set_data(
    pd.DataFrame(
        {
            "n_min": [700, 700, 700, 700, 0, 16000],
            "n_max": [20000, 20000, 20000, 20000, 50000, 24000],
        },
        index=nutrients,
    )
)

Define data using a python dictionary

ampl.get_parameter("amt").set_values(
    pd.DataFrame(
        np.array(
            [
                [60, 8, 8, 40, 15, 70, 25, 60],
                [20, 0, 10, 40, 35, 30, 50, 20],
                [10, 20, 15, 35, 15, 15, 25, 15],
                [15, 20, 10, 10, 15, 15, 15, 10],
                [928, 2180, 945, 278, 1182, 896, 1329, 1397],
                [295, 770, 440, 430, 315, 400, 379, 450],
            ]
        ),
        columns=foods,
        index=nutrients,
    )
)

Step 7: Solve the model

ampl.solve()
Gurobi 10.0.2: Gurobi 10.0.2: optimal solution; objective 119.9897589
5 simplex iterations
 

Step 8: Create a Pandas DataFrame with the values of the variable ‘Buy’

ampl.get_variable("Buy").to_pandas()
Buy.val
BEEF 5.226933
CHK 2.000000
FISH 2.000000
HAM 10.000000
MCH 10.000000
MTL 10.000000
SPG 9.439734
TUR 2.000000

Step 9: Display the objective value

totalcost = ampl.get_objective("Total_Cost")
print("Objective is:", totalcost.value())
Objective is: 119.98975893599335

Step 10: Increase the costs of beef and ham

cost = ampl.get_parameter("cost")
cost.set_values({"BEEF": 5.01, "HAM": 4.55})
print("Increased costs of beef and ham.")
Increased costs of beef and ham.

Step 11: Solve the model with the new costs

ampl.solve()
Gurobi 10.0.2: Gurobi 10.0.2: optimal solution; objective 144.0120033
0 simplex iterations
 

Step 12: Display the new objective value

print("New objective value:", totalcost.value())
New objective value: 144.01200332502077

Step 13: Display the value of Buy[‘BEEF’]

Buy = ampl.get_variable("Buy")
print("Buy['BEEF'].val = {}".format(Buy["BEEF"].value()))
Buy['BEEF'].val = 5.226932668329175

Step 14: Display the dual value of each diet constraint

diet = ampl.get_constraint("Diet")
for nutr in nutrients:
    print("Diet['{}'].dual = {}".format(nutr, diet[nutr].dual()))
Diet['A'].dual = 0.0
Diet['C'].dual = 0.0
Diet['B1'].dual = 0.0
Diet['B2'].dual = 0.7999285120532004
Diet['NA'].dual = -0.007531172069825437
Diet['CAL'].dual = 0.0

Step 15: Display the values of the variable ‘Buy’ using Bokeh

rows = [tuple(row) for row in Buy.get_values()]
factors = [index for index, value in rows]
x = [value for index, value in rows]

dot = figure(
    title="Categorical Dot Plot",
    tools="",
    toolbar_location=None,
    y_range=factors,
    x_range=[0, 12],
)

dot.segment(0, factors, x, factors, line_width=2, line_color="green")
dot.circle(x, factors, size=15, fill_color="orange", line_color="green", line_width=3)
show(dot)