Operations Research topics: SAS/OR,
SAS Optimization, and SAS Simulation Studio

Combinations

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 17
Accepted Solution

Combinations

[ Edited ]

Hi,

 

If there are 66 items, we want to get 8 at a time. 66C6 = 5.7Billion+ combinations and look at the distribution from such event.

 

Each Item will have a value

 Item    1 to 8 has value of 1;
Item   9 to 16 has value of 2;
Item 17 to 24 has value of 3;
Item 25 to 32 has value of 4;
Item 33 to 40 has value of 5;
Item 41 to 48 has value of 6;
Item 49 to 56 has value of 7;
Item 57 to 64 has value of 8;
Item 65 to 66 has value of 0.3;

 

we want to get distribution on

count how many Eights can be formed with the items + how many 0.3 was drawn -> Ecnt

How many items not used to form eight -> Rcnt

how many 0.3 was drawn -> Jcnt

 

Examples are:

 

 1 2 2 2 2 2 6 8 -> Ecnt: 3(three groups of eights formed), Rcnt 1 (one item not used), Jcnt:0 (no 0.3 )

 1 1 1 1 2 2 2 5 -> Ecnt: 1, Rcnt 4(although 5 2 1 can also form 8 and there will be 5 remainder we consider forming less Remainder as possible) 

 

.3 1 2 2 2 2 8 8-> Ecnt 4, Rcnt 1,Jcnt 1

 

in the end we want 

EnctRcntJcntFreq
1001
110?
120?
130?
140?
150?
160?
170?
181?
200?
211?
....
....
....
800.

 

 

to generate this frequency i have the codes below, but it is too slow.

can anyone help me improve this or any idea on another way we can do this?

 

any help is appriciated.

 

%macro Loop;

 

/* suppress log generation 5.7Billion x  Xlog lines will kill any EG and desktop*/

  options nonotes nomlogic nomprint nosymbolgen nosource nosource2;

 

proc sql;

 Drop table FINAL, FINALX, temp;

quit;

%put Start: %sysfunc(time(),timeampm.);

 

/* create lexi comb 66C8 loop*/

%do i1=1 %to 59;

 %do i2=&i1+1 %to 60;

  %do i3=&i2+1 %to 61;

   %do i4=&i3+1 %to 62;

    %do i5=&i4+1 %to 63;

     %do i6=&i5+1 %to 64;

      %do i7=&i6+1 %to 65;

       %do i8=&i7+1 %to 66;

 

 

data temp;

/* initialize counters*/

Ecnt=0;

Rcnt=0;

Jcnt=0;

Freq=1;

 

/* Assign Value of cards*/

       if 1<=&i1<=8 then i1=1;

else if 9<=&i1<=16 then i1=2;

else if 17<=&i1<=24 then i1=3;

else if 25<=&i1<=32 then i1=4;

else if 33<=&i1<=40 then i1=5;

else if 41<=&i1<=48 then i1=6;

else if 49<=&i1<=56 then i1=7;

else if 57<=&i1<=64 then i1=8;

else if 65<=&i1<=66 then i1=.3;

      if 1<=&i2<=8  then i2=1;

else if 9<=&i2<=16 then i2=2;

else if 17<=&i2<=24 then i2=3;

else if 25<=&i2<=32 then i2=4;

else if 33<=&i2<=40 then i2=5;

else if 41<=&i2<=48 then i2=6;

else if 49<=&i2<=56 then i2=7;

else if 57<=&i2<=64 then i2=8;

else if 65<=&i2<=66 then i2=.3;

      if 1<=&i3<=8 then i3=1;

else if 9<=&i3<=16 then i3=2;

else if 17<=&i3<=24 then i3=3;

else if 25<=&i3<=32 then i3=4;

else if 33<=&i3<=40 then i3=5;

else if 41<=&i3<=48 then i3=6;

else if 49<=&i3<=56 then i3=7;

else if 57<=&i3<=64 then i3=8;

else if 65<=&i3<=66 then i3=.3;

      if 1<=&i4<=8 then i4=1;

else if 9<=&i4<=16 then i4=2;

else if 17<=&i4<=24 then i4=3;

else if 25<=&i4<=32 then i4=4;

else if 33<=&i4<=40 then i4=5;

else if 41<=&i4<=48 then i4=6;

else if 49<=&i4<=56 then i4=7;

else if 57<=&i4<=64 then i4=8;

else if 65<=&i4<=66 then i4=.3;

      if 1<=&i5<=8 then i5=1;

else if 9<=&i5<=16 then i5=2;

else if 17<=&i5<=24 then i5=3;

else if 25<=&i5<=32 then i5=4;

else if 33<=&i5<=40 then i5=5;

else if 41<=&i5<=48 then i5=6;

else if 49<=&i5<=56 then i5=7;

else if 57<=&i5<=64 then i5=8;

else if 65<=&i5<=66 then i5=.3;

      if 1<=&i6<=8 then i6=1;

else if 9<=&i6<=16 then i6=2;

else if 17<=&i6<=24 then i6=3;

else if 25<=&i6<=32 then i6=4;

else if 33<=&i6<=40 then i6=5;

else if 41<=&i6<=48 then i6=6;

else if 49<=&i6<=56 then i6=7;

else if 57<=&i6<=64 then i6=8;

else if 65<=&i6<=66 then i6=.3;

      if 1<=&i7<=8 then i7=1;

else if 9<=&i7<=16 then i7=2;

else if 17<=&i7<=24 then i7=3;

else if 25<=&i7<=32 then i7=4;

else if 33<=&i7<=40 then i7=5;

else if 41<=&i7<=48 then i7=6;

else if 49<=&i7<=56 then i7=7;

else if 57<=&i7<=64 then i7=8;

else if 65<=&i7<=66 then i7=.3;

      if 1<=&i8<=8 then i8=1;

else if 9<=&i8<=16 then i8=2;

else if 17<=&i8<=24 then i8=3;

else if 25<=&i8<=32 then i8=4;

else if 33<=&i8<=40 then i8=5;

else if 41<=&i8<=48 then i8=6;

else if 49<=&i8<=56 then i8=7;

else if 57<=&i8<=64 then i8=8;

else if 65<=&i8<=66 then i8=.3;

 

/* Check group of eights use most cards as possible C8 to C1*/

/* if combination sum is 8 then add to Ecnt counter and replace value as 0*/

/*C8*/

if i1+i2+i3+i4+i5+i6+i7+i8=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; i6=0; i7=0; i8=0

ecnt+1; end;

/*C7*/

if i2+i3+i4+i5+i6+i7+i8=8 then do; i2=0; i3=0; i4=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i3+i4+i5+i6+i7+i8=8 then do; i1=0; i3=0; i4=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i4+i5+i6+i7+i8=8 then do; i1=0; i2=0; i4=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i3+i5+i6+i7+i8=8 then do; i1=0; i2=0; i3=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i3+i4+i6+i7+i8=8 then do; i1=0; i2=0; i3=0; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i3+i4+i5+i7+i8=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i3+i4+i5+i6+i8=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1+i2+i3+i4+i5+i6+i7=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

/*C6*/

if i3+i4+i5+i6+i7+i8=8 then do;  i3=0; i4=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2+i4+i5+i6+i7+i8=8 then do;  i2=0; i4=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2+i3+i5+i6+i7+i8=8 then do;  i2=0; i3=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2+i3+i4+i6+i7+i8=8 then do;  i2=0; i3=0; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2+i3+i4+i5+i7+i8=8 then do;  i2=0; i3=0; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i2+i3+i4+i5+i6+i8=8 then do;  i2=0; i3=0; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i2+i3+i4+i5+i6+i7=8 then do;  i2=0; i3=0; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1+i4+i5+i6+i7+i8=8 then do; i1=0; i4=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i3+i5+i6+i7+i8=8 then do; i1=0; i3=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i3+i4+i6+i7+i8=8 then do; i1=0; i3=0; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i3+i4+i5+i7+i8=8 then do; i1=0; i3=0; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1+i3+i4+i5+i6+i8=8 then do; i1=0; i3=0; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1+i3+i4+i5+i6+i7=8 then do; i1=0; i3=0; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1+i2+i5+i6+i7+i8=8 then do; i1=0; i2=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i4+i6+i7+i8=8 then do; i1=0; i2=0; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i4+i5+i7+i8=8 then do; i1=0; i2=0; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i4+i5+i6+i8=8 then do; i1=0; i2=0; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1+i2+i4+i5+i6+i7=8 then do; i1=0; i2=0; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1+i2+i3+i6+i7+i8=8 then do; i1=0; i2=0; i3=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i3+i5+i7+i8=8 then do; i1=0; i2=0; i3=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i3+i5+i6+i8=8 then do; i1=0; i2=0; i3=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1+i2+i3+i5+i6+i7=8 then do; i1=0; i2=0; i3=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1+i2+i3+i4+i7+i8=8 then do; i1=0; i2=0; i3=0; i4=0; i7=0; i8=0; ecnt+1; end;

if i1+i2+i3+i4+i6+i8=8 then do; i1=0; i2=0; i3=0; i4=0; i6=0; i8=0; ecnt+1; end;

if i1+i2+i3+i4+i6+i7=8 then do; i1=0; i2=0; i3=0; i4=0; i6=0; i7=0; ecnt+1; end;

if i1+i2+i3+i4+i5+i8=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; i8=0; ecnt+1; end;

if i1+i2+i3+i4+i5+i7=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; i7=0; ecnt+1; end;

if i1+i2+i3+i4+i5+i6=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; i6=0; ecnt+1; end;

 

/*C5*/

if i1 + i2 + i3 + i4 + i5=8 then do; i1=0; i2=0; i3=0; i4=0; i5=0; ecnt+1; end;

if i1 + i2 + i3 + i4 + i6=8 then do; i1=0; i2=0; i3=0; i4=0; i6=0; ecnt+1; end;

if i1 + i2 + i3 + i4 + i7=8 then do; i1=0; i2=0; i3=0; i4=0; i7=0; ecnt+1; end;

if i1 + i2 + i3 + i4 + i8=8 then do; i1=0; i2=0; i3=0; i4=0; i8=0; ecnt+1; end;

if i1 + i2 + i3 + i5 + i6=8 then do; i1=0; i2=0; i3=0; i5=0; i6=0; ecnt+1; end;

if i1 + i2 + i3 + i5 + i7=8 then do; i1=0; i2=0; i3=0; i5=0; i7=0; ecnt+1; end;

if i1 + i2 + i3 + i5 + i8=8 then do; i1=0; i2=0; i3=0; i5=0; i8=0; ecnt+1; end;

if i1 + i2 + i3 + i6 + i7=8 then do; i1=0; i2=0; i3=0; i6=0; i7=0; ecnt+1; end;

if i1 + i2 + i3 + i6 + i8=8 then do; i1=0; i2=0; i3=0; i6=0; i8=0; ecnt+1; end;

if i1 + i2 + i3 + i7 + i8=8 then do; i1=0; i2=0; i3=0; i7=0; i8=0; ecnt+1; end;

if i1 + i2 + i4 + i5 + i6=8 then do; i1=0; i2=0; i4=0; i5=0; i6=0; ecnt+1; end;

if i1 + i2 + i4 + i5 + i7=8 then do; i1=0; i2=0; i4=0; i5=0; i7=0; ecnt+1; end;

if i1 + i2 + i4 + i5 + i8=8 then do; i1=0; i2=0; i4=0; i5=0; i8=0; ecnt+1; end;

if i1 + i2 + i4 + i6 + i7=8 then do; i1=0; i2=0; i4=0; i6=0; i7=0; ecnt+1; end;

if i1 + i2 + i4 + i6 + i8=8 then do; i1=0; i2=0; i4=0; i6=0; i8=0; ecnt+1; end;

if i1 + i2 + i4 + i7 + i8=8 then do; i1=0; i2=0; i4=0; i7=0; i8=0; ecnt+1; end;

if i1 + i2 + i5 + i6 + i7=8 then do; i1=0; i2=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1 + i2 + i5 + i6 + i8=8 then do; i1=0; i2=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1 + i2 + i5 + i7 + i8=8 then do; i1=0; i2=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1 + i2 + i6 + i7 + i8=8 then do; i1=0; i2=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1 + i3 + i4 + i5 + i6=8 then do; i1=0; i3=0; i4=0; i5=0; i6=0; ecnt+1; end;

if i1 + i3 + i4 + i5 + i7=8 then do; i1=0; i3=0; i4=0; i5=0; i7=0; ecnt+1; end;

if i1 + i3 + i4 + i5 + i8=8 then do; i1=0; i3=0; i4=0; i5=0; i8=0; ecnt+1; end;

if i1 + i3 + i4 + i6 + i7=8 then do; i1=0; i3=0; i4=0; i6=0; i7=0; ecnt+1; end;

if i1 + i3 + i4 + i6 + i8=8 then do; i1=0; i3=0; i4=0; i6=0; i8=0; ecnt+1; end;

if i1 + i3 + i4 + i7 + i8=8 then do; i1=0; i3=0; i4=0; i7=0; i8=0; ecnt+1; end;

if i1 + i3 + i5 + i6 + i7=8 then do; i1=0; i3=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1 + i3 + i5 + i6 + i8=8 then do; i1=0; i3=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1 + i3 + i5 + i7 + i8=8 then do; i1=0; i3=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1 + i3 + i6 + i7 + i8=8 then do; i1=0; i3=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1 + i4 + i5 + i6 + i7=8 then do; i1=0; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1 + i4 + i5 + i6 + i8=8 then do; i1=0; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1 + i4 + i5 + i7 + i8=8 then do; i1=0; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1 + i4 + i6 + i7 + i8=8 then do; i1=0; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i1 + i5 + i6 + i7 + i8=8 then do; i1=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2 + i3 + i4 + i5 + i6=8 then do; i2=0; i3=0; i4=0; i5=0; i6=0; ecnt+1; end;

if i2 + i3 + i4 + i5 + i7=8 then do; i2=0; i3=0; i4=0; i5=0; i7=0; ecnt+1; end;

if i2 + i3 + i4 + i5 + i8=8 then do; i2=0; i3=0; i4=0; i5=0; i8=0; ecnt+1; end;

if i2 + i3 + i4 + i6 + i7=8 then do; i2=0; i3=0; i4=0; i6=0; i7=0; ecnt+1; end;

if i2 + i3 + i4 + i6 + i8=8 then do; i2=0; i3=0; i4=0; i6=0; i8=0; ecnt+1; end;

if i2 + i3 + i4 + i7 + i8=8 then do; i2=0; i3=0; i4=0; i7=0; i8=0; ecnt+1; end;

if i2 + i3 + i5 + i6 + i7=8 then do; i2=0; i3=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i2 + i3 + i5 + i6 + i8=8 then do; i2=0; i3=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i2 + i3 + i5 + i7 + i8=8 then do; i2=0; i3=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i2 + i3 + i6 + i7 + i8=8 then do; i2=0; i3=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2 + i4 + i5 + i6 + i7=8 then do; i2=0; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i2 + i4 + i5 + i6 + i8=8 then do; i2=0; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i2 + i4 + i5 + i7 + i8=8 then do; i2=0; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i2 + i4 + i6 + i7 + i8=8 then do; i2=0; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2 + i5 + i6 + i7 + i8=8 then do; i2=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i3 + i4 + i5 + i6 + i7=8 then do; i3=0; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i3 + i4 + i5 + i6 + i8=8 then do; i3=0; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i3 + i4 + i5 + i7 + i8=8 then do; i3=0; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i3 + i4 + i6 + i7 + i8=8 then do; i3=0; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i3 + i5 + i6 + i7 + i8=8 then do; i3=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i4 + i5 + i6 + i7 + i8=8 then do; i4=0; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

 

 

/*C4*/

if i1+ i2+ i3+ i4=8 then do; i1=0; i2=0; i3=0; i4=0; ecnt+1; end;

if i1+ i2+ i3+ i5=8 then do; i1=0; i2=0; i3=0; i5=0; ecnt+1; end;

if i1+ i2+ i3+ i6=8 then do; i1=0; i2=0; i3=0; i6=0; ecnt+1; end;

if i1+ i2+ i3+ i7=8 then do; i1=0; i2=0; i3=0; i7=0; ecnt+1; end;

if i1+ i2+ i3+ i8=8 then do; i1=0; i2=0; i3=0; i8=0; ecnt+1; end;

if i1+ i2+ i4+ i5=8 then do; i1=0; i2=0; i4=0; i5=0; ecnt+1; end;

if i1+ i2+ i4+ i6=8 then do; i1=0; i2=0; i4=0; i6=0; ecnt+1; end;

if i1+ i2+ i4+ i7=8 then do; i1=0; i2=0; i4=0; i7=0; ecnt+1; end;

if i1+ i2+ i4+ i8=8 then do; i1=0; i2=0; i4=0; i8=0; ecnt+1; end;

if i1+ i2+ i5+ i6=8 then do; i1=0; i2=0; i5=0; i6=0; ecnt+1; end;

if i1+ i2+ i5+ i7=8 then do; i1=0; i2=0; i5=0; i7=0; ecnt+1; end;

if i1+ i2+ i5+ i8=8 then do; i1=0; i2=0; i5=0; i8=0; ecnt+1; end;

if i1+ i2+ i6+ i7=8 then do; i1=0; i2=0; i6=0; i7=0; ecnt+1; end;

if i1+ i2+ i6+ i8=8 then do; i1=0; i2=0; i6=0; i8=0; ecnt+1; end;

if i1+ i2+ i7+ i8=8 then do; i1=0; i2=0; i7=0; i8=0; ecnt+1; end;

if i1+ i3+ i4+ i5=8 then do; i1=0; i3=0; i4=0; i5=0; ecnt+1; end;

if i1+ i3+ i4+ i6=8 then do; i1=0; i3=0; i4=0; i6=0; ecnt+1; end;

if i1+ i3+ i4+ i7=8 then do; i1=0; i3=0; i4=0; i7=0; ecnt+1; end;

if i1+ i3+ i4+ i8=8 then do; i1=0; i3=0; i4=0; i8=0; ecnt+1; end;

if i1+ i3+ i5+ i6=8 then do; i1=0; i3=0; i5=0; i6=0; ecnt+1; end;

if i1+ i3+ i5+ i7=8 then do; i1=0; i3=0; i5=0; i7=0; ecnt+1; end;

if i1+ i3+ i5+ i8=8 then do; i1=0; i3=0; i5=0; i8=0; ecnt+1; end;

if i1+ i3+ i6+ i7=8 then do; i1=0; i3=0; i6=0; i7=0; ecnt+1; end;

if i1+ i3+ i6+ i8=8 then do; i1=0; i3=0; i6=0; i8=0; ecnt+1; end;

if i1+ i3+ i7+ i8=8 then do; i1=0; i3=0; i7=0; i8=0; ecnt+1; end;

if i1+ i4+ i5+ i6=8 then do; i1=0; i4=0; i5=0; i6=0; ecnt+1; end;

if i1+ i4+ i5+ i7=8 then do; i1=0; i4=0; i5=0; i7=0; ecnt+1; end;

if i1+ i4+ i5+ i8=8 then do; i1=0; i4=0; i5=0; i8=0; ecnt+1; end;

if i1+ i4+ i6+ i7=8 then do; i1=0; i4=0; i6=0; i7=0; ecnt+1; end;

if i1+ i4+ i6+ i8=8 then do; i1=0; i4=0; i6=0; i8=0; ecnt+1; end;

if i1+ i4+ i7+ i8=8 then do; i1=0; i4=0; i7=0; i8=0; ecnt+1; end;

if i1+ i5+ i6+ i7=8 then do; i1=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i1+ i5+ i6+ i8=8 then do; i1=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i1+ i5+ i7+ i8=8 then do; i1=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i1+ i6+ i7+ i8=8 then do; i1=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i2+ i3+ i4+ i5=8 then do; i2=0; i3=0; i4=0; i5=0; ecnt+1; end;

if i2+ i3+ i4+ i6=8 then do; i2=0; i3=0; i4=0; i6=0; ecnt+1; end;

if i2+ i3+ i4+ i7=8 then do; i2=0; i3=0; i4=0; i7=0; ecnt+1; end;

if i2+ i3+ i4+ i8=8 then do; i2=0; i3=0; i4=0; i8=0; ecnt+1; end;

if i2+ i3+ i5+ i6=8 then do; i2=0; i3=0; i5=0; i6=0; ecnt+1; end;

if i2+ i3+ i5+ i7=8 then do; i2=0; i3=0; i5=0; i7=0; ecnt+1; end;

if i2+ i3+ i5+ i8=8 then do; i2=0; i3=0; i5=0; i8=0; ecnt+1; end;

if i2+ i3+ i6+ i7=8 then do; i2=0; i3=0; i6=0; i7=0; ecnt+1; end;

if i2+ i3+ i6+ i8=8 then do; i2=0; i3=0; i6=0; i8=0; ecnt+1; end;

if i2+ i3+ i7+ i8=8 then do; i2=0; i3=0; i7=0; i8=0; ecnt+1; end;

if i2+ i4+ i5+ i6=8 then do; i2=0; i4=0; i5=0; i6=0; ecnt+1; end;

if i2+ i4+ i5+ i7=8 then do; i2=0; i4=0; i5=0; i7=0; ecnt+1; end;

if i2+ i4+ i5+ i8=8 then do; i2=0; i4=0; i5=0; i8=0; ecnt+1; end;

if i2+ i4+ i6+ i7=8 then do; i2=0; i4=0; i6=0; i7=0; ecnt+1; end;

if i2+ i4+ i6+ i8=8 then do; i2=0; i4=0; i6=0; i8=0; ecnt+1; end;

if i2+ i4+ i7+ i8=8 then do; i2=0; i4=0; i7=0; i8=0; ecnt+1; end;

if i2+ i5+ i6+ i7=8 then do; i2=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i2+ i5+ i6+ i8=8 then do; i2=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i2+ i5+ i7+ i8=8 then do; i2=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i2+ i6+ i7+ i8=8 then do; i2=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i3+ i4+ i5+ i6=8 then do; i3=0; i4=0; i5=0; i6=0; ecnt+1; end;

if i3+ i4+ i5+ i7=8 then do; i3=0; i4=0; i5=0; i7=0; ecnt+1; end;

if i3+ i4+ i5+ i8=8 then do; i3=0; i4=0; i5=0; i8=0; ecnt+1; end;

if i3+ i4+ i6+ i7=8 then do; i3=0; i4=0; i6=0; i7=0; ecnt+1; end;

if i3+ i4+ i6+ i8=8 then do; i3=0; i4=0; i6=0; i8=0; ecnt+1; end;

if i3+ i4+ i7+ i8=8 then do; i3=0; i4=0; i7=0; i8=0; ecnt+1; end;

if i3+ i5+ i6+ i7=8 then do; i3=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i3+ i5+ i6+ i8=8 then do; i3=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i3+ i5+ i7+ i8=8 then do; i3=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i3+ i6+ i7+ i8=8 then do; i3=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i4+ i5+ i6+ i7=8 then do; i4=0; i5=0; i6=0; i7=0; ecnt+1; end;

if i4+ i5+ i6+ i8=8 then do; i4=0; i5=0; i6=0; i8=0; ecnt+1; end;

if i4+ i5+ i7+ i8=8 then do; i4=0; i5=0; i7=0; i8=0; ecnt+1; end;

if i4+ i6+ i7+ i8=8 then do; i4=0; i6=0; i7=0; i8=0; ecnt+1; end;

if i5+ i6+ i7+ i8=8 then do; i5=0; i6=0; i7=0; i8=0; ecnt+1; end;

 

/*C3*/

if i1+ i2+ i3=8 then do; i1=0; i2=0; i3=0; ecnt+1; end;

if i1+ i2+ i4=8 then do; i1=0; i2=0; i4=0; ecnt+1; end;

if i1+ i2+ i5=8 then do; i1=0; i2=0; i5=0; ecnt+1; end;

if i1+ i2+ i6=8 then do; i1=0; i2=0; i6=0; ecnt+1; end;

if i1+ i2+ i7=8 then do; i1=0; i2=0; i7=0; ecnt+1; end;

if i1+ i2+ i8=8 then do; i1=0; i2=0; i8=0; ecnt+1; end;

if i1+ i3+ i4=8 then do; i1=0; i3=0; i4=0; ecnt+1; end;

if i1+ i3+ i5=8 then do; i1=0; i3=0; i5=0; ecnt+1; end;

if i1+ i3+ i6=8 then do; i1=0; i3=0; i6=0; ecnt+1; end;

if i1+ i3+ i7=8 then do; i1=0; i3=0; i7=0; ecnt+1; end;

if i1+ i3+ i8=8 then do; i1=0; i3=0; i8=0; ecnt+1; end;

if i1+ i4+ i5=8 then do; i1=0; i4=0; i5=0; ecnt+1; end;

if i1+ i4+ i6=8 then do; i1=0; i4=0; i6=0; ecnt+1; end;

if i1+ i4+ i7=8 then do; i1=0; i4=0; i7=0; ecnt+1; end;

if i1+ i4+ i8=8 then do; i1=0; i4=0; i8=0; ecnt+1; end;

if i1+ i5+ i6=8 then do; i1=0; i5=0; i6=0; ecnt+1; end;

if i1+ i5+ i7=8 then do; i1=0; i5=0; i7=0; ecnt+1; end;

if i1+ i5+ i8=8 then do; i1=0; i5=0; i8=0; ecnt+1; end;

if i1+ i6+ i7=8 then do; i1=0; i6=0; i7=0; ecnt+1; end;

if i1+ i6+ i8=8 then do; i1=0; i6=0; i8=0; ecnt+1; end;

if i1+ i7+ i8=8 then do; i1=0; i7=0; i8=0; ecnt+1; end;

if i2+ i3+ i4=8 then do; i2=0; i3=0; i4=0; ecnt+1; end;

if i2+ i3+ i5=8 then do; i2=0; i3=0; i5=0; ecnt+1; end;

if i2+ i3+ i6=8 then do; i2=0; i3=0; i6=0; ecnt+1; end;

if i2+ i3+ i7=8 then do; i2=0; i3=0; i7=0; ecnt+1; end;

if i2+ i3+ i8=8 then do; i2=0; i3=0; i8=0; ecnt+1; end;

if i2+ i4+ i5=8 then do; i2=0; i4=0; i5=0; ecnt+1; end;

if i2+ i4+ i6=8 then do; i2=0; i4=0; i6=0; ecnt+1; end;

if i2+ i4+ i7=8 then do; i2=0; i4=0; i7=0; ecnt+1; end;

if i2+ i4+ i8=8 then do; i2=0; i4=0; i8=0; ecnt+1; end;

if i2+ i5+ i6=8 then do; i2=0; i5=0; i6=0; ecnt+1; end;

if i2+ i5+ i7=8 then do; i2=0; i5=0; i7=0; ecnt+1; end;

if i2+ i5+ i8=8 then do; i2=0; i5=0; i8=0; ecnt+1; end;

if i2+ i6+ i7=8 then do; i2=0; i6=0; i7=0; ecnt+1; end;

if i2+ i6+ i8=8 then do; i2=0; i6=0; i8=0; ecnt+1; end;

if i2+ i7+ i8=8 then do; i2=0; i7=0; i8=0; ecnt+1; end;

if i3+ i4+ i5=8 then do; i3=0; i4=0; i5=0; ecnt+1; end;

if i3+ i4+ i6=8 then do; i3=0; i4=0; i6=0; ecnt+1; end;

if i3+ i4+ i7=8 then do; i3=0; i4=0; i7=0; ecnt+1; end;

if i3+ i4+ i8=8 then do; i3=0; i4=0; i8=0; ecnt+1; end;

if i3+ i5+ i6=8 then do; i3=0; i5=0; i6=0; ecnt+1; end;

if i3+ i5+ i7=8 then do; i3=0; i5=0; i7=0; ecnt+1; end;

if i3+ i5+ i8=8 then do; i3=0; i5=0; i8=0; ecnt+1; end;

if i3+ i6+ i7=8 then do; i3=0; i6=0; i7=0; ecnt+1; end;

if i3+ i6+ i8=8 then do; i3=0; i6=0; i8=0; ecnt+1; end;

if i3+ i7+ i8=8 then do; i3=0; i7=0; i8=0; ecnt+1; end;

if i4+ i5+ i6=8 then do; i4=0; i5=0; i6=0; ecnt+1; end;

if i4+ i5+ i7=8 then do; i4=0; i5=0; i7=0; ecnt+1; end;

if i4+ i5+ i8=8 then do; i4=0; i5=0; i8=0; ecnt+1; end;

if i4+ i6+ i7=8 then do; i4=0; i6=0; i7=0; ecnt+1; end;

if i4+ i6+ i8=8 then do; i4=0; i6=0; i8=0; ecnt+1; end;

if i4+ i7+ i8=8 then do; i4=0; i7=0; i8=0; ecnt+1; end;

if i5+ i6+ i7=8 then do; i5=0; i6=0; i7=0; ecnt+1; end;

if i5+ i6+ i8=8 then do; i5=0; i6=0; i8=0; ecnt+1; end;

if i5+ i7+ i8=8 then do; i5=0; i7=0; i8=0; ecnt+1; end;

if i6+ i7+ i8=8 then do; i6=0; i7=0; i8=0; ecnt+1; end;

 

/*C2*/

if i1+ i2=8 then do; i1=0; i2=0; ecnt+1; end;

if i1+ i3=8 then do; i1=0; i3=0; ecnt+1; end;

if i1+ i4=8 then do; i1=0; i4=0; ecnt+1; end;

if i1+ i5=8 then do; i1=0; i5=0; ecnt+1; end;

if i1+ i6=8 then do; i1=0; i6=0; ecnt+1; end;

if i1+ i7=8 then do; i1=0; i7=0; ecnt+1; end;

if i1+ i8=8 then do; i1=0; i8=0; ecnt+1; end;

if i2+ i3=8 then do; i2=0; i3=0; ecnt+1; end;

if i2+ i4=8 then do; i2=0; i4=0; ecnt+1; end;

if i2+ i5=8 then do; i2=0; i5=0; ecnt+1; end;

if i2+ i6=8 then do; i2=0; i6=0; ecnt+1; end;

if i2+ i7=8 then do; i2=0; i7=0; ecnt+1; end;

if i2+ i8=8 then do; i2=0; i8=0; ecnt+1; end;

if i3+ i4=8 then do; i3=0; i4=0; ecnt+1; end;

if i3+ i5=8 then do; i3=0; i5=0; ecnt+1; end;

if i3+ i6=8 then do; i3=0; i6=0; ecnt+1; end;

if i3+ i7=8 then do; i3=0; i7=0; ecnt+1; end;

if i3+ i8=8 then do; i3=0; i8=0; ecnt+1; end;

if i4+ i5=8 then do; i4=0; i5=0; ecnt+1; end;

if i4+ i6=8 then do; i4=0; i6=0; ecnt+1; end;

if i4+ i7=8 then do; i4=0; i7=0; ecnt+1; end;

if i4+ i8=8 then do; i4=0; i8=0; ecnt+1; end;

if i5+ i6=8 then do; i5=0; i6=0; ecnt+1; end;

if i5+ i7=8 then do; i5=0; i7=0; ecnt+1; end;

if i5+ i8=8 then do; i5=0; i8=0; ecnt+1; end;

if i6+ i7=8 then do; i6=0; i7=0; ecnt+1; end;

if i6+ i8=8 then do; i6=0; i8=0; ecnt+1; end;

if i7+ i8=8 then do; i7=0; i8=0; ecnt+1; end;

 

/*C1*/

if i8=8 then do; i8=0; ecnt+1; end;

if i7=8 then do; i7=0; ecnt+1; end;

if i6=8 then do; i6=0; ecnt+1; end;

if i5=8 then do; i5=0; ecnt+1; end;

if i4=8 then do; i4=0; ecnt+1; end;

if i3=8 then do; i3=0; ecnt+1; end;

if i2=8 then do; i2=0; ecnt+1; end;

if i1=8 then do; i1=0; ecnt+1; end;

 

/*cards not used*/

if i1>0 then Rcnt+1;

if i2>0 then Rcnt+1;

if i3>0 then Rcnt+1;

if i4>0 then Rcnt+1;

if i5>0 then Rcnt+1;

if i6>0 then Rcnt+1;

if i7>0 then Rcnt+1;

if i8>0 then Rcnt+1;

 

/*Joker*/

if i1=.3 then do; Jcnt+1; ecnt+1; end;

if i2=.3 then do; Jcnt+1; ecnt+1; end;

if i3=.3 then do; Jcnt+1; ecnt+1; end;

if i4=.3 then do; Jcnt+1; ecnt+1; end;

if i5=.3 then do; Jcnt+1; ecnt+1; end;

if i6=.3 then do; Jcnt+1; ecnt+1; end;

if i7=.3 then do; Jcnt+1; ecnt+1; end;

if i8=.3 then do; Jcnt+1; ecnt+1; end;

 

keep Ecnt Rcnt Jcnt Freq;

 

run;

 

/* append result to Freq table*/

proc append base=FINAL data=temp force;

quit;

 

/* summarize freq table w/o recurrsive warning*/

proc sql;

create table FINALx as

select Ecnt , Rcnt , Jcnt , sum(Freq) as Freq

from FINAL

group by  Ecnt , Rcnt , Jcnt;

 

create table FINAL as

select * from FINALX;

 

Drop table FINALX, temp;

 

quit;

 

/* repeat*/

       %end;

      %end;

     %end;

    %end;

   %end;

  %end;

 %end;

%end;

 

 

 

%put END: %sysfunc(time(),timeampm.);

 

%mend loop;

 

%loop;


Accepted Solutions
Solution
‎05-20-2016 01:27 AM
SAS Employee
Posts: 448

Re: Combinations

If I understand your problem correctly, the following PROC OPTMODEL code should do what you want.  It calls the CLP solver to find the 11,583 combinations and then calls the MILP solver in a COFOR loop to optimize each combination.  It takes about 30 seconds on my machine.

 

proc optmodel printlevel=0;
   num n = 9;
   num Xub {j in 1..n} = (if j <= 8 then 8 else 2);
   /* X[j] = number of copies of j chosen */
   var X {j in 1..n} integer >= 0 <= Xub[j];
   con ChooseEight:
      sum {j in 1..n} X[j] = 8;
   problem P1 include X ChooseEight;
   use problem P1;
   solve with CLP / findallsolns;
   num nsol1;
   num xsol {1..n, 1..nsol1};
   num solsum {1..nsol1};
   nsol1 = _NSOL_;
   for {s in 1..nsol1} do;
      for {j in 1..n} xsol[j,s] = round(X[j].sol[s]);
      solsum[s] = sum {j in 1..n-1} j * xsol[j,s];
   end;

   /* for each solution, maximize the number of groups with sum 8 and minimize remainder */
   num curr_sol;
   set GROUPS = 1..solsum[curr_sol]/8;
   var NumInGroup {j in 1..n-1, GROUPS} integer >= 0 <= xsol[j,curr_sol];
   var Unassigned {j in 1..n-1}         integer >= 0 <= xsol[j,curr_sol];
   var IsEight {GROUPS} binary;
   /* primary objective: maximize NumEights, secondary objective: minimize NumUnassigned */
   impvar NumEights     = sum {g in GROUPS} IsEight[g];
   impvar NumUnassigned = sum {j in 1..n-1} Unassigned[j];
   /* 1-unit increase in NumEights is more valuable than 8-unit decrease in NumUnassigned */
   max Objective = 9 * NumEights - NumUnassigned;
   con NumInGroupCon {j in 1..n-1}:
      sum {g in GROUPS} NumInGroup[j,g] + Unassigned[j] = xsol[j,curr_sol];
   con IsEightCon {g in GROUPS}:
      sum {j in 1..n-1} j * NumInGroup[j,g] = 8 * IsEight[g];
   problem P2 include NumInGroup Unassigned IsEight Objective NumInGroupCon IsEightCon;
   use problem P2;

   str solstatus {1..nsol1};
   num Ecnt {1..nsol1};
   num Rcnt {1..nsol1};
   num Jcnt {1..nsol1};
   num count {1..nsol1};
   /* independent problems, so can solve in parallel by using COFOR */
   option nonotes;
   cofor {s in 1..nsol1} do;
      curr_sol = s;
      solve;
      solstatus[s] = _solution_status_;
      Jcnt[s] = xsol[n,s];
      Ecnt[s] = round(NumEights.sol + Jcnt[s]);
      Rcnt[s] = round(sum {j in 1..n-1} Unassigned[j].sol);
      count[s] = prod {j in 1..n} comb(Xub[j],xsol[j,s]);
   end;
   option notes;
   create data out(drop=s) from [s]=(1..nsol1) solstatus
      {j in 1..n} <col('X'||j)=xsol[j,s]>
      Ecnt Rcnt Jcnt count;
quit;

proc freq data=out noprint;
   table Ecnt*Rcnt*Jcnt / out=freqout(rename=(count=Freq));
   weight count;
quit;

/* check that total is comb(66,8) */
proc sql;
   select sum(Freq) format=best20., comb(66,8) format=best20. from freqout;
quit;

View solution in original post


All Replies
Super User
Posts: 5,317

Re: Combinations

I don't work with OR or mathematics, so i clearly don't understand what you are trying to achieve.

But I guess that your problem is programmatic, so you could benefit from help from ordinary programmers if you can explain your problem, in more popular terms.

Like, what is a "0.3", and "5.7B"?

please provide some sample input data, and desired outcome (and with an explanation how you wish to use the output further). 

Data never sleeps
Occasional Contributor
Posts: 17

Re: Combinations

[ Edited ]

hi @LinusH,

 

we want to take 66C8. out of the 66 items we want to take 8 at a time and see the distribution of Ecnt Rcnt and Jcnt.

 

problem is taking 66C8 would have 5.7Billion outcomes.

0.3 is just a value that we want to keep track of with Jcnt.(well Ecnt as well)

 

EcntRcntJcntFreq
1001
110?
120?
130?
140?
150?
160?
170?
181?
200?
211?
....
....
....
800.
Super User
Posts: 18,577

Re: Combinations

[ Edited ]

That doesn't help a lot with explanations. From a code perspective, look at the DRY principle - Don't Repeat Yourself. Your code has a lot of that so find ways to simplify it. For example consider a format instead of all of the IF/Then for this particular piece of logic. 

 

Or it looks like it's mathematically equivalent to

i1=ifn(&i1<=64, floor((&i1-1)/8), 0.3);

 

/* Assign Value of cards*/
       if 1<=&i1<=8 then i1=1;
else if 9<=&i1<=16 then i1=2;
else if 17<=&i1<=24 then i1=3;
else if 25<=&i1<=32 then i1=4;
else if 33<=&i1<=40 then i1=5;
else if 41<=&i1<=48 then i1=6;
else if 49<=&i1<=56 then i1=7;
else if 57<=&i1<=64 then i1=8;
else if 65<=&i1<=66 then i1=.3;
      if 1<=&i2<=8  then i2=1;
else if 9<=&i2<=16 then i2=2;
else if 17<=&i2<=24 then i2=3;
else if 25<=&i2<=32 then i2=4;
else if 33<=&i2<=40 then i2=5;
else if 41<=&i2<=48 then i2=6;
else if 49<=&i2<=56 then i2=7;
else if 57<=&i2<=64 then i2=8;
else if 65<=&i2<=66 then i2=.3;
      if 1<=&i3<=8 then i3=1;
else if 9<=&i3<=16 then i3=2;
else if 17<=&i3<=24 then i3=3;
else if 25<=&i3<=32 then i3=4;
else if 33<=&i3<=40 then i3=5;
else if 41<=&i3<=48 then i3=6;
else if 49<=&i3<=56 then i3=7;
else if 57<=&i3<=64 then i3=8;
else if 65<=&i3<=66 then i3=.3;
      if 1<=&i4<=8 then i4=1;
else if 9<=&i4<=16 then i4=2;
else if 17<=&i4<=24 then i4=3;
else if 25<=&i4<=32 then i4=4;
else if 33<=&i4<=40 then i4=5;
else if 41<=&i4<=48 then i4=6;
else if 49<=&i4<=56 then i4=7;
else if 57<=&i4<=64 then i4=8;
else if 65<=&i4<=66 then i4=.3;
      if 1<=&i5<=8 then i5=1;
else if 9<=&i5<=16 then i5=2;
else if 17<=&i5<=24 then i5=3;
else if 25<=&i5<=32 then i5=4;
else if 33<=&i5<=40 then i5=5;
else if 41<=&i5<=48 then i5=6;
else if 49<=&i5<=56 then i5=7;
else if 57<=&i5<=64 then i5=8;
else if 65<=&i5<=66 then i5=.3;
      if 1<=&i6<=8 then i6=1;
else if 9<=&i6<=16 then i6=2;
else if 17<=&i6<=24 then i6=3;
else if 25<=&i6<=32 then i6=4;
else if 33<=&i6<=40 then i6=5;
else if 41<=&i6<=48 then i6=6;
else if 49<=&i6<=56 then i6=7;
else if 57<=&i6<=64 then i6=8;
else if 65<=&i6<=66 then i6=.3;
      if 1<=&i7<=8 then i7=1;
else if 9<=&i7<=16 then i7=2;
else if 17<=&i7<=24 then i7=3;
else if 25<=&i7<=32 then i7=4;
else if 33<=&i7<=40 then i7=5;
else if 41<=&i7<=48 then i7=6;
else if 49<=&i7<=56 then i7=7;
else if 57<=&i7<=64 then i7=8;
else if 65<=&i7<=66 then i7=.3;
      if 1<=&i8<=8 then i8=1;
else if 9<=&i8<=16 then i8=2;
else if 17<=&i8<=24 then i8=3;
else if 25<=&i8<=32 then i8=4;
else if 33<=&i8<=40 then i8=5;
else if 41<=&i8<=48 then i8=6;
else if 49<=&i8<=56 then i8=7;
else if 57<=&i8<=64 then i8=8;
else if 65<=&i8<=66 then i8=.3;

 

 

 

Occasional Contributor
Posts: 17

Re: Combinations

@ReezaGreate tip. i chaged it to i1=ifn(&i1<=64, CEIL((&i1)/8), 0.3); 

 

basically given there are 8pcs of 1, 2, 3,4,5,6,7and8, and 2pcs 0.3. if you randomly take 8pcs there would be 5.7Billion possible results. and we want to get frequency distribution of how many groups of 8 can be formed, 0.3 appearance and how many items are left out or not used.

creating 5.7Billion is too big so i created the codes to check each combination 1 at a time and update the freqncy table but it takes too long.

Trusted Advisor
Posts: 1,115

Re: Combinations

Hi @Tj_chua,

 

Please note that your nested macro %DO loops would produce comb(66,8)*362=2,079,173,107,440 (>2.0E12) lines of SAS code (not counting blank lines and comments) to be sent to the compiler. You say "it is too slow." I doubt it is even possible.

 

You should do as much as possible with data step DO loops and simplify repetitive code by using arrays and mathematical functions (cf. Reeza's suggestion).

 

Most importantly, you should follow the advice I gave you in the other thread: Loop through the 11,583 different combinations of values and not through the 5,743,572,120 different combinations of items. Given the fairly complicated operations you want to perform in each iteration, you should really take the opportunity to reduce the number of iterations by a factor of about 500,000.

 

Also, I'm still a bit skeptical about your definitions. In my last post in the other thread I gave an example of a combination where different numbers of eights could be formed with the same number of "remaining items." So, your criterion "we consider forming less Remainder as possible" should be defined more precisely.

Super User
Posts: 10,871

Re: Combinations

Try this code. The result will have 8 values as the combinations. NOTE: it will take awhile to run. I will leave you to use the result to calculate the rest as I cannont wait long enough for this to complete. NOTE: The results are generated in minimum change order so it takes a largish number of iterations to get to where your combinations have many values containing 7s and 8s, much less the 0.3s.

data junk;
   array x x1-x66;
   do _i_ = 1 to 64;
      x[_i_] = ceil(_i_/8);
   end;
   x[65]=0.3;
   x[66]=0.3;
   array c[8] ;/* to hold results*/
   array i[8] (0 0 0 0 0 0 0 0) ;/* index values into array x*/
   n=dim(x);
   k=dim(i);
   ncomb=comb(n,k);
   do j=1 to ncomb;
/*   do j=1 to 50;*/
      call allcombi(n,k, of i[*]);
      do h=1 to k;
         c[h]=x[i[h]];
      end;
      output;
   end;
   keep c: ;
run; 
Super User
Posts: 10,871

Re: Combinations

Try this code. The result will have 8 values as the combinations. NOTE: it will take awhile to run. I will leave you to use the result to calculate the rest as I cannont wait long enough for this to complete. NOTE: The results are generated in minimum change order so it takes a largish number of iterations to get to where your combinations have many values containing 7s and 8s, much less the 0.3s.

data junk;
   array x x1-x66;
   do _i_ = 1 to 64;
      x[_i_] = ceil(_i_/8);
   end;
   x[65]=0.3;
   x[66]=0.3;
   array c[8] ;/* to hold results*/
   array i[8] (0 0 0 0 0 0 0 0) ;/* index values into array x*/
   n=dim(x);
   k=dim(i);
   ncomb=comb(n,k);
   do j=1 to ncomb;
/*   do j=1 to 50;*/
      call allcombi(n,k, of i[*]);
      do h=1 to k;
         c[h]=x[i[h]];
      end;
      output;
   end;
   keep c: ;
run; 
Super User
Posts: 10,871

Re: Combinations

Try this code. The result will have 8 values as the combinations. NOTE: it will take awhile to run. I will leave you to use the result to calculate the rest as I cannont wait long enough for this to complete. NOTE: The results are generated in minimum change order so it takes a largish number of iterations to get to where your combinations have many values containing 7s and 8s, much less the 0.3s.

data junk;
   array x x1-x66;
   do _i_ = 1 to 64;
      x[_i_] = ceil(_i_/8);
   end;
   x[65]=0.3;
   x[66]=0.3;
   array c[8] ;/* to hold results*/
   array i[8] (0 0 0 0 0 0 0 0) ;/* index values into array x*/
   n=dim(x);
   k=dim(i);
   ncomb=comb(n,k);
   do j=1 to ncomb;
/*   do j=1 to 50;*/
      call allcombi(n,k, of i[*]);
      do h=1 to k;
         c[h]=x[i[h]];
      end;
      output;
   end;
   keep c: ;
run; 
Solution
‎05-20-2016 01:27 AM
SAS Employee
Posts: 448

Re: Combinations

If I understand your problem correctly, the following PROC OPTMODEL code should do what you want.  It calls the CLP solver to find the 11,583 combinations and then calls the MILP solver in a COFOR loop to optimize each combination.  It takes about 30 seconds on my machine.

 

proc optmodel printlevel=0;
   num n = 9;
   num Xub {j in 1..n} = (if j <= 8 then 8 else 2);
   /* X[j] = number of copies of j chosen */
   var X {j in 1..n} integer >= 0 <= Xub[j];
   con ChooseEight:
      sum {j in 1..n} X[j] = 8;
   problem P1 include X ChooseEight;
   use problem P1;
   solve with CLP / findallsolns;
   num nsol1;
   num xsol {1..n, 1..nsol1};
   num solsum {1..nsol1};
   nsol1 = _NSOL_;
   for {s in 1..nsol1} do;
      for {j in 1..n} xsol[j,s] = round(X[j].sol[s]);
      solsum[s] = sum {j in 1..n-1} j * xsol[j,s];
   end;

   /* for each solution, maximize the number of groups with sum 8 and minimize remainder */
   num curr_sol;
   set GROUPS = 1..solsum[curr_sol]/8;
   var NumInGroup {j in 1..n-1, GROUPS} integer >= 0 <= xsol[j,curr_sol];
   var Unassigned {j in 1..n-1}         integer >= 0 <= xsol[j,curr_sol];
   var IsEight {GROUPS} binary;
   /* primary objective: maximize NumEights, secondary objective: minimize NumUnassigned */
   impvar NumEights     = sum {g in GROUPS} IsEight[g];
   impvar NumUnassigned = sum {j in 1..n-1} Unassigned[j];
   /* 1-unit increase in NumEights is more valuable than 8-unit decrease in NumUnassigned */
   max Objective = 9 * NumEights - NumUnassigned;
   con NumInGroupCon {j in 1..n-1}:
      sum {g in GROUPS} NumInGroup[j,g] + Unassigned[j] = xsol[j,curr_sol];
   con IsEightCon {g in GROUPS}:
      sum {j in 1..n-1} j * NumInGroup[j,g] = 8 * IsEight[g];
   problem P2 include NumInGroup Unassigned IsEight Objective NumInGroupCon IsEightCon;
   use problem P2;

   str solstatus {1..nsol1};
   num Ecnt {1..nsol1};
   num Rcnt {1..nsol1};
   num Jcnt {1..nsol1};
   num count {1..nsol1};
   /* independent problems, so can solve in parallel by using COFOR */
   option nonotes;
   cofor {s in 1..nsol1} do;
      curr_sol = s;
      solve;
      solstatus[s] = _solution_status_;
      Jcnt[s] = xsol[n,s];
      Ecnt[s] = round(NumEights.sol + Jcnt[s]);
      Rcnt[s] = round(sum {j in 1..n-1} Unassigned[j].sol);
      count[s] = prod {j in 1..n} comb(Xub[j],xsol[j,s]);
   end;
   option notes;
   create data out(drop=s) from [s]=(1..nsol1) solstatus
      {j in 1..n} <col('X'||j)=xsol[j,s]>
      Ecnt Rcnt Jcnt count;
quit;

proc freq data=out noprint;
   table Ecnt*Rcnt*Jcnt / out=freqout(rename=(count=Freq));
   weight count;
quit;

/* check that total is comb(66,8) */
proc sql;
   select sum(Freq) format=best20., comb(66,8) format=best20. from freqout;
quit;
Occasional Contributor
Posts: 17

Re: Combinations

hi @RobPratt,

 

Thanks for the help again. 

i got this error

solve with CLP / findallsolns;
                ___
                585
ERROR 585-782: Solver 'CLP' is unknown.

 

I do have SAS/OR and OR OPT not sure if clp requires a different license.

 

SAS Employee
Posts: 448

Re: Combinations

You need SAS/OR 13.2 or later to use the CLP solver in PROC OPTMODEL.  As a workaround, you can use PROC CLP instead:

 

proc clp out=clpout findallsolns;
   var (X1-X8)=[0,8];
   var X9=[0,2];
   lincon X1 + X2 + X3 + X4 + X5 + X6 + X7 + X8 + X9 = 8;
run;

proc optmodel printlevel=0;
   num n = 9;
   num Xub {j in 1..n} = (if j <= 8 then 8 else 2);
   set OBS;
   num nsol1 = card(OBS);
   num xsol {1..n, 1..nsol1};
   read data clpout into OBS=[_N_] {j in 1..n} <xsol[j,_N_]=col('X'||j)>;
   num solsum {s in 1..nsol1} = sum {j in 1..n-1} j * xsol[j,s];

   /* for each solution, maximize the number of groups with sum 8 and minimize remainder */
   num curr_sol;
   set GROUPS = 1..solsum[curr_sol]/8;
   var NumInGroup {j in 1..n-1, GROUPS} integer >= 0 <= xsol[j,curr_sol];
   var Unassigned {j in 1..n-1}         integer >= 0 <= xsol[j,curr_sol];
   var IsEight {GROUPS} binary;
   /* primary objective: maximize NumEights, secondary objective: minimize NumUnassigned */
   impvar NumEights     = sum {g in GROUPS} IsEight[g];
   impvar NumUnassigned = sum {j in 1..n-1} Unassigned[j];
   /* 1-unit increase in NumEights is more valuable than 8-unit decrease in NumUnassigned */
   max Objective = 9 * NumEights - NumUnassigned;
   con NumInGroupCon {j in 1..n-1}:
      sum {g in GROUPS} NumInGroup[j,g] + Unassigned[j] = xsol[j,curr_sol];
   con IsEightCon {g in GROUPS}:
      sum {j in 1..n-1} j * NumInGroup[j,g] = 8 * IsEight[g];

   str solstatus {1..nsol1};
   num Ecnt {1..nsol1};
   num Rcnt {1..nsol1};
   num Jcnt {1..nsol1};
   num count {1..nsol1};
   /* independent problems, so can solve in parallel by using COFOR */
   option nonotes;
   cofor {s in 1..nsol1} do;
      curr_sol = s;
      solve;
      solstatus[s] = _solution_status_;
      Jcnt[s] = xsol[n,s];
      Ecnt[s] = round(NumEights.sol + Jcnt[s]);
      Rcnt[s] = round(sum {j in 1..n-1} Unassigned[j].sol);
      count[s] = prod {j in 1..n} comb(Xub[j],xsol[j,s]);
   end;
   option notes;
   create data out(drop=s) from [s]=(1..nsol1) solstatus
      {j in 1..n} <col('X'||j)=xsol[j,s]>
      Ecnt Rcnt Jcnt count;
quit;

proc freq data=out noprint;
   table Ecnt*Rcnt*Jcnt / out=freqout(rename=(count=Freq));
   weight count;
quit;

/* check that total is comb(66,8) */
proc sql;
   select sum(Freq) format=best20., comb(66,8) format=best20. from freqout;
quit;
Occasional Contributor
Posts: 17

Re: Combinations

@eally appreciate the help @RobPratt,

 

Hmm looks like i dont have license for cofor as well.

 

 

cofor {s in 1..nsol1} do;
_____
180
ERROR 180-322: Statement is not valid or it is used out of proper order.

 

 

SAS Employee
Posts: 448

Re: Combinations

COFOR was introduced in SAS/OR 13.1. As a workaround, you can use FOR instead to solve the problems in serial.
Occasional Contributor
Posts: 17

Re: Combinations

Hi @RobPratt,

 

this works greate

 

Just a quick last question in this code have we considered 3 3 3 3 3 3 3 3 can not form a group of 8?

 

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 17 replies
  • 691 views
  • 9 likes
  • 6 in conversation