Contract Allocation

https://img.shields.io/badge/AIMMS_4.85-ZIP:_Contract_Alocation-blue https://img.shields.io/badge/AIMMS_4.85-Github:_Contract_Alocation-blue https://img.shields.io/badge/AIMMS_Community-Forum-yellow

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 we used 10 northwestern states for the contracts and 5 cities from that region for the producers. To import the data into our model, we are currently using DEX library through Excel (NothWesternStates.xlsx). You can add more data freely without changing the sheets structure.

Procedure pr_importExcelData

This procedure will add and read the xml mapping available. Take a look at Mappings/inputs.xml.

 1dex::AddMapping(
 2   mappingName :  "inputs",
 3   mappingFile :  "Mappings/inputs.xml");
 4
 5dex::ReadFromFile(
 6   dataFile         :  "NothWesternStates.xlsx",
 7   mappingName      :  "inputs",
 8   emptyIdentifiers :  1,
 9   emptySets        :  1,
10   resetCounters    :  1);
11
12ep_actualContract := first(i_contract);
13ep_actualProducer := first(i_producer);

We also use create a page action and a dialog for users to export the results to several different DEX supported formats (Excel, JSON, CSV, etc.). You can add more identifiers to be exported by using the DEX annotations.

Procedure pr_openExportPage

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. It will also initialize identifiers used in our dialog and open that dialog page.

 1!Generating all possible mappings
 2dex::GenerateDatasetMappings();
 3
 4!Selecting the Excel mapping as initial value
 5if not ep_selectedMapping then
 6    ep_selectedMapping
 7    :=  First(i_generatedMappings | FindString(
 8            SearchString  :  i_generatedMappings,
 9            Key           :  "excel",
10            CaseSensitive :  0,
11            WordOnly      :  0,
12            IgnoreWhite   :  0));
13endif;
14
15!Defining Dialog and actions - Only done required
16s_actions:= data { Done };
17ep_pageId := 'export_page';
18
19!Opening dialog page - no action on done - webui::NoOp1 does nothing
20webui::OpenDialogPage(
21    pageId  :  ep_pageId,
22    title   :  "Export data",
23    actions :  s_actions,
24    onDone  :  'webui::NoOp1');
Procedure pr_exportExcelData

This procedure will that will write the file and provide it for download using the download widget.

 1! writing the output file locally
 2dex::WriteToFile(
 3    dataFile    :  sp_FileName,
 4    mappingName :  ep_selectedMapping,
 5    pretty      :  1);
 6
 7! we want to download a file
 8FileLocation := sp_FileName;
 9
10! we store the location of the file in string parameter FinalLocation
11FinalLocation := webui::GetIOFilePath(FileLocation);
12
13! checking if the previous write statement was successful or not
14if FileExists(FinalLocation) then
15   ! if successful, statusCode is set to 'CREATED' which will trigger the download widget to show the Get button
16   StatusCode := webui::ReturnStatusCode('CREATED');
17   ! displaying the status message as Ready to download exported data! instead of the default "File ready to download"
18   StatusDescription := "Ready to download exported data!";
19else    !if previous write statement was not successful
20   ! setting the statusCode to 'ERROR' and the download widget will not show the Get button anymore
21   statusCode := webui::ReturnStatusCode('ERROR');
22   !displaying a custom error message
23   statusDescription := "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 (stacked bar chart).

The following WebUI features are used:

UI Styling

For this project, we used a main css file named colors.css, please check it out directly on the folder. Below there are the css files you will find with comments on what they change.

1:root {
2   --bg_app-logo: 15px 50% / 30px 30px no-repeat url(/app-resources/resources/images/budgeting.png);
3   --spacing_app-logo_width: 45px;
4}
 1/*Change color of the active step*/
 2.workflow-panel .step-item.current {
 3   box-shadow: inset 0.3125rem 0 0 var(--primary);
 4}
 5
 6/*Change color of the titles*/
 7.workflow-panel .step-item.active.complete .title,
 8.workflow-panel .step-item.active.incomplete .title {
 9   color: var(--primaryDark);
10}
11
12/*Change color of the icons*/
13.workflow-panel .step-item.active.complete .icon,
14.workflow-panel .step-item.active.incomplete .icon {
15   color: var(--primaryDark);
16   border: 1px solid var(--primaryDark);
17}
 1/*Change table text color*/
 2.tag-table .grid-viewport .cell:not(.flag-readOnly),
 3html:not(.using-touch) .tag-table .grid-viewport .cell:not(.flag-readOnly) {
 4   color: var(--primaryDark);
 5}
 6
 7/*Change scalar text color*/
 8.tag-scalar .kpi .value {
 9   color: var(--primaryDark);
10}
11
12/*Link color*/
13.ql-snow a {
14   color: var(--primaryDark);
15}
16
17/*Change table default text color*/
18.tag-table .grid-viewport .cell.flag-default,
19html:not(.using-touch) .tag-table .grid-viewport .cell.flag-default {
20   color: white;
21}
1/*Add image on the background*/
2.scroll-wrapper--pagev2 .page-container {
3   content: " ";
4   background: url(img/RightBackground.png) rgb(249, 249, 249) no-repeat left/contain;
5}
1.theme-aimms header.tag-application {
2   border-bottom: 2px solid var(--primary);
3}
1/*Change color of togglelegend of the combination chart*/
2.togglelegend-button svg{
3   fill: var(--primaryDark);
4}
5
6.togglelegend-button-active:hover svg g, .togglelegend-button-active svg g {
7   fill: var(--primary);
8}
 1/*Change color after tab click*/
 2.sidepanel-container .sidepanel-tab.active {
 3   background-color: var(--primary);
 4}
 5
 6/*Change letter color on hover*/
 7.sidepanel-container .sidepanel-tab.active:hover {
 8   color: white;
 9}
10
11/*Change icon color*/
12.sidepanel-container .sidepanel-tab .sidepanel-icon,
13.sidepanel-container .sidepanel-tab:hover {
14   color: var(--primary);
15}
16
17/*Change color after all tabs*/
18.sidepanel-container .sidepanel-tabs-container:after {
19   background: var(--primary);
20}
21
22/*Change the color below sidepanel tabs*/
23.sidepanel-container {
24   background-color: rgba(249, 249, 249, 0.438)
25}
1/*Change color of the busy button*/
2.veil-msg.state-busy .ui-button {
3   background-color: var(--primary);
4}
 1.page-action-v2 .page-action-menu,
 2.page-action-v2 .page-action-menu.open {
 3   background: var(--primaryDark);
 4}
 5
 6.page-action-v2 .page-action-menu:hover,
 7.page-action-v2 .page-action-menu:hover {
 8   background: var(--primary);
 9}
10
11.page-action-v2 .page-action-holder .page-action-item .page-action-icon,
12.page-action-v2 .page-action-holder .page-action-item .page-action-letter {
13   background-color: var(--primaryDark);
14}
15
16.page-action-v2 .page-action-holder .page-action-item .page-action-icon:hover,
17.page-action-v2 .page-action-holder .page-action-item .page-action-letter:hover {
18   background-color: var(--primary);
19}
1.tag-table.focused .focus-cell {
2   box-shadow: inset 0 0 0 1px var(--primaryDark);
3}

Minimal Requirements

AIMMS Community license is sufficient for working with this example.