Vessel Scheduling

https://img.shields.io/badge/AIMMS_24.5-ZIP:_Vessel_Scheduling-blue https://img.shields.io/badge/AIMMS_24.5-Github:_Vessel_Scheduling-blue https://img.shields.io/badge/AIMMS_Community-Forum-yellow ../../_images/project-1920-high7.gif

Story

In this practical example, an efficient plan is developed for delivering large cargoes using oil tankers.

The model assumes each ship can carry only one cargo at a time, and once the time horizon begins, all vessels head directly to the loading port. Upon loading, each vessel proceeds directly to the delivery location within its designated time window.

Constraints include ensuring each cargo is loaded inside the determined time window, each cargo being transported by only one vessel, and each charter vessels being assigned to only one route at a time.

The objective is to minimize costs associated to combinations of cargoes and routes.

Mathematical Model

To appreciate the complexity of the below mathematical formulation, it is important to note that the number of routes grows combinatorially with the number of cargos. For instance, with 7 vessels and 20 cargos, the number of routes can exceed half a million.

Vessel Scheduling Model

Sets and indices:

\(v\), \(v \in Vessels\)

Vessels

\(c\), \(c \in Cargos\)

Cargos

\(r\), \(r \in Routes\)

Routes

Parameters:

\(D_{v,r} \in \{ 0, 1 \}\)

Route \(r\) used by vessel \(v\): p_def_domainAllocateVesselToRoute

\(CR_{c,r} \in \{ 0, 1 \}\)

Cargo \(c\) on route \(r\): p_def_cargoesOnRoute

\(IC_{v} \in \mathbb{R_{+}}\)

Idle cost for vessel \(v\): p_def_idleCostVesselNotUsed

\(SC_{c} \in \mathbb{R_{+}}\)

Cost cargo \(c\) handled on spot market: p_spotCostVessel

\(T_{r} \in \mathbb{R_{+}}\)

Cost executing route \(r\): p_def_operationalCostPerRoute

Variables:

\(a_{(v,r)|D_{v,r}} \in \{ 0, 1 \}\)

allocate vessel \(v\) to route \(r\): v_allocateVesselToRoute

\(s_{c} \in \{0..1\}\)

cargo \(c\) is left to the spot market: bv_cargoOnCharteredVessel

\(i_{v} \in \{0..1\}\)

vessel \(v\) remains idle: v_idleVessel

Constraints:

1

\(\forall c: \sum_r a_{v,r} * CR_{c,r} + s_{c} = 1\)

Cargo on a single vessel, or left to spot market

2

\(\forall v: \sum_r a_{v,r} + i_{v} = 1\)

Each vessel can take only one route, or is idle

Minimize:

\(\sum_{v,r} T_{r} * a_{v,r} +\)

Operational cost

\(\sum_{v} IC_{v} * i_{v} +\)

Unused vessel cost

\(\sum_{c} SC_{p,c} * S_{c}\)

Total cost of cargos left to the spot market

Language

Route Generation

Before optimization, all possible routes are generated after data import, taking into account each cargo’s loading window to ensure timely delivery.

During the mathematical optimization process, each cargo is then assigned to either a time-chartered or voyage-chartered vessel within the model.

In this example, the vessel scheduling problem is solved by first generating the routes, followed by the mathematical optimization. The majority of the time is spent on route generation.

Example

A single vessel, vessel1, located at Caracas, is to handle two cargos, labeled: a1 and a2.

  1. a1 load in Paramaribo, deliver in Sao Paolo

  2. a2 load in Montevideo, deliver in Rio de Janeiro.

Then there are five potential routes:

  1. vessel1_a1_a2: with actions:

    1. Sail to Caracas to Paramaribo

    2. Load Cargo a1

    3. Sail to Sao Paolo

    4. Deliver Cargo a1

    5. Sail to Montevideo

    6. Load Cargo a2

    7. Sail to Rio de Janeiro

    8. Deliver Cargo a2

  2. vessel1_a2_a1: similar as vessel1_a1_a2, just a different order of locations; and thus also different vessel sailing times and cargo pickup moments.

  3. vessel1_a1: vessel1 only handles cargo a1

  4. vessel1_a2: vessel1 only handles cargo a2

  5. vessel1 Remains at port Caracas

The route generation procedure is as follows:

  1. For each vessel i, the idle route is generated: vessel<i>. Together they initialize the set of just generated routes, JG.

  2. Move the set of just generated routes JG, to the set of input routes IR.

  3. For each r in IR, all cargos c are considered to be appended for a new route r'. A route r' = r_c is accepted if:

    • c is not a part of r,

    • c is picked up in its time window, and

      • c is delivered before the end of the horizon.

      All routes r' just generated, form the new set of just generated routes JG. If the set JG is empty, stop, otherwise continue with step 2.

Because a route r' ends later than route r, this procedure is finite.

In order to determine the cost of a route, careful administration of each leg needs to be done (sailing to the loading location, perhaps waiting, sailing to the delivery location).

Python Service

This section is largely based on the how-to articles in Develop an AIMMS Service. Selected differences will be pointed out:

Produce Service: The service is named solveVesselScheduling, accepts an Excel workbook as input, and provides as response also an Excel workbook.

Consume Service: Only a Python client is provided; and the requests call in that python app uses a files argument instead of a data argument.

WebUI Features

On input page, if you click around the graphs, a highlighted cell will appear identifying the last clicked element. The results are displayed in a combination chart (stacked bar chart).

The following WebUI features are used:

UI Styling

Below there are the css files you will find with comments on what they change.

 1:root {
 2   --primaryDark: #DA2063;
 3   --primaryDarker: #FF4940;
 4   --secondary90Transparent: #ff4a4023;
 5   --secondary: #2E324F;
 6
 7   --bg_app-logo: 15px 50% / 40px 40px no-repeat url(/app-resources/resources/images/schedule.png); /*app logo*/
 8   --spacing_app-logo_width: 60px;
 9   --color_border_app-header-divider: var(--secondary); /*line color after header*/
10
11   --color_workflow-item-divider: var(--secondary90Transparent); /*workflow step divider color*/
12   --color_bg_workflow_current: var(--primaryDark); /*bg color when step is selected*/
13   --color_workflow_active: var(--primaryDark); /*font and icon color when step is active*/
14   --color_workflow-icon-border: var(--primaryDark); /*round border of the step*/
15   --color_bg_workflow_active: #ff4a400e;;
16
17   --color_bg_app-canvas: url(/app-resources/resources/images/RightBackground.png) rgb(249, 249, 249) no-repeat left/contain; /*background color*/
18   --color_bg_widget-header: linear-gradient(90deg, rgba(255,73,64,0.75) 0%, rgba(218,32,99,0.75)  100%); /*widget header background color*/
19   --border_widget-header: 2px solid var(--secondary); /*line color after widget header*/
20
21   --color_text_widget-header: var(--secondary);
22   --color_text_edit-select-link: var(--primaryDark);
23
24   --color_bg_button_primary: var(--primaryDark);
25   --color_bg_button_primary_hover: var(--primaryDarker);
26}
 1/*Hide checkbox contents of delete and edit annotations*/
 2.annotation-edit-element input.boolean-cell-editor-contents,
 3.annotation-delete-element input.boolean-cell-editor-contents{
 4   visibility: hidden;
 5   display: block;
 6}
 7
 8.annotation-edit-element {
 9   background: white url(img/pencil.png) no-repeat 50%/contain;
10   background-size: auto 70% ;
11}
12
13.annotation-delete-element {
14   background: white url(img/minus.png) no-repeat 50%/contain;
15   background-size: auto 50% ;
16
17}
18
19.annotation-NotInUse,
20.annotation-DeliveringPort,
21.annotation-VisibleLocations{
22   fill: #FE493F;
23   background: #FE493F !important;
24}
25
26.annotation-InUse,
27.annotation-LoadingPort{
28   fill: #9E3869;
29   background: #9E3869 !important;
30}
31
32.annotation-not-fulfilled{
33   background: #ffc21b2c;
34}
35
36.annotation-highlight-cell {
37   background: var(--secondary90Transparent);
38}
 1/*Centering cells*/
 2.tag-table .cell.flag-string .cell-wrapper,
 3.tag-table .cell.flag-number input,
 4.tag-table .cell.flag-string input{
 5   text-align: center;
 6}
 7
 8.tag-slider .slider-value {
 9   color: var(--color_text_edit-select-link);
10}
11
12.widget-menu__item .title {
13   color: var(--color_text_app-footer);
14}
15
16.ql-snow a {
17   color: var(--color_text_edit-select-link) !important;
18}
19
20input.boolean-cell-editor-contents {
21   accent-color: var(--primaryDark) /*boolean color*/
22}
23
24.react-contextmenu .react-contextmenu-item .display-text {
25   color: inherit;
26}
27
28.aimms-widget[data-widget\.uri="scl_EditAddElements"] .awf-dock.top,
29.aimms-widget[data-widget\.uri="msl_selecRoutes"] .awf-dock.top,
30.aimms-widget[data-widget\.uri="MappingCargoesWithCollors_1"] .awf-dock.top,
31.aimms-widget[data-widget\.uri="Vessel loading_1"] .awf-dock.top{
32   display: none;
33}
34
35.status-message:hover,
36.status-message.clickable:hover .status-display-text {
37   background-color: #ffcdcb2d;
38   color: #505767;
39}

Minimal Requirements

AIMMS Community license is sufficient for working with this example. To run the Python client, you will need to have Python installed, for this example we used Python 3.11.

References

#. Gustavo Diz, Luiz Felipe Scavarda, Roger Rocha, Silvio Hamacher (2014) Decision Support System for PETROBRAS Ship Scheduling. Interfaces 44(6):555-566.

Release Notes

v1.3 (07/10/2024)

Fixing integration problems (import and export) when using the project on AIMMS PRO Portal.

v1.2 (23/09/2024)

Added support for AimmsCmd, the task output now has three sheets, and the python now reads from the data folder inside the AIMMS Project.

v1.1 (19/09/2024)

Performance of the route generation procedure was updated. Now you are able to solve using a Python call.

v1.0 (15/08/2024)

First version of this application.