GLPK/IAJAAR.H project

From Wikibooks, open books for an open world
Jump to: navigation, search

This page describes a C++ class that wraps the C-style GLPK vectors ia, ja, and ar. The class can be used directly with C++ or via language bindings for Java and R created with SWIG.

IAJAAR.H project[edit]

IAJAAR.H is a small project that provides the specialized triple container class IAJAAR. The purpose of this C++ class is to offer more convenient problem build calls than those available using straight C code. The author is Nigel Galloway.

C++ class IAJAAR definition[edit]

The C++ IAJAAR class definition is:

//  File: 'iajaar.h'
//  Provides: C++ class 'IAJAAR'
 
class IAJAAR
{
private:
  int *    xia;
  int *    xja;
  double * xar;
  int      entry;
  int      maxSize;
public:
 ~IAJAAR();                                  // destructor, deallocate memory
  IAJAAR(int s);                             // constructor, s is maximum array length
  const int * ia();                          // return C-style int array
  const int * ja();                          // return C-style int array
  const double * ar();                       // return C-style double array
  void Add(int row, int col, double value);
  int ne();                                  // return number of entries
};

The member function IAJAAR::Add adds 3-tuples (triples) in the form (row, col, value). The respective arrays can be later retrieved using the member functions IAJAAR::ia, IAJAAR::ja, and IAJAAR::ar. The member function IAJAAR::ne returns the current number of entries.

IAJAAR is designed to work with the following GLPK routine:

void glp_load_matrix(glp_prob *lp, int ne, const int ia[], const int ja[], const double ar[]);


It would be possible to reformulate class IAJAAR using std::vectors internally. That would omit the need to pre-specify the maximum size s in advance, although an optional hint could be given.

C++ usage[edit]

Usage with C++ is straightforward — no special language bindings are required. A description of the underlying problem is can be found on the project website.

//  File: 'igst10yo.cpp'
//  An example of using IAJAAR.H with GLPK in C++.
//  Usage: 'igst10yo.cpp 6.5 7' will calculate 6.5 divided by 7.
//  Nigel Galloway / July 2009
 
#include <iostream>
#include <stdlib.h>
#include "iajaar.h"          // see above on wikipage
#include "glpk.h"
 
int main(int argc, char * argv[])
{
  double Q = atof(argv[1]);
  int    N = atoi(argv[2]);
  IAJAAR * igst10yo = new IAJAAR(5*N);
  glp_prob * lp = glp_create_prob();
  // col 1 is M
  // cols 2 .. N+1 is a sample of N numbers which sum to Q
  // cols N+2 .. 2*N+1 are v[1..N]
  glp_add_rows(lp,N+2);
  glp_add_cols(lp,2*N+1);
  for(int i=1; i<=2*N+1; i++) glp_set_col_bnds(lp,i,GLP_FR,0,0);
  glp_set_row_bnds(lp,N+1,GLP_FX,Q,Q);
  glp_set_row_bnds(lp,N+2,GLP_FX,0,0);
  try {
    for(int i=1; i<=N; i++) {
      glp_set_row_bnds(lp,i,GLP_FX,0,0);
      igst10yo->Add(i,i+1,-1);
      igst10yo->Add(i,1,1);
      igst10yo->Add(i,i+N+1,1);
      igst10yo->Add(N+1,i+1,1);
      igst10yo->Add(N+2,i+N+1,1);
    }
  } catch (char * error) {
    std::cout << error << std::endl;
  }
  glp_load_matrix(lp,igst10yo->ne(),igst10yo->ia(),igst10yo->ja(),igst10yo->ar());
  glp_simplex(lp,NULL);
  double Result = glp_get_col_prim(lp,1);
  std::cout << "The arithmetic mean of a sample of " << N
            << " numbers whose sum is " << Q << " is " << Result
            << std::endl;
  delete igst10yo;
  glp_delete_prob(lp);
  return 0;
}

Python usage[edit]

IAJAAR can be used with Python. This February 2011 posting explains more.

Java usage[edit]

Java usage requires dedicated language bindings. Unlike the C++ example, Q and N are hardcoded.

/*
  File: 'gmst10yo.java'
  Usage: 'java -classpath IAJAAR_JAVA.jar;GLPK_JAVA.jar;. gmst10yo'
  will calculate 22 divided by 7.
  Modify Q and N below to try alternatives.
  Nigel Galloway / July 2009
*/
 
import org.gnu.glpk.*;
 
public class gmst10yo {
  static {
    System.loadLibrary("IAJAAR_JAVA");
  }
  public static void main(String argv[]) {
    double Q = 22;
    int N = 7;
    IAJAAR t = new IAJAAR(3*N);
    glp_prob lp = GLPK.glp_create_prob();
    GLPK.glp_add_rows(lp,N+1);
    /* col 1 is M
       cols 2 .. N+1 are S[n]
    */
    GLPK.glp_add_cols(lp,N+1);
    for(int i=1; i<=N+1; i++) GLPK.glp_set_col_bnds(lp,i,GLPK.GLP_FR,0,0);
    t.Add(1,1,1);
    t.Add(1,2,1);
    t.Add(N+1,2,1);
    GLPK.glp_set_row_bnds(lp,N+1,GLPK.GLP_FX,0,0);
    GLPK.glp_set_row_bnds(lp,1,GLPK.GLP_FX,Q,Q);
    for(int i=2; i<=N; i++){
            GLPK.glp_set_row_bnds(lp,i,GLPK.GLP_FX,0,0);
            t.Add(i,1,1);
            t.Add(i,i+1,1);
            t.Add(N+1,i+1,1);
    }
    GLPK.glp_load_matrix(lp,t.ne(),t.ia(),t.ja(),t.ar());
    GLPK.glp_simplex(lp,null);
    double Result = GLPK.glp_get_col_prim(lp,1);
    GLPK.glp_delete_prob(lp);
    System.out.println("The arithmetic mean of a sample of " + N 
                       + " numbers which sum to " + Q + " is " + Result);
  }
}

R usage[edit]

R usage requires dedicated language bindings. Unlike the C++ example, Q and N are hard-coded.

#  File: 'gist10yo.R'
#  Nigel Galloway / July 2009

dyn.load(paste("GLPK_R", .Platform$dynlib.ext, sep=""))
source("GLPKconstants.R")
source("GLPK_R.R")
cacheMetaData(1)
Q <- 22
N <- 7
t <- IAJAAR(6)
lp <- glp_create_prob()
glp_add_rows(lp,3)
#  col 1 is M
#  col 2 is v1
#  col 3 is v2
glp_add_cols(lp,3)
glp_set_col_bnds(lp,1,GLP_FR,0,0)
glp_set_col_bnds(lp,2,GLP_FR,0,0)
glp_set_col_bnds(lp,3,GLP_FR,0,0)
IAJAAR_Add(t,1,1,1)
IAJAAR_Add(t,1,2,1)
IAJAAR_Add(t,2,1,1)
IAJAAR_Add(t,2,3,1)
IAJAAR_Add(t,3,2,1)
IAJAAR_Add(t,3,3,N-1)
glp_set_row_bnds(lp,1,GLP_FX,Q,Q)
glp_set_row_bnds(lp,2,GLP_FX,0,0)
glp_set_row_bnds(lp,3,GLP_FX,0,0)
loadMatrix(t,lp);
delete(t)
if (glp_simplex(lp,t)==0) {
  R <- glp_get_col_prim(lp,1)
  print(sprintf("The arithmetic mean of a sample of %f numbers which sum to %f is %f",N,Q,R))
} else {
  print("No solution")
}

Further information is available from the project website. In particular, the source code for iajaar.cpp is worth reviewing.