AMPL Christmas Model created by ChatGPT#
Description: Christmas model generated by ChatGPT
Tags: christmas, chatgpt, amplpy, highlights
Notebook author: Filipe Brandão <fdabrandao@gmail.com>
Model author: ChatGPT
# Install dependencies
%pip install -q amplpy pandas
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook
ampl = ampl_notebook(
modules=["highs", "cbc", "gurobi"], # modules to install
license_uuid="default", # license to use
) # instantiate AMPL object and register magics
ChatGPT & AMPL#
The AMPL dev team spent some time this week asking ChatGPT to write AMPL models. Sometimes the responses were not perfect, which is to be expected, but we would work WITH ChatGPT on lines of code that were incorrect and it LEARNED from its errors, corrected the model and provided us with an updated version.
Social media posts with video: LinkedIn Post | Twitter Post | YouTube Video
Christmas model by ChatGPT#
Problem description, mathematical model, AMPL model and data copied directly from ChatGPT:
In this optimization problem, we are trying to choose the best gift for each person, given a set of people PEOPLE
and a set of gifts GIFTS
, in order to maximize the total happiness. Each gift has a certain cost, and we have a budget that we cannot exceed. Each person can only receive one gift. The decision variables x[p,g]
represent whether each person p
receives each gift g
, and must be binary (either 0 or 1).
The mathematical formulation of the problem is as follows:
%%ampl_eval
reset; # clear previous definitions
# define the set of people
set PEOPLE;
# define the set of gifts
set GIFTS;
# define the cost of each gift
param cost{GIFTS};
# define the happiness level for each person receiving each gift
param happiness{PEOPLE, GIFTS};
# define the budget for gift-giving
param budget;
# define the decision variables:
# x[p,g] is 1 if person p receives gift g, 0 otherwise
var x{PEOPLE, GIFTS} binary;
# the objective is to maximize total happiness
maximize total_happiness: sum{p in PEOPLE, g in GIFTS} happiness[p,g] * x[p,g];
# subject to the budget constraint:
# the total cost of the gifts must be less than or equal to the budget
subject to budget_constraint: sum{p in PEOPLE, g in GIFTS} cost[g] * x[p,g] <= budget;
# each person can only receive one gift
subject to one_gift_per_person{p in PEOPLE}: sum{g in GIFTS} x[p,g] = 1;
Load data directly from python data structures using amplpy#
ampl.set["PEOPLE"] = ["Alice", "Bob", "Carol", "Dave", "Eve"]
ampl.set["GIFTS"] = ["Book", "Toy", "Chocolate", "Wine", "Flowers"]
ampl.param["cost"] = {"Book": 10, "Toy": 20, "Chocolate": 5, "Wine": 15, "Flowers": 7}
ampl.param["budget"] = 50
import pandas as pd
happiness_df = pd.DataFrame(
{
"Book": [3, 2, 5, 1, 4],
"Toy": [5, 2, 4, 3, 1],
"Chocolate": [1, 3, 4, 5, 2],
"Wine": [2, 5, 3, 4, 1],
"Flowers": [4, 3, 1, 2, 5],
},
index=["Alice", "Bob", "Carol", "Dave", "Eve"],
)
display(happiness_df) # display 2D Pandas DataFrame
Book | Toy | Chocolate | Wine | Flowers | |
---|---|---|---|---|---|
Alice | 3 | 5 | 1 | 2 | 4 |
Bob | 2 | 2 | 3 | 5 | 3 |
Carol | 5 | 4 | 4 | 3 | 1 |
Dave | 1 | 3 | 5 | 4 | 2 |
Eve | 4 | 1 | 2 | 1 | 5 |
happiness_df_stacked = happiness_df.stack().to_frame()
display(happiness_df_stacked) # display Pandas DataFrame with Multi-Index
0 | ||
---|---|---|
Alice | Book | 3 |
Toy | 5 | |
Chocolate | 1 | |
Wine | 2 | |
Flowers | 4 | |
Bob | Book | 2 |
Toy | 2 | |
Chocolate | 3 | |
Wine | 5 | |
Flowers | 3 | |
Carol | Book | 5 |
Toy | 4 | |
Chocolate | 4 | |
Wine | 3 | |
Flowers | 1 | |
Dave | Book | 1 |
Toy | 3 | |
Chocolate | 5 | |
Wine | 4 | |
Flowers | 2 | |
Eve | Book | 4 |
Toy | 1 | |
Chocolate | 2 | |
Wine | 1 | |
Flowers | 5 |
# To load the data for the parameter happiness you can use either happiness_df or happiness_df_stacked in the same way
ampl.param["happiness"] = happiness_df
Solve with HiGHS and retrieve solution#
ampl.option["solver"] = "highs"
ampl.solve()
solution = ampl.get_data("{p in PEOPLE, g in GIFTS: x[p, g] > 0} x[p, g]").to_dict()
print(f"Solution:\n\t{solution}")
print("\nTo maximize the total happiness:")
for person, gift in solution:
print(f"- give {gift} to {person}.")
HiGHS 1.6.0: HiGHS 1.6.0: optimal solution; objective 24
3 simplex iterations
1 branching nodes
Solution:
{('Alice', 'Flowers'): 1, ('Bob', 'Wine'): 1, ('Carol', 'Book'): 1, ('Dave', 'Chocolate'): 1, ('Eve', 'Flowers'): 1}
To maximize the total happiness:
- give Flowers to Alice.
- give Wine to Bob.
- give Book to Carol.
- give Chocolate to Dave.
- give Flowers to Eve.
Change the budget and solve with Gurobi#
ampl.param["budget"] = 100
ampl.option["solver"] = "gurobi"
ampl.solve()
solution = ampl.var["x"].to_pandas() # retrieve variable values as a Pandas DataFrame
print("Solution:")
display(solution[solution["x.val"] == 1]) # display rows with x.val == 1
print("\nTo maximize the total happiness:")
for person, gift in solution.index[solution["x.val"] == 1].tolist():
print(f"- give {gift} to {person}.")
Gurobi 11.0.0: Gurobi 11.0.0: optimal solution; objective 25
0 simplex iterations
Solution:
x.val | ||
---|---|---|
index0 | index1 | |
Alice | Toy | 1 |
Bob | Wine | 1 |
Carol | Book | 1 |
Dave | Chocolate | 1 |
Eve | Flowers | 1 |
To maximize the total happiness:
- give Toy to Alice.
- give Wine to Bob.
- give Book to Carol.
- give Chocolate to Dave.
- give Flowers to Eve.
Change the budget once again and solve with CBC#
ampl.param["budget"] = 30
ampl.option["solver"] = "cbc"
ampl.solve()
solution = ampl.var["x"].to_dict() # retrieve variable values as a dictionary
print(f"Solution:\n\t{solution}")
print("\nTo maximize the total happiness:")
for person, gift in solution:
if solution[person, gift] == 1:
print(f"- give {gift} to {person}.")
cbc 2.10.10: cbc 2.10.10: optimal solution; objective 21
0 simplex iterations
Solution:
{('Alice', 'Book'): 0, ('Alice', 'Chocolate'): 0, ('Alice', 'Flowers'): 1, ('Alice', 'Toy'): 0, ('Alice', 'Wine'): 0, ('Bob', 'Book'): 0, ('Bob', 'Chocolate'): 1, ('Bob', 'Flowers'): 0, ('Bob', 'Toy'): 0, ('Bob', 'Wine'): 0, ('Carol', 'Book'): 0, ('Carol', 'Chocolate'): 1, ('Carol', 'Flowers'): 0, ('Carol', 'Toy'): 0, ('Carol', 'Wine'): 0, ('Dave', 'Book'): 0, ('Dave', 'Chocolate'): 1, ('Dave', 'Flowers'): 0, ('Dave', 'Toy'): 0, ('Dave', 'Wine'): 0, ('Eve', 'Book'): 0, ('Eve', 'Chocolate'): 0, ('Eve', 'Flowers'): 1, ('Eve', 'Toy'): 0, ('Eve', 'Wine'): 0}
To maximize the total happiness:
- give Flowers to Alice.
- give Chocolate to Bob.
- give Chocolate to Carol.
- give Chocolate to Dave.
- give Flowers to Eve.
Some useful information:#
You can see more models at the AMPL Model Colaboratory: https://colab.ampl.com
You can ask for help at the AMPL Discourse Forum: https://discuss.ampl.com
You can get a free AMPL Community Edition license: https://ampl.com/ce/