diff --git a/tutorial/transport/0_transport-tutorial_platform-setup.ipynb b/tutorial/transport/0_transport-tutorial_platform-setup.ipynb
index eebbd1d0..098459a2 100644
--- a/tutorial/transport/0_transport-tutorial_platform-setup.ipynb
+++ b/tutorial/transport/0_transport-tutorial_platform-setup.ipynb
@@ -26,7 +26,7 @@
"\n",
"This tutorial consists of three Jupyter notebooks:\n",
"\n",
- "0. Set up an **ixmp4.Platform** to store the scenario input data and solution\n",
+ "0. Set up an `ixmp4.Platform` to store the scenario input data and solution\n",
"1. Implement the **baseline version of the transport problem** and solve it\n",
"2. Create an **alternative scenario** and solve it "
]
@@ -83,7 +83,7 @@
"id": "b6209e20-9979-4f3b-b6b7-fe37a1c09366",
"metadata": {},
"source": [
- "## Defining units in the platform and database\n",
+ "## Defining units in the `Platform` and database\n",
"\n",
"The **ixmp4** package requires that units are defined explicitly before adding data using them.\n",
"\n",
@@ -92,7 +92,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"id": "9be63ed0-aca6-44e3-a6c6-d8fdf8ec2549",
"metadata": {},
"outputs": [],
@@ -154,7 +154,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 5,
"id": "6c1a395d-6c8a-489c-9aa8-39d24895ca51",
"metadata": {},
"outputs": [],
@@ -195,19 +195,11 @@
"The prompt will ask whether you also want to delete the SQLite database file from your computer, \n",
"answer `y` for a complete deletion."
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "9395354e-2a0a-45f1-b819-34af7d925805",
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3 (ipykernel)",
+ "display_name": ".venv",
"language": "python",
"name": "python3"
},
@@ -221,7 +213,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.2"
+ "version": "3.12.3"
}
},
"nbformat": 4,
diff --git a/tutorial/transport/1_transport-tutorial.ipynb b/tutorial/transport/1_transport-tutorial.ipynb
index 72c64cdd..73dbb0c3 100644
--- a/tutorial/transport/1_transport-tutorial.ipynb
+++ b/tutorial/transport/1_transport-tutorial.ipynb
@@ -25,7 +25,7 @@
"\n",
"This tutorial consists of three Jupyter notebooks:\n",
"\n",
- "0. Set up an **ixmp4.Platform** to store the scenario input data and solution\n",
+ "0. Set up an `ixmp4.Platform` to store the scenario input data and solution\n",
"1. Implement the **baseline version of the transport problem** and solve it\n",
"2. Create an **alternative scenario** and solve it "
]
@@ -45,7 +45,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "## The platform as a connection to the database\n",
+ "## The `Platform` as a connection to the database\n",
"\n",
"An [**ixmp4.Platform**](https://docs.ece.iiasa.ac.at/projects/ixmp4/en/latest/devs/ixmp4.core/platform.html#ixmp4.core.platform.Platform)\n",
"is the connection to a database instance that can hold scenario data and relevant additional information."
@@ -57,15 +57,8 @@
"metadata": {},
"outputs": [],
"source": [
- "import ixmp4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
+ "import ixmp4\n",
+ "\n",
"platform = ixmp4.Platform(\"transport-tutorial\")"
]
},
@@ -75,14 +68,14 @@
"source": [
"An [**ixmp4.Run**](https://docs.ece.iiasa.ac.at/projects/ixmp4/en/latest/devs/ixmp4.core/run.html#ixmp4.core.run.Run)\n",
"is an object that holds all relevant information for one quantification of a \"scenario\". \n",
- "A run is identified by a *model name*, a *scenario name* and an automatically assigned *version number*.\n",
+ "A `Run` is identified by a *model name*, a *scenario name* and an automatically assigned *version number*.\n",
"\n",
- "As a first step to solve the **transport problem**, we create a new run."
+ "As a first step to solve the **transport problem**, we create a new `Run`."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@@ -95,13 +88,13 @@
"source": [
"## Defining the structure of the optimization problem\n",
"\n",
- "### The IndexSets\n",
+ "### The `IndexSet`s\n",
"\n",
- "An **IndexSet** defines a list of elements with a name. These sets can be used for \"indexed assignment\" of parameters, variables and equations. \n",
- "The entries of these parameters, etc. are then validated against the elements of the linked set. \n",
- "In database terms, a column of a parameter, etc. can be \"foreign-keyed\" onto an set.\n",
+ "An `IndexSet` defines a list of elements with a name. These sets can be used for \"indexed assignment\" of `Parameter`s, `Variable`s and `Equation`s. \n",
+ "The entries of these `Parameter`s, etc. are then validated against the elements of the linked set. \n",
+ "In database terms, a column of a `Parameter`, etc. is \"foreign-keyed\" onto a `IndexSet`.\n",
"\n",
- "Below, we first show the data as they would be written in the linopy tutorial."
+ "Below, we first show the data as they would be written in the **GAMS** tutorial."
]
},
{
@@ -122,7 +115,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -134,7 +127,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "We can display the elements of any **IndexSet** as a Python list:"
+ "We can display the data (a.k.a elements) of any `IndexSet` as a Python list:"
]
},
{
@@ -150,12 +143,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "An **IndexSet** can have a docstring as a means for documentation."
+ "An `IndexSet` can have a docstring as a means for documentation."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@@ -166,14 +159,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "For simplicity, the steps of creating an **IndexSet** and assigning elements can be done in one line.\n",
+ "For simplicity, the steps of creating an `IndexSet` and assigning elements can be done in one line.\n",
"\n",
- "We illustrate this for the second index-set of the transport problem."
+ "We illustrate this for the second `IndexSet` of the transport problem."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
@@ -184,12 +177,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "To add the docstring, we now have to explicitly get the index-set *j* and add the documentation."
+ "To add the docstring, we now have to explicitly get the `IndexSet` *j* and add the documentation."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@@ -202,10 +195,10 @@
"source": [
"### Parameters of the optimization problem\n",
"\n",
- "A **Parameter** is a table with a number of index columns (each constrained to an **IndexSet**) as well as *units* and *values* columns.\n",
+ "A `Parameter` is a table with a number of index columns (each constrained to an `IndexSet`) as well as *units* and *values* columns.\n",
"\n",
"As a next step to solving the transport problem, we define the parameters *capacity* and *demand*.\n",
- "The parameters are assigned on the indexsets *i* and *j*, respectively."
+ "The parameters are assigned on the `IndexSet`s *i* and *j*, respectively."
]
},
{
@@ -226,12 +219,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "The parameter data can be assigned as a dictionary."
+ "The data of the `Parameter` can be assigned as a dictionary."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
@@ -250,18 +243,17 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Alternatively, the parameter data can be passed as a **pandas.DataFrame**."
+ "Alternatively, the data can be passed as a `pandas.DataFrame`."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"\n",
- "\n",
"b = run.optimization.parameters.create(\"b\", constrained_to_indexsets=[\"j\"])\n",
"b.docs = \"Demand at market j\"\n",
"\n",
@@ -280,7 +272,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Notice how the data has three columns but has only been linked to one **IndexSet**? That's on purpose: Every **Parameter** needs to have (the columns) *values* and *units*. The value(s) can be any number(s), but the units have to be defined a-priori in the **ixmp4.Platform**.\n",
+ "Notice how the data has three columns but has only been linked to one `IndexSet`? That's on purpose: Every `Parameter` needs to have (the columns) *values* and *units*. The value(s) can be any number(s), but the units have to be defined a-priori in the `ixmp4.Platform`.\n",
"\n",
"Here's how to access `parameter.data` to e.g. quickly confirm that *b* is set correctly:"
]
@@ -315,14 +307,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "It is possible to add data to a parameter in several steps...\n",
+ "It is possible to add data to a `Parameter` in several steps...\n",
"\n",
"Here, we first define the parameter *d* and add four datapoints."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
@@ -347,7 +339,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
@@ -361,7 +353,7 @@
"source": [
"
\n",
"\n",
- "Every time you add data, **all** columns of the parameter must be present!\n",
+ "Every time you add data, **all** columns of the `Parameter` must be present!\n",
"\n",
"
"
]
@@ -372,7 +364,7 @@
"source": [
"### Scalars\n",
"\n",
- "Another type of input data for optimization problems is a **Scalar**. These are not linked to an **IndexSet**, but consist of only a value and a unit (and a docstring)."
+ "Another type of input data for optimization problems is a `Scalar`. These are not linked to an `IndexSet`, but consist of only a *value* and a *unit* (and a docstring)."
]
},
{
@@ -384,11 +376,13 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
- "f = run.optimization.scalars.create(name=\"f\", value=90, unit=\"dollars per case per 1000 miles\")\n",
+ "f = run.optimization.scalars.create(\n",
+ " name=\"f\", value=90, unit=\"dollars per case per 1000 miles\"\n",
+ ")\n",
"f.docs = \"Freight\""
]
},
@@ -398,9 +392,9 @@
"source": [
"### Defining the solution structure\n",
"\n",
- "The solution of an optimization problem are a list of **Variable** and **Equation** objects.\n",
+ "The solution of an optimization problem is a list of `Variable` and `Equation` objects.\n",
"\n",
- "We first define the variables and equations in the **ixmp4.Run**. The values of the solution (level and marginal, mathematically speaking) are read from the **linopy** output after solving the problem."
+ "We first define the `Variable`s and `Equation`s in the `ixmp4.Run`. The values of the solution (level and marginal, mathematically speaking) are read from the **linopy** output after solving the problem."
]
},
{
@@ -421,14 +415,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Here, *supply* can only come from the canning plant in **IndexSet** *i*, while *demand* needs to be met at the markets in **IndexSet** *j*.\n",
+ "Here, *supply* can only come from the canning plant in `IndexSet` *i*, while *demand* needs to be met at the markets in `IndexSet` *j*.\n",
"\n",
"Shipment is defined from a canning plant to a market, so *x* needs to be assigned to both *i* and *j*."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
@@ -445,13 +439,13 @@
"source": [
"## Solve the scenario\n",
"\n",
- "In this tutorial, we solve the tutorial using the open-source solver *highs* in **linopy**. \n",
+ "In this tutorial, we solve the tutorial using the open-source solver [*highs*](https://github.com/ERGO-Code/HiGHS) in **linopy**. \n",
"\n",
- "The ``create_dantzig_model()`` function is a convenience shortcut to retrieve the data from the **ixmp4.Run**\n",
- "and set up a linopy model correctly to solve the transport problem. Please see ``linopy_model.py`` for details.\n",
+ "The ``create_dantzig_model()`` function is a convenience shortcut to retrieve the data from the `ixmp4.Run`\n",
+ "and set up a **linopy** model correctly to solve the transport problem. Please see ``linopy_model.py`` for details.\n",
"\n",
"The solution of the transport problem is stored with the model object automatically.\n",
- "The function ``store_dantzig_solution()`` reads the solution and stores it in the respective **Variable** and **Equation** objects of the **ixmp4.Run**."
+ "The function ``store_dantzig_solution()`` reads the solution and stores it in the respective `Variable` and `Equation` objects of the `ixmp4.Run`."
]
},
{
@@ -465,7 +459,6 @@
" read_dantzig_solution,\n",
")\n",
"\n",
- "\n",
"linopy_model = create_dantzig_model(run=run)\n",
"linopy_model.solve(\"highs\")\n",
"read_dantzig_solution(model=linopy_model, run=run)"
@@ -511,7 +504,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "The levels and marginals of the **Equation** show the shipped quantities and shadow prices (\"dual variables\") of the least-cost solution."
+ "The levels and marginals of the `Equation`s show the shipped quantities and shadow prices (\"dual variables\") of the least-cost solution."
]
},
{
@@ -536,36 +529,29 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "## Setting a default version of a run\n",
+ "## Setting a default version of a `Run`\n",
"\n",
- "The key benefit of **ixmp4** is handling a large number of scenarios - aka **ixmp4.Run** objects - in a version-controlled database.\n",
- "Each run is identified by a *model name*, a *scenario name* and an automatically assigned *version number*.\n",
+ "The key benefit of **ixmp4** is handling a large number of scenarios - aka `ixmp4.Run` objects - in a version-controlled database.\n",
+ "Each `Run` is identified by a *model name*, a *scenario name* and an automatically assigned *version number*.\n",
"\n",
- "For every model-scenario combination, we can assign one run as the *default version*.\n",
+ "For every model-scenario combination, we can assign one `Run` as the *default version*.\n",
"This allows to keep previous versions in the database (for easy reference and comparison) but have a well-defined approach to get the \"right\" version (e.g., the latest version of a scenario)."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"run.set_as_default()"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
- "display_name": "Python 3 (ipykernel)",
+ "display_name": ".venv",
"language": "python",
"name": "python3"
},
@@ -579,7 +565,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.2"
+ "version": "3.12.3"
}
},
"nbformat": 4,
diff --git a/tutorial/transport/2_transport-tutorial_variant.ipynb b/tutorial/transport/2_transport-tutorial_variant.ipynb
index e8b1b2d7..fa8f87bc 100644
--- a/tutorial/transport/2_transport-tutorial_variant.ipynb
+++ b/tutorial/transport/2_transport-tutorial_variant.ipynb
@@ -25,7 +25,7 @@
"\n",
"This tutorial consists of three Jupyter notebooks:\n",
"\n",
- "0. Set up an **ixmp4.Platform** to store the scenario input data and solution\n",
+ "0. Set up an `ixmp4.Platform` to store the scenario input data and solution\n",
"1. Implement the **baseline version of the transport problem** and solve it\n",
"2. Create an **alternative scenario** and solve it "
]
@@ -45,7 +45,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "## The platform as a connection to the database\n",
+ "## The `Platform` as a connection to the database\n",
"\n",
"An [**ixmp4.Platform**](https://docs.ece.iiasa.ac.at/projects/ixmp4/en/latest/devs/ixmp4.core/platform.html#ixmp4.core.platform.Platform)\n",
"is the connection to a database instance that can hold scenario data and relevant additional information."
@@ -53,20 +53,21 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "[INFO] 11:36:49 - ixmp4.conf.auth: Connecting to service anonymously and without credentials.\n",
+ "[INFO] 11:36:49 - ixmp4.data.backend.db: Creating database engine for platform 'transport-tutorial'.\n"
+ ]
+ }
+ ],
"source": [
"import ixmp4\n",
- "import pandas as pd"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
+ "\n",
"platform = ixmp4.Platform(\"transport-tutorial\")"
]
},
@@ -75,14 +76,63 @@
"metadata": {},
"source": [
"As a first step, we list all scenarios (aka [**ixmp4.Run**](https://docs.ece.iiasa.ac.at/projects/ixmp4/en/latest/devs/ixmp4.core/run.html#ixmp4.core.run.Run) instances)\n",
- "available in the platform connected to the database instance."
+ "available in the `Platform` connected to the database instance."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " model | \n",
+ " scenario | \n",
+ " version | \n",
+ " is_default | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " transport problem | \n",
+ " standard | \n",
+ " 1 | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " model scenario version is_default\n",
+ "0 transport problem standard 1 True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"platform.runs.tabulate()"
]
@@ -103,14 +153,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "## Retrieve a run from the platform\n",
+ "## Retrieve a `Run` from the `Platform`\n",
"\n",
- "As a first step in this notebook, you can load the **ixmp4.Run** that you created in Notebook 1."
+ "As a first step in this notebook, you can load the `ixmp4.Run` that you created in [Notebook 1](1_transport-tutorial.ipynb)."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -126,9 +176,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"run.version"
]
@@ -137,15 +198,26 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "You can check that the solution from Notebook 1 was indeed saved by inspecting an **ixmp4.Variable**. \n",
+ "You can check that the solution from [Notebook 1](1_transport-tutorial.ipynb) was indeed saved by inspecting an `ixmp4.Variable`. \n",
"The `data` of any optimization object is stored internally as a dictionary."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 5,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'levels': [151.875], 'marginals': [-0.0]}"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"run.optimization.variables.get(\"z\").data"
]
@@ -154,27 +226,101 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "For instances of a **Variable** or a **Parameter** that have multiple dimensions,\n",
+ "For instances of a `Variable` or a `Parameter` that have multiple dimensions,\n",
"you can use **pandas** for filtering and inspecting the data.\n",
"\n",
- "The following cell shows the data for a using the distance parameter *d* and cast the `Parameter.data` to a **pandas.DataFrame**."
+ "The following cell shows how to retrieve the distance parameter *d* and cast the `Parameter.data` to a `pandas.DataFrame`."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
+ "import pandas as pd\n",
+ "\n",
"d = run.optimization.parameters.get(\"d\")\n",
"distance = pd.DataFrame(d.data)"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**pandas** enables easy and powerful filtering, e.g. showing only the distances for connections from Seattle:"
+ ]
+ },
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " i | \n",
+ " j | \n",
+ " values | \n",
+ " units | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 3 | \n",
+ " seattle | \n",
+ " chicago | \n",
+ " 1.7 | \n",
+ " 1000 miles | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " seattle | \n",
+ " new-york | \n",
+ " 2.5 | \n",
+ " 1000 miles | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " seattle | \n",
+ " topeka | \n",
+ " 1.8 | \n",
+ " 1000 miles | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " i j values units\n",
+ "3 seattle chicago 1.7 1000 miles\n",
+ "4 seattle new-york 2.5 1000 miles\n",
+ "5 seattle topeka 1.8 1000 miles"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"distance[distance[\"i\"] == \"seattle\"]"
]
@@ -188,9 +334,66 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 8,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " i | \n",
+ " j | \n",
+ " values | \n",
+ " units | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 3 | \n",
+ " seattle | \n",
+ " chicago | \n",
+ " 1.7 | \n",
+ " 1000 miles | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " seattle | \n",
+ " topeka | \n",
+ " 1.8 | \n",
+ " 1000 miles | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " i j values units\n",
+ "3 seattle chicago 1.7 1000 miles\n",
+ "5 seattle topeka 1.8 1000 miles"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"distance.loc[(distance[\"i\"] == \"seattle\") & (distance[\"j\"].isin([\"chicago\", \"topeka\"]))]"
]
@@ -218,7 +421,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 46,
"metadata": {},
"outputs": [],
"source": [
@@ -234,9 +437,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 47,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'transport problem'"
+ ]
+ },
+ "execution_count": 47,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"run_detroit.model.name"
]
@@ -246,12 +460,12 @@
"metadata": {},
"source": [
"We now modify the structure and parameters of the *detroit* scenario.\n",
- "First, we reduce the demand in *chicago* to ensure a feasible problem.."
+ "First, we reduce the demand in *chicago* to ensure a feasible problem."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
@@ -269,7 +483,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 49,
"metadata": {},
"outputs": [],
"source": [
@@ -282,7 +496,7 @@
" \"i\": [\"seattle\", \"san-diego\"],\n",
" \"j\": [\"detroit\", \"detroit\"],\n",
" \"values\": [1.7, 1.9],\n",
- " \"units\": [\"km\", \"km\"],\n",
+ " \"units\": [\"1000 miles\", \"1000 miles\"],\n",
" }\n",
")"
]
@@ -294,21 +508,49 @@
"### Solve the new scenario\n",
"\n",
"Now, we create a **linopy** model, solve it, and read the solution to store it\n",
- "in the respective **Variable** and **Equation** objects of the **ixmp4.Run**."
+ "in the respective `Variable` and `Equation` objects of the `ixmp4.Run`."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 50,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Running HiGHS 1.9.0 (git hash: fa40bdf): Copyright (c) 2024 HiGHS under MIT licence terms\n",
+ "Coefficient ranges:\n",
+ " Matrix [1e+00, 1e+00]\n",
+ " Cost [1e-01, 2e-01]\n",
+ " Bound [0e+00, 0e+00]\n",
+ " RHS [2e+02, 6e+02]\n",
+ "Presolving model\n",
+ "6 rows, 8 cols, 16 nonzeros 0s\n",
+ "6 rows, 8 cols, 16 nonzeros 0s\n",
+ "Presolve : Reductions: rows 6(-0); columns 8(-0); elements 16(-0) - Not reduced\n",
+ "Problem not reduced by presolve: solving the LP\n",
+ "Using EKK dual simplex solver - serial\n",
+ " Iteration Objective Infeasibilities num(sum)\n",
+ " 0 0.0000000000e+00 Pr: 4(950) 0s\n",
+ " 5 1.6132500000e+02 Pr: 0(0) 0s\n",
+ "Model name : linopy-problem-46ex2ggk\n",
+ "Model status : Optimal\n",
+ "Simplex iterations: 5\n",
+ "Objective value : 1.6132500000e+02\n",
+ "Relative P-D gap : 0.0000000000e+00\n",
+ "HiGHS run time : 0.00\n",
+ "Writing the solution to /tmp/linopy-solve-zx4bkwxw.sol\n"
+ ]
+ }
+ ],
"source": [
"from tutorial.transport.dantzig_model_linopy import (\n",
" create_dantzig_model,\n",
" read_dantzig_solution,\n",
")\n",
"\n",
- "\n",
"linopy_model_detroit = create_dantzig_model(run=run_detroit)\n",
"linopy_model_detroit.solve(\"highs\")\n",
"read_dantzig_solution(model=linopy_model_detroit, run=run_detroit)"
@@ -320,12 +562,12 @@
"source": [
"## Setting a default version of the scenario\n",
"\n",
- "As in Notebook 1, we set the *detroit* scenario as the default version so that we can easily retrieve it later."
+ "As in [Notebook 1](1_transport-tutorial.ipynb), we set the *detroit* scenario as the default version so that we can easily retrieve it later."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 51,
"metadata": {},
"outputs": [],
"source": [
@@ -338,33 +580,55 @@
"source": [
"## Display and analyze the results\n",
"\n",
- "We can now compare the *standard* instance of the *transport problem* and the *detroit* scenario.\n",
+ "We can now compare the *standard* instance of the **transport problem** and the *detroit* scenario.\n",
"\n",
- "The next two cells show the objective values of the two runs."
+ "The next two cells show the objective values of the two `Run`s."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 52,
"metadata": {
"jupyter": {
"name": "scen-z"
}
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[151.875]"
+ ]
+ },
+ "execution_count": 52,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"run.optimization.variables.get(\"z\").levels"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 53,
"metadata": {
"jupyter": {
"name": "scen-detroit-z"
}
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[161.325]"
+ ]
+ },
+ "execution_count": 53,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"run_detroit.optimization.variables.get(\"z\").levels"
]
@@ -375,34 +639,296 @@
"source": [
"You see that the *detroit* scenario has higher total cost.\n",
"\n",
- "The next two cells compare the optimal assignment of shipments from plants to markets in the two runs."
+ "The next two cells compare the optimal assignment of shipments from plants to markets in the two `Run`s."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 54,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " i | \n",
+ " j | \n",
+ " levels | \n",
+ " marginals | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " seattle | \n",
+ " new-york | \n",
+ " 0.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " seattle | \n",
+ " chicago | \n",
+ " 75.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " seattle | \n",
+ " topeka | \n",
+ " 275.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " san-diego | \n",
+ " new-york | \n",
+ " 325.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " san-diego | \n",
+ " chicago | \n",
+ " 225.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " san-diego | \n",
+ " topeka | \n",
+ " 0.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " i j levels marginals\n",
+ "0 seattle new-york 0.0 -0.0\n",
+ "1 seattle chicago 75.0 -0.0\n",
+ "2 seattle topeka 275.0 -0.0\n",
+ "3 san-diego new-york 325.0 -0.0\n",
+ "4 san-diego chicago 225.0 -0.0\n",
+ "5 san-diego topeka 0.0 -0.0"
+ ]
+ },
+ "execution_count": 54,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"pd.DataFrame(run.optimization.variables.get(\"x\").data)"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 55,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " i | \n",
+ " j | \n",
+ " levels | \n",
+ " marginals | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " san-diego | \n",
+ " chicago | \n",
+ " 150.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " san-diego | \n",
+ " detroit | \n",
+ " 0.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " san-diego | \n",
+ " new-york | \n",
+ " 200.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " san-diego | \n",
+ " topeka | \n",
+ " 250.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " seattle | \n",
+ " chicago | \n",
+ " 0.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " seattle | \n",
+ " detroit | \n",
+ " 275.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " seattle | \n",
+ " new-york | \n",
+ " 0.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " seattle | \n",
+ " topeka | \n",
+ " 75.0 | \n",
+ " -0.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " i j levels marginals\n",
+ "0 san-diego chicago 150.0 -0.0\n",
+ "1 san-diego detroit 0.0 -0.0\n",
+ "2 san-diego new-york 200.0 -0.0\n",
+ "3 san-diego topeka 250.0 -0.0\n",
+ "4 seattle chicago 0.0 -0.0\n",
+ "5 seattle detroit 275.0 -0.0\n",
+ "6 seattle new-york 0.0 -0.0\n",
+ "7 seattle topeka 75.0 -0.0"
+ ]
+ },
+ "execution_count": 55,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"pd.DataFrame(run_detroit.optimization.variables.get(\"x\").data)"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 56,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " j | \n",
+ " levels | \n",
+ " marginals | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " chicago | \n",
+ " 150.0 | \n",
+ " 0.153 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " detroit | \n",
+ " 275.0 | \n",
+ " 0.126 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " new-york | \n",
+ " 200.0 | \n",
+ " 0.153 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " topeka | \n",
+ " 325.0 | \n",
+ " 0.225 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " j levels marginals\n",
+ "0 chicago 150.0 0.153\n",
+ "1 detroit 275.0 0.126\n",
+ "2 new-york 200.0 0.153\n",
+ "3 topeka 325.0 0.225"
+ ]
+ },
+ "execution_count": 56,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "run_detroit.optimization.equations.get(\"demand\").data"
+ "pd.DataFrame(run_detroit.optimization.equations.get(\"demand\").data)"
]
},
{
@@ -411,16 +937,73 @@
"source": [
"## Scenario version management\n",
"\n",
- "As above, you can now list all scenarios available in the database instance to which the **ixmp4.Platform** is connected.\n",
+ "As above, you can now list all scenarios available in the database instance to which the `ixmp4.Platform` is connected.\n",
"\n",
"You should now see (at least) two scenarios."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 57,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " model | \n",
+ " scenario | \n",
+ " version | \n",
+ " is_default | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " transport problem | \n",
+ " standard | \n",
+ " 1 | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " transport problem | \n",
+ " detroit | \n",
+ " 2 | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " model scenario version is_default\n",
+ "0 transport problem standard 1 True\n",
+ "1 transport problem detroit 2 True"
+ ]
+ },
+ "execution_count": 57,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"platform.runs.tabulate()"
]
@@ -431,15 +1014,15 @@
"source": [
"When developing scenarios, we often make minor variations to numerous scenarios, and changing the *scenario name* every time is not practical.\n",
"\n",
- "The **ixmp4** package provides a more efficient approach to scenario version management: Every time that you *create* a new run or *clone* an existing run and the *model-scenario-name* combination already exists, a new *version* will be created.\n",
+ "The **ixmp4** package provides a more efficient approach to scenario version management: Every time that you `create()` a new `Run` or `clone()` an existing `Run` and the *model-scenario-name* combination already exists, a new *version* will be created.\n",
"\n",
- "You can get a specific *version* by including the version number in the call to get an **ixmp4.Run** like\n",
+ "You can get a specific *version* by including the version number in the call to get an `ixmp4.Run` like\n",
"\n",
"```python\n",
"platforms.runs.get(model, scenario, version)\n",
"```\n",
"\n",
- "You also can assign one of the versions as *default*, so that this run will be retrieved when you call\n",
+ "You also can assign one of the versions as *default*, so that this `Run` will be retrieved when you call\n",
"\n",
"```python\n",
"platforms.runs.get(model, scenario)\n",
@@ -447,16 +1030,81 @@
"\n",
"without a version number.\n",
"\n",
- "All versions will be kept in the database and are accessible via the **ixmp4.Platform**.\n",
+ "All versions will be kept in the database and are accessible via the `ixmp4.Platform`.\n",
"\n",
- "If you have run this tutorial multiple times, you can tabulate all runs - including the non-default versions - as illustrated below."
+ "If you have run this tutorial multiple times, you can tabulate all `Run`s - including the non-default versions - as illustrated below."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 58,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " model | \n",
+ " scenario | \n",
+ " version | \n",
+ " is_default | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " transport problem | \n",
+ " standard | \n",
+ " 1 | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " transport problem | \n",
+ " detroit | \n",
+ " 1 | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " transport problem | \n",
+ " detroit | \n",
+ " 2 | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " model scenario version is_default\n",
+ "0 transport problem standard 1 True\n",
+ "1 transport problem detroit 1 False\n",
+ "2 transport problem detroit 2 True"
+ ]
+ },
+ "execution_count": 58,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"platform.runs.tabulate(default_only=False)"
]
@@ -474,21 +1122,14 @@
"ixmp4 platforms remove transport-tutorial\n",
"```\n",
"\n",
- "The prompt will ask whether you also want to delete the SQLite database file from your computer."
+ "The prompt will ask whether you also want to delete the SQLite database file from your computer, answer `y` for a complete deletion."
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
- "display_name": "Python 3 (ipykernel)",
+ "display_name": ".venv",
"language": "python",
"name": "python3"
},
@@ -502,7 +1143,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.2"
+ "version": "3.12.3"
}
},
"nbformat": 4,