Here's a way to use the CLP solver with the ELEMENT predicate to solve your sample problem:
proc optmodel;
set ISET = 1..3;
set JSET = 1..3;
num a {ISET, JSET} = [
3 4 5
6 7 8
1 2 3
];
num v {ISET} = [100 200 300];
var Index {ISET} >= 1 <= 3 integer;
var X {ISET} integer;
min f = sum {i in ISET} v[i]*X[i];
/* X[i] = a[i,Index[i]] */
con ElementCon {i in ISET}:
element(Index[i], {j in JSET} a[i,j], X[i]);
solve;
print Index X;
quit;
[1] | Index | X |
---|---|---|
1 | 1 | 3 |
2 | 1 | 6 |
3 | 1 | 1 |
I neet to take the values from the input table that I put in the previous post if there is a way to do it. And create arrays.
Maybe I understood what you need.
The following code I wrote is very clumsy .
Maybe @RobPratt could give you succinct and better code.
/**************************************/
data have;
input cod $ vol pcs;
cards;
M1 100 10
M1 100 10.5
S1 300 11
S1 300 11.5
S2 400 12
S2 400 .
;
run;
data temp;
set have;
id+1;
run;
proc transpose data=temp out=temp2(where=(col1 is not missing));
by id cod;
var vol pcs;
run;
data vol pcs;
set temp2;
if _name_='vol' then output vol;
if _name_='pcs' then output pcs;
run;
proc sql;
create table temp3 as
select a.cod as cod,a.col1 as vol,b.col1 as pcs
from vol as a,pcs as b
where a.cod=b.cod;
quit;
data want;
set temp3;
if cod ne 'M1' then vol=-vol;
run;
/*Make marco variables to be parameters*/
proc sql noprint;
select count(*) into :nobs from want;
select pcs into :pcs separated by ' ' from want;
select vol into :vol separated by ' ' from want;
quit;
data idx;
set want;
by cod notsorted;
retain start;
if first.cod then start=_n_;
if last.cod then do;end=_n_;idx+1;output;end;
keep idx cod start end;
run;
filename x temp;
data _null_;
set idx;
file x;
put 'con con' idx +(-1)':sum{a' idx 'in ' start +(-1)'..' end '} a[a' idx +(-1)']=1;';
run;
proc optmodel;
set idx={1..&nobs.};
num x{idx}=[&pcs.];
num v{idx}=[&vol.];
var a{idx} binary;
min obj=abs(sum{i in idx} a[i]*x[i]*v[i]);
%include x;
solve linearize;
/* solve with blackbox; */
/* solve with clp ; */
print obj a x v;
quit;
Nice solution, I have just matched this issue:
OK. Try this code.
data have;
input cod $ vol pcs;
cards;
M1 100 10
M1 100 10.5
S1 300 11
S1 300 11.5
S2 400 12
S2 400 .
;
run;
data temp;
set have;
id+1;
run;
proc transpose data=temp out=temp2(where=(col1 is not missing));
by id cod;
var vol pcs;
run;
data vol pcs;
set temp2;
if _name_='vol' then output vol;
if _name_='pcs' then output pcs;
run;
proc sql;
create table temp3 as
select a.cod as cod,a.col1 as vol,b.col1 as pcs
from vol as a,pcs as b
where a.cod=b.cod;
quit;
data want;
set temp3;
if cod ne 'M1' then vol=-vol;
run;
/*Make marco variables to be parameters*/
data idx;
set want;
by cod notsorted;
retain start;
if first.cod then start=_n_;
if last.cod then do;end=_n_;idx+1;output;end;
keep idx cod start end;
run;
filename x temp;
data _null_;
set idx;
file x;
put 'con con' idx +(-1)':sum{a' idx 'in ' start +(-1)'..' end '} a[a' idx +(-1)']=1;';
run;
proc optmodel;
set idx ;
num x{idx};
num v{idx};
var a{idx} binary;
read data want into idx=[_n_] x=pcs v=vol ;
min obj=abs(sum{i in idx} a[i]*x[i]*v[i]);
%include x;
solve linearize;
/* solve with blackbox; */
/* solve with clp ; */
print obj a x v;
quit;
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.