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;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.