From f643dcb026dd14d0e8464f2e82cfd792518f47d0 Mon Sep 17 00:00:00 2001 From: anandhkb Date: Tue, 3 Mar 2026 14:16:07 -0800 Subject: [PATCH 1/2] Add ARM libs download comment to trnsport_cuopt notebook --- .../trnsport_cuopt.ipynb | 2829 ++++++----------- 1 file changed, 915 insertions(+), 1914 deletions(-) diff --git a/GAMSPy_integration_example/trnsport_cuopt.ipynb b/GAMSPy_integration_example/trnsport_cuopt.ipynb index 1f85c37..0093b3e 100644 --- a/GAMSPy_integration_example/trnsport_cuopt.ipynb +++ b/GAMSPy_integration_example/trnsport_cuopt.ipynb @@ -1,1953 +1,954 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:15.883029Z", - "iopub.status.busy": "2025-07-17T10:21:15.882854Z", - "iopub.status.idle": "2025-07-17T10:21:40.914508Z", - "shell.execute_reply": "2025-07-17T10:21:40.914244Z" + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:15.883029Z", + "iopub.status.busy": "2025-07-17T10:21:15.882854Z", + "iopub.status.idle": "2025-07-17T10:21:40.914508Z", + "shell.execute_reply": "2025-07-17T10:21:40.914244Z" + }, + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "# GAMSPy model example\n", + "\n", + "## Introduction\n", + "\n", + "This quick start guide is designed to provide you with a concise overview of GAMSPy and its key features. By the end of this guide, you'll have a solid understanding of how to create basic mathematical models using GAMSPy. For more advanced features, we recommend exploring our comprehensive [user guide](https://gamspy.readthedocs.io/en/latest/user/index.html) and the extensive [model library](https://gamspy.readthedocs.io/en/latest/user/model_library.html).\n", + "\n", + "While not mandatory, having a basic understanding of Python programming and familiarity with the [Pandas library](https://pandas.pydata.org/). will be helpful in following this tutorial.\n", + "\n", + "## A Transportation Problem\n", + "\n", + "In this guide, we'll delve into an example of the transportation problem. This classic scenario involves managing supplies from various plants to meet demands at multiple markets for a single commodity. Additionally, we have the unit costs associated with shipping the commodity from plants to markets. The fundamental economic question here is: \n", + "\n", + "> How can we optimize the shipment quantities between each plant and market to minimize the total transport cost?\n", + "\n", + "The problem's algebraic representation typically takes the following format:\n", + "\n", + "Indices (Sets):\n", + "\n", + "- $i$ = plants\n", + "- $j$ = markets\n", + "\n", + "Given Data (Parameters):\n", + "\n", + "- $a_i$ = supply of commodity at plant $i$ (in cases)\n", + "- $b_j$ = demand for commodity at market $j$ (in cases)\n", + "- $c_{ij}$ = cost per unit of shipment between plant $i$ and market $j$\n", + "\n", + "Decision Variables:\n", + "\n", + "- $x_{ij}$ = amount of commodity to ship from plant $i$ to market $j$ where $x_{ij} \\ge 0$ for all $i,j$\n", + "\n", + "Constraints:\n", + "\n", + "- Observe supply limit at plant $i$: $\\sum_j x_{ij} \\le a_i \\: \\forall i$\n", + "- Satisfy demand at market $j$: $\\sum_i x_{ij} \\ge b_j \\: \\forall j$\n", + "- Objective Function: Minimize $\\sum_i \\sum_j c_{ij} \\cdot x_{ij}$" + ] }, - "vscode": { - "languageId": "shellscript" - } - }, - "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Archive: cuopt-link-release.zip\n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/librapids_logger.so \n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/gamsconfig.yaml \n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/libgomp-5fc1ad8c.so.1.0.0 \n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/gmscuopt.run \n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/gmscuopt.out \n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/libmps_parser.so \n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/libcuopt.so \n", - " inflating: /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/optcuopt.def \n" - ] + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import subprocess\n", + "import html\n", + "from IPython.display import display, HTML\n", + "\n", + "def check_gpu():\n", + " try:\n", + " result = subprocess.run([\"nvidia-smi\"], capture_output=True, text=True, timeout=5)\n", + " result.check_returncode()\n", + " lines = result.stdout.splitlines()\n", + " gpu_info = lines[2] if len(lines) > 2 else \"GPU detected\"\n", + " gpu_info_escaped = html.escape(gpu_info)\n", + " display(HTML(f\"\"\"\n", + "
\n", + "

✅ GPU is enabled

\n", + "
{gpu_info_escaped}
\n", + "
\n", + " \"\"\"))\n", + " return True\n", + " except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError, IndexError) as e:\n", + " display(HTML(\"\"\"\n", + "
\n", + "

⚠️ GPU not detected!

\n", + "

This notebook requires a GPU runtime.

\n", + " \n", + "

If running in Google Colab:

\n", + "
    \n", + "
  1. Click on Runtime → Change runtime type
  2. \n", + "
  3. Set Hardware accelerator to GPU
  4. \n", + "
  5. Then click Save and Runtime → Restart runtime.
  6. \n", + "
\n", + " \n", + "

If running in Docker:

\n", + "
    \n", + "
  1. Ensure you have NVIDIA Docker runtime installed (nvidia-docker2)
  2. \n", + "
  3. Run container with GPU support: docker run --gpus all ...
  4. \n", + "
  5. Or use: docker run --runtime=nvidia ... for older Docker versions
  6. \n", + "
  7. Verify GPU access: docker run --gpus all nvidia/cuda:12.0.0-base-ubuntu22.04 nvidia-smi
  8. \n", + "
\n", + " \n", + "

Additional resources:

\n", + " \n", + "
\n", + " \"\"\"))\n", + " return False\n", + "\n", + "check_gpu()" + ] }, { - "data": { - "text/plain": [ - "CompletedProcess(args='unzip -o cuopt-link-release.zip -d /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base', returncode=0)" + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Enable this in case you are running this in google colab or such places where cuOpt is not yet installed\n", + "#!pip uninstall -y cuda-python cuda-bindings cuda-core\n", + "#!pip install --upgrade --extra-index-url=https://pypi.nvidia.com cuopt-cu12 nvidia-nvjitlink-cu12 rapids-logger==0.1.19\n", + "#!pip install --upgrade --extra-index-url=https://pypi.nvidia.com cuopt-cu13 nvidia-nvjitlink-cu13 rapids-logger==0.1.1" ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# GAMSPy model example\n", - "\n", - "## Introduction\n", - "\n", - "This quick start guide is designed to provide you with a concise overview of GAMSPy and its key features. By the end of this guide, you'll have a solid understanding of how to create basic mathematical models using GAMSPy. For more advanced features, we recommend exploring our comprehensive [user guide](https://gamspy.readthedocs.io/en/latest/user/index.html) and the extensive [model library](https://gamspy.readthedocs.io/en/latest/user/model_library.html).\n", - "\n", - "While not mandatory, having a basic understanding of Python programming and familiarity with the [Pandas library](https://pandas.pydata.org/). will be helpful in following this tutorial.\n", - "\n", - "## A Transportation Problem\n", - "\n", - "In this guide, we'll delve into an example of the transportation problem. This classic scenario involves managing supplies from various plants to meet demands at multiple markets for a single commodity. Additionally, we have the unit costs associated with shipping the commodity from plants to markets. The fundamental economic question here is: \n", - "\n", - "> How can we optimize the shipment quantities between each plant and market to minimize the total transport cost?\n", - "\n", - "The problem's algebraic representation typically takes the following format:\n", - "\n", - "Indices (Sets):\n", - "\n", - "- $i$ = plants\n", - "- $j$ = markets\n", - "\n", - "Given Data (Parameters):\n", - "\n", - "- $a_i$ = supply of commodity at plant $i$ (in cases)\n", - "- $b_j$ = demand for commodity at market $j$ (in cases)\n", - "- $c_{ij}$ = cost per unit of shipment between plant $i$ and market $j$\n", - "\n", - "Decision Variables:\n", - "\n", - "- $x_{ij}$ = amount of commodity to ship from plant $i$ to market $j$ where $x_{ij} \\ge 0$ for all $i,j$\n", - "\n", - "Constraints:\n", - "\n", - "- Observe supply limit at plant $i$: $\\sum_j x_{ij} \\le a_i \\: \\forall i$\n", - "- Satisfy demand at market $j$: $\\sum_i x_{ij} \\ge b_j \\: \\forall j$\n", - "- Objective Function: Minimize $\\sum_i \\sum_j c_{ij} \\cdot x_{ij}$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import subprocess\n", - "import html\n", - "from IPython.display import display, HTML\n", - "\n", - "def check_gpu():\n", - " try:\n", - " result = subprocess.run([\"nvidia-smi\"], capture_output=True, text=True, timeout=5)\n", - " result.check_returncode()\n", - " lines = result.stdout.splitlines()\n", - " gpu_info = lines[2] if len(lines) > 2 else \"GPU detected\"\n", - " gpu_info_escaped = html.escape(gpu_info)\n", - " display(HTML(f\"\"\"\n", - "
\n", - "

✅ GPU is enabled

\n", - "
{gpu_info_escaped}
\n", - "
\n", - " \"\"\"))\n", - " return True\n", - " except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError, IndexError) as e:\n", - " display(HTML(\"\"\"\n", - "
\n", - "

⚠️ GPU not detected!

\n", - "

This notebook requires a GPU runtime.

\n", - " \n", - "

If running in Google Colab:

\n", - "
    \n", - "
  1. Click on Runtime → Change runtime type
  2. \n", - "
  3. Set Hardware accelerator to GPU
  4. \n", - "
  5. Then click Save and Runtime → Restart runtime.
  6. \n", - "
\n", - " \n", - "

If running in Docker:

\n", - "
    \n", - "
  1. Ensure you have NVIDIA Docker runtime installed (nvidia-docker2)
  2. \n", - "
  3. Run container with GPU support: docker run --gpus all ...
  4. \n", - "
  5. Or use: docker run --runtime=nvidia ... for older Docker versions
  6. \n", - "
  7. Verify GPU access: docker run --gpus all nvidia/cuda:12.0.0-base-ubuntu22.04 nvidia-smi
  8. \n", - "
\n", - " \n", - "

Additional resources:

\n", - " \n", - "
\n", - " \"\"\"))\n", - " return False\n", - "\n", - "check_gpu()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Enable this in case you are running this in google colab or such places where cuOpt is not yet installed\n", - "#!pip uninstall -y cuda-python cuda-bindings cuda-core\n", - "#!pip install --upgrade --extra-index-url=https://pypi.nvidia.com cuopt-cu12 nvidia-nvjitlink-cu12 rapids-logger==0.1.19\n", - "#!pip install --upgrade --extra-index-url=https://pypi.nvidia.com cuopt-cu13 nvidia-nvjitlink-cu13 rapids-logger==0.1.1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Install other dependencies (if not already installed)\n", - "\n", - "!pip install -q gamspy\n", - "import subprocess\n", - "import sys\n", - "!wget -nc -nv -O cuopt-link-release.zip \"https://github.com/GAMS-dev/cuoptlink-builder/releases/download/v0.0.1/cuopt-link-release.zip\"\n", - "gams_base_path = subprocess.check_output([sys.executable, '-m', 'gamspy', 'show', 'base']).decode('utf-8').strip()\n", - "subprocess.run(f\"unzip -o cuopt-link-release.zip -d {gams_base_path}\", shell=True, check=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Data\n", - "\n", - "Before we dive into the optimization process, let's handle our data using the [Pandas library](https://pandas.pydata.org/). We'll begin by organizing the necessary information, which we will subsequently feed into our optimization model." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:40.915536Z", - "iopub.status.busy": "2025-07-17T10:21:40.915457Z", - "iopub.status.idle": "2025-07-17T10:21:41.083438Z", - "shell.execute_reply": "2025-07-17T10:21:41.083230Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
capacity
city
seattle350
san-diego600
\n", - "
" - ], - "text/plain": [ - " capacity\n", - "city \n", - "seattle 350\n", - "san-diego 600" + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Install other dependencies (if not already installed)\n", + "\n", + "!pip install -q gamspy\n", + "import subprocess\n", + "import sys\n", + "# For ARM: download ARM libs from https://github.com/GAMS-dev/cuoptlink-builder/releases\n", + "!wget -nc -nv -O cuopt-link-release.zip \"https://github.com/GAMS-dev/cuoptlink-builder/releases/download/v0.0.1/cuopt-link-release.zip\"\n", + "gams_base_path = subprocess.check_output([sys.executable, '-m', 'gamspy', 'show', 'base']).decode('utf-8').strip()\n", + "subprocess.run(f\"unzip -o cuopt-link-release.zip -d {gams_base_path}\", shell=True, check=True)" ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import pandas as pd\n", - "\n", - "capacities = pd.DataFrame(\n", - " [[\"seattle\", 350], [\"san-diego\", 600]], columns=[\"city\", \"capacity\"]\n", - ").set_index(\"city\")\n", - "\n", - "capacities" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.084284Z", - "iopub.status.busy": "2025-07-17T10:21:41.084168Z", - "iopub.status.idle": "2025-07-17T10:21:41.086987Z", - "shell.execute_reply": "2025-07-17T10:21:41.086797Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
demand
city
new-york325
chicago300
topeka275
\n", - "
" - ], - "text/plain": [ - " demand\n", - "city \n", - "new-york 325\n", - "chicago 300\n", - "topeka 275" + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Data\n", + "\n", + "Before we dive into the optimization process, let's handle our data using the [Pandas library](https://pandas.pydata.org/). We'll begin by organizing the necessary information, which we will subsequently feed into our optimization model." ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "demands = pd.DataFrame(\n", - " [[\"new-york\", 325], [\"chicago\", 300], [\"topeka\", 275]], columns=[\"city\", \"demand\"]\n", - ").set_index(\"city\")\n", - "\n", - "demands" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.087770Z", - "iopub.status.busy": "2025-07-17T10:21:41.087633Z", - "iopub.status.idle": "2025-07-17T10:21:41.091517Z", - "shell.execute_reply": "2025-07-17T10:21:41.091358Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
distance
fromto
seattlenew-york2.5
chicago1.7
topeka1.8
san-diegonew-york2.5
chicago1.8
topeka1.4
\n", - "
" - ], - "text/plain": [ - " distance\n", - "from to \n", - "seattle new-york 2.5\n", - " chicago 1.7\n", - " topeka 1.8\n", - "san-diego new-york 2.5\n", - " chicago 1.8\n", - " topeka 1.4" + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:40.915536Z", + "iopub.status.busy": "2025-07-17T10:21:40.915457Z", + "iopub.status.idle": "2025-07-17T10:21:41.083438Z", + "shell.execute_reply": "2025-07-17T10:21:41.083230Z" + } + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "capacities = pd.DataFrame(\n", + " [[\"seattle\", 350], [\"san-diego\", 600]], columns=[\"city\", \"capacity\"]\n", + ").set_index(\"city\")\n", + "\n", + "capacities" ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "distances = pd.DataFrame(\n", - " [\n", - " [\"seattle\", \"new-york\", 2.5],\n", - " [\"seattle\", \"chicago\", 1.7],\n", - " [\"seattle\", \"topeka\", 1.8],\n", - " [\"san-diego\", \"new-york\", 2.5],\n", - " [\"san-diego\", \"chicago\", 1.8],\n", - " [\"san-diego\", \"topeka\", 1.4],\n", - " ],\n", - " columns=[\"from\", \"to\", \"distance\"],\n", - ").set_index([\"from\", \"to\"])\n", - "\n", - "distances" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.092111Z", - "iopub.status.busy": "2025-07-17T10:21:41.092042Z", - "iopub.status.idle": "2025-07-17T10:21:41.093337Z", - "shell.execute_reply": "2025-07-17T10:21:41.093174Z" - } - }, - "outputs": [], - "source": [ - "freight_cost = 90" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Symbol Declaration\n", - "\n", - "In line with our systematic breakdown of the transportation problem into sets, parameters, variables, and constraints, we will adopt a similar approach to define the problem as a GAMSPy `Model`. To do so, it is essential to import the `gamspy` library initially." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.093948Z", - "iopub.status.busy": "2025-07-17T10:21:41.093881Z", - "iopub.status.idle": "2025-07-17T10:21:41.163655Z", - "shell.execute_reply": "2025-07-17T10:21:41.163440Z" - } - }, - "outputs": [], - "source": [ - "from gamspy import Container, Set, Parameter, Variable, Equation, Model, Sum, Sense" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Container\n", - "\n", - "Before we proceed further, let's create a `Container` to encapsulate all the relevant information for our GAMSPy ``Model``. This ``Container`` acts as a centralized hub, gathering essential data, sets, parameters, variables, and constraints, providing a clear structure for our optimization problem." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.164784Z", - "iopub.status.busy": "2025-07-17T10:21:41.164605Z", - "iopub.status.idle": "2025-07-17T10:21:41.172679Z", - "shell.execute_reply": "2025-07-17T10:21:41.172515Z" - } - }, - "outputs": [], - "source": [ - "m = Container()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sets\n", - "\n", - "Sets serve as the fundamental building blocks of a GAMSPy ``Model``, directly corresponding to the indices in the algebraic representations of models. In our transportation problem context, we have defined the following indices:\n", - "\n", - "- $i$ = plants\n", - "- $j$ = markets\n", - "\n", - "For detailed guidance on using sets, please refer to the [set section](https://gamspy.readthedocs.io/en/latest/user/basics/set.html) of our user guide.\n", - "\n", - "There a two ways to declare sets:\n", - "\n", - "1. Separate declaration and data assignment\n", - "2. Combine declaration and data assignment\n", - "\n", - "#### Separate declaration and data assignment\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.173454Z", - "iopub.status.busy": "2025-07-17T10:21:41.173302Z", - "iopub.status.idle": "2025-07-17T10:21:41.179619Z", - "shell.execute_reply": "2025-07-17T10:21:41.179429Z" - } - }, - "outputs": [], - "source": [ - "i = Set(container=m, name=\"i\", description=\"plants\")\n", - "i.setRecords(capacities.index)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Combine declaration and data assignment\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.180411Z", - "iopub.status.busy": "2025-07-17T10:21:41.180278Z", - "iopub.status.idle": "2025-07-17T10:21:41.190480Z", - "shell.execute_reply": "2025-07-17T10:21:41.190323Z" }, - "tags": [] - }, - "outputs": [], - "source": [ - "j = Set(container=m, name=\"j\", description=\"markets\", records=demands.index)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The effect of using the above `Set` statements is that we declared two sets, namely $i$ and $j$. Additionally, we provided descriptions to elaborate on their meaning, enhancing the readability of our ``Model``. Lastly, we assigned members to the sets, establishing a clear connection between the abstract sets and their real-world counterparts.\n", - "\n", - "$i$ = {Seattle, San Diego}\n", - "\n", - "$j$ = {New York, Chicago, Topeka}\n", - "\n", - "To verify the content of a set, you can use `.records`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.191227Z", - "iopub.status.busy": "2025-07-17T10:21:41.191108Z", - "iopub.status.idle": "2025-07-17T10:21:41.193520Z", - "shell.execute_reply": "2025-07-17T10:21:41.193371Z" - } - }, - "outputs": [ { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
unielement_text
0seattle
1san-diego
\n", - "
" - ], - "text/plain": [ - " uni element_text\n", - "0 seattle \n", - "1 san-diego " + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.084284Z", + "iopub.status.busy": "2025-07-17T10:21:41.084168Z", + "iopub.status.idle": "2025-07-17T10:21:41.086987Z", + "shell.execute_reply": "2025-07-17T10:21:41.086797Z" + } + }, + "outputs": [], + "source": [ + "demands = pd.DataFrame(\n", + " [[\"new-york\", 325], [\"chicago\", 300], [\"topeka\", 275]], columns=[\"city\", \"demand\"]\n", + ").set_index(\"city\")\n", + "\n", + "demands" ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "i.records" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.194209Z", - "iopub.status.busy": "2025-07-17T10:21:41.194141Z", - "iopub.status.idle": "2025-07-17T10:21:41.196323Z", - "shell.execute_reply": "2025-07-17T10:21:41.196172Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
unielement_text
0new-york
1chicago
2topeka
\n", - "
" - ], - "text/plain": [ - " uni element_text\n", - "0 new-york \n", - "1 chicago \n", - "2 topeka " + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.087770Z", + "iopub.status.busy": "2025-07-17T10:21:41.087633Z", + "iopub.status.idle": "2025-07-17T10:21:41.091517Z", + "shell.execute_reply": "2025-07-17T10:21:41.091358Z" + } + }, + "outputs": [], + "source": [ + "distances = pd.DataFrame(\n", + " [\n", + " [\"seattle\", \"new-york\", 2.5],\n", + " [\"seattle\", \"chicago\", 1.7],\n", + " [\"seattle\", \"topeka\", 1.8],\n", + " [\"san-diego\", \"new-york\", 2.5],\n", + " [\"san-diego\", \"chicago\", 1.8],\n", + " [\"san-diego\", \"topeka\", 1.4],\n", + " ],\n", + " columns=[\"from\", \"to\", \"distance\"],\n", + ").set_index([\"from\", \"to\"])\n", + "\n", + "distances" ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "j.records" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Parameters\n", - "\n", - "Declaring parameters involves using `Parameter`. Each parameter is assigned a name and a description. Note that parameter $a_i$ is indexed by $i$. To accommodate these indices, we include the `domain` attribute, pointing to the corresponding set.\n", - "\n", - "It is worth mentioning that, similar to sets, you have the flexibility to either combine or separate the declaration and data assignment steps. For convenience, we will proceed by combining the declaration and data assignment.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.196997Z", - "iopub.status.busy": "2025-07-17T10:21:41.196933Z", - "iopub.status.idle": "2025-07-17T10:21:41.201694Z", - "shell.execute_reply": "2025-07-17T10:21:41.201542Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cityvalue
0seattle350.0
1san-diego600.0
\n", - "
" - ], - "text/plain": [ - " city value\n", - "0 seattle 350.0\n", - "1 san-diego 600.0" + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.092111Z", + "iopub.status.busy": "2025-07-17T10:21:41.092042Z", + "iopub.status.idle": "2025-07-17T10:21:41.093337Z", + "shell.execute_reply": "2025-07-17T10:21:41.093174Z" + } + }, + "outputs": [], + "source": [ + "freight_cost = 90" ] - }, - "execution_count": 43, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = Parameter(\n", - " container=m, \n", - " name=\"a\",\n", - " domain=i,\n", - " description=\"supply of commodity at plant i (in cases)\",\n", - " records=capacities.reset_index(),\n", - ")\n", - "a.records" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.202335Z", - "iopub.status.busy": "2025-07-17T10:21:41.202270Z", - "iopub.status.idle": "2025-07-17T10:21:41.206850Z", - "shell.execute_reply": "2025-07-17T10:21:41.206694Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cityvalue
0new-york325.0
1chicago300.0
2topeka275.0
\n", - "
" - ], - "text/plain": [ - " city value\n", - "0 new-york 325.0\n", - "1 chicago 300.0\n", - "2 topeka 275.0" + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Symbol Declaration\n", + "\n", + "In line with our systematic breakdown of the transportation problem into sets, parameters, variables, and constraints, we will adopt a similar approach to define the problem as a GAMSPy `Model`. To do so, it is essential to import the `gamspy` library initially." ] - }, - "execution_count": 44, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "b = Parameter(\n", - " container=m,\n", - " name=\"b\",\n", - " domain=j,\n", - " description=\"demand for commodity at market j (in cases)\",\n", - " records=demands.reset_index(),\n", - ")\n", - "b.records" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.207532Z", - "iopub.status.busy": "2025-07-17T10:21:41.207468Z", - "iopub.status.idle": "2025-07-17T10:21:41.209778Z", - "shell.execute_reply": "2025-07-17T10:21:41.209610Z" - } - }, - "outputs": [], - "source": [ - "c = Parameter(\n", - " container=m,\n", - " name=\"c\",\n", - " domain=[i, j],\n", - " description=\"cost per unit of shipment between plant i and market j\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The cost per unit of shipment between plant $i$ and market $j$ is derived from the distance between $i$ and $j$ and can be calculated as follows:\n", - "\n", - "$c_{ij} = \\frac{90 \\cdot d_{ij}}{1000}$,\n", - "\n", - "where $d_{ij}$ denotes the distance between $i$ and $j$.\n", - "\n", - "We have two options to calculate $c_{ij}$ and assign the data to the GAMSPy parameter:\n", - "\n", - "1. Python assignment - calculation in Python, e.g., using Pandas and `.setRecords()`\n", - "2. GAMSPy assignment - calculation in GAMSPy\n", - "\n", - "#### Python Assignment" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.210541Z", - "iopub.status.busy": "2025-07-17T10:21:41.210390Z", - "iopub.status.idle": "2025-07-17T10:21:41.213168Z", - "shell.execute_reply": "2025-07-17T10:21:41.213001Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
distance
fromto
seattlenew-york0.225
chicago0.153
topeka0.162
san-diegonew-york0.225
chicago0.162
topeka0.126
\n", - "
" - ], - "text/plain": [ - " distance\n", - "from to \n", - "seattle new-york 0.225\n", - " chicago 0.153\n", - " topeka 0.162\n", - "san-diego new-york 0.225\n", - " chicago 0.162\n", - " topeka 0.126" + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.093948Z", + "iopub.status.busy": "2025-07-17T10:21:41.093881Z", + "iopub.status.idle": "2025-07-17T10:21:41.163655Z", + "shell.execute_reply": "2025-07-17T10:21:41.163440Z" + } + }, + "outputs": [], + "source": [ + "from gamspy import Container, Set, Parameter, Variable, Equation, Model, Sum, Sense" ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cost = freight_cost * distances / 1000\n", - "cost" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.213745Z", - "iopub.status.busy": "2025-07-17T10:21:41.213681Z", - "iopub.status.idle": "2025-07-17T10:21:41.218945Z", - "shell.execute_reply": "2025-07-17T10:21:41.218784Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
fromtovalue
0seattlenew-york0.225
1seattlechicago0.153
2seattletopeka0.162
3san-diegonew-york0.225
4san-diegochicago0.162
5san-diegotopeka0.126
\n", - "
" - ], - "text/plain": [ - " from to value\n", - "0 seattle new-york 0.225\n", - "1 seattle chicago 0.153\n", - "2 seattle topeka 0.162\n", - "3 san-diego new-york 0.225\n", - "4 san-diego chicago 0.162\n", - "5 san-diego topeka 0.126" + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Container\n", + "\n", + "Before we proceed further, let's create a `Container` to encapsulate all the relevant information for our GAMSPy ``Model``. This ``Container`` acts as a centralized hub, gathering essential data, sets, parameters, variables, and constraints, providing a clear structure for our optimization problem." ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "c.setRecords(cost.reset_index())\n", - "c.records" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GAMSPy Assignment\n", - "\n", - "For the direct assignment we need to declare a new ``Parameter`` denoting the distances between $i$ and $j$.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.219662Z", - "iopub.status.busy": "2025-07-17T10:21:41.219599Z", - "iopub.status.idle": "2025-07-17T10:21:41.225144Z", - "shell.execute_reply": "2025-07-17T10:21:41.224999Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
fromtovalue
0seattlenew-york2.5
1seattlechicago1.7
2seattletopeka1.8
3san-diegonew-york2.5
4san-diegochicago1.8
5san-diegotopeka1.4
\n", - "
" - ], - "text/plain": [ - " from to value\n", - "0 seattle new-york 2.5\n", - "1 seattle chicago 1.7\n", - "2 seattle topeka 1.8\n", - "3 san-diego new-york 2.5\n", - "4 san-diego chicago 1.8\n", - "5 san-diego topeka 1.4" + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.164784Z", + "iopub.status.busy": "2025-07-17T10:21:41.164605Z", + "iopub.status.idle": "2025-07-17T10:21:41.172679Z", + "shell.execute_reply": "2025-07-17T10:21:41.172515Z" + } + }, + "outputs": [], + "source": [ + "m = Container()" ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "d = Parameter(\n", - " container=m,\n", - " name=\"d\",\n", - " domain=[i, j],\n", - " description=\"distance between plant i and market j\",\n", - " records=distances.reset_index(),\n", - ")\n", - "d.records" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.225778Z", - "iopub.status.busy": "2025-07-17T10:21:41.225715Z", - "iopub.status.idle": "2025-07-17T10:21:41.230168Z", - "shell.execute_reply": "2025-07-17T10:21:41.229995Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
ijvalue
0seattlenew-york0.225
1seattlechicago0.153
2seattletopeka0.162
3san-diegonew-york0.225
4san-diegochicago0.162
5san-diegotopeka0.126
\n", - "
" - ], - "text/plain": [ - " i j value\n", - "0 seattle new-york 0.225\n", - "1 seattle chicago 0.153\n", - "2 seattle topeka 0.162\n", - "3 san-diego new-york 0.225\n", - "4 san-diego chicago 0.162\n", - "5 san-diego topeka 0.126" + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sets\n", + "\n", + "Sets serve as the fundamental building blocks of a GAMSPy ``Model``, directly corresponding to the indices in the algebraic representations of models. In our transportation problem context, we have defined the following indices:\n", + "\n", + "- $i$ = plants\n", + "- $j$ = markets\n", + "\n", + "For detailed guidance on using sets, please refer to the [set section](https://gamspy.readthedocs.io/en/latest/user/basics/set.html) of our user guide.\n", + "\n", + "There a two ways to declare sets:\n", + "\n", + "1. Separate declaration and data assignment\n", + "2. Combine declaration and data assignment\n", + "\n", + "#### Separate declaration and data assignment\n" ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "c[i, j] = freight_cost * d[i, j] / 1000\n", - "c.records" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Further information on the usage of parameters can be found in our [parameter section](https://gamspy.readthedocs.io/en/latest/user/basics/parameter.html) of the user guide." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Variables\n", - "\n", - "GAMSPy variables are declared using `Variable`. Each ``Variable`` is assigned a name, a domain if necessary, a type, and, optionally, a description." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.230884Z", - "iopub.status.busy": "2025-07-17T10:21:41.230819Z", - "iopub.status.idle": "2025-07-17T10:21:41.233170Z", - "shell.execute_reply": "2025-07-17T10:21:41.233016Z" - } - }, - "outputs": [], - "source": [ - "x = Variable(\n", - " container=m,\n", - " name=\"x\",\n", - " domain=[i, j],\n", - " type=\"Positive\",\n", - " description=\"amount of commodity to ship from plant i to market j\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This statement results in the declaration of a shipment variable for each (i,j) pair.\n", - "\n", - "More information on variables can be found in the [variable section](https://gamspy.readthedocs.io/en/latest/user/basics/variable.html) of our user guide." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Equations\n", - "A GAMSPy ``Equation`` must be declared and defined in two separate statements. The format of the declaration is the same as for other GAMSPy symbols. First comes the keyword, `Equation` in this case, followed by the name, domain and text. The transportation problem has two constraints:\n", - "\n", - "Supply: observe supply limit at plant $i$: $\\sum_j x_{ij} \\le a_i \\: \\forall i$\n", - "\n", - "Demand: satisfy demand at market $j$: $\\sum_i x_{ij} \\ge b_j \\: \\forall j$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.233875Z", - "iopub.status.busy": "2025-07-17T10:21:41.233798Z", - "iopub.status.idle": "2025-07-17T10:21:41.237181Z", - "shell.execute_reply": "2025-07-17T10:21:41.237005Z" - } - }, - "outputs": [], - "source": [ - "supply = Equation(\n", - " container=m, name=\"supply\", domain=i, description=\"observe supply limit at plant i\"\n", - ")\n", - "demand = Equation(\n", - " container=m, name=\"demand\", domain=j, description=\"satisfy demand at market j\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The components of an ``Equation`` definition are:\n", - "1. The Python variable of the ``Equation`` being defined\n", - "2. The domain (optional)\n", - "3. Domain restricting conditions (optional)\n", - "4. A `=` sign\n", - "5. Left hand side expression\n", - "6. Relational operator (`==`, `<=`, `>=`)\n", - "7. The right hand side expression.\n", - "\n", - "The ``Equation`` definition for the supply constraint of the transportation problem is implemented as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.237863Z", - "iopub.status.busy": "2025-07-17T10:21:41.237785Z", - "iopub.status.idle": "2025-07-17T10:21:41.240437Z", - "shell.execute_reply": "2025-07-17T10:21:41.240285Z" - } - }, - "outputs": [], - "source": [ - "supply[i] = Sum(j, x[i, j]) <= a[i]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the same logic as above, we can define the demand equation as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.241111Z", - "iopub.status.busy": "2025-07-17T10:21:41.241033Z", - "iopub.status.idle": "2025-07-17T10:21:41.243421Z", - "shell.execute_reply": "2025-07-17T10:21:41.243270Z" - } - }, - "outputs": [], - "source": [ - "demand[j] = Sum(i, x[i, j]) >= b[j]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "More information on equations is given in the [equation section](https://gamspy.readthedocs.io/en/latest/user/basics/equation.html) of our user guide." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Objective\n", - "The objective function of a GAMSPy ``Model`` does not require a separate ``Equation`` declaration. You can assign the objective expression to a Python variable or use it directly in the ``Model()`` statement of the [next section](#model).\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.244117Z", - "iopub.status.busy": "2025-07-17T10:21:41.244038Z", - "iopub.status.idle": "2025-07-17T10:21:41.245432Z", - "shell.execute_reply": "2025-07-17T10:21:41.245247Z" - } - }, - "outputs": [], - "source": [ - "obj = Sum((i, j), c[i, j] * x[i, j])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Model\n", - "\n", - "A GAMSPy `Model()` consolidates constraints, an objective function, a sense (minimize, maximize, and feasibility), and a problem type. It also possesses a name and is associated with a ``Container``.\n", - "\n", - "To define our transportation problem as a GAMSPy ``Model``, we assign it to a Python variable, link it to our ``Container`` (populated with symbols and data), name it \"transport\", specify the equations, set the problem type as linear program (LP), specify the sense of the objective function (``Sense.MIN``), and point to the objective expression.\n", - "\n", - "GAMSPy allows two alternatives to assign equations to a `Model`:\n", - "1. Using a list of equations,\n", - "2. Retrieving _all_ equations by calling `m.getEquations()`.\n", - "\n", - "### Using a List of Equations\n", - "Using a list of equations is especially useful if you want to define multiple GAMSPy ``Model``s with a subset of the equations in your ``Container``. For the transportation problem this can be done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.246093Z", - "iopub.status.busy": "2025-07-17T10:21:41.246032Z", - "iopub.status.idle": "2025-07-17T10:21:41.248358Z", - "shell.execute_reply": "2025-07-17T10:21:41.248217Z" - } - }, - "outputs": [], - "source": [ - "transport = Model(\n", - " m,\n", - " name=\"transport\",\n", - " equations=[supply, demand],\n", - " problem=\"LP\",\n", - " sense=Sense.MIN,\n", - " objective=obj,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Retrieving all Equations\n", - "Using `m.getEquations()` is especially convenient if you want to include all equations of your ``Container`` to be associated with your model. For the transportation problem this can be done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.248970Z", - "iopub.status.busy": "2025-07-17T10:21:41.248907Z", - "iopub.status.idle": "2025-07-17T10:21:41.251180Z", - "shell.execute_reply": "2025-07-17T10:21:41.251016Z" - } - }, - "outputs": [], - "source": [ - "transport_2 = Model(\n", - " m,\n", - " name=\"transport2\",\n", - " equations=m.getEquations(),\n", - " problem=\"LP\",\n", - " sense=Sense.MIN,\n", - " objective=obj,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "More information on the usage of a GAMSPy `Model` can be found in the [model section](https://gamspy.readthedocs.io/en/latest/user/basics/model.html) of our user guide." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Solve\n", - "\n", - "Upon defining the GAMSPy ``Model``, it's ready for being solved. The ``solve()`` statement triggers the generation of the specific model instance, creates suitable data structures for the solver, and invokes the solver. To view solver output in the console, the ``sys`` library can be used, passing the ``output=sys.stdout`` attribute to ``transport.solve()``.\n", - "\n", - "**Note**: The following cell contains the two most important pieces to get a GAMSPy model being solved by NVIDIA cuOpt:\n", - "1. Disable solver validation via `gp.set_options({\"SOLVER_VALIDATION\": 0})` as the solver is manually \"plugged into\" GAMSPy\n", - "2. Choose cuOpt as solver with `transport.solve(solver=\"cuopt\", ...)`\n", - "\n", - "Furthermore it sets two cuOpt solver options:\n", - "1. The [LP solution method](https://docs.nvidia.com/cuopt/user-guide/latest/lp-milp-settings.html#method) to PDLP\n", - "2. The [crossover flag](https://docs.nvidia.com/cuopt/user-guide/latest/lp-milp-settings.html#crossover) to false" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.251912Z", - "iopub.status.busy": "2025-07-17T10:21:41.251772Z", - "iopub.status.idle": "2025-07-17T10:21:41.453729Z", - "shell.execute_reply": "2025-07-17T10:21:41.453525Z" - } - }, - "outputs": [ + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "--- Job _rxnMrrkkTdSMAdg_gVb7vw.gms Start 07/29/25 15:17:04 50.2.0 d60bb663 LEX-LEG x86 64bit/Linux\n", - "--- Applying:\n", - " /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/gmsprmun.txt\n", - " /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/gamsconfig.yaml\n", - "--- GAMS Parameters defined\n", - " LP cuopt\n", - " Input /tmp/tmpz9ur7fc2/_rxnMrrkkTdSMAdg_gVb7vw.gms\n", - " Output /tmp/tmpz9ur7fc2/_rxnMrrkkTdSMAdg_gVb7vw.lst\n", - " ScrDir /tmp/tmpz9ur7fc2/tmpl56e8q64/\n", - " SysDir /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/\n", - " LogOption 3\n", - " Trace /tmp/tmpz9ur7fc2/_rxnMrrkkTdSMAdg_gVb7vw.txt\n", - " License /home/gamsuser/andre/.venv/lib/python3.12/site-packages/gamspy_base/gamslice.txt\n", - " OptFile 1\n", - " OptDir /tmp/tmpz9ur7fc2/\n", - " LimRow 0\n", - " LimCol 0\n", - " TraceOpt 3\n", - " GDX /tmp/tmpz9ur7fc2/_rxnMrrkkTdSMAdg_gVb7vwout.gdx\n", - " SolPrint 0\n", - " PreviousWork 1\n", - " gdxSymbols newOrChanged\n", - "System information: 12 physical cores and 62 Gb physical memory detected\n", - "--- Starting compilation\n", - "--- _rxnMrrkkTdSMAdg_gVb7vw.gms(71) 4 Mb\n", - "--- Starting execution: elapsed 0:00:00.000\n", - "--- Generating LP model transport\n", - "--- _rxnMrrkkTdSMAdg_gVb7vw.gms(142) 4 Mb\n", - "--- 6 rows 7 columns 19 non-zeroes\n", - "--- Range statistics (absolute non-zero finite values)\n", - "--- RHS [min, max] : [ 2.750E+02, 6.000E+02] - Zero values observed as well\n", - "--- Bound [min, max] : [ NA, NA] - Zero values observed as well\n", - "--- Matrix [min, max] : [ 1.260E-01, 1.000E+00]\n", - "--- Executing CUOPT (Solvelink=2): elapsed 0:00:00.000\n", - "Reading parameter(s) from \"/tmp/tmpz9ur7fc2/cuopt.opt\"\n", - ">> method 1\n", - ">> crossover 0\n", - "Finished reading from \"/tmp/tmpz9ur7fc2/cuopt.opt\"\n", - "Setting parameter method to 1\n", - "Setting parameter crossover to false\n", - "Setting parameter log_file to /tmp/tmpz9ur7fc2/tmpl56e8q64/cuopt.dat\n", - "Solving a problem with 5 constraints 6 variables (0 integers) and 12 nonzeros\n", - "Objective offset -0.000000 scaling_factor 1.000000\n", - " Iter Primal Obj. Dual Obj. Gap Primal Res. Dual Res. Time\n", - " 0 +0.00000000e+00 +0.00000000e+00 0.00e+00 5.21e+02 0.00e+00 0.010s\n", - " 1 +0.00000000e+00 +1.54766674e+02 1.55e+02 5.21e+02 3.70e-02 0.013s\n", - " 120 +1.53675002e+02 +1.53675000e+02 2.40e-06 0.00e+00 0.00e+00 0.021s\n", - "LP Solver status: Optimal\n", - "Primal objective: +1.53675002e+02\n", - "Dual objective: +1.53675000e+02\n", - "Duality gap (abs/rel): +2.40e-06 / +7.77e-09\n", - "Primal infeasibility (abs/rel): +0.00e+00 / +0.00e+00\n", - "Dual infeasibility (abs/rel): +0.00e+00 / +0.00e+00\n", - "PDLP finished\n", - "Status: Optimal Objective: 1.53675002e+02 Iterations: 120 Time: 0.021s\n", - "--- Reading solution for model transport\n", - "--- Executing after solve: elapsed 0:00:00.184\n", - "--- _rxnMrrkkTdSMAdg_gVb7vw.gms(201) 4 Mb\n", - "--- GDX File /tmp/tmpz9ur7fc2/_rxnMrrkkTdSMAdg_gVb7vwout.gdx\n", - "*** Status: Normal completion\n", - "--- Job _rxnMrrkkTdSMAdg_gVb7vw.gms Stop 07/29/25 15:17:04 elapsed 0:00:00.184\n" - ] + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.173454Z", + "iopub.status.busy": "2025-07-17T10:21:41.173302Z", + "iopub.status.idle": "2025-07-17T10:21:41.179619Z", + "shell.execute_reply": "2025-07-17T10:21:41.179429Z" + } + }, + "outputs": [], + "source": [ + "i = Set(container=m, name=\"i\", description=\"plants\")\n", + "i.setRecords(capacities.index)" + ] }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Solver StatusModel StatusObjectiveNum of EquationsNum of VariablesModel TypeSolverSolver Time
0NormalOptimalGlobal153.67500267LPCUOPT0.0
\n", - "
" - ], - "text/plain": [ - " Solver Status Model Status Objective Num of Equations \\\n", - "0 Normal OptimalGlobal 153.675002 6 \n", - "\n", - " Num of Variables Model Type Solver Solver Time \n", - "0 7 LP CUOPT 0.0 " + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Combine declaration and data assignment\n" ] - }, - "execution_count": 57, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import sys\n", - "import gamspy as gp\n", - "\n", - "gp.set_options({\"SOLVER_VALIDATION\": 0})\n", - "transport.solve(solver=\"cuopt\", solver_options=dict(method=1, crossover=0), output=sys.stdout)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Retrieving Results\n", - "### Variable Values\n", - "The values of the variables in the solution can be retrieved using using ``.records``. The level specifies the shipment quantities $x_{ij}$. Other variable attributes are the marginal values, lower and upper bounds, and the variable's scaling factor." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.454555Z", - "iopub.status.busy": "2025-07-17T10:21:41.454455Z", - "iopub.status.idle": "2025-07-17T10:21:41.458669Z", - "shell.execute_reply": "2025-07-17T10:21:41.458521Z" - } - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
levelmarginallowerupperscale
ij
seattlenew-york26.6746076.551882e-100.0inf1.0
chicago300.0000074.425912e-100.0inf1.0
topeka0.0000003.600000e-020.0inf1.0
san-diegonew-york298.3253976.551882e-100.0inf1.0
chicago0.0000009.000000e-030.0inf1.0
topeka275.0000001.093570e-140.0inf1.0
\n", - "
" - ], - "text/plain": [ - " level marginal lower upper scale\n", - "i j \n", - "seattle new-york 26.674607 6.551882e-10 0.0 inf 1.0\n", - " chicago 300.000007 4.425912e-10 0.0 inf 1.0\n", - " topeka 0.000000 3.600000e-02 0.0 inf 1.0\n", - "san-diego new-york 298.325397 6.551882e-10 0.0 inf 1.0\n", - " chicago 0.000000 9.000000e-03 0.0 inf 1.0\n", - " topeka 275.000000 1.093570e-14 0.0 inf 1.0" + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.180411Z", + "iopub.status.busy": "2025-07-17T10:21:41.180278Z", + "iopub.status.idle": "2025-07-17T10:21:41.190480Z", + "shell.execute_reply": "2025-07-17T10:21:41.190323Z" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "j = Set(container=m, name=\"j\", description=\"markets\", records=demands.index)" ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "x.records.set_index([\"i\", \"j\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Objective Value\n", - "The optimal objective function value can be accessed by `.objective_value`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2025-07-17T10:21:41.459304Z", - "iopub.status.busy": "2025-07-17T10:21:41.459237Z", - "iopub.status.idle": "2025-07-17T10:21:41.460707Z", - "shell.execute_reply": "2025-07-17T10:21:41.460556Z" - } - }, - "outputs": [ + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The effect of using the above `Set` statements is that we declared two sets, namely $i$ and $j$. Additionally, we provided descriptions to elaborate on their meaning, enhancing the readability of our ``Model``. Lastly, we assigned members to the sets, establishing a clear connection between the abstract sets and their real-world counterparts.\n", + "\n", + "$i$ = {Seattle, San Diego}\n", + "\n", + "$j$ = {New York, Chicago, Topeka}\n", + "\n", + "To verify the content of a set, you can use `.records`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.191227Z", + "iopub.status.busy": "2025-07-17T10:21:41.191108Z", + "iopub.status.idle": "2025-07-17T10:21:41.193520Z", + "shell.execute_reply": "2025-07-17T10:21:41.193371Z" + } + }, + "outputs": [], + "source": [ + "i.records" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.194209Z", + "iopub.status.busy": "2025-07-17T10:21:41.194141Z", + "iopub.status.idle": "2025-07-17T10:21:41.196323Z", + "shell.execute_reply": "2025-07-17T10:21:41.196172Z" + } + }, + "outputs": [], + "source": [ + "j.records" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parameters\n", + "\n", + "Declaring parameters involves using `Parameter`. Each parameter is assigned a name and a description. Note that parameter $a_i$ is indexed by $i$. To accommodate these indices, we include the `domain` attribute, pointing to the corresponding set.\n", + "\n", + "It is worth mentioning that, similar to sets, you have the flexibility to either combine or separate the declaration and data assignment steps. For convenience, we will proceed by combining the declaration and data assignment.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.196997Z", + "iopub.status.busy": "2025-07-17T10:21:41.196933Z", + "iopub.status.idle": "2025-07-17T10:21:41.201694Z", + "shell.execute_reply": "2025-07-17T10:21:41.201542Z" + } + }, + "outputs": [], + "source": [ + "a = Parameter(\n", + " container=m, \n", + " name=\"a\",\n", + " domain=i,\n", + " description=\"supply of commodity at plant i (in cases)\",\n", + " records=capacities.reset_index(),\n", + ")\n", + "a.records" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.202335Z", + "iopub.status.busy": "2025-07-17T10:21:41.202270Z", + "iopub.status.idle": "2025-07-17T10:21:41.206850Z", + "shell.execute_reply": "2025-07-17T10:21:41.206694Z" + } + }, + "outputs": [], + "source": [ + "b = Parameter(\n", + " container=m,\n", + " name=\"b\",\n", + " domain=j,\n", + " description=\"demand for commodity at market j (in cases)\",\n", + " records=demands.reset_index(),\n", + ")\n", + "b.records" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.207532Z", + "iopub.status.busy": "2025-07-17T10:21:41.207468Z", + "iopub.status.idle": "2025-07-17T10:21:41.209778Z", + "shell.execute_reply": "2025-07-17T10:21:41.209610Z" + } + }, + "outputs": [], + "source": [ + "c = Parameter(\n", + " container=m,\n", + " name=\"c\",\n", + " domain=[i, j],\n", + " description=\"cost per unit of shipment between plant i and market j\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The cost per unit of shipment between plant $i$ and market $j$ is derived from the distance between $i$ and $j$ and can be calculated as follows:\n", + "\n", + "$c_{ij} = \\frac{90 \\cdot d_{ij}}{1000}$,\n", + "\n", + "where $d_{ij}$ denotes the distance between $i$ and $j$.\n", + "\n", + "We have two options to calculate $c_{ij}$ and assign the data to the GAMSPy parameter:\n", + "\n", + "1. Python assignment - calculation in Python, e.g., using Pandas and `.setRecords()`\n", + "2. GAMSPy assignment - calculation in GAMSPy\n", + "\n", + "#### Python Assignment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.210541Z", + "iopub.status.busy": "2025-07-17T10:21:41.210390Z", + "iopub.status.idle": "2025-07-17T10:21:41.213168Z", + "shell.execute_reply": "2025-07-17T10:21:41.213001Z" + } + }, + "outputs": [], + "source": [ + "cost = freight_cost * distances / 1000\n", + "cost" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.213745Z", + "iopub.status.busy": "2025-07-17T10:21:41.213681Z", + "iopub.status.idle": "2025-07-17T10:21:41.218945Z", + "shell.execute_reply": "2025-07-17T10:21:41.218784Z" + } + }, + "outputs": [], + "source": [ + "c.setRecords(cost.reset_index())\n", + "c.records" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GAMSPy Assignment\n", + "\n", + "For the direct assignment we need to declare a new ``Parameter`` denoting the distances between $i$ and $j$.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.219662Z", + "iopub.status.busy": "2025-07-17T10:21:41.219599Z", + "iopub.status.idle": "2025-07-17T10:21:41.225144Z", + "shell.execute_reply": "2025-07-17T10:21:41.224999Z" + } + }, + "outputs": [], + "source": [ + "d = Parameter(\n", + " container=m,\n", + " name=\"d\",\n", + " domain=[i, j],\n", + " description=\"distance between plant i and market j\",\n", + " records=distances.reset_index(),\n", + ")\n", + "d.records" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.225778Z", + "iopub.status.busy": "2025-07-17T10:21:41.225715Z", + "iopub.status.idle": "2025-07-17T10:21:41.230168Z", + "shell.execute_reply": "2025-07-17T10:21:41.229995Z" + } + }, + "outputs": [], + "source": [ + "c[i, j] = freight_cost * d[i, j] / 1000\n", + "c.records" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Further information on the usage of parameters can be found in our [parameter section](https://gamspy.readthedocs.io/en/latest/user/basics/parameter.html) of the user guide." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Variables\n", + "\n", + "GAMSPy variables are declared using `Variable`. Each ``Variable`` is assigned a name, a domain if necessary, a type, and, optionally, a description." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.230884Z", + "iopub.status.busy": "2025-07-17T10:21:41.230819Z", + "iopub.status.idle": "2025-07-17T10:21:41.233170Z", + "shell.execute_reply": "2025-07-17T10:21:41.233016Z" + } + }, + "outputs": [], + "source": [ + "x = Variable(\n", + " container=m,\n", + " name=\"x\",\n", + " domain=[i, j],\n", + " type=\"Positive\",\n", + " description=\"amount of commodity to ship from plant i to market j\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This statement results in the declaration of a shipment variable for each (i,j) pair.\n", + "\n", + "More information on variables can be found in the [variable section](https://gamspy.readthedocs.io/en/latest/user/basics/variable.html) of our user guide." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Equations\n", + "A GAMSPy ``Equation`` must be declared and defined in two separate statements. The format of the declaration is the same as for other GAMSPy symbols. First comes the keyword, `Equation` in this case, followed by the name, domain and text. The transportation problem has two constraints:\n", + "\n", + "Supply: observe supply limit at plant $i$: $\\sum_j x_{ij} \\le a_i \\: \\forall i$\n", + "\n", + "Demand: satisfy demand at market $j$: $\\sum_i x_{ij} \\ge b_j \\: \\forall j$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.233875Z", + "iopub.status.busy": "2025-07-17T10:21:41.233798Z", + "iopub.status.idle": "2025-07-17T10:21:41.237181Z", + "shell.execute_reply": "2025-07-17T10:21:41.237005Z" + } + }, + "outputs": [], + "source": [ + "supply = Equation(\n", + " container=m, name=\"supply\", domain=i, description=\"observe supply limit at plant i\"\n", + ")\n", + "demand = Equation(\n", + " container=m, name=\"demand\", domain=j, description=\"satisfy demand at market j\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The components of an ``Equation`` definition are:\n", + "1. The Python variable of the ``Equation`` being defined\n", + "2. The domain (optional)\n", + "3. Domain restricting conditions (optional)\n", + "4. A `=` sign\n", + "5. Left hand side expression\n", + "6. Relational operator (`==`, `<=`, `>=`)\n", + "7. The right hand side expression.\n", + "\n", + "The ``Equation`` definition for the supply constraint of the transportation problem is implemented as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.237863Z", + "iopub.status.busy": "2025-07-17T10:21:41.237785Z", + "iopub.status.idle": "2025-07-17T10:21:41.240437Z", + "shell.execute_reply": "2025-07-17T10:21:41.240285Z" + } + }, + "outputs": [], + "source": [ + "supply[i] = Sum(j, x[i, j]) <= a[i]" + ] + }, { - "data": { - "text/plain": [ - "153.67500205075316" + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using the same logic as above, we can define the demand equation as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.241111Z", + "iopub.status.busy": "2025-07-17T10:21:41.241033Z", + "iopub.status.idle": "2025-07-17T10:21:41.243421Z", + "shell.execute_reply": "2025-07-17T10:21:41.243270Z" + } + }, + "outputs": [], + "source": [ + "demand[j] = Sum(i, x[i, j]) >= b[j]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "More information on equations is given in the [equation section](https://gamspy.readthedocs.io/en/latest/user/basics/equation.html) of our user guide." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Objective\n", + "The objective function of a GAMSPy ``Model`` does not require a separate ``Equation`` declaration. You can assign the objective expression to a Python variable or use it directly in the ``Model()`` statement of the [next section](#model).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.244117Z", + "iopub.status.busy": "2025-07-17T10:21:41.244038Z", + "iopub.status.idle": "2025-07-17T10:21:41.245432Z", + "shell.execute_reply": "2025-07-17T10:21:41.245247Z" + } + }, + "outputs": [], + "source": [ + "obj = Sum((i, j), c[i, j] * x[i, j])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model\n", + "\n", + "A GAMSPy `Model()` consolidates constraints, an objective function, a sense (minimize, maximize, and feasibility), and a problem type. It also possesses a name and is associated with a ``Container``.\n", + "\n", + "To define our transportation problem as a GAMSPy ``Model``, we assign it to a Python variable, link it to our ``Container`` (populated with symbols and data), name it \"transport\", specify the equations, set the problem type as linear program (LP), specify the sense of the objective function (``Sense.MIN``), and point to the objective expression.\n", + "\n", + "GAMSPy allows two alternatives to assign equations to a `Model`:\n", + "1. Using a list of equations,\n", + "2. Retrieving _all_ equations by calling `m.getEquations()`.\n", + "\n", + "### Using a List of Equations\n", + "Using a list of equations is especially useful if you want to define multiple GAMSPy ``Model``s with a subset of the equations in your ``Container``. For the transportation problem this can be done as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.246093Z", + "iopub.status.busy": "2025-07-17T10:21:41.246032Z", + "iopub.status.idle": "2025-07-17T10:21:41.248358Z", + "shell.execute_reply": "2025-07-17T10:21:41.248217Z" + } + }, + "outputs": [], + "source": [ + "transport = Model(\n", + " m,\n", + " name=\"transport\",\n", + " equations=[supply, demand],\n", + " problem=\"LP\",\n", + " sense=Sense.MIN,\n", + " objective=obj,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Retrieving all Equations\n", + "Using `m.getEquations()` is especially convenient if you want to include all equations of your ``Container`` to be associated with your model. For the transportation problem this can be done as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.248970Z", + "iopub.status.busy": "2025-07-17T10:21:41.248907Z", + "iopub.status.idle": "2025-07-17T10:21:41.251180Z", + "shell.execute_reply": "2025-07-17T10:21:41.251016Z" + } + }, + "outputs": [], + "source": [ + "transport_2 = Model(\n", + " m,\n", + " name=\"transport2\",\n", + " equations=m.getEquations(),\n", + " problem=\"LP\",\n", + " sense=Sense.MIN,\n", + " objective=obj,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "More information on the usage of a GAMSPy `Model` can be found in the [model section](https://gamspy.readthedocs.io/en/latest/user/basics/model.html) of our user guide." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solve\n", + "\n", + "Upon defining the GAMSPy ``Model``, it's ready for being solved. The ``solve()`` statement triggers the generation of the specific model instance, creates suitable data structures for the solver, and invokes the solver. To view solver output in the console, the ``sys`` library can be used, passing the ``output=sys.stdout`` attribute to ``transport.solve()``.\n", + "\n", + "**Note**: The following cell contains the two most important pieces to get a GAMSPy model being solved by NVIDIA cuOpt:\n", + "1. Disable solver validation via `gp.set_options({\"SOLVER_VALIDATION\": 0})` as the solver is manually \"plugged into\" GAMSPy\n", + "2. Choose cuOpt as solver with `transport.solve(solver=\"cuopt\", ...)`\n", + "\n", + "Furthermore it sets two cuOpt solver options:\n", + "1. The [LP solution method](https://docs.nvidia.com/cuopt/user-guide/latest/lp-milp-settings.html#method) to PDLP\n", + "2. The [crossover flag](https://docs.nvidia.com/cuopt/user-guide/latest/lp-milp-settings.html#crossover) to false" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.251912Z", + "iopub.status.busy": "2025-07-17T10:21:41.251772Z", + "iopub.status.idle": "2025-07-17T10:21:41.453729Z", + "shell.execute_reply": "2025-07-17T10:21:41.453525Z" + } + }, + "outputs": [], + "source": [ + "import sys\n", + "import gamspy as gp\n", + "\n", + "gp.set_options({\"SOLVER_VALIDATION\": 0})\n", + "transport.solve(solver=\"cuopt\", solver_options=dict(method=1, crossover=0), output=sys.stdout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Retrieving Results\n", + "### Variable Values\n", + "The values of the variables in the solution can be retrieved using using ``.records``. The level specifies the shipment quantities $x_{ij}$. Other variable attributes are the marginal values, lower and upper bounds, and the variable's scaling factor." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.454555Z", + "iopub.status.busy": "2025-07-17T10:21:41.454455Z", + "iopub.status.idle": "2025-07-17T10:21:41.458669Z", + "shell.execute_reply": "2025-07-17T10:21:41.458521Z" + } + }, + "outputs": [], + "source": [ + "x.records.set_index([\"i\", \"j\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Objective Value\n", + "The optimal objective function value can be accessed by `.objective_value`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "execution": { + "iopub.execute_input": "2025-07-17T10:21:41.459304Z", + "iopub.status.busy": "2025-07-17T10:21:41.459237Z", + "iopub.status.idle": "2025-07-17T10:21:41.460707Z", + "shell.execute_reply": "2025-07-17T10:21:41.460556Z" + } + }, + "outputs": [], + "source": [ + "transport.objective_value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n", + "\n", + "SPDX-License-Identifier: Apache-2.0\n", + "\n", + "Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "you may not use this file except in compliance with the License.\n", + "You may obtain a copy of the License at\n", + "\n", + "http://www.apache.org/licenses/LICENSE-2.0\n", + "\n", + "Unless required by applicable law or agreed to in writing, software\n", + "distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "See the License for the specific language governing permissions and\n", + "limitations under the License." ] - }, - "execution_count": 59, - "metadata": {}, - "output_type": "execute_result" } - ], - "source": [ - "transport.objective_value" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n", - "\n", - "SPDX-License-Identifier: Apache-2.0\n", - "\n", - "Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "you may not use this file except in compliance with the License.\n", - "You may obtain a copy of the License at\n", - "\n", - "http://www.apache.org/licenses/LICENSE-2.0\n", - "\n", - "Unless required by applicable law or agreed to in writing, software\n", - "distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "See the License for the specific language governing permissions and\n", - "limitations under the License." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 4 + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } From bd61bbfe631628e574168085d4ddcfe5dff43d5d Mon Sep 17 00:00:00 2001 From: anandhkb Date: Fri, 6 Mar 2026 08:50:06 -0800 Subject: [PATCH 2/2] Rename trnsport_cuopt to transport_cuopt, update cuopt-link to v0.0.5e cu13 x86_64 Signed-off-by: anandhkb --- ...port_cuopt.ipynb => transport_cuopt.ipynb} | 199 +++++++++--------- 1 file changed, 100 insertions(+), 99 deletions(-) rename GAMSPy_integration_example/{trnsport_cuopt.ipynb => transport_cuopt.ipynb} (96%) diff --git a/GAMSPy_integration_example/trnsport_cuopt.ipynb b/GAMSPy_integration_example/transport_cuopt.ipynb similarity index 96% rename from GAMSPy_integration_example/trnsport_cuopt.ipynb rename to GAMSPy_integration_example/transport_cuopt.ipynb index 0093b3e..d46cba0 100644 --- a/GAMSPy_integration_example/trnsport_cuopt.ipynb +++ b/GAMSPy_integration_example/transport_cuopt.ipynb @@ -2,7 +2,6 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:15.883029Z", @@ -14,7 +13,6 @@ "languageId": "shellscript" } }, - "outputs": [], "source": [ "# GAMSPy model example\n", "\n", @@ -52,13 +50,13 @@ "- Observe supply limit at plant $i$: $\\sum_j x_{ij} \\le a_i \\: \\forall i$\n", "- Satisfy demand at market $j$: $\\sum_i x_{ij} \\ge b_j \\: \\forall j$\n", "- Objective Function: Minimize $\\sum_i \\sum_j c_{ij} \\cdot x_{ij}$" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "import subprocess\n", "import html\n", @@ -108,36 +106,39 @@ " return False\n", "\n", "check_gpu()" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "# Enable this in case you are running this in google colab or such places where cuOpt is not yet installed\n", "#!pip uninstall -y cuda-python cuda-bindings cuda-core\n", "#!pip install --upgrade --extra-index-url=https://pypi.nvidia.com cuopt-cu12 nvidia-nvjitlink-cu12 rapids-logger==0.1.19\n", "#!pip install --upgrade --extra-index-url=https://pypi.nvidia.com cuopt-cu13 nvidia-nvjitlink-cu13 rapids-logger==0.1.1" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "# Install other dependencies (if not already installed)\n", "\n", "!pip install -q gamspy\n", "import subprocess\n", "import sys\n", - "# For ARM: download ARM libs from https://github.com/GAMS-dev/cuoptlink-builder/releases\n", - "!wget -nc -nv -O cuopt-link-release.zip \"https://github.com/GAMS-dev/cuoptlink-builder/releases/download/v0.0.1/cuopt-link-release.zip\"\n", + "# Change the zip URL below depending on your target CUDA version and architecture (x86_64 or aarch64).\n", + "# See https://github.com/GAMS-dev/cuoptlink-builder/releases for available builds.\n", + "!wget -nc -nv -O cuopt-link-release.zip \"https://github.com/GAMS-dev/cuoptlink-builder/releases/download/v0.0.5e/cuopt-link-release-cu13-x86_64.zip\"\n", "gams_base_path = subprocess.check_output([sys.executable, '-m', 'gamspy', 'show', 'base']).decode('utf-8').strip()\n", "subprocess.run(f\"unzip -o cuopt-link-release.zip -d {gams_base_path}\", shell=True, check=True)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -150,7 +151,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:40.915536Z", @@ -159,7 +159,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.083230Z" } }, - "outputs": [], "source": [ "import pandas as pd\n", "\n", @@ -168,11 +167,12 @@ ").set_index(\"city\")\n", "\n", "capacities" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.084284Z", @@ -181,18 +181,18 @@ "shell.execute_reply": "2025-07-17T10:21:41.086797Z" } }, - "outputs": [], "source": [ "demands = pd.DataFrame(\n", " [[\"new-york\", 325], [\"chicago\", 300], [\"topeka\", 275]], columns=[\"city\", \"demand\"]\n", ").set_index(\"city\")\n", "\n", "demands" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.087770Z", @@ -201,7 +201,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.091358Z" } }, - "outputs": [], "source": [ "distances = pd.DataFrame(\n", " [\n", @@ -216,11 +215,12 @@ ").set_index([\"from\", \"to\"])\n", "\n", "distances" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.092111Z", @@ -229,10 +229,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.093174Z" } }, - "outputs": [], "source": [ "freight_cost = 90" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -245,7 +246,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.093948Z", @@ -254,10 +254,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.163440Z" } }, - "outputs": [], "source": [ "from gamspy import Container, Set, Parameter, Variable, Equation, Model, Sum, Sense" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -270,7 +271,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.164784Z", @@ -279,10 +279,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.172515Z" } }, - "outputs": [], "source": [ "m = Container()" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -307,7 +308,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.173454Z", @@ -316,11 +316,12 @@ "shell.execute_reply": "2025-07-17T10:21:41.179429Z" } }, - "outputs": [], "source": [ "i = Set(container=m, name=\"i\", description=\"plants\")\n", "i.setRecords(capacities.index)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -331,7 +332,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.180411Z", @@ -341,10 +341,11 @@ }, "tags": [] }, - "outputs": [], "source": [ "j = Set(container=m, name=\"j\", description=\"markets\", records=demands.index)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -361,7 +362,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.191227Z", @@ -370,14 +370,14 @@ "shell.execute_reply": "2025-07-17T10:21:41.193371Z" } }, - "outputs": [], "source": [ "i.records" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.194209Z", @@ -386,10 +386,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.196172Z" } }, - "outputs": [], "source": [ "j.records" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -404,7 +405,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.196997Z", @@ -413,7 +413,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.201542Z" } }, - "outputs": [], "source": [ "a = Parameter(\n", " container=m, \n", @@ -423,11 +422,12 @@ " records=capacities.reset_index(),\n", ")\n", "a.records" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.202335Z", @@ -436,7 +436,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.206694Z" } }, - "outputs": [], "source": [ "b = Parameter(\n", " container=m,\n", @@ -446,11 +445,12 @@ " records=demands.reset_index(),\n", ")\n", "b.records" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.207532Z", @@ -459,7 +459,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.209610Z" } }, - "outputs": [], "source": [ "c = Parameter(\n", " container=m,\n", @@ -467,7 +466,9 @@ " domain=[i, j],\n", " description=\"cost per unit of shipment between plant i and market j\",\n", ")" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -489,7 +490,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.210541Z", @@ -498,15 +498,15 @@ "shell.execute_reply": "2025-07-17T10:21:41.213001Z" } }, - "outputs": [], "source": [ "cost = freight_cost * distances / 1000\n", "cost" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.213745Z", @@ -515,11 +515,12 @@ "shell.execute_reply": "2025-07-17T10:21:41.218784Z" } }, - "outputs": [], "source": [ "c.setRecords(cost.reset_index())\n", "c.records" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -532,7 +533,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.219662Z", @@ -541,7 +541,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.224999Z" } }, - "outputs": [], "source": [ "d = Parameter(\n", " container=m,\n", @@ -551,11 +550,12 @@ " records=distances.reset_index(),\n", ")\n", "d.records" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.225778Z", @@ -564,11 +564,12 @@ "shell.execute_reply": "2025-07-17T10:21:41.229995Z" } }, - "outputs": [], "source": [ "c[i, j] = freight_cost * d[i, j] / 1000\n", "c.records" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -588,7 +589,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.230884Z", @@ -597,7 +597,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.233016Z" } }, - "outputs": [], "source": [ "x = Variable(\n", " container=m,\n", @@ -606,7 +605,9 @@ " type=\"Positive\",\n", " description=\"amount of commodity to ship from plant i to market j\",\n", ")" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -631,7 +632,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.233875Z", @@ -640,7 +640,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.237005Z" } }, - "outputs": [], "source": [ "supply = Equation(\n", " container=m, name=\"supply\", domain=i, description=\"observe supply limit at plant i\"\n", @@ -648,7 +647,9 @@ "demand = Equation(\n", " container=m, name=\"demand\", domain=j, description=\"satisfy demand at market j\"\n", ")" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -668,7 +669,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.237863Z", @@ -677,10 +677,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.240285Z" } }, - "outputs": [], "source": [ "supply[i] = Sum(j, x[i, j]) <= a[i]" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -691,7 +692,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.241111Z", @@ -700,10 +700,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.243270Z" } }, - "outputs": [], "source": [ "demand[j] = Sum(i, x[i, j]) >= b[j]" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -722,7 +723,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.244117Z", @@ -731,10 +731,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.245247Z" } }, - "outputs": [], "source": [ "obj = Sum((i, j), c[i, j] * x[i, j])" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -756,7 +757,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.246093Z", @@ -765,7 +765,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.248217Z" } }, - "outputs": [], "source": [ "transport = Model(\n", " m,\n", @@ -775,7 +774,9 @@ " sense=Sense.MIN,\n", " objective=obj,\n", ")" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -787,7 +788,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.248970Z", @@ -796,7 +796,6 @@ "shell.execute_reply": "2025-07-17T10:21:41.251016Z" } }, - "outputs": [], "source": [ "transport_2 = Model(\n", " m,\n", @@ -806,7 +805,9 @@ " sense=Sense.MIN,\n", " objective=obj,\n", ")" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -834,7 +835,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.251912Z", @@ -843,14 +843,15 @@ "shell.execute_reply": "2025-07-17T10:21:41.453525Z" } }, - "outputs": [], "source": [ "import sys\n", "import gamspy as gp\n", "\n", "gp.set_options({\"SOLVER_VALIDATION\": 0})\n", "transport.solve(solver=\"cuopt\", solver_options=dict(method=1, crossover=0), output=sys.stdout)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -863,7 +864,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.454555Z", @@ -872,17 +872,18 @@ "shell.execute_reply": "2025-07-17T10:21:41.458521Z" } }, - "outputs": [], "source": [ "x.records.set_index([\"i\", \"j\"])" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], - "source": [] + "source": [], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -894,7 +895,6 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2025-07-17T10:21:41.459304Z", @@ -903,10 +903,11 @@ "shell.execute_reply": "2025-07-17T10:21:41.460556Z" } }, - "outputs": [], "source": [ "transport.objective_value" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -951,4 +952,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file