# Implementing column generation in SAS

I am currently trying to implement this model in SAS. Unfortunately, I always get this error. How can I solve this and finally get the final roster $$x$$ and the total value of $$slack_{ts}$$ (preferably in an Excel list)?

This is the code:

  /* declare sets and parameters */
set ISET, TSET, SSET;
num demand {TSET, SSET};

/* read input data here */
set ISET = {1, 2, 3};
set SSET = {1, 2, 3};
set TSET = {1, 2, 3, 4, 5, 6, 7};
num demand{TSET, SSET} = {(1, 1): 2, (1, 2): 1, (1, 3): 0, (2, 1): 1, (2, 2): 2, (2, 3): 0, (3, 1): 1, (3, 2): 1, (3, 3): 1,
(4, 1): 1, (4, 2): 2, (4, 3): 0, (5, 1): 2, (5, 2): 0, (5, 3): 1, (6, 1): 1, (6, 2): 1, (6, 3): 1,
(7, 1): 0, (7, 2): 3, (7, 3): 0};
/* Generate random values for alpha */
execute INIT_RANDOM(123); /* Set a seed for reproducibility */
alpha{i in ISET, t in TSET} = rand("Uniform", 0, 1);

/* declare decision variables */
var motivation {ISET, TSET, SSET} >= 0 <= 1;
var slack {TSET, SSET} >= 0;
var mood {ISET, TSET} >= 0 <= 1;
var x {ISET, TSET, SSET} binary;

/* declare objective */
minimize z = sum {t in TSET, s in SSET} slack[t,s];

/* declare constraints */
con SatisfyDemand {t in TSET, s in SSET}:
sum {i in ISET} motivation[i,t,s] + slack[t,s] = demand[t,s];

con Indicator {i in ISET, t in TSET, s in SSET}:
x[i,t,s] = 1 implies motivation[i,t,s] = mood[i,t]
suffixes=(block=i);

con MotivationImpliesX {i in ISET, t in TSET, s in SSET}:
motivation[i,t,s] <= x[i,t,s]
suffixes=(block=i);

con AlphaMood {i in ISET, t in TSET}:
alpha * sum {s in SSET} x[i,t,s] + mood[i,t] = 1
suffixes=(block=i);

/* call MILP solver with Dantzig-Wolfe decomposition algorithm */
solve with milp / decomp;

/* write output data here */
quit;


Here is correct SAS code. You need only one SOLVE statement, but I provided three for illustration. You can also read from data sets by using the READ DATA statement.

proc optmodel;
/* declare sets and parameters */
set ISET = 1..3, TSET = 1..3, SSET = 1..7;
num demand{TSET, SSET} = [
2, 1, 0,
1, 2, 0,
1, 1, 1,
1, 2, 0,
2, 0, 1,
1, 1, 1,
0, 3, 0
];
/* Generate random values for alpha */
call streaminit(123); /* Set a seed for reproducibility */
num alpha{ISET, TSET};
for {i in ISET, t in TSET} alpha[i,t] = rand("Uniform", 0, 1);

/* declare decision variables */
var motivation {ISET, TSET, SSET} >= 0 <= 1;
var slack {TSET, SSET} >= 0;
var mood {ISET, TSET} >= 0 <= 1;
var x {ISET, TSET, SSET} binary;

/* declare objective */
minimize z = sum {t in TSET, s in SSET} slack[t,s];

/* declare constraints */
con SatisfyDemand {t in TSET, s in SSET}:
sum {i in ISET} motivation[i,t,s] + slack[t,s] = demand[t,s];

con Indicator {i in ISET, t in TSET, s in SSET}:
x[i,t,s] = 1 implies motivation[i,t,s] = mood[i,t]
suffixes=(block=i);

con MotivationImpliesX {i in ISET, t in TSET, s in SSET}:
motivation[i,t,s] <= x[i,t,s]
suffixes=(block=i);

con AlphaMood {i in ISET, t in TSET}:
alpha[i,t] * sum {s in SSET} x[i,t,s] + mood[i,t] = 1
suffixes=(block=i);

/* call MILP solver with (default) branch-and-cut algorithm */
solve;

/* call MILP solver with Dantzig-Wolfe decomposition algorithm and connected components as blocks */
solve with milp / decomp=(method=concomp);

/* call MILP solver with Dantzig-Wolfe decomposition algorithm and user-defined blocks */
solve with milp / decomp;

/* write output data */
create data SolutionData_its from [i t s] x;
create data SolutionData_ts from [t s] slack;
quit;

proc export data=SolutionData_its dbms=xlsx
outfile="myoutfile1.xlsx"
replace;
run;

proc export data=SolutionData_ts dbms=xlsx
outfile="myoutfile2.xlsx"
replace;
run;