### Solving MINLP problems with AIMMS Outer Approximation

For solving Mixed Integer Nonlinear Programming (MINLP) problems AIMMS offers, besides the solvers BARON and KNITRO, the AIMMS Outer Approximation algorithm, or AOA for short.

There exist two versions of the AOA algorithm in AIMMS. The old version is available as a solver which calls the module OuterApproximation and was developed before GMP functionality was added to AIMMS. The new version uses GMP functions and has been implemented in the module GMPOuterApproximation. You can install this system module via Menu > Settings > Install System Module and select the *GMP Outer Approximation Module* to be installed. GMP-AOA is not a solver and cannot be called using the normal ‘solve’ statement. Instead you should use:

! First we must generate the GMP for our MathProgram. myGMP := GMP::Instance::Generate( myMP ) ; ! The GMP is passed as argument to the main procedure of GMP-AOA. GMPOuterApprox::DoOuterApproximation( myGMP );

An example can be found in this ZIP file.

There are several reasons why you should use GMP-AOA instead of old AOA. First, the GMP-AOA algorithm offers more possibilities to customize the algorithm to your needs, for example by using functions from the GMP library.

Second, the GMP version can be used in combination with the nonlinear presolver which may reduce the size of the model and tighten the variable bounds which likely help the AOA algorithm to find a better solution or improve its performance. From AIMMS 3.12 onwards GMP-AOA by default starts by calling the nonlinear presolver.

Third, for non-convex problems AOA might sometimes have difficulties in finding a good feasible solution. In that case it might help to combine the AOA with the multi-start algorithm. The way to do this has been explained in a white paper that describes GMP-AOA. This paper is available from our web site:

Old AOA cannot be combined with the nonlinear presolver nor the multi-start algorithm.

**Note**: In the special case that the MINLP problem contains only convex quadratic and/or second-order cone constraints also linear solvers like CPLEX or GUROBI can be used.

### Deploying a project with AIMMS as a self-contained solution

When you are finished with creating your project and want to deploy it in such a way that it requires as little steps from the end-user as possible, you can make use of our installation free version of AIMMS. One of the features in these installation free versions is that it will check if there exists a folder StartupProject in the same folder as the installation free executable. If this folder exists, AIMMS will automatically start the first project (.prj file) that it finds in this directory.

So you can deploy a self-contained solution (i.e. the required AIMMS executable and your project) to your end-users by just creating a ZIP file containing the executable and your project in the subfolder StartupProject. Please note that the name of the installation free executable of AIMMS can be changed freely.

See the two pictures below for an example I created with the Gate Assignment project that is in the AIMMS index of all examples.

In the picture above you can see that an installation free executable of AIMMS was renamed to Gate Assignment Solver.exe. When the user double clicks on this executable, this installation free version of AIMMS will start the first .prj file it can find the StartupProject folder. In the picture below, you can see that this is Gate Assignment.prj.

**Note: **Deploying this way does not automatically install a license. The first time a user starts the project, he/she will be asked to provide license information. If you will be deploying your application in combination with an AIMMS network license, you could skip this step by creating a configuration folder besides the StartupProject folder and use the –config-dir commandline option of AIMMS. For more information about this option, see the section “Calling AIMMS” in the AIMMS User’s guide.

### Display Multiple Identifiers in a 2D Chart

A 2D Chart not only makes it possible to display your AIMMS data in various two-dimensional chart types, such as a plot chart, a bar chart, a pie chart, etc, it also allows displaying multiple identifiers with different measurements and different chart types in the same chart, like the following.

In this charts, “Existing Resources” and “Capacity Deficit” are in MW and displayed as stacking bars; “Demand Growth” and “New Resources Growth” are in percentage and displayed as plot curves. In order to set this chart up, you only need to specify the Y-Axis and Y2-Axis properties in the 2D chart properties dialog as shown below.

The appearance of each identifier, for example, colors, width, labels, etc. can be modified to the desired look in the properties dialog. For the details, you may check the attached 2D Chart example.

### Selecting variables and constraints for a Math Program

One of the features of AIMMS is that you can have multiple mathematical programs in one project, each having its own set of variables and constraints.When you solve a mathematical program (or generate it via the GMP functions), AIMMS will use the values of the Constraints and Variables attributes of the mathematical program identifier to determine which symbolic variables and constraints should actually be considered in the model. In these Constraints and Variables attributes of the math program identifier, you must provide a subset of the predefined sets AllConstraints and AllVariables, respectively. Each of these sets must contain exactly those symbolic constraints/variables which should be considered when generating the model. If you do not provide any values (or leave the default as is), AIMMS by default will use AllConstraints and AllVariables. This means that all constraints and variables in your project will be considered.

You can create your own sets for constraints and variables to be considered by introducing two new set identifiers in AIMMS, e.g. ModelVariables and ModelConstraints. You then make ModelVariables a subset of the predefined set AllVariables and make ModelConstraints a subset of the predefined set AllConstraints. After that, in your math program identifier you should use these two new sets for the Variables and Constraints attributes. Finally, you can now set data for these two new sets, either by filling them in a procedure with data, or using the definition attribute of the set in to select which variables/constraints should be part of the subset.

Different approaches/methods can be used to fill these subsets of variables/constraints (automatically) with elements. I will show different examples for this in future blog articles.

**Be careful with variables that have a definition**. Please keep in mind that for each variable with a definition in your model, AIMMS will actually generate both the variable and additional equality constraint. For example, if you have the variable [latex]X[/latex] that has [latex]Y + Z[/latex] in its definition attribute, AIMMS will actually generate two things:

- Variable
**X** - Equality constraint
**X_definition**defined as [latex]X = Y + Z[/latex]

If you use the above mentioned approach of selecting certain variables and constraints for a mathematical program identifier in AIMMS, you must ensure that all the defined variables are also in the set of selected constraints. Otherwise, AIMMS would only consider the variable and not its corresponding equality constraint.

### Using block statement to temporary use other project settings

Sometimes it is useful to run one or more statements in AIMMS with a different value for one of the AIMMS project settings. As displayed in the figure on the right, statement 2 should be executed while one or more project settings temporary have a different value.An example of this is the code in the article Inspecting SQL statements created by AIMMS, where you want to run certain statements with the database tracing options set to a specific value. One possibility is to manually store the option value before the statement(s), then modify the option and run the statement(s), after which you restore the original value.

This approach can also be done easier in AIMMS by using the block statement. The code in the other blog article can be rewritten to:

```
!Only trace SQL statements, and not the data itself
!And store the tracing information to the given file
block where
database_trace_level := 1,
database_trace_file := "TraceReadLocationTable.txt" ;
!Statements within this block are executed with the above project settings
read from table LocationTable;
endblock ;
!The two options will now have the same value they had before
!block statement
!Trace both SQL statements and data transferred
!And store the tracing information to the given file
block where
database_trace_level := 2,
database_trace_file := "TraceReadDepotTable.txt" ;
!Statements within this block are executed with the above project settings
read from table DepotTable;
endblock ;
```

When using this block statement, AIMMS will take care of storing the value of the setting before the execution of the statements within the block and also restoring this original value after the execution of the statements in the block is finished.

### Check if given variable values satisfy all constraints

Sometimes you might want to check whether a given combination of value assignments for the variables in your model actually satisfy all the constraints. One possibility is to add an assignment constraint for each of your variables that fixes the variable to the given value and then solve the model again. If the solver returns with the status infeasible, you know that these variables values do not satisfy all constraints and otherwise the values of the variables are a feasible solution for your model.

Another approach to figure out whether the given values for the variables are a feasible solution that requires no modifications to your actual model, is to make use of the GMP function GMP::Solution::Check.

Suppose we have the following simple model:

[latex]\mathrm{min\ }x[/latex]

s.t.

[latex]x + y \ge 5[/latex]

[latex]x,y \ge 0[/latex]

and we want to check whether the assignment [latex]x=1\ ,\ y=1[/latex] is actually a feasible solution. We must first add identifiers for the required variables (x,y,obj) and constraint to an AIMMS project. After that, you add a math program identifier that links these variables and constraints. Finally, we can then use the following code to actually check whether the assignment [latex]x=1\ ,\ y=1[/latex] is a feasible solution:

```
!We want to check if x=1, y=1 is a feasible solution for our MathProgram
!First we must generate the GMP for our MathProgram
generatedMP := GMP::Instance::Generate(
MP : MathProgram ) ;
!Then we must assign the values we want to check to the variables
x := 1 ;
y := 1 ;
!Now retrieve the values from the variables in the model to
!solution number 1 of this generated math program.
GMP::Solution::RetrieveFromModel(
GMP : generatedMP ,
solution : 1 ) ;
!We can now use the GMP::Solution::Check to check solution
!number 1.
GMP::Solution::Check(
GMP : generatedMP , !The Math program we want to use
solution : 1 , !The solution number we want to check
numInfeas : numberOfInfeasibilities , !store # of infeasibilities
sumInfeas : sumOfInfeasibilities , !store sum infeasibilities
skipObj : 1 ) ; !Objective can be skipped
!Now we can check the number of infeasibilities. If there are no
!infeasibilities, it means the variables values satisfy all constraints
if numberOfInfeasibilities then
message := "Variable values do not satisfy all constraints:\n" ;
message += "Number of infeasibilities = " + numberOfInfeasibilities + "\n" ;
message += "Sum of infeasibilities = " + sumOfInfeasibilities ;
dialogMessage( message ) ;
else
dialogMessage("Variable values are feasible for all constraints") ;
endif ;
```

After running the above code, you will get the message that assignment [latex]x=1\ ,\ y=1[/latex] does not satisfy all the constraints.

You can download the above example code in a complete AIMMS project. Please note that this file can only be opened in AIMMS versions 3.11 and newer.

### Operations Research Memes

To bring awareness of OR to the masses and get people to wonder what OR is, Tallys Yunes (O.R. by the beach) created some nice Operations Research related memes. One example of a meme he created is the following

Some other OR bloggers have created a couple of other memes already also. Tallys keeps a complete overview of what has been created in the “Operations Research Memes” article on his OR by the beach blog.

**Update**: Could not resist to create one myself also. Created it based on something I heard often from the students during my PhD years, namely that they were always talking about a solution that was even more optimal than the other solution.

### Emptying sets

To remove all the elements from a set, you can use the empty statement in AIMMS. However, it is important to keep in mind that this empty statement might not have the desired effect in case the set you want to empty is a subset of the predefined set AllIdentifiers.

The behavior of the empty statement depends on the set that you provide as an argument:

- The set is not a subset of AllIdentifiers. In this case the empty statement will remove all elements from the given set.
- The set is a subset of AllIdentifiers. In this case the empty statement will empty all the identifiers that are in the given subset.

To demonstrate the difference, I will give a small example, for which we need the following two identifiers:

```
SET:
identifier : NormalSet
SET:
identifier : ActiveVariables
subset of : AllVariables
```

As you can see, it holds that:

ActiveVariables [latex]\subseteq[/latex] AllVariables [latex]\subseteq[/latex] AllIdentifiers

because the predefined set AllVariables is defined in AIMMS to be a subset of AllVariablesConstraints, which in turn is subset of AllIdentifiers again. You can verify this by opening the attribute window of these predefined sets.

This means that the empty statement will have different behavior when used on NormalSet and on ActiveVariables:

```
!This will remove all elements from the set NormalSet
empty NormalSet ;
!This will clear the values of all variables in the subset ActiveVariables
!After the empty statement, the set itself will still contain elements!
empty ActiveVariables ;
!This will actually remove all elements from the set ActiveVariables
ActiveVariables := {} ;
```

### Inspecting SQL statements created by AIMMS

When you are reading/writing data from/to a database with AIMMS via database table identifiers, internally AIMMS will communicate with the database via SQL statements.

If you have a situation where you expect data to be present in AIMMS after a database read, but it is not, you have the option to instruct AIMMS to output the actual SQL statements that are executed to communicate with the database.

By default, AIMMS will not log this information. You can modify this behavior by changing the two project settings

**Database trace file**: indicates to which file the information should be logged,**Database trace level**: indicates how much information should be logged:- 0 – No tracing
- 1 – Only trace the SQL statements without the data
- 2 – Trace the SQL statements including the data

You can set these project options via the Project Options in the settings menu, or within the AIMMS Code. For example, the code below will switch on statement-only tracing for the first read statement and statement-and-data tracing for the second read statement. Finally, the tracing is switched off again for subsequent database communication.

```
!Only trace SQL statements, and not the data itself
OptionSetValue("Database trace level", 1) ;
!And store the tracing information to this file
option database_trace_file := "TraceReadLocationTable.txt";
read from table LocationTable;
!Trace both SQL statements and data transferred
OptionSetValue("Database trace level", 2) ;
!And store the tracing information to this file
option database_trace_file := "TraceReadDepotTable.txt";
read from table DepotTable;
!Switch off the tracing again for subsequent communication
OptionSetValue("Database trace level", 0) ;
```

The above code will create a separate trace file for both read statements. The contents of the TraceReadLocationTable.txt file will be the following:

Starting transaction on datasource "AIMMS Transport Example Database.udl" Creating SELECT command for AIMMS READ statement: SELECT `Location`, `XCoord`, `YCoord` FROM `Locations` Start executing READ statement Reading data with SELECT statement End executing READ statement (75 row(s) read) Committing transaction on datasource "AIMMS Transport Example Database.udl"

While the contents of the TraceReadDepotTable.txt file will be the following:

Starting transaction on datasource "AIMMS Transport Example Database.udl" Creating SELECT command for AIMMS READ statement: SELECT `Depot`, `Supply` FROM `Depots` Start executing READ statement Reading data with SELECT statement Column 1; Type: WString; Value: "Eindhoven" Column 2; Type: Double; Value: 14500.000000 Column 1; Type: WString; Value: "Haarlem" Column 2; Type: Double; Value: 10800.000000 Column 1; Type: WString; Value: "Heerenveen" Column 2; Type: Double; Value: 14300.000000 Column 1; Type: WString; Value: "Middelburg" Column 2; Type: Double; Value: 12400.000000 Column 1; Type: WString; Value: "Zutphen" Column 2; Type: Double; Value: 13000.000000 End executing READ statement (5 row(s) read) Committing transaction on datasource "AIMMS Transport Example Database.udl"

When using these tracing options, please keep in mind that especially tracing with all data (i.e. database trace level = 2) can result in very large trace files.

### Various (integer) linear modeling tricks

Modeling problems with an (integer) linear program sometimes requires some experience to recognize certain structures in the problem description that can be formulated in a linear way.

On the website of the Naval Postgraduate School, you can find the document Formulating Integer Linear Programs: A Rogues’ Gallery that tries to demystify the art of formulating linear and integer linear programs. They do this by introducing *formulettes*, which consist of a verbal description and the constraints and variables that model this verbal description.

The first simple example of a formulette they provide is the following:

For each unit of [latex]X_1[/latex], there must be at least 5 units of [latex]X_2[/latex]

which can be modeled with

[latex]5X_1 le X_2[/latex].

The document contains a lot more of such formulettes of varying complexity.

Furthermore, in our book Optimization Modeling you can also find various modeling tricks in the chapters “Linear Programming Tricks” and “Integer Programming Tricks”. The Optimization Modeling book can either be found online via the link above, or you can find it under the Help menu after you started AIMMS.