# Prepare for the Deprecation of Compound Sets¶

Note

We are actively updating this topic during the deprecation stages. Your feedback is welcome and appreciated, as it may help others facing the same issue.

## Summary¶

AIMMS will deprecate compound sets soon after January 1, 2020.

The functionality of compound sets can be achieved with a set mapping.

This document provides a process to replace the compound sets with a set mapping.

For an overview of the rationale and timeline for deprecating compound sets, read AIMMS Knowledge: Overview: Deprecation of Compound Sets

## Identifying compound sets in your application¶

A compound set is defined as one of these:

• It is a subset of a Cartesian product with an index or element parameter declared in its attribute form.
• It is a subset of another compound set.

We provide a library with tools to identify compound sets based on these characteristics.

To identify compound sets in your application,

1. Download the attached AIMMS project download and run it using AIMMS 4.54 or more recent.

2. Copy the DeprecateCompoundSetUtilities library to your AIMMS project.

3. Run the procedure dcsu::prIdentifyCompoundSets. This tests for compound sets, according to the following rules:

• A set whose string in the subset of attribute has a comma, and has defined the attribute index or the attribute parameter. (These are compound root sets.)
• A set with a compound set as its domain set. (These are not compound root sets.)
4. The procedure fills the sets dcsu::sCompoundRootSets, dcsu::sCompoundSets, and dcsu::sCompoundSetsThatAreNotRootSets. Using these results, you may continue to the conversion procedure below.

## Replacing compound sets with set mapping¶

This conversion procedure explains how to convert compound sets to set mappings in your application. This ensures that your model will function in the same way but without compound sets.

Note

The conversion procedure contains a multitude of steps, and you may wonder whether this is necessary?

To determine the scope that this conversion procedure needs to handle, note that compound data is present in AIMMS Cases and compound data identifiers are present in both WinUI and WebUI pages of that AIMMS application. AIMMS cases cannot be edited manually. The format of both WinUI and WebUI pages are designed for fast serialization instead of for human editing. Obviously, this conversion procedure should not overlook the need to adapt the model itself.

The multitude of steps are too gradually transform the information in cases, pages, and model.

Overview of the conversion procedure

Step 1: Create backups of your application and cases.

Step 2: Add DeprecateCompoundSetUtilities library to your application.

Step 3: Create Set Mapping with data of compound sets.

Step 4: Create Set Mapping declarations and copy them to your main model.

Step 5: Create a shadow case for each case with shadow data for the compound data identifiers.

Step 6: Adapt the model to remove compound sets.

Step 7 Move compound indexes to the corresponding set mapping sets.

Step 8: Copy each shadow case back to its corresponding original case.

Step 9: Remove DeprecateCompoundSetUtilities library from your application.

### Step 1: Create backups of your data¶

The importance of creating backups before starting maintenance on your projects cannot be overemphasized.

1. Simply create a physical copy of the project and cases and store this in a safe place.
2. Consider putting the project in a Source Code Management system, if you haven’t done so already.

### Step 2: Add library DeprecateCompoundSetUtilities¶

The AIMMS project download provides an example app and utility library DeprecateCompoundSetUtilities.

Copy the library from that example and add it to your application.

### Step 3: Create Set Mapping¶

There are two things to watch out for:

1. The definition of a compound set should be suitable for a relation as well.

Use the data from compound sets in your project to create corresponding relations. The definition (if any) of a compound set must be suitable for a relation as well.

Consider the following example:

Set C {
SubsetOf: (S, T, U);
Tags: (TS, TT, TU);
Index: h ;
Definition: {
{ (i,j,k) | pAllowedElementsC(i,j,k) = 1 }
}
}
Set D {
SubsetOf: C;
Index: g ;
definition: {
{ h | pAllowedElementsD(h.TS, h.TT, h.TU) = 1 }
}
}


In the example above, the definition of C can also be used for a relation, $$R$$, that is a subset of the Cartesian product $$S \times T \times U$$. The definition of D cannot be used for a relation, so it must be rewritten:

Set D {
SubsetOf: C;
Index: g ;
definition: {
{ (i,j,k) | pAllowedElementsC(i,j,k) = 1 and pAllowedElementsD(i, j, k) = 1 }
}
}


The new definition of D is now based on tuples instead of individual elements and can be used for a relation.

2. The predeclared set Integers cannot be used as a component in the domain of a compound set for conversion.

As an example consider the set

Set E {
SubsetOf: (S, Integers);
Tags: (TS, Int);
Index:  i_e ;
}


The language construct ie.Int will be converted to the use of an element parameter. To fill this element parameter with the appropriate contents, a slicing is formulated and this slicing involves an index of each component. For instance as follows:

ElementParameter epTag_E_int {
IndexDomain: iSMI_E;
Range: Integers;
Definition: first( IndexIntegers | exists( i | ( i, IndexIntegers, iSMI_E ) in sSetMappingRelation_E ) );
}


When the set Integers is used as a component, then IndexIntegers is an index that varies over 2G elements. An attempt to do so would trigger the error message The set Integers is too big to be used as the range of running index "IndexIntegers".

Therefore we should introduce a new set, say s_SomeIntegers and fill it using the integer elements actually used. Then we should replace the component Integers in the compound set, for instance as follows:

Set E {
SubsetOf: (S, s_SomeIntegers);
Tags: (TS, Int);
Index:  i_e ;
}


The set s_SomeIntegers should not be declared to be a subset of the set Integers. Once the compound set conversion is complete, we can make s_SomeIntegers a subset of the set Integers.

### Step 4: Create Set Mapping declarations¶

Now let’s create a set mapping for each compound set in your model. Group set mappings according to namespace (main model, library or module).

Open the WinUI page: Deprecate Compound Set Control Page of the library DeprecateCompoundSetUtilities, and press the button Create Set Mapping Declarations. A section named set mapping declarations appears in the main model.

Sections named <prefix> set mapping declarations appear in each library/module where compound sets are defined. These sections are created in the runtime library CompoundSetMappingRuntimeLibrary as runtime libraries are the only place where a library or main model may create new AIMMS code.

The model explorer should now look something like this:

Perform the following sequence for each set mapping declarations section.

1. Go to Edit > Export to save a file (e.g., smd.ams).
2. Select focus on the main model, library or module and create a section named Set Mapping Declarations.
3. Select that newly created section and go to Edit > Import to select the file you saved (e.g., smd.ams).

Caution

Do not Copy/Paste the section Set Mapping Declarations of the runtime library! When you Copy/Paste, the copied section still contains references to the runtime indexes. This causes compilation errors upon restart.

Now is a good time to save the project, exit AIMMS, and create another backup copy of your project.

### Step 5: Create shadow cases¶

Shadow cases are cases where the compound data is replaced by atomic shadow data.

You can convert cases with compound data to shadow cases using a tool in the DeprecateCompoundSetUtilities library.

You can convert multiple cases contained in one folder using the Folder option, or convert each case separately using the File option.

1. Go to Deprecate Compound Set Control Page of the DeprecateCompoundSetUtilities library.

2. In the section labeled Forward - creating shadow cases:

1. Specify the input file/folder (to pull original cases containing compound data).
2. Specify the output file/folder (to push converted cases containing atomic data).
3. Then click the Copy button to convert.

### Step 6: Adapt model to remove compound sets¶

This section shows how to convert models using compound sets to use the set mappings created in step 3 above.

#### Example case¶

In this conversion step we will use a running example that contains:

• One dimensional sets $$S, T, U$$, with indexes respectively $$i, j, k$$.
• A relation $$R$$ that is subset of the Cartesian product $$S \times T \times U$$.
• A compound set $$C$$ with index $$h$$ defined as $$\{ (i, j, k) | (i, j, k) \in R \}$$. The tags of this compound set are $$(TS,TT,TU)$$
• A compound subset $$D \subset C$$ with index $$g$$. Note that $$D$$ inherits its tags from $$C$$.
• A parameter $$P$$ declared over the index for the compound set: $$P_h$$
• A parameter $$P1$$ declared over the index for the compound subset: $$P1_g$$
• A parameter $$Q$$ declared over the indexes for the one dimensional sets: $$Q_{i,j,k}$$
• A parameter $$Q1$$ declared over the index $$i$$: $$Q1_i$$

#### Replace use of tags¶

The following Parameter contains a tag referencing a compound set:

Parameter p1 {
IndexDomain: h;
Definition: A(h.ts);
}


AIMMS displays the error message: The "TS" is not a tag that can be associated with index "h".

You can replace it with a tag referencing a set mapping:

Parameter p1 {
IndexDomain: h;
Definition: A(epTag_C_TS(h));
}


#### Replace atomic indexes with set mapping index¶

Consider the declaration of compound data parameter P:

Parameter P {
IndexDomain: h;
}


Then using P is not allowed in an expression such as:

Parameter PS {
IndexDomain: (i,j,k);
Definition: p(i,j,k);
}


It is not allowed, as the automatic mapping between h and (i,j,k) is no longer supported.

AIMMS displays a compilation error The number of arguments in the parameter "P" is not correct.

You can replace this definition by:

Parameter PS {
IndexDomain: (i,j,k);
Definition: sum(h|(i,j,k,h) in sMappingSet_C_Relation,p(h));
}


#### Replace the function Tuple¶

The function Tuple is a predeclared function to create an element in a compound set from elements in the atomic sets that together form the domain of that compound set.

Consider the function:

epC := Tuple( epS, epT, epU );


Here epS, epT, and epU contain the elements, and Tuple will create a corresponding element in the compound set C, where C is the range of the element parameter epC.

With the deprecation of compound sets, Tuple is no longer supported , and this should be replaced by:

epC := first( iSMI_C | ( epS, epT, epU, iSMI_C ) in sSetMappingRelation_C );


### Step 7: Move compound indexes to set mapping sets¶

To ensure screen definitions are not broken, you must move indexes from the declarations of compound sets to the declaration of the corresponding set mapping set.

To move an index that is declared as part of a set declaration:

1. Delete it using the wizard at the index attribute.
2. Re-create it in the destination set.

### Step 8: Move shadow cases back to original cases¶

You can convert shadow cases created in step 5 back to the original case locations using the same tool in the DeprecateCompoundSetUtilities library.

You can convert multiple cases contained in one folder using the Folder option, or convert each case separately using the File option.

1. Go to Deprecate Compound Set Control Page of the DeprecateCompoundSetUtilities library.

2. In the section labeled Backward - creating cases with original identifiers without compound data:

1. Specify the input file/folder (to pull cases containing converted data).
2. Specify the output file/folder (to push to the original case folder location).
3. Then click the Copy button to convert.

### Step 9: Remove the library DeprecateCompoundSetUtilities¶

Now that you have removed compound sets from your project, you can remove the library DeprecateCompoundSetUtililities.

## Glossary of Terms Used¶

Atomic sets
One-dimensional sets that are not compound sets are called atomic sets. Examples of atomic sets are sets containing names, calendars and subsets of the set Integers. To declare a relation, AIMMS only allows atomic sets in the subset of attribute of that relation.
Atomic index
An atomic index is an index in an atomic set. A compound index is an index in a compound set.
Set mapping

A set mapping is a collection of identifiers that together provide an alternative for the functionality of a single compound set.

A set mapping consists of:

• A set mapping set is an atomic set with elements that look like elements from a compound set.
• A set mapping index is an index in a set mapping set. Note that a set mapping index is an atomic index.
• A set mapping relation is a relation that contains the same set of tuples as a compound set.
• A set mapping parameter is an element parameter that contains the data to handle the “tags” functionality of a compound set.
Compound data
A compound data identifier is a parameter, variable, or constraint with at least one compound index in its index domain. Thus, compound data is the data of a compound data identifier.
Screen definition
A screen definition is a serialized representation of a screen. The point and click types of UI provided by AIMMS, both WinUI and WebUI, store these screen definitions as text files within an AIMMS project.
Consider a parameter A, then a shadow parameter, say A_Shadow`, is a parameter with the same element values.