From 8fb6cf1d14c80542882f8d019a18faaf8e9d59c0 Mon Sep 17 00:00:00 2001 From: Carlos Quesada Date: Thu, 16 Oct 2025 11:58:39 +0200 Subject: [PATCH 1/4] =?UTF-8?q?Mejora:=20actualizar=20tutorial=20inicial?= =?UTF-8?q?=20de=20instalaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/tutorial/00-Getting-Started.ipynb | 4 +++- .../01-How-Solutions-are-Represented.ipynb | 23 ++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/source/tutorial/00-Getting-Started.ipynb b/docs/source/tutorial/00-Getting-Started.ipynb index 2964be62..c494bb34 100644 --- a/docs/source/tutorial/00-Getting-Started.ipynb +++ b/docs/source/tutorial/00-Getting-Started.ipynb @@ -6,11 +6,13 @@ "source": [ "# Getting Started with Job Shop Lib\n", "\n", + "Recall that the Job Shop Scheduling Problem consists **of determining the optimal sequence of operations for a set of jobs to be processed on a set of machines**, where each job is composed of a series of operations that must be performed in a specific order, and each operation requires a specific machine for a given processing time. The objective is typically to minimize a performance criterion such as the total completion time (makespan) while respecting constraints such as machine capacity (only one job can be processed on a machine at a time) and job precedence relationships.\n", + "\n", "The main class of the library is the `JobShopInstance` class, which stores a list of jobs and its operations.\n", "\n", "Each operation is also a class, which stores the machine(s) in which the operation can be processed and its duration (also known as processing time). Let's see an example of how to use the `JobShopInstance` class to model a JSSP instance.\n", "\n", - "In this example, we model a simple Job Shop Scheduling Problem using the `JobShopInstance` class. We define three types of machines: CPU, GPU, and Data Center, each represented by a unique identifier." + "In this example, we model a simple Job Shop Scheduling Problem using the `JobShopInstance` class. We define three types of machines: CPU, GPU, and Data Center, each represented by a unique identifier. This just defines the problem, later on, we will find solutions and finally we will try to optimize them." ] }, { diff --git a/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb b/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb index 28f477c4..755f506c 100644 --- a/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb +++ b/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb @@ -14,7 +14,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "First, the operations from the previous example are organized by their respective machines." + "Recall the previous example:" ] }, { @@ -44,6 +44,13 @@ ")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, the operations are organized by their respective machines." + ] + }, { "cell_type": "code", "execution_count": 2, @@ -135,6 +142,13 @@ "print(\"Makespan:\", schedule.makespan())" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the Job Shop Scheduling Problem has a solution, it can be represented, as follows" + ] + }, { "cell_type": "code", "execution_count": 6, @@ -157,6 +171,13 @@ "_ = plot_gantt_chart(schedule, job_labels=[\"Job 1\", \"Job 2\", \"Job 3\"])" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Without any algorithm it is easy to improve this solution by a simple visual inspection. We can manually rearrange the job sequences to obtain a better solution." + ] + }, { "cell_type": "code", "execution_count": 7, From 3b5c6ce85e8257d1db38d27c9badd6a31c12d4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Ari=C3=B1o?= <72697714+Pabloo22@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:06:31 +0100 Subject: [PATCH 2/4] [Docs] Fix typo in tutorial 01 Suggestion by gemini Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- docs/source/tutorial/01-How-Solutions-are-Represented.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb b/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb index 755f506c..8bacae9d 100644 --- a/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb +++ b/docs/source/tutorial/01-How-Solutions-are-Represented.ipynb @@ -146,7 +146,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now that the Job Shop Scheduling Problem has a solution, it can be represented, as follows" + "Now that the Job Shop Scheduling Problem has a solution, it can be represented as follows:" ] }, { From 5dbd258f019f96b487e13d966e2127c0b02f39bb Mon Sep 17 00:00:00 2001 From: Carlos Quesada Date: Wed, 12 Nov 2025 13:51:35 +0100 Subject: [PATCH 3/4] Mejora: actualizar tutorial --- .DS_Store | Bin 0 -> 6148 bytes docs/.DS_Store | Bin 0 -> 6148 bytes docs/source/.DS_Store | Bin 0 -> 6148 bytes .../tutorial/02-Solving-the-Problem.ipynb | 16 ++++++++--- .../tutorial/03-Generating-New-Problems.ipynb | 4 ++- .../tutorial/04-Simulated-Annealing.ipynb | 26 ++++++------------ 6 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 .DS_Store create mode 100644 docs/.DS_Store create mode 100644 docs/source/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..58db9a7a83cd6c38669e9f0b7ecd223d7207907d GIT binary patch literal 6148 zcmeH~O-jT-5QSfB76ZDNrOUp8H)w|O1Rg-iWT6s>5Zq_ywSDz7kRb@Oav`sv`gK=V zrOCHQr2&+~*YF7J0qp3e__kqdwr{?%n~azid&V%I#(tVcF0M7J?J!`%3G=%C9v=+$ zc)^S}&OSLC@s9qSbnOYs69Ewr0TB=Z5m*z*Hod!B2Q?P~5fA|quyn$ z6@c0??8dp@C8*T`)Rwx0GD0g+N{!NzSBw(njMvO-sY_^-qxi{uPM%!yhEn`=#;d2J zv`~#AAOe>JZezK({{KY(<^F$Jq?HJWz`r6;y5sZlz*oxNx_LS4wUz!#KO1vBorAYx is<&b;tQ9}3@~X|b-%^)QFK67#srnHxE;14L3j#kj{u^un literal 0 HcmV?d00001 diff --git a/docs/.DS_Store b/docs/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4015781419dee65b318019588f239979a01da695 GIT binary patch literal 6148 zcmeHKI|>3Z5S>vG!N$@uSMUZw^aNf&{B**CV!xH=@@T&K6fUcs7Rno#yks&jA+Olk z5fNQp4-1i*h)m#yaHoVVuBZSN_$vi;wA!qecv9BZ-s7y+7Wfu!Id`}j=1#%jKyo842-m813XGt_XiIg9ZKP*0-x zBxLoPD(U+=>r`~QG(TltnNeEiFQ z8^^&mX;gp;Pys4H1*pKP3S@b0pI1GVhfx74umuI|`%vJ9HE{~`PX`8X0e}s{ZkT&7 z0W1~(*2F0g5ts%Q7*x#`LxYZZ$-J641qNL-n-9&KH9Hjb+i`yJbkQ2fkqS_OxdOXb z?ydfx;CK4}If*MOKm|6XfHue1V}~bYZCyOhYHfj^;g)lQn_=!03|@|bUXHP_a(wWl b$SXF-eodSLosPKEf&3XTU1(I`(F*(mayb>N literal 0 HcmV?d00001 diff --git a/docs/source/tutorial/02-Solving-the-Problem.ipynb b/docs/source/tutorial/02-Solving-the-Problem.ipynb index 6d0ae525..841dc61f 100644 --- a/docs/source/tutorial/02-Solving-the-Problem.ipynb +++ b/docs/source/tutorial/02-Solving-the-Problem.ipynb @@ -7,7 +7,7 @@ "## Solving the Problem\n", "As you can see, manually creating solutions is a tedious task and requires taking into account each constraint carefully. This is the reason the `Dispatcher` class was created. This class allow us to just define the order in which operations are sequenced and the machines in which they are processed. The `Dispatcher` class will take care of the rest.\n", "\n", - "Let's see an example of how to use the `Dispatcher` class to solve the previous instance. In this case, a reasonable solution is to process the operations in the order they are defined in the instance. We can do this as follows:" + "Let's see an example of how to use the `Dispatcher` class to solve the previous instance. In this case, a reasonable solution is to process, for each job, the operations in the order they are defined in the instance. We can do this as follows:" ] }, { @@ -47,6 +47,13 @@ " dispatcher.dispatch(job_3[i], job_3[i].machine_id)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The dispatcher took care of any possible overlaps providing the expected solution, as we can see below" + ] + }, { "cell_type": "code", "execution_count": 3, @@ -76,8 +83,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "Even though the dispatcher creates solutions easily, they are crafted manually/procedurally and therefore will usually be far from optimal. It is interesting to introduce solvers that find solutions according to certain optimality criteria.\n", "\n", - "A solver is any `Callable` object that takes as input a `JobShopInstance` class and returns a `Schedule` with a complete solution of the instance.\n", + "A **solver** is any `Callable` object that takes as input a `JobShopInstance` class and returns a `Schedule` with a complete solution of the instance.\n", "\n", "In this example, we are going to use the `CPSolver` class, contained inside `job_shop_lib.solvers` package, which uses [CP-SAT solver from Google OR-Tools](https://developers.google.com/optimization/cp/cp_solver)." ] @@ -118,7 +126,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This class returns a `Schedule` object with a complete solution of the instance. It also set some metadata of the solution, such as the time it took to solve the instance and the status of the solution:" + "This class returns a `Schedule` object with a complete solution of the instance. It also incorporates some metadata of the solution, such as the time it took to solve the instance and the status of the solution:" ] }, { @@ -146,7 +154,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Finally, we can plot the gantt chart of the solution using the `plot_gantt_chart` method." + "We can now plot the gantt chart of the solution provided by the solver which is not only valid and complete, but clearly better in terms of makespan." ] }, { diff --git a/docs/source/tutorial/03-Generating-New-Problems.ipynb b/docs/source/tutorial/03-Generating-New-Problems.ipynb index 4bd6ed09..3cd586b5 100644 --- a/docs/source/tutorial/03-Generating-New-Problems.ipynb +++ b/docs/source/tutorial/03-Generating-New-Problems.ipynb @@ -7,7 +7,9 @@ "source": [ "# Tutorial 03 - Generating New Problems (Random Instance Generation)\n", "\n", - "This notebook shows how to generate random **JobShopInstance** objects using the function `modular_instance_generator`.\n", + "This notebook shows how to generate random **JobShopInstance** objects using the function `modular_instance_generator`. It’s important to note that this process is not about solving a given problem, but rather about creating entirely new problems. Each JobShopInstance represents a unique problem configuration with its own jobs, machines, and processing times.\n", + "\n", + "Generating problem instances is a crucial step in machine learning workflows, as it provides the data required for training and evaluating algorithms under a variety of conditions.\n", "\n", "> **Deprecated:** The classes `InstanceGenerator` and `GeneralInstanceGenerator` are deprecated. Use `modular_instance_generator` instead." ] diff --git a/docs/source/tutorial/04-Simulated-Annealing.ipynb b/docs/source/tutorial/04-Simulated-Annealing.ipynb index 62711977..fb54c131 100644 --- a/docs/source/tutorial/04-Simulated-Annealing.ipynb +++ b/docs/source/tutorial/04-Simulated-Annealing.ipynb @@ -16,7 +16,7 @@ "3. **Iteratively explore neighbors:** The algorithm then iteratively explores \"neighboring\" solutions. A neighbor is a new schedule created by making a small change to the current one, for example, by swapping the order of two operations on a single machine.\n", "4. **Accept or reject new solutions:**\n", " * If the neighbor solution has a lower energy (is better), it is always accepted as the new current solution.\n", - " * If the neighbor solution has a higher energy (is worse), it might still be accepted with a certain probability. This probability is higher at the beginning (when the \"temperature\" is high) and decreases over time. This allows the algorithm to escape local optima and explore a wider range of solutions.\n", + " * If the neighbor solution has a higher energy (is worse), it might still be accepted with a certain probability. This probability is higher at the beginning (when a threshold called \"temperature\" is high) and decreases over time. This allows the algorithm to escape local optima and explore a wider range of solutions.\n", "5. **Cooling down:** The \"temperature\" gradually decreases, reducing the probability of accepting worse solutions. The process stops when the system has \"cooled down\" (the temperature is low) or after a certain number of iterations.\n", "\n", "## Core Components\n", @@ -28,7 +28,7 @@ " * **Neighbor Generators:** These are functions that define how to create a \"neighbor\" schedule from a current one.\n", " * **Objective Functions:** The `energy` function calculates the objective value of a schedule, which is typically the makespan plus any penalties for constraint violations.\n", "\n", - "## The `SimulatedAnnealingSolver`\n", + "### The `SimulatedAnnealingSolver`\n", "\n", "This is the main entry point for using the solver. When you create an instance of this class, you can configure various parameters of the annealing process:\n", "\n", @@ -38,7 +38,7 @@ " * `neighbor_generator`: The function used to generate neighboring solutions. The default is `swap_in_critical_path`.\n", " * `seed`: A random seed for reproducibility.\n", "\n", - "## Neighbor Generation Strategies\n", + "### Neighbor Generation Strategies\n", "\n", "A key part of the simulated annealing process is how you explore the solution space by moving from one solution to a \"neighbor\". This implementation provides three different neighbor generation strategies in `_neighbor_generators.py`:\n", "\n", @@ -48,7 +48,7 @@ "\n", "3. **`swap_in_critical_path` (Default):** This is the most sophisticated of the three. It identifies the critical path of the current schedule (the sequence of operations that determines the makespan) and looks for consecutive operations on that path that are on the same machine. It then swaps one of these pairs. The idea is that modifying the critical path is the most direct way to try to reduce the makespan. If no such pair exists, it falls back to a standard adjacent swap.\n", "\n", - "## The Objective Function\n", + "### The Objective Function\n", "\n", "The objective function is what the simulated annealing algorithm tries to minimize. In the context of job shop scheduling, this is typically the makespan (the total time to complete all jobs) plus any penalties for violating constraints (like deadlines).\n", "\n", @@ -58,7 +58,7 @@ "\n", "### Basic Usage\n", "\n", - "This example shows how to solve a benchmark instance (\"ft06\") with a specific seed to get a reproducible result." + "This example shows how to solve a specific JSSP problem, the benchmark instance \"ft06\", with a specific seed to get a reproducible result." ] }, { @@ -109,7 +109,7 @@ "source": [ "### Using a Different Neighbor Generator\n", "\n", - "Although it's not recommended, you can easily plug in a different neighbor generation strategy by passing it to the `SimulatedAnnealingSolver`'s constructor. Here's how to use `swap_adjacent_operations`:\n" + "You can specify a different neighbor generator by passing it to the `SimulatedAnnealingSolver` constructor. Here, we use `swap_adjacent_operations` as an example although its usage is not recommended: it produces very local changes and often generates infeasible neighbors that require repeated retries, which slows the search and reduces effectiveness. However, for the shake of experimentation:\n" ] }, { @@ -313,7 +313,6 @@ "# Durations between 2 and 15 to have some variability\n", "duration_creator = get_default_duration_matrix_creator((2, 15))\n", "\n", - "\n", "def deadlines_creator(duration_matrix, rng):\n", " deadlines: list[list[int]] = []\n", " for job_row in duration_matrix:\n", @@ -326,7 +325,6 @@ " deadlines.append(row)\n", " return deadlines\n", "\n", - "\n", "instance_gen = modular_instance_generator(\n", " machine_matrix_creator=machine_creator,\n", " duration_matrix_creator=duration_creator,\n", @@ -350,8 +348,6 @@ "baseline_schedule = baseline_solver.solve(instance)\n", "\n", "# Helper: count deadline violations\n", - "\n", - "\n", "def count_deadline_violations(schedule):\n", " violations = 0\n", " for machine_sched in schedule.schedule:\n", @@ -438,17 +434,11 @@ "source": [ "Note that, in this case, we needed to use a higher initial temperature to effectively explore the solution space and reduce deadline violations. Otherwise, because of the high penalty, very few solutions would be accepted, hindering the search process. In general, the more violations we expect, the higher the initial temperature should be to allow the algorithm to explore a wider range of solutions." ] - }, - { - "cell_type": "markdown", - "id": "51f0604d", - "metadata": {}, - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "job-shop-lib-gOF0HMZJ-py3.12", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -462,7 +452,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.12.11" } }, "nbformat": 4, From 2f848b5126949f295db79bd9f5343bb0f25f0f2f Mon Sep 17 00:00:00 2001 From: Pabloo22 Date: Sun, 23 Nov 2025 16:04:00 +0000 Subject: [PATCH 4/4] [Chore] Ignore `.DS_Store` files Remove unnecessary .DS_Store files from the repository --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 3 +++ docs/.DS_Store | Bin 6148 -> 0 bytes docs/source/.DS_Store | Bin 6148 -> 0 bytes 4 files changed, 3 insertions(+) delete mode 100644 .DS_Store delete mode 100644 docs/.DS_Store delete mode 100644 docs/source/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 58db9a7a83cd6c38669e9f0b7ecd223d7207907d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~O-jT-5QSfB76ZDNrOUp8H)w|O1Rg-iWT6s>5Zq_ywSDz7kRb@Oav`sv`gK=V zrOCHQr2&+~*YF7J0qp3e__kqdwr{?%n~azid&V%I#(tVcF0M7J?J!`%3G=%C9v=+$ zc)^S}&OSLC@s9qSbnOYs69Ewr0TB=Z5m*z*Hod!B2Q?P~5fA|quyn$ z6@c0??8dp@C8*T`)Rwx0GD0g+N{!NzSBw(njMvO-sY_^-qxi{uPM%!yhEn`=#;d2J zv`~#AAOe>JZezK({{KY(<^F$Jq?HJWz`r6;y5sZlz*oxNx_LS4wUz!#KO1vBorAYx is<&b;tQ9}3@~X|b-%^)QFK67#srnHxE;14L3j#kj{u^un diff --git a/.gitignore b/.gitignore index 36e601cb..ad7e3619 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# macOS file system metadata +.DS_Store + # Development files .vscode/ tests/notebooks diff --git a/docs/.DS_Store b/docs/.DS_Store deleted file mode 100644 index 4015781419dee65b318019588f239979a01da695..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKI|>3Z5S>vG!N$@uSMUZw^aNf&{B**CV!xH=@@T&K6fUcs7Rno#yks&jA+Olk z5fNQp4-1i*h)m#yaHoVVuBZSN_$vi;wA!qecv9BZ-s7y+7Wfu!Id`}j=1#%jKyo842-m813XGt_XiIg9ZKP*0-x zBxLoPD(U+=>r`~QG(TltnNeEiFQ z8^^&mX;gp;Pys4H1*pKP3S@b0pI1GVhfx74umuI|`%vJ9HE{~`PX`8X0e}s{ZkT&7 z0W1~(*2F0g5ts%Q7*x#`LxYZZ$-J641qNL-n-9&KH9Hjb+i`yJbkQ2fkqS_OxdOXb z?ydfx;CK4}If*MOKm|6XfHue1V}~bYZCyOhYHfj^;g)lQn_=!03|@|bUXHP_a(wWl b$SXF-eodSLosPKEf&3XTU1(I`(F*(mayb>N