diff --git a/resources/examples/bin-packing.ipynb b/resources/examples/bin-packing.ipynb
index 119b0d2..c5595c7 100644
--- a/resources/examples/bin-packing.ipynb
+++ b/resources/examples/bin-packing.ipynb
@@ -202,7 +202,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.5"
+ "version": "3.12.7"
}
},
"nbformat": 4,
diff --git a/resources/examples/consecutive-shift-scheduling.ipynb b/resources/examples/consecutive-shift-scheduling.ipynb
index 7430a2b..faf8cee 100644
--- a/resources/examples/consecutive-shift-scheduling.ipynb
+++ b/resources/examples/consecutive-shift-scheduling.ipynb
@@ -8,7 +8,7 @@
"# Consecutive shift scheduling\n",
"\n",
"
\n",
- " ⓘ The code in this notebook requires a valid Opvious account. You may execute it from your browser
here if you update the client's creation below to use an explicit API token corresponding to your account.\n",
+ " ⓘ The code in this notebook requires a valid Opvious license. You may execute it from your browser
at this URL if you update the client's creation below to point to your licensed API.\n",
"
"
]
},
@@ -210,7 +210,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.5"
+ "version": "3.12.7"
}
},
"nbformat": 4,
diff --git a/resources/guides/uploading-a-model.ipynb b/resources/guides/uploading-a-model.ipynb
deleted file mode 100644
index cd8859f..0000000
--- a/resources/guides/uploading-a-model.ipynb
+++ /dev/null
@@ -1,266 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "b1e45002-aa7d-44f8-ae0e-aeb33d2e9eab",
- "metadata": {},
- "source": [
- "## Uploading a model\n",
- "\n",
- "\n",
- "\n",
- "In this notebook we show how to upload a model such that it can be solved without access to the original specification. This approach is useful in automated environments and production, particularly in combination with version tags."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "dd3e2c07-1f43-4ad1-809b-badc3f7c8a66",
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install opvious"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a8167f57-87d4-4f88-99d7-837f51a5e7af",
- "metadata": {},
- "source": [
- "## Formulation\n",
- "\n",
- "We will use the [bin-packing problem](https://www.opvious.io/notebooks/retro/notebooks/?path=examples/bin-packing.ipynb) as example and use the same formulation."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "de9a68f2-7e9a-4def-b479-6c5f32981024",
- "metadata": {},
- "outputs": [],
- "source": [
- "import opvious.modeling as om\n",
- "\n",
- "class BinPacking(om.Model):\n",
- " \"\"\"Bin-packing MIP formulation\"\"\"\n",
- " \n",
- " items = om.Dimension() # Set of items to be put into bins\n",
- " weight = om.Parameter.non_negative(items) # Weight of each item\n",
- " bins = om.interval(1, om.size(items), name=\"B\") # Set of bins\n",
- " max_weight = om.Parameter.non_negative() # Maximum weight allowed in a bin\n",
- " assigned = om.Variable.indicator(bins, items, qualifiers=['bins']) # 1 if an item is assigned to a given bin, 0 otherwise\n",
- " used = om.Variable.indicator(bins) # 1 if a bin is used, 0 otherwise\n",
- "\n",
- " @om.constraint\n",
- " def each_item_is_assigned_once(self):\n",
- " \"\"\"Constrains each item to be assigned to exactly one bin\"\"\"\n",
- " for i in self.items:\n",
- " yield om.total(self.assigned(b, i) for b in self.bins) == 1\n",
- "\n",
- " @om.constraint\n",
- " def bin_weights_are_below_max(self):\n",
- " \"\"\"Constrains each bin's total weight to be below the maximum allowed\"\"\"\n",
- " for b in self.bins:\n",
- " bin_weight = om.total(self.weight(i) * self.assigned(b, i) for i in self.items)\n",
- " yield bin_weight <= self.used(b) * self.max_weight()\n",
- "\n",
- " @om.objective\n",
- " def minimize_bins_used(self):\n",
- " \"\"\"Minimizes the total number of bins with at least one item\"\"\"\n",
- " return om.total(self.used(b) for b in self.bins)\n",
- "\n",
- "model = BinPacking()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "9270a9d3-acbb-4574-992b-35260c7f39a0",
- "metadata": {},
- "source": [
- "## Application\n",
- "\n",
- "Instead of optimizing directly from the model as in the original notebook, we will first upload it. This requires two main pieces:\n",
- "\n",
- "+ An API token, from which to generate an authenticated client.\n",
- "+ A name for the uploaded formulation, which later be used to refer to it when optimizing."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "699cb44d-5fb9-4f3c-a737-104a6e3af89a",
- "metadata": {},
- "outputs": [],
- "source": [
- "import opvious\n",
- "\n",
- "client = opvious.Client.from_environment(default_endpoint=opvious.DEMO_ENDPOINT)\n",
- "\n",
- "FORMULATION_NAME = \"bin-packing\"\n",
- "\n",
- "async def upload_model(version_tag=None):\n",
- " \"\"\"Saves the bin-packing model so that it can be solved just from the formulation name\n",
- "\n",
- " Args:\n",
- " version_tag: Optional versioning tag used to target specific model versions.\n",
- " \"\"\"\n",
- " await client.register_specification(model.specification(), FORMULATION_NAME, tag_names=[version_tag] if version_tag else None)\n",
- "\n",
- "await upload_model()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "2df2c83c-946a-45a8-b61a-094e47201268",
- "metadata": {},
- "source": [
- "We can now get solutions just with the formulation name. The code is very similar to the one in the original bin-packing example, we simply replaced the inline specification with a `FormulationSpecification`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "308e053a-b931-45a4-adda-c37dec3bdf25",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": "[('heavy',), ('light', 'medium')]"
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "async def optimal_assignment(bin_max_weight, item_weights, version_tag=None):\n",
- " \"\"\"Returns a grouping of items which minimizes the number of bins used\n",
- " \n",
- " Args:\n",
- " bin_max_weight: The maximum allowable total weight for all items assigned to a given bin\n",
- " item_weights: Mapping from item name to its (non-negative) weight\n",
- " version_tag: Model version tag\n",
- " \"\"\"\n",
- " problem = opvious.Problem(\n",
- " specification=opvious.FormulationSpecification(FORMULATION_NAME), # Note the formulation reference\n",
- " parameters={'weight': item_weights, 'maxWeight': bin_max_weight},\n",
- " )\n",
- " solution = await client.solve(problem)\n",
- " assignment = solution.outputs.variable('assigned')\n",
- " return list(assignment.reset_index().groupby('bins')['items'].agg(tuple))\n",
- "\n",
- "await optimal_assignment(15, {\n",
- " 'light': 5,\n",
- " 'medium': 10,\n",
- " 'heavy': 15,\n",
- "})"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "ddb53774-b219-4a22-8d80-8f85224bc6e5",
- "metadata": {},
- "source": [
- "We can also make requests without the SDK: under the hood everything goes through the same API (see its OpenAPI specification [here](https://api.try.opvious.io/openapi.yaml)). To show how, we implement below a function which returns the minimum number of bins needed to fit the input items (our model's objective value) using the popular `requests` library."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "0b6b5530-1c0d-42e8-b985-7a7c5d5d8f35",
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install requests"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "id": "171d4c7e-5b5e-4d02-8dc0-b4165c600da8",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": "2"
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import os\n",
- "import requests\n",
- "\n",
- "_token = os.environ.get('OPVIOUS_TOKEN')\n",
- "\n",
- "def minimum_bin_count(bin_max_weight, item_weights, version_tag='latest'):\n",
- " \"\"\"Returns the minimum number of bins needed to fit the input items\n",
- "\n",
- " Args:\n",
- " bin_max_weight: The maximum allowable total weight for all items assigned to a given bin\n",
- " item_weights: Mapping from item name to its (non-negative) weight\n",
- " version_tag: Model version tag\n",
- " \"\"\"\n",
- " response = requests.post(\n",
- " url=f'{client.executor.endpoint}/solve',\n",
- " headers={\n",
- " 'accept': 'application/json',\n",
- " 'authorization': f'Bearer {_token}',\n",
- " },\n",
- " json={\n",
- " 'problem': {\n",
- " 'formulation': {'name': FORMULATION_NAME, 'specificationTagName': version_tag},\n",
- " 'inputs': {\n",
- " 'parameters': [\n",
- " {'label': 'maxWeight', 'entries': [{'key': [], 'value': bin_max_weight}]},\n",
- " {'label': 'weight', 'entries': [{'key': k, 'value': v} for k, v in item_weights.items()]},\n",
- " ]\n",
- " }\n",
- " }\n",
- " }\n",
- " )\n",
- " return response.json()['outcome']['objectiveValue']\n",
- "\n",
- "if _token:\n",
- " minimum_bin_count(15, {\n",
- " 'light': 5,\n",
- " 'medium': 10,\n",
- " 'heavy': 15,\n",
- " })"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "id": "dc047f77-7b0f-466e-87e1-a9c361a76f0e",
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "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.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
\ No newline at end of file
diff --git a/resources/guides/welcome.ipynb b/resources/guides/welcome.ipynb
index b3b8b70..5a1720f 100644
--- a/resources/guides/welcome.ipynb
+++ b/resources/guides/welcome.ipynb
@@ -10,7 +10,7 @@
"In this notebook we introduce [Opvious](https://www.opvious.io), a _batteries-included optimization platform_, by walking through an end-to-end optimization example.\n",
"\n",
"\n",
- " ⓘ This example can be run directly from your browser when accessed via its
opvious.io/notebooks URL. No Opvious account required.\n",
+ " ⓘ This example can be run directly from your browser when accessed via its
opvious.io/notebooks URL.\n",
"
\n",
"\n",
"Let's imagine that we are tasked with allocating a budget between various projects. We are also given an expected cost and value for each project. Our goal is to __pick projects__ which __maximize total value__ while keeping __total cost within the budget__. It turns out that our task can be formulated naturally as an [integer programming problem](https://en.wikipedia.org/wiki/Integer_programming) (it is actually an instance of the [knapsack problem](https://en.wikipedia.org/wiki/Knapsack_problem)) which--unlike heuristics--will be guaranteed to give us an optimal allocation.\n",
@@ -239,7 +239,6 @@
"## Next steps\n",
"\n",
"+ Browse our other interactive [guides and examples](https://www.opvious.io/notebooks/retro)\n",
- "+ Create a (free) account via the [Optimization Hub](https://hub.cloud.opvious.io) to solve larger problems\n",
"+ Try the platform out locally with a [self-hosted API server](https://hub.docker.com/r/opvious/api-server)"
]
},
@@ -268,7 +267,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.5"
+ "version": "3.12.7"
}
},
"nbformat": 4,