Quick Start

This section will show a simple example to illustrate various functionalities of the AMPL Java interface. The full example prints the version of the AMPL interpreter used, loads a model from file and the corresponding data file, solves it, gets some of the AMPL entities in Java and uses them to get the results and to assign data programmatically. This section assumes that you are already familiar with the Java language. Where screenshots are displayed, they refer to Eclipse, a free development environment. Full class reference is given in Java API Reference.

Complete listing

This is the complete listing of the example. Please note that, for clarity of presentation, all the code in the examples below does not include exceptions handling.

// Create an AMPL instance
AMPL ampl = new AMPL();

/*
// If the AMPL installation directory is not in the system search path:
Environment env = new Environment(
    "full path to the AMPL installation directory");
AMPL ampl = new AMPL(env);
*/

try {
    // Interpret the two files
    ampl.read("models/diet.mod");
    ampl.readData("models/diet.dat");

    // Solve
    ampl.solve();

    // Get objective entity by AMPL name
    Objective totalcost = ampl.getObjective("Total_Cost");
    // Print it
    System.out.format("Objective is: %f%n", totalcost.value());

    // Reassign data - specific instances
    Parameter cost = ampl.getParameter("cost");
    cost.setValues(new Object[] { "BEEF", "HAM" }, new double[] { 5.01, 4.55 });
    System.out.println("Increased costs of beef and ham.");

    // Resolve and display objective
    ampl.solve();
    System.out.format("New objective value: %f%n", totalcost.value());

    // Reassign data - all instances
    cost.setValues(new double[] { 3, 5, 5, 6, 1, 2, 5.01, 4.55 });
    System.out.println("Updated all costs");

    // Resolve and display objective
    ampl.solve();
    System.out.format("New objective value: %f%n", totalcost.value());

    // Get the values of the variable Buy in a dataframe object
    Variable buy = ampl.getVariable("Buy");
    DataFrame df = buy.getValues();
    // Print them
    System.out.println(df);

    // Get the values of an expression into a DataFrame object
    DataFrame df2 = ampl.getData("{j in FOOD} 100*Buy[j]/Buy[j].ub");
    // Print them
    System.out.println(df2);
} catch (IOException e) {
    System.out.println(e.getMessage());
} finally {
    ampl.close();
}

Create a project and add references

This section depends on the chosen development environment. The screenshots below refer to Eclipse.

Creating a new project

Open Eclipse, choose an appropriate workspace and create a new Java project as shown in figure Create a project. Please note that the minimum required JRE is version 1.6.

Create a new project in eclipse

Create a project

Add a reference to the AMPL Java library

Right click on the project name, click on Properties, select the tab Java Build Path and in the tab Libraries click on Add External JARs (figure Add references to Eclipse) and select the file ampl-1.0.jar which can be found in the AMPL API installation directory. This will give access to all the types and methods defined in the library. The reference AMPL API should now be visible in the Referenced Libraries folder in the Package Explorer.

Add references

Add references to Eclipse

The resulting package explorer view is shown in figure Project with properly configured references below.

Project with properly configured references

Project with properly configured references

Java imports and AMPL environment creation

For a simple hello world program, first import the needed classes from the library, with the following statements:

import java.io.IOException;
import com.ampl.AMPL;
import com.ampl.DataFrame;
import com.ampl.Objective;
import com.ampl.Parameter;
import com.ampl.Variable;

Then copy the following statements to have a hello world application which gets the value of the option version as defined in the underlying AMPL executable and prints the result on the console.

AMPL ampl = new AMPL();
System.out.println(ampl.getOption("version"));

The first line creates a new Ampl object with all default settings. The second, which is the preferred way to access AMPL options, gets the value of the option version from AMPL as a string and prints the result on the active console.

Load a model from file

The following lines use the method AMPL.read to load a model and data stored in external (AMPL) files. If the files are not found, an IOException is thrown.

ampl.read("models/diet.mod");
ampl.readData("models/diet.dat");

Once these commands are executed, the AMPL interpreter will have interpreted the content of the two files. No further communication is made between the AMPL interpreter and the Java object, as every entity is created lazily (as needed).

Solve a problem

To solve the currently loaded problem instance, it is sufficient to issue the command:

ampl.solve();

Get an AMPL entity in the programming environment (get objective value)

AMPL API provides java representations of the AMPL entities. Usually, not all the entities are of interest for the programmer. The generic procedure is:

  1. Identify the entities that need interaction (either data read or modification)

  2. For each of these entities, create an object of the appropriate class in Java

  3. Get the entity through the AMPL API using AMPL.getEntity or one of its type safe alternatives (AMPL.getVariable, AMPL.getParameter, AMPL.getObjective , AMPL.getSet, AMPL.getConstraint)

Objective totalcost = ampl.getObjective("Total_Cost");
System.out.format("Objective is: %f%n",totalcost.get().value());

It can be noted that we access an Objective to interrogate AMPL API about the objective function. It is a collections of objectives. To access the single instance, the function get() should be used in case of the objective, which gets the only instance of the objective. Since objectives are often single instance, the value() function has been implemented in the class Objective. So, equivalently to the call above, the following call would return the same value, as it gives direct access to the objective function value:

totalcost.value();

The output of the program above is:

Objective is: 118.05940323955669

Modify model data (assign values to parameters)

The input data of an optimisation model is stored in its parameters; these can be scalar or vectorial entities. Two ways are provided to change the value of vectorial parameter: change specific values or change all values at once. The example shows an example of both ways, reassigning the values of the parameter costs firstly specifically, then altogether. Each time, it then solves the model and get the objective function. The function used to change the values is overloaded, and is in both cases Parameter.setValues.

Parameter cost = ampl.getParameter("cost");
cost.setValues( new Object[] { "BEEF", "HAM" }, new double[] { 5.01, 4.55 });
System.out.println("Increased costs of beef and ham.");
ampl.solve();
System.out.format("New objective value: %f%n", totalcost.value());

The code above assigns the values 5.01 and 4.55 to the parameter cost for the objects beef and ham respectively. If the order of the indexing of an entity is known (i.e. for multiple reassignment), it is not necessary to specify both the index and the value. A collection of values is assigned to each of the parameter values, in the order they are represented in AMPL.

cost.setValues(new double[] {3, 5, 5, 6, 1, 2, 5.01, 4.55 });
System.out.println("Updated all costs");
// Resolve and display objective
ampl.solve();
System.out.format("New objective value: %f%n", totalcost.value());

The statements above produce the following output:

Objective is: 118.05940323955669
Increased costs of beef and ham.
New objective value: 144.41572037510653
Updated all costs
New objective value: 164.54375000000002

Get numeric values from variables

To access all the numeric values contained in a Variable or any other entity, use a DataFrame object. Doing so, the data is detached from the entity, and there is a considerable performance gain. To do so, we first get the Variable object from AMPL, then we get its data with the function Entity.getValues.

// Get the values of the variable Buy in a dataframe object
Variable buy = ampl.getVariable("Buy");
DataFrame df = buy.getValues();
// Print them
System.out.println(df);

Get arbitrary values via ampl expressions

Often we are interested in very specific values coming out of the optimization session. To make use of the power of AMPL expressions and avoiding cluttering up the environment by creating entities, fetching data through arbitrary AMPL expressions is possible. For this model, we are interested in knowing how close each decision variable is to its upper bound, in percentage. We can obtain this data into a dataframe with the code:

// Get the values of an expression into a DataFrame object
DataFrame df2 = ampl.getData("{j in FOOD} 100*Buy[j]/Buy[j].ub");
// Print them
System.out.println(df2);

Close the AMPL object to free the resources

It is good practice to make sure that the AMPL object is closed and all its resources released when it is not needed anymore. This can be easily achieved by enclosing all the body of the program in a try block, and by calling the AMPL.close function in the finally block.

AMPL ampl = new AMPL();
try{
   // use ampl object here
} finally{
   // close all AMPL related resources here
   ampl.close();
}