Skip to content

Commit

Permalink
Update to latest version of AMPL
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastian-quintero committed Feb 21, 2024
1 parent aebfa8a commit 51c2033
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 68 deletions.
4 changes: 2 additions & 2 deletions knapsack-ampl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ The most important files created are `main.py`, `input.json`, and
* `main.py` implements a MIP knapsack solver.
* `input.json` is a sample input file.
* `KEY.template` is a file demonstrating how to use the AMPL UUID license key.
Copy this file into a `KEY` file and replace the contents with your actual
license key.
Remove the `.template` extension and replace the contents with your actual
license key to be left with a file named `KEY`.

Follow these steps to run locally.

Expand Down
95 changes: 52 additions & 43 deletions knapsack-ampl/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,14 @@
import time
from typing import Any

from amplpy import AMPL, modules
from amplpy import AMPL, ErrorHandler, OutputHandler, modules

# Duration parameter for the solver.
SUPPORTED_PROVIDER_DURATIONS = {
"baron": "maxtime",
"cbc": "timelimit",
"conopt": "maxftime",
"copt": "timelimit",
"cplex": "timelimit",
"gcg": "timelimit",
"gurobi": "timelimit",
"highs": "timelimit",
"ilogcp": "timelimit",
"knitro": "maxtime_cpu",
"lgo": "timelim",
"lindoglobal": "maxtime",
"loqo": "timlim",
"mosek": "timelimit",
"scip": "timelimit",
"xpress": "timelimit",
}
Expand All @@ -41,6 +31,28 @@
]


class CollectOutput(OutputHandler):
def __init__(self):
self.buffer = ""

def output(self, kind, msg):
self.buffer += msg


output_handler = CollectOutput()


class CollectWarnings(ErrorHandler):
def __init__(self):
self.buffer = ""

def warning(self, exception):
self.buffer += str(exception)


error_handler = CollectWarnings()


def main() -> None:
"""Entry point for the template."""

Expand Down Expand Up @@ -74,10 +86,10 @@ def main() -> None:

# Read input "data", solve the problem and write the solution.
input_data = read_input(args.input)
# log("Solving knapsack problem:")
# log(f" - items: {len(input_data.get('items', []))}")
# log(f" - capacity: {input_data.get('weight_capacity', 0)}")
# log(f" - max duration: {args.duration} seconds")
log("Solving knapsack problem:")
log(f" - items: {len(input_data.get('items', []))}")
log(f" - capacity: {input_data.get('weight_capacity', 0)}")
log(f" - max duration: {args.duration} seconds")
solution = solve(input_data, args.duration, args.provider)
write_output(args.output, solution)

Expand All @@ -87,50 +99,47 @@ def solve(input_data: dict[str, Any], duration: int, provider: str) -> dict[str,

start_time = time.time()

# Make sure the provider is supported.
if provider not in SUPPORTED_PROVIDER_DURATIONS:
raise ValueError(
f"Unsupported provider: {provider}. The supported providers are: "
f"{', '.join(SUPPORTED_PROVIDER_DURATIONS.keys())}"
)

# Defines the model.
ampl = AMPL()
ampl.set_output_handler(output_handler)
ampl.set_error_handler(error_handler)
ampl.eval(
"""
# Sets
set I; # Set of items.
r"""
# Sets
set I; # Set of items.
# Parameters
param W >= 0; # Maximum weight capacity.
param v {I} >= 0; # Value of each item.
param w {I} >= 0; # Weight of each item.
# Parameters
param W >= 0; # Maximum weight capacity.
param v {I} >= 0; # Value of each item.
param w {I} >= 0; # Weight of each item.
# Variables
var x {I} binary; # 1 if item is selected, 0 otherwise.
# Variables
var x {I} binary; # 1 if item is selected, 0 otherwise.
# Objective
maximize z: sum {i in I} v[i] * x[i];
# Objective
maximize z: sum {i in I} v[i] * x[i];
# Constraints
s.t. weight_limit: sum {i in I} w[i] * x[i] <= W;
"""
# Constraints
s.t. weight_limit: sum {i in I} w[i] * x[i] <= W;
"""
)

# Sets the solver and options.
ampl.option["solver"] = provider
ampl.option[f"{provider}_options"] = f"{SUPPORTED_PROVIDER_DURATIONS[provider]}={duration}"
ampl.option["solver_msg"] = 0
ampl.option["outlev"] = 0
if provider in SUPPORTED_PROVIDER_DURATIONS:
ampl.option[f"{provider}_options"] = f"{SUPPORTED_PROVIDER_DURATIONS[provider]}={duration}"

# Set the data on the model.
ampl.set["I"] = [item["id"] for item in input_data["items"]]
ampl.param["W"] = input_data["weight_capacity"]
ampl.param["v"] = {item["id"]: item["value"] for item in input_data["items"]}
ampl.param["w"] = {item["id"]: item["weight"] for item in input_data["items"]}

# Solves the problem.
ampl.solve()
# Solves the problem. Verbose mode is turned off to avoid printing to
# stdout. Only the output should be printed to stdout.
ampl.solve(verbose=False)
log(f"AMPL output after solving: {output_handler.buffer}")
log(f"AMPL errors after solving: {error_handler.buffer}")

# Convert to solution format.
value = ampl.get_objective("z")
Expand All @@ -151,10 +160,10 @@ def solve(input_data: dict[str, Any], duration: int, provider: str) -> dict[str,
statistics = {
"result": {
"custom": {
"constraints": ampl.get_constraints().size(),
"constraints": ampl.get_value("_ncons"),
"provider": provider,
"status": status,
"variables": ampl.get_variables().size(),
"variables": ampl.get_value("_nvars"),
},
"duration": ampl.get_value("_total_solve_time"),
"value": value.value(),
Expand Down
36 changes: 13 additions & 23 deletions knapsack-ampl/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
ampl-module-amplgsl==20231107
ampl-module-baron==20230405
# Look for AMPL’s packages in the AMPL package index.
--index-url https://pypi.ampl.com
--extra-index-url https://pypi.org/simple

# AMPL packages.
amplpy==0.13.3
ampltools==0.7.4
ampl-module-base==20240126
ampl-module-cbc==20240115
ampl-module-coin==20240115
ampl-module-conopt==20211109
ampl-module-copt==20240115
ampl-module-cplex==20240115
ampl-module-gcg==20230919
ampl-module-gecode==20220504
ampl-module-gjh==20231111
ampl-module-gokestrel==20211022
ampl-module-gurobi==20240115
ampl-module-highs==20240115
ampl-module-ilogcp==20230228
ampl-module-knitro==20240209
ampl-module-lgo==20190908
ampl-module-lindoglobal==20210406
ampl-module-loqo==20210410
ampl-module-minos==20211109
ampl-module-mosek==20240118
ampl-module-open==20240121
ampl-module-plugins==20240102
ampl-module-scip==20240121
ampl-module-snopt==20211109
ampl-module-xpress==20240115
amplpy==0.13.2
ampltools==0.7.4
certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.6
requests==2.31.0
urllib3==2.2.1

# Other packages.
numpy==1.26.4
pandas==2.2.0
scipy==1.12.0

0 comments on commit 51c2033

Please sign in to comment.