Contract Allocation

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

Story

In this model we have a set of contracts, where every contract represents an amount of commodity that has to be supplied. The objective is to determine which of the producers will take care of which contract such that the total costs are minimal, under the following conditions:

  • The demand for every contract is met.

  • The amount supplied by each producer does not exceed the total amount available for supply.

  • If a producer supplies a part of a contract then this contribution has a given minimal size.

  • There is a minimal number of suppliers for every contract.

  • The total cost associated with all the deliveries is minimal.

Mathematical Model

This AIMMS project illustrates the use of a semi-continuous variable. A semi-continuous variable is either zero or within a certain range. This type of variables can be used in conditions like, whenever there is a transport this transport has a minimum size.

Contract Allocation Problem

Sets and indices:

\(P\), \(p \in P\)

Producers

\(C\), \(c \in C\)

Contracts

Parameters:

\(M_{p} \in \mathbb{R_{+}}\)

minimal delivery

\(A_{p} \in \mathbb{R_{+}}\)

available capacity

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

contract size

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

minimal number of contributors

\(T_{p,c} \in \mathbb{R_{+}}\)

delivery cost by p for c

Variables:

\(X_{p,c} \in \{0\} \cup \{M_{p}..10000\}\)

amount of commodity delivered by p to c

\(Y_{p,c} \in \{0..1\}\)

p produce to c

Constraints:

1

\(\forall p: \sum_c X_{p,c} \leq A_{p}\)

production capacity for p

2

\(\forall c: \sum_p X_{p,c} \geq S_{c}\)

demand fulfillment for c

3

\(\forall c: \sum_p X_{p,c} \geq N_{c}\)

minimal number of contributors to c

4

\(\forall p, c: X_{p,c} \geq M_{p} * Y_{p,c}\)

if p delivers to c

Minimize:

\(\sum_{p,c} T_{p,c} * X_{p,c}\)

The number of matches

Language

In this example, there are two main ways to import data: by a custom Excel file, and by a pre-defined Excel which is currently on the project’s main directory. You can choose which one to use on any page trough the Page Action buttons.

For the default data import, you will be importing 10 northwestern states for the contracts and 5 cities from that region for the producers. You can add more data freely without changing the sheets structure.

In this project, you will not find any Upload or Download Widget being used to integrate data, every integration, either import or export, was developed using the webui::RequestFileUpload and webui::RequestFileDownload. Let’s first understand the custom import procedure.

Procedure pr_requestCustomExcel

Since we want to request the file upload via a Page Action, we need a procedure without any arguments, so this procedure will simply call webui::RequestFileUpload passing the procedure with the read functions.

1webui::RequestFileUpload(onDone :  'pr_uploadFile');
Procedure pr_uploadFile(fname, StatusCode, StatusDescription)

Here we add the DEX mapping and read from the file the end-user selected.

 1block ! import a custom Excel file
 2   ! we store the location of the file in string parameter UploadLocation
 3   UploadLocation := webui::GetIOFilePath(fname);
 4
 5   dex::AddMapping("inputs", "Mappings/inputs.xml");
 6
 7   if dex::ReadFromFile(
 8      dataFile         :  UploadLocation,
 9      mappingName      :  "inputs",
10      emptyIdentifiers :  1,
11      emptySets        :  1,
12      resetCounters    :  1)
13   then
14
15      ! displaying the status message, and logging it in the WebUI messages
16      sp_loc_message := "File was uploaded and read successfully";
17      webui::ShowMessage('info', sp_loc_message);
18
19   endif;
20
21onerror ep_err do
22
23   !displaying a custom error message
24   sp_loc_message := "Error when reading file " + errh::Message( ep_err );
25   webui::ShowMessage('error', sp_loc_message);
26
27   errh::MarkAsHandled(ep_err) ;
28
29endblock;

For exporting the results Excel, we do something similar:

Procedure pr_requestResults

This procedure will generate all the possible mappings in DEX based on current identifier DEX annotations. Details on how to setup annotations can be found here. We will then make a copy of an empty Excel file to write our information. Then, using webui::RequestFileDownload to export.

 1dex::GenerateDatasetMappings();
 2
 3sp_loc_fileName := "Results.xlsx";
 4
 5FileCopy("empty.xlsx", sp_loc_fileName);
 6
 7! writing the output file locally
 8dex::WriteToFile(
 9   dataFile    :  sp_loc_fileName,
10   mappingName :  ep_def_selectedMapping,
11   pretty      :  1);
12
13sp_loc_IOPath := webui::GetIOFilePath(sp_loc_fileName);
14
15! this is required so it works on the cloud
16FileCopy(sp_loc_fileName, sp_loc_IOPath);
17
18if FileExists(sp_loc_IOPath) then
19   webui::RequestFileDownload(sp_loc_IOPath);
20   webui::ShowMessage('info',"Export complete.");
21
22else
23   webui::ShowMessage('error',"Something went wrong when creating the file.");
24endif;

See also

To understand in depth check out DEX documentation.

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 widget.

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/*---------------------------------------------------------------------
 3      COLORS
 4----------------------------------------------------------------------*/
 5--primary: #3DDAB4;
 6--primaryDark: #00B569;
 7--primary90Transparent: #3ddab33b;
 8
 9
10--bg_app-logo: 15px 50% / 30px 30px no-repeat url(/app-resources/resources/images/budgeting.png); /*app logo*/
11--spacing_app-logo_width: 45px;
12--color_border_app-header-divider: var(--primaryDark); /*line color after header*/
13--color_bg_app-canvas: url(/app-resources/resources/images/RightBackground.png) rgb(249, 249, 249) no-repeat left/contain; /*background color*/
14--border_widget-header: 1px solid var(--primaryDark); /*line color after widget header*/
15
16--color_bg_button_primary: var(--primaryDark);
17--color_bg_button_primary_hover: var(--primary);
18--color_text_edit-select-link: var(--primaryDark);
19--color_text_edit-select-link_hover:  var(--primary);
20
21/*---------------------------------------------------------------------
22      WORKFLOW
23----------------------------------------------------------------------*/
24/* Header text*/
25--color_workflow-header: #505767;
26
27/* Step background and content (text, icon) colors for the 4 states*/
28/*current + current with error*/
29--color_bg_workflow_current: var(--primaryDark);
30--color_workflow_current: var(--color_text_inverted);
31--color_bg_workflow_error-current: #d1454b;
32
33/*active*/
34--color_bg_workflow_active: #e6edff;
35--color_workflow_active: var(--primaryDark);
36
37/*inactive*/
38--color_bg_workflow_inactive: #dde0e8;
39--color_workflow_inactive: #b0b5c2;
40
41/*error*/
42--color_bg_workflow_error: #f9e9e9;
43--color_workflow_error: #d1454b;
44
45/* Child indentation, border colors */
46--spacing_workflow-child-indent: 1rem;
47--color_workflow-item-divider: var(--primaryDark);
48
49/* Icon background, border, for non-error state */
50--color_bg_workflow-icon: #ffffff;
51--color_workflow-icon-border: var(--primaryDark);
52}
 1.annotation-bkg-cell {
 2   background: var(--primary90Transparent);
 3}
 4
 5.annotation-bkg-cell-default {
 6   background: var(--primary90Transparent);
 7}
 8
 9.annotation-bkg-cell-default input{
10   color: transparent;
11}
12
13.annotation-reach-maximum {
14   background: rgba(255, 0, 0, 0.438);
15}
16
17.annotation-reach-minimum {
18   background: rgba(255, 255, 0, 0.438);
19}
20
21.annotation-between {
22   background: rgba(0, 128, 0, 0.438);
23}
 1/*Change table default text color*/
 2.tag-table .grid-viewport .cell.flag-default,
 3html:not(.using-touch) .tag-table .grid-viewport .cell.flag-default {
 4   color: white;
 5}
 6
 7/*Centering cells*/
 8.tag-table .cell.flag-string .cell-wrapper,
 9.tag-table .cell.flag-number input,
10.tag-table .cell.flag-string input{
11   text-align: center;
12}

Minimal Requirements

AIMMS Community license is sufficient for working with this example.

Release Notes

v1.6 (24/09/2024)

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

v1.5 (20/09/2024)

Upgrading AIMMS version and WebUI library version.

v1.4 (27/02/2024)

Upgrading AIMMS version, updating theme and fixing Default Data import.

v1.3 (09/08/2023)

Correcting download procedure, adding new options when importing data.

v1.2 (15/06/2023)

Updated to 4.95 and added dependent styling using annotation on Results page.

v1.1 (15/05/2023)

Updated to 4.94 and improved Input page for better UX flow.

v1.0 (17/03/2023)

First logged version with the new workflow structure and colors.