Data Binding and Dimensional Flexibility in RASON Models

Our example RASON optimization model (on the previous page) includes the data -– the x,y coordinates of six cities -– in the RASON request.

    data :
    {
        dx : { dimensions: [6], value: [1, 0.5, 2, 2, 2, 0.5] },
        dy : { dimensions: [6], value: [4,   3, 4, 2, 5,   6] }
    },

It’s easy to change the data in JavaScript, by referencing request.data.dx.value, but the request itself will find a solution only for the included data. What if you want to solve this model for many different sets of data? RASON makes that easy, too.

For a small problem like this one, with a slight modification to the model, you can pass new data directly in the REST API call, via standard HTTP GET query string parameters:

    data :
    {
            dx : { dimensions: [6], binding: "GET" },
            dy : { dimensions: [6], binding: "GET" }
    }
    
$.get("https://rason.net/api/optimize?dx=1,0.5,2,2,2,0.5&dy=4,3,4,2,5,6", ...

But many realistic models use large tables of data, often drawn from multiple data files or databases. Further, our example model is “fixed” to six cities, but we might want to solve this problem many times, each time for a different number of cities -– changing the dimensions of parameters dx and dy, or even changing the dimensions of arrays of decision variables, uncertain variables or constraints.

Here is a variant of the Airline Hub model that obtains its data from an external data source, here a simple CSV file.

{
    engineSettings : { engine : 'GRG Nonlinear' },
    datasources :
    {
        city_data: { type: 'csv', connection: 'AirlineHubData.csv', indexCols: ['cities'], valueCols: ['dx', 'dy'] }
    },
    variables :
    {
    	x : { value: 1.0, finalValue: [] },
    	y : { value: 1.0, finalValue: [] },
    	z : { value: 1.0, finalValue: [] }
    },
    data :
    {
        dx : { binding: 'city_data',  valueCol: 'dx' },
        dy : { binding: 'city_data',  valueCol: 'dy' }
    },
    constraints :
    {
        c : { dimensions: ['cities', 1], upper: 0, formula: "sqrt((x - dx)^2 + (y - dy)^2) - z" }
    },
    objective :
    {
        obj : { type: 'minimize', formula: 'z', finalValue: [] }
    }
}

(We've used single quotes in this example, which are interchangeable with double quotes.) The datasources section defines a source for the data values formerly in the data section, in this case a comma-separated-value (CSV) file named AirlineHubData.csv. In the data section of the model, we bind the names dx and dy to corresponding value columns in the data source. The data source also defines an index column, and we use this to dimension the array of constraints. Our model can now be used to solve many different instances of this facility location problem, for a variable number of cities.

The CSV file looks like this. Other currently supported data source types are 'excel', 'access' and 'odbc' for Oracle, SQL Server and other databases; OData support is coming soon.

cities,dx,dy
1,1,4
2,0.5,3
3,2,4
4,2,2
5,2,5
6,0.5,6

Since the data source gave no URL or path for AirlineHubData.csv, this file must be in the 'current folder' when the model executes on the RASON back-end server; you can upload files to this folder along with your REST request. To try this yourself, create a text file AirlineHubData.csv from the values shown above (or below), upload AirlineHubData.csv using the button on the Editor page, create a model resource using POST rason.net/api/model, then use GET rason.net/api/model/id/optimize and GET rason.net/api/model/id/result. (The "quick solve" POST rason.net/api/optimize endpoint doesn't accept uploaded files.)

Index columns and index sets are much more general than the 1 through 6 values in the example above. If our CSV file contained instead:

cities,dx,dy
'Los Angeles',1,4
'Pomona',0.5,3
'Anaheim',2,4
'Long Beach',2,2
'Thousand Oaks',2,5
'Riverside',0.5,6

Our model would still solve. Further, we could refer to dx['Pomona'] -- "subscripting" the dx array with the index set element name, and get the value 0.5. More general references can return "slices" of multidimensional arrays, as we'll show in future examples.

Next: Using the REST API in Your Applications