0
$\begingroup$

I am trying to model a routing instance in AMPL C++ API. The AMPL Book presents a strategy for modeling routing instances via AMPL (Figures 6-2a and 6-2b, Page 95, Chapter 6), as it is presented below:

set V; # nodes
set A within {V,V}; # arcs
param cost{A}; # costs

However, I am having a hard time to find resources showing of how to achieve this by means of the AMPL C++ API. Below follows a C++ code with the parts in which I am lost.

#include <iostream>
#include <string> 

#include "ampl/ampl.h"

using namespace std;
using namespace ampl;

int main(int argc, char **argv) {
    try {
        /* INPUT */

        // Nodes ids
        size_t n = 10;

        char ** V = (char **) malloc(n * sizeof(char*));
        for (int i = 0; i < n; i++) {
            // up to 10 characters of id
            V[i] = (char *) malloc(10 * sizeof(char));
            sprintf(V[i], "%d", i);
        }

        // Arcs
        vector<pair<int, int>> A = {make_pair(1, 0), make_pair(2, 5)};

        /* AMPL process */
        AMPL ampl;

        // Sets
        // Nodes
        ampl.eval("set V;");
        ampl.getSet("V").setValues(V, n);

        // Arcs
        ampl.eval("set A within {V,V};");
        ampl.getSet("A");
        // how to set A???

        // cost
        ampl.eval("param cost{A};");
        ampl.getParameter("cost");
        // how to set populate cost???

        // Closing
        ampl.close();

        // Cleaning
        for (int i = 0; i < n; i++) 
            free(V[i]);
        free(V);

        return 0;
    } catch (const std::exception &e) {
        std::cout << e.what() << "\n";
        return 1;
    }
}

For those who want to replicate the experiments locally, just follow the steps of this repo.

I took the time to read the API documentation, specifically wrt to the classes Set and Parameter, but I still couldn't find a way of using the functions setValues. I would like to know if anyone ever passed by such a situation before.

Thanks and regards.

$\endgroup$

1 Answer 1

1
$\begingroup$

In the API examples there is one with nodes, links and costs (https://ampl.com/api/latest/cpp/examples.html#example-4-operate-with-multidimensional-data) that is very similar to what you are trying to do. The following snippet uses AMPL::setData like in the multidimensional data example to pass a DataFrame with the elements of set A and the values for the parameter cost:

ampl::AMPL ampl;

std::vector<double> V = {0, 1, 2, 5};
ampl.eval("set V;");
ampl.getSet("V").setValues(V.data(), V.size());

std::vector<std::pair<double, double>> A = {std::make_pair(1, 0), std::make_pair(2, 5)};
ampl.eval("set A within {V,V};");
ampl.eval("param cost{A};");
ampl.getParameter("cost");

ampl::DataFrame df(2, ampl::StringArgs("i", "j", "cost"));
std::vector<double> v1;
std::vector<double> v2;
std::vector<double> cost;
for (auto p : A)
{
  v1.push_back(p.first);
  v2.push_back(p.second);
  cost.push_back(3.14);
}
df.setColumn("i", v1.data(), v1.size());
df.setColumn("j", v2.data(), v2.size());
df.setColumn("cost", cost.data(), cost.size());
ampl.setData(df, "A");

ampl.eval("display cost;");
ampl.close();
$\endgroup$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.