Solve in a Loop

https://img.shields.io/badge/Zip-white?style=for-the-badge&logo=github&labelColor=000081&color=1847c9 https://img.shields.io/badge/Repository-white?style=for-the-badge&logo=github&labelColor=000081&color=1847c9 https://img.shields.io/badge/AIMMS-26.4-white?style=for-the-badge&labelColor=009B00&color=00D400 https://img.shields.io/badge/AimmsXLLibrary-26.1.1.1-white?style=for-the-badge&labelColor=009B00&color=00D400

This article provides an example of how to solve several instances of a problem at once, using a loop.

If the input data is being loaded from an external source (like an Excel file), you should iterate through each external source, read in the data, solve the math program and store the output. The input data can also be loaded from an AIMMS case file or AIMMS identifiers with an index for the iteration.

The structure of execution usually follows this format:

  1. Define the collection of inputs

  2. Process each input in a loop

The example project is linked at the top of this article. The Excel input files come with it, in the project’s data folder, so it runs as soon as you open it.

Logic of the Iterative Operation

The flow of a procedure to solve a math program multiple times is shown below. These operations can be done using any iterative operator like for or while. The loop starts by selecting the first input file from the list of files to be iterated through.

When using a while loop, you must initialize the iterator before the loop block is written. This is not necessary when using a for loop because it uses a set index in AIMMS.

../../_images/flow-logic.png

Fig. 14 Logic of the iterative operation

In the example, we use a for loop:

1for i_fn do !loop operation described in the article
2   sp_Workbook := sp_BatchExcelInputFolder + sp_InputFileNames(i_fn);
3
4   !read the workbook, solve, write the solution back
5   pr_ExecuteSingleRun( sp_Workbook );
6endfor ;

In the example project, go to section Iterative Solve to find the procedure pr_ExecuteBatch. This procedure contains some additional error handling statements to ensure the proper working of this example.

Running the Loop on AIMMS Cloud

pro::DelegateToServer does not delegate a single solve statement. Its unit of delegation is a procedure, and by default that is the procedure the call sits in. That one fact decides how a batch loop behaves on the cloud.

Delegating the Whole Loop

Add the delegation as the first thing pr_ExecuteBatch does:

 1if pro::GetPROEndPoint() then
 2    if pro::DelegateToServer(
 3          waitForCompletion   :  1,
 4          completionCallback  :  'pro::session::LoadResultsCallBack' )
 5    then
 6        return 1;
 7    endif;
 8endif;
 9
10! the rest of pr_ExecuteBatch as it ships: fix the folder, list the
11! workbooks, then loop over them

That procedure then runs twice, and the value pro::DelegateToServer returns is what tells the two runs apart.

On the client, the call on line 2 saves the current state of the application as a case, sends it to the Cloud together with the name of the procedure it sits in, and returns 1. The return 1 on line 6 then ends the client run, so nothing below it executes locally.

On the Cloud, PRO loads that case and calls the same procedure again. This time pro::DelegateToServer returns 0, the if is false, and execution simply falls through into the rest of the procedure: the folder, the list of workbooks, the loop, and every solve inside it.

That is why the call belongs at the top. Everything below it is what the Cloud will run.

The two remaining arguments control what the client does while it waits. Line 3 makes it block until the Cloud has finished, and line 4 names the callback that loads the results back into the client session once it has.

Line 1 is a separate question: whether there is a PRO to delegate to at all. pro::GetPROEndPoint returns the endpoint the session is connected to, so it is empty when the application runs standalone and the loop simply runs where it is. Use this rather than ProjectDeveloperMode, which reports whether AIMMS is in developer mode and says nothing about PRO: an end user running a standalone application is not in developer mode either, and would take the delegation branch with no Cloud to delegate to.

The Cloud walks the loop itself: one workbook after another, each solve after the previous one has finished, all inside a single job. This is the answer to “solve consecutively on the cloud”.

An AIMMS PRO solver session can handle 0, 1 or more solve statements. There is no rule that a session corresponds to a solve, which is exactly why a whole loop fits comfortably inside one.

Note

The example project does not include the AIMMS PRO library, so the block above is what you add in a project that does. Note also why the input folder is fixed to data inside the project rather than chosen from disk: a delegated session receives the project, and therefore the workbooks, while a folder picked on your own machine does not exist on the Cloud.

Submitting Each Solve as Its Own Job

The other shape is to delegate from inside pr_ExecuteSingleRun, so each workbook is submitted separately. The requests are then queued independently, and the Cloud starts each one as the resources it needs become free.

That is a reasonable thing to want, and it is not as simple as moving the call. Someone has to decide when all the sub jobs are done, collect what each produced, and report back to the client. Those intricacies are worked through in Waiting for sub jobs to complete.

See also