Wednesday, April 1, 2015

Interesting Xpress log

On a very small (convex) MIQCP model (it solves within the limits of the demo version of GAMS/Xpress) we see Xpress struggling mightily. Commercial solvers like Xpress are very robust for LP and MIP models, but they seem somewhat less reliable with respect to quadratic models, probably because they are less exposed to quadratic models.

MODEL STATISTICS

BLOCKS OF EQUATIONS          51    SINGLE EQUATIONS           51
BLOCKS OF VARIABLES          89    SINGLE VARIABLES           89
NON ZERO ELEMENTS           241     NON LINEAR N-Z             80
DERIVATIVE POOL              20     CONSTANT POOL              36
CODE LENGTH                 400     DISCRETE VARIABLES         40

FICO-Xpress      24.4.1 r50296 Released Dec 20, 2014 WEI x86 64bit/MS Windows

Xpress Optimizer 27.01
Xpress-Optimizer 64-bit v27.01.02 (Hyper capacity)
(c) Copyright Fair Isaac Corporation 1983-2014. All rights reserved
Licensed for use by: GAMS Development Corp. for GAMS

Reading Problem m
Problem Statistics
          50 (      0 spare) rows
          88 (      0 spare) structural columns
         200 (      0 spare) non-zero elements
          80 quadratic elements in 40 quadratic constraints
Global Statistics
          40 entities        0 sets        0 set members
Minimizing MIQCQP m
Original problem has:
        50 rows           88 cols          200 elements        40 globals
        40 qrows          80 qrowelem
Presolved problem has:
        50 rows           88 cols          200 elements        40 globals
        40 qrows          80 qrowelem
Will try to keep branch and bound tree memory usage below 21.7Gb
Barrier cache sizes : L1=32K L2=8192K
Using AVX support
Cores per CPU (CORESPERCPU): 8
Barrier starts, with L2 cache 1024K
Matrix ordering - Dense cols.:      0   NZ(L):       950   Flops:        14984
  Its   P.inf      D.inf      U.inf      Primal obj.     Dual obj.      Compl.
   0  1.91e+001  1.19e+001  9.70e+000  2.8159564e+003 -2.6134886e+002  3.8e+003
   1  7.49e+000  5.91e+000  1.54e+000  5.8570174e+002 -8.3787742e+001  7.2e+002
   2  1.28e+000  3.28e-001  1.10e-002  2.9030624e+000 -1.2271889e+001  1.9e+001
   3  9.84e-002  1.92e-002  8.10e-004  1.6036787e-001 -1.0029935e+000  2.0e+000
   4  7.98e-004  3.67e-003  5.07e-006  1.9140695e-003 -7.4258213e-003  2.5e-002
   5  2.11e-006  1.03e-005  1.33e-008  5.1448073e-006 -1.5450951e-005  6.0e-005
   6  2.13e-009  1.05e-008  1.34e-011  5.2140230e-009 -1.5655265e-008  6.1e-008
Barrier method finished in 0 seconds
Crossover starts

   Its         Obj Value      S   Ninf  Nneg        Sum Inf  Time
    42           .000000      P     45     0     416.304867     0
     0           .000000      N     45     0     416.304867     0
     0           .000000      D     45     0        .000000     0
Crossover successful
Objective function value:      .000000 time: 0
     0           .000000      P     12    36       6.913862     0
    14           .000000      P      0     0        .000000     0
Optimal solution found
Barrier solved problem
  6 barrier and 56 simplex iterations in 0s

Final objective                         : 0.000000000000000e-01
  Max primal violation      (abs / rel) :       0.0 /       0.0
  Max dual violation        (abs / rel) :       0.0 /       0.0
  Max complementarity viol. (abs / rel) :       0.0 /       0.0
All values within tolerances

Starting root cutting & heuristics

Its Type    BestSoln    BestBound   Sols    Add    Del     Gap     GInf   Time
+           75.710978      .000000      1               75.7110        0      0
+           75.297982      .000000      2               75.2980        0      0
   1  O     75.297982      .487605      2     50     20   99.35%      29      0
   2  O     75.297982    13.426199      2     51     48   82.17%      26      0
   3  O     75.297982    33.375760      2     38     25   55.68%      12      0
   4  O     75.297982    60.087607      2     52     40   20.20%      18      0
   5  O     75.297982    71.987890      2     34     40    4.40%      12      0
   6  O     75.297982    74.005329      2     30     24    1.72%       6      0
   7  K     75.297982    74.005329      2     13     23    1.72%      16      0
   8  K     75.297982    74.005329      2      5     15    1.72%      16      0
   9  K     75.297982    74.005329      2      7      5    1.72%      10      0
  10  K     75.297982    74.005329      2      0      7    1.72%      10      0
Heuristic search started
Heuristic search stopped

Cuts in the matrix         : 73
Cut elements in the matrix : 216
Its Type    BestSoln    BestBound   Sols    Add    Del     Gap     GInf   Time
   1  O     75.297982    74.005329      2     35      5    1.72%       0      0
   2  O     75.297982    74.005329      2     19     36    1.72%       0      0
   3  O     75.297982    74.005329      2     23     17    1.72%       0      0
Will try to keep branch and bound tree memory usage below 21.7Gb

Starting tree search

    Node     BestSoln    BestBound   Sols Active  Depth     Gap     GInf   Time
       1    75.297982    74.005329      2      2      1    1.72%      18      0
       2    75.297982    74.005329      2      1      2    1.72%      21      0
       3    75.297982    74.005329      2      2      3    1.72%      20      0
       4    75.297982    74.005329      2      3      4    1.72%      20      0
       5    75.297982    74.005329      2      4      5    1.72%      20      0
       6    75.297982    74.005329      2      5      6    1.72%      19      0
       7    75.297982    74.005381      2      6      3    1.72%      19      0
       8    75.297982    74.005383      2      7      7    1.72%      19      0
       9    75.297982    74.031433      2      8      5    1.68%      18      0
      10    75.297982    74.031433      2      9      6    1.68%      16      0
+     15    74.628262    74.031433      3     11     10    0.80%       0      0
+     19    74.628249    74.031433      4     11     14    0.80%       0      0
      20    74.628249    74.031433      4     11     14    0.80%       2      0
      30    74.628249    74.031433      4     18     14    0.80%       4      0
      40    74.628249    74.031449      4     25     11    0.80%       8      0
      50    74.628249    74.077101      4     31      8    0.74%      16      0
+     59    74.576175    74.077101      5     31     16    0.67%       0      0
      60    74.576175    74.077101      5     31     16    0.67%       2      0
+     60    74.525346    74.077101      6     31     17    0.60%       0      0
B&B tree size: 144k total

    Node     BestSoln    BestBound   Sols Active  Depth     Gap     GInf   Time
      70    74.525346    74.077154      6     36      6    0.60%      14      0
+     79    74.501844    74.077154      7     36     14    0.57%       0      0
      80    74.501844    74.077154      7     36     14    0.57%       2      0
+     80    74.451129    74.077154      8     36     15    0.50%       0      0
      90    74.451129    74.079222      8     39      4    0.50%      16      0
     100    74.451129    74.079222      8     45      4    0.50%      16      0
     200    74.451129    74.100052      8     89     14    0.47%       6      0
     300    74.451129    74.105467      8    134      9    0.46%      16      0
     400    74.451129    74.123164      8    161     14    0.44%       6      0
     500    74.451129    74.131429      8    185     11    0.43%       8      0
     600    74.451129    74.172380      8    207     16    0.37%       2      0
     700    74.451129    74.179219      8    245     10    0.37%       4      0
     800    74.451129    74.203200      8    265     13    0.33%       6      0
+    884    74.441499    74.205322      9    289     20    0.32%       0      0
     900    74.441499    74.205322      9    290     14    0.32%       8      0
    1000    74.441499    74.205322      9    311     11    0.32%       2      0
    1200    74.441499    74.205322      9    367     16    0.32%      12      0
+   1217    74.408242    74.205322     10    369     23    0.27%       0      0
    1300    74.408242    74.220873     10    352     17    0.25%       4      0
    1400    74.408242    74.231426     10    363     10    0.24%       8      0
B&B tree size: 1.0Mb total

    Node     BestSoln    BestBound   Sols Active  Depth     Gap     GInf   Time
    1500    74.408242    74.231426     10    382     16    0.24%       4      1
    1700    74.408242    74.250990     10    415     14    0.21%       8      1
    1800    74.408242    74.257529     10    439     15    0.20%       6      1
+   1818    74.408060    74.257529     11    436     20    0.20%       0      1
    1900    74.408060    74.261403     11    443     17    0.20%       4      1
    2000    74.408060    74.271531     11    448     10    0.18%       7      1
    2100    74.408060    74.277093     11    451     11    0.18%       6      1
    2200    74.408060    74.279215     11    462     16    0.17%       4      1
    2300    74.408060    74.283948     11    468     13    0.17%       2      1
    2400    74.408060    74.287506     11    477     16    0.16%       4      1
    2500    74.408060    74.299222     11    468     11    0.15%       2      1
    2600    74.408060    74.305186     11    477      7    0.14%      10      1
    2700    74.408060    74.305319     11    485     14    0.14%       8      1
    2800    74.408060    74.305319     11    479     15    0.14%       4      1
    3000    74.408060    74.315007     11    449     16    0.13%       4      1
    3100    74.408060    74.327330     11    427     17    0.11%       4      2
    3200    74.408060    74.331422     11    420     15    0.10%       2      2
    3400    74.408060    74.342707     11    377     13    0.09%       8      2
    3500    74.408060    74.352660     11    363     15    0.07%       2      2
    3600    74.408060    74.359277     11    339     19    0.07%       4      2
B&B tree size: 1.3Mb total

    Node     BestSoln    BestBound   Sols Active  Depth     Gap     GInf   Time
    3700    74.408060    74.373115     11    303     13    0.05%       2      2
    3900    74.408060    74.379200     11    275     15    0.04%       4      2
    4000    74.408060    74.379212     11    258     14    0.04%       2      2
    4200    74.408060    74.387502     11    192     19    0.03%       5      2
    4500    74.408060    74.405315     11     59     15   0.004%       4      3
    4600    74.408060    74.405640     11     15     15   0.003%      10      3
*** Search completed ***     Time:     3 Nodes:       4629
Number of integer feasible solutions found is 11
Best integer solution found is    74.408060
Best bound is    74.408060
Warning: 6 node(s) could not be solved or branched. Final bound or status may be incorrect.

Uncrunching matrix
fixing discrete vars and re-solving as an LP.
Minimizing QCQP m
Original problem has:
        50 rows           88 cols          200 elements
        40 qrows          80 qrowelem
Presolved problem has:
        40 rows           48 cols          120 elements
        40 qrows          80 qrowelem
Barrier cache sizes : L1=32K L2=8192K
Using AVX support
Cores per CPU (CORESPERCPU): 8
Barrier starts, with L2 cache 1024K
Matrix ordering - Dense cols.:      0   NZ(L):       376   Flops:         2520
  Its   P.inf      D.inf      U.inf      Primal obj.     Dual obj.      Compl.
   0  1.83e+001  2.52e+001  1.16e+001  1.5112915e+003 -9.4937458e+002  2.6e+003
   1  4.74e+000  9.55e+000  1.19e+000  2.5408247e+002 -2.9217970e+002  3.9e+002
   2  2.34e+000  3.44e+000  3.35e-001  7.8404847e+001 -1.0977438e+002  1.4e+002
   3  7.92e-001  6.84e-001  1.89e-002  5.2158577e+000 -1.3750171e+001  1.4e+001
   4  6.28e-001  6.38e-001  1.33e-002  4.1020675e+000 -7.8600545e+000  1.1e+001
   5  4.37e-001  3.32e-001  8.43e-003  9.0795149e+000  3.4120483e-001  1.5e+001
   6  1.98e-001  2.61e-001  3.73e-003  9.3869573e+000  4.9561739e+000  8.6e+000
   7  3.63e-002  6.02e-002  3.74e-004  8.7705271e+000  7.9879673e+000  1.3e+000
   8  8.70e-003  2.50e-002  3.59e-005  8.6114463e+000  8.6224795e+000  1.4e-001
   9  2.28e-003  1.31e-002  4.91e-006  8.5979647e+000  8.6831580e+000  2.5e-002
  10  3.52e-004  2.47e-003  4.60e-009  8.5944005e+000  8.5952389e+000  2.2e-004
  11  5.07e-005  7.03e-004  6.92e-012  8.5943916e+000  8.5948297e+000  2.1e-005
  12  8.59e-006  2.20e-004  8.78e-016  8.5943913e+000  8.5944862e+000  2.5e-006
  13  1.56e-006  7.24e-005  8.78e-016  8.5943913e+000  8.5944094e+000  2.9e-007
  14  3.00e-007  2.42e-005  1.10e-015  8.5943913e+000  8.5943941e+000  3.3e-008
Barrier method finished in 0 seconds
Uncrunching matrix
Optimal solution found

   Its         Obj Value      S   Ninf  Nneg        Sum Inf  Time
     0          8.594391      B      0     0        .000000     0
Barrier solved problem
  14 barrier iterations in 0s

Final objective                         : 8.594391251039179e+00
  Max primal violation      (abs / rel) : 8.474e-07 / 5.042e-08
  Max dual violation        (abs / rel) :       0.0 /       0.0
  Max complementarity viol. (abs / rel) : 4.300e-07 / 1.758e-08
All values within tolerances

fixed LP solved successfully, objective = 8.59439125104.

Integer solution proven optimal.

MIP solution  :          8.594391
Best possible :         74.408060
Absolute gap  :        -65.813669     optca :          0.000000
Relative gap  :         -0.884497     optcr :          0.000000

The correct optimal objective is 0.8404.

Tuesday, March 31, 2015

Reliability of NLP solvers

NLP solvers can fail for a number of reasons. One way to increase the reliability of a production run is to use a back-up solver in case the main solver fails. In GAMS primal and dual information is passed between SOLVE statements even if different solvers are used. This is actually very useful in a case I just observed.

Solver Status
mosek Near Optimal
ipopt Solved to Acceptable Level
mosek + ipopt Optimal Solution Found

Here both Mosek and IPOPT are getting into trouble and are not able to give us an optimal solution (in this case it was close, but I have seen cases where “near optimal” could be interpreted as “far away from optimal”). But the sequence: first Mosek, then IPOPT actually solves the problem to optimality.

We programmed this essentially as:

option nlp=mosek;
solve allocationmodel minimizing entropy using nlp;
if (allocationmodel.modelstat > 2,       { not optimal }
    option nlp=ipopt;
    solve allocationmodel minimizing entropy using nlp;
);

k-means clustering heuristic in GAMS and the XOR operator

In http://yetanothermathprogrammingconsultant.blogspot.com/2015/03/k-means-clustering-formulated-as-miqcp.html we were quite underwhelmed by the performance of MIQCPs (Mixed Integer Quadratically Constrained Problems).

A standard heuristic is easily formulated in GAMS:

$ontext

 
K-means clustering heuristic

$offtext


option seed=101;

sets
   k 
'clusters' /k1*k4/
   i 
'data points' /i1*i100/
   ik(i,k)
'assignment of points to clusters'
   xy
'coordinates of points' /x,y/
;
parameter
   m(k,xy)
'random clusters to generate data points'
   p(i,*) 
'data points'
   numk   
'number of clusters'
   cluster(i)   
'cluster number'
;

numk =
card(k);
alias(ii,i);

*------------------------------------------------
* generate random data
* points are around some clusters
*------------------------------------------------
m(k,xy) = uniform(0,4);
cluster(i) = uniformint(1,numk);
ik(i,k) = cluster(i)=
ord(k);
p(i,xy) =
sum(ik(i,k),m(k,xy)) + uniform(0,1);
display m,p;

sets
  ik(i,k)
'assignment of points to clusters'
  ik_prev(i,k)
'previous assignment of points to clusters'
  ik_diff
  trial  
'number of trials' /trial1*trial15/
  iter   
'max number of iterations' /iter1*iter20/
;
parameters
  n(k)      
'number of points assigned to cluster'
  c(k,xy)   
'centroids'
  notconverged 
'0=converged,else not converged'
  d(i,k)    
'squared distance'
  dclose(i) 
'distance closest cluster'
  trace(trial,iter)
'reporting'
;

loop(trial,

*------------------------------------------------
* Step 1
* Random assignment
*------------------------------------------------

      cluster(i) = uniformint(1,numk);
      ik(i,k) = cluster(i)=
ord(k);

      notConverged = 1;
     
loop(iter$notConverged,

*------------------------------------------------
* Step 2
* Calculate centroids
*------------------------------------------------
          n(k) =
sum(ik(i,k), 1);
          c(k,xy)$n(k) =
sum(ik(i,k), p(i,xy))/n(k);

*------------------------------------------------
* Step 3
* Re-assign points
*------------------------------------------------

          ik_prev(i,k) = ik(i,k);
          d(i,k) =
sum(xy, sqr(p(i,xy)-c(k,xy)));
          dclose(i) =
smin(k, d(i,k));
          ik(i,k) =
yes$(dclose(i) = d(i,k));

*------------------------------------------------
* Step 4
* Check convergence
*------------------------------------------------

          ik_diff(i,k) = ik(i,k)
xor ik_prev(i,k);
          notConverged =
card(ik_diff);

          trace(trial,iter) =
sum(ik(i,k),d(i,k));
      );
);

display trace;

The results show it is important to use different starting configurations (i.e. multiple trials):

----    100 PARAMETER trace  reporting

              iter1       iter2       iter3       iter4       iter5       iter6

trial1      366.178      28.135      14.566
trial2      271.458      26.741      14.566
trial3      316.975      23.912      14.566
trial4      299.522      24.511      14.566
trial5      346.148      77.747      14.566
trial6      313.978      64.730      14.865      14.566
trial7      310.735      27.412      14.566
trial8      330.829     213.308     184.504     102.191      76.611      74.210
trial9      356.897      90.286      16.112      14.566
trial10     345.086      82.716      76.154      76.146
trial11     354.545     169.648      75.626      74.350      71.929      67.385
trial12     310.257      52.175      18.800      14.566
trial13     289.293      23.505      14.566
trial14     337.024      20.783      14.566
trial15     336.969      28.747      14.566

      +       iter7       iter8       iter9      iter10

trial8       67.933      42.621      14.881      14.566
trial11      59.815      59.591

The consensus is that 14.566 is the optimal sum of the squared distances. Note that this was an extremely easy problem:

image

Notes:

  1. We use an xor operator to find the difference between if the sets ik_prev and ik. If there is no difference card(ik_diff)=0 and thus notConverged=0. See below for a small example illustrating the xor.
  2. The assignment
    ik(i,k) = yes$(dclose(i) = d(i,k));
    is incorrect if point i is exactly between two clusters. In that case we assign the point to two clusters. We can fix this by a more complicated loop:
    ik(i,k) = no;
    loop((i,k)$(dclose(i) = d(i,k)),
      ik(i,k)$(
    sum(ik(i,kk),1)=0) = yes;
    );

  3. The construct
    cluster(i) = uniformint(1,numk); ik(i,k) = cluster(i)=ord(k);
    cannot be simplified to 
    ik(i,k) = uniformint(1,numk)=ord(k);
    The latter version is incorrect.
  4. The assignment
    c(k,xy)$n(k) = sum(ik(i,k), p(i,xy))/n(k); 
    will keep a cluster with zero points at its current location.
The XOR operator

This fragment illustrates a few different ways to calculate the difference between two sets:

set
   i
/a*z/
   j(i)
/a,b/
   k(i)
/  b,c/
   diff(i)
'difference between sets: card(diff)=0 if equal'
;

diff(i) = (j(i)-k(i)) + (k(i)-j(i));
display diff;

diff(i) = j(i)
xor k(i);
display diff;

diff(i) = 1$j(i) <> 1$k(i);
display diff;

----      9 SET diff  difference between sets: card(diff)=0 if equal

a,    c

----     12 SET diff  difference between sets: card(diff)=0 if equal

a,    c

----     15 SET diff  difference between sets: card(diff)=0 if equal

a,    c


My preferred syntax diff(i)=j(i)<>k(i) is not allowed. In my opinion, notation should really try to help readability, and not show off mathematical prowess.

Monday, March 30, 2015

More oligopolistic behavior

Even very simple models require attention to detail. In [link] we described simple model from the literature. A related model with a coupling constraint that limits pollution emissions is described in:

  1. Jacek Krawczyk and James Zuccollo, NIRA-3: An improved MATLAB package for finding Nash equilibria in infinite games, Victoria University of Wellington, December 2006
  2. Lars Mathiesen, Regulation of pollution in a Cournot equilibrium, The Norwegian School of Economics and Business Administration, Bergen, June 2008.

The Nash-Cournot model without pollution controls is simply:

image

Adding the pollution controls using taxes (or tradable quotas) is not that difficult:

image

Still for this simple model I get different results for the base case (no pollution controls). My results are:

----    135 PARAMETER results 

                     output      profit    emission       price

no control  .j1      55.351      61.274
no control  .j2      14.914      13.345
no control  .j3      53.684      57.639
no control  .k1                             419.978
no control  .k2                             301.125
no control  .-                                            1.761
with control.j1      21.145       8.942
with control.j2      16.028      15.414
with control.j3       2.726       0.149
with control.k1                             100.000
with control.k2                              81.164
with control.-                                            2.601

The paper [1] has the following results:

image

The second part corresponds to my solutions, but the first part shows differences. As the problem with controls is an extension of the problem without controls, there is actually a reasonable chance my solution is correct. 

Friday, March 27, 2015

MIP Links

  • Ed Klotz (Cplex): Identification, Assessment and Correction of Ill-Conditioning and Numerical Instability in Linear and Integer Programs [slides and recording].
  • Performance Variability
    • Performance Variability Defined [link]
    • Performance Variability: Good Readings [link]
    • Performance Variability: Consequences [link]
    • Cplex Performance Variability [link]

Thursday, March 26, 2015

K-means clustering formulated as MIQCP optimization problem

It is instructive to formulate the k-means clustering problem as a Mixed-Integer Quadratically Constrained Problem (MIQCP) in GAMS. It looks trivial at first sight but in fact requires a little bit of attention.

We start with a small data set. E.g. 3 clusters and 50 data points in two dimensions (x and y). I.e. our sets look like:

image

We generate some random clusters as follows:

image

Should be an easy problem:

image

The clustering model could look like:

image

We solver here for two things simultaneously:

  1. The location of the clusters (continuous variables c)
  2. The assignment of points to clusters (binary variables x)

The equation distances computes all (squared) distances between the points and the clusters. We multiply by x so that we only sum these distances when a point is assigned to a cluster (in that case x=1). Finally we make sure each point is assigned to exactly one cluster.

Unfortunately this model is non-convex, so we can solve this only with global solvers such as Baron or GloMiQo.

Convexification

We can make the model convex as follows:

image

We use a big-M construct where the upper bound of d forms a reasonable tight value for M. Here we have that d(i,k)=0 if point i is not assigned to cluster k (note that d≥0). The objective has become linear in this case.

Now we can solve the problem with commercial solvers like Cplex and Gurobi. The results (with the location of the clusters from variable c) are:

image

Performance

For larger data sets it turns out the performance is not very good. E.g. with 100 points and 4 clusters we have 400 binary variables and it takes hours or days to prove optimality. Both Cplex and Gurobi are not able to prove optimality even when we load an optimal solution using MIPSTART. Xpress has even more troubles, and returns bad solutions. We see more often that MIQP/MIQCP solvers are not as robust and fast as (linear) MIP solvers. It is too bad the MIQCP solvers are doing so poorly on this problem.

Using a solver would have opened up possibly interesting extensions like additional constraints on the clustering, such as “at least n points in each cluster”.

Bug in Gurobi

We were able to confuse Gurobi by writing the model as:

image

It now accepts the model (although it is non-convex) and produces a bogus solution: all points are assigned to cluster 1. Gurobi should have refused to solve the problem (with some message about Q matrix not PSD).

Wednesday, March 25, 2015

Oligopolistic producer behavior or why airline tickets are not cheaper


Small example from the literature:
image 
Note: John Nash just won the Abel prize (http://www.nature.com/news/beautiful-mind-john-nash-adds-abel-prize-to-his-nobel-1.17179).
image
We implement different behaviors with a GAMS model:
Behavior Equations
Oligopolistic (MCP)

Nash-Cournot Equilibrium
image
image
Monopolistic (NLP)

Think of this as firms are merged.
image
image
Competitive (NLP)

Technique:
Optimize Social Welfare Objective.

Check solution by: Price= Marginal Cost.
image
image

image
Here q(i) is quantity supplied by firm i. We see most profit is to be made by merging firms and reducing capacity, just as happened in the US airline industry (Europe is a very different story). See also: https://www.nytimes.com/2015/03/24/business/dealbook/as-oil-prices-fall-air-fares-still-stay-high.html.
Another small example from energy markets: https://yetanothermathprogrammingconsultant.blogspot.com/2013/07/microeconomic-principles.html

Sparse sum: set cover problem in GAMS

In a set cover problem (http://en.wikipedia.org/wiki/Set_cover_problem)  we can organize the sets in two different ways:

  1. Use a (sparse) two dimensional set. The cover equation will contain a construct like: sum[c(s,i), x(s)].
  2. Use a (sparse) zero-one parameter. In this case the cover equation can have something like: sum[s, c(s,i)*x(s)].

The question came up. What is better? I like the set construct a bit better but that is purely based on aesthetics. The performance is exactly the same.

Data structure: set Data structure: 0/1 parameter
image image

The sets are randomly generated. We solve here just as an LP as we are only interested in the performance of GAMS generating the problem.

Thursday, March 12, 2015

gdx2sqlite –fast option

The –fast option in the tool gdx2sqlite is sometimes really helpful. This is especially the case if there are many tables:

image

The column avg table size indicates the average number of rows in a table. It looks like if this number is small the effect of –fast is most pronounced.

The –fast option will issue PRAGMA synchronous = OFF and PRAGMA journal_mode = MEMORY to SQLite.


Here is a nice presentation on SQLite:

Interesting tidbit: statistics on SQLite: 2e9 running instances, 5e5 applications (May 2014).