The following code uses PROC OPTMODEL in SAS/OR or SAS Optimization to maximize the number of zero-sum groups:
data have;
input amount;
datalines;
-56
76
10
-76
56
20
-45
-3
15
-35
40
4
4
;
proc optmodel;
/* declare parameters and read input data set */
set OBS;
num amount {OBS};
read data have into OBS=[_N_] amount;
num numGroups = card(OBS)/2;
set GROUPS = 1..numGroups;
/* declare decision variables */
var UseGroup {GROUPS} binary;
var Assign {OBS, GROUPS} binary;
/* declare objective */
max NumGroupsUsed = sum {g in GROUPS} UseGroup[g];
/* declare constraints */
con OneGroupPerObs {i in OBS}:
sum {g in GROUPS} Assign[i,g] <= 1;
con GroupSumZero {g in GROUPS}:
sum {i in OBS} amount[i] * Assign[i,g] = 0;
con AssignImpliesUse {i in OBS, g in GROUPS}:
Assign[i,g] <= UseGroup[g];
con UseImpliesAssign {g in GROUPS}:
2*UseGroup[g] <= sum {i in OBS} Assign[i,g];
con Symmetry {g in GROUPS diff {1}}:
UseGroup[g] <= UseGroup[g-1];
/* call MILP solver */
solve;
/* create output data set */
num assignedGroup {OBS};
for {i in OBS} do;
for {g in GROUPS: Assign[i,g].sol > 0.5} do;
assignedGroup[i] = g;
leave;
end;
end;
create data want from [i] amount assignedGroup;
quit;
The resulting optimal solution has 4 groups:
Obs | i | amount | assignedGroup |
---|---|---|---|
1 | 1 | -56 | 4 |
2 | 2 | 76 | 2 |
3 | 3 | 10 | . |
4 | 4 | -76 | 2 |
5 | 5 | 56 | 4 |
6 | 6 | 20 | 3 |
7 | 7 | -45 | 1 |
8 | 8 | -3 | 1 |
9 | 9 | 15 | 3 |
10 | 10 | -35 | 3 |
11 | 11 | 40 | 1 |
12 | 12 | 4 | 1 |
13 | 13 | 4 | 1 |
See also Solved: Net Groups of Lines in a Table to $0.00 - SAS Support Communities for an alternative greedy approach.
Can you provide some sample data and an explanation from that?
Ok. The first output is quite simple.
Regaring the second output.. Do you want ALL combinations of values that equal zero when summed?
I think you can't get job done simply by data step code.
You need SAS/OR to solve this kind of question.
Post it at OR forum
https://communities.sas.com/t5/Mathematical-Optimization/bd-p/operations_research
And calling out @RobPratt
The following code uses PROC OPTMODEL in SAS/OR or SAS Optimization to maximize the number of zero-sum groups:
data have;
input amount;
datalines;
-56
76
10
-76
56
20
-45
-3
15
-35
40
4
4
;
proc optmodel;
/* declare parameters and read input data set */
set OBS;
num amount {OBS};
read data have into OBS=[_N_] amount;
num numGroups = card(OBS)/2;
set GROUPS = 1..numGroups;
/* declare decision variables */
var UseGroup {GROUPS} binary;
var Assign {OBS, GROUPS} binary;
/* declare objective */
max NumGroupsUsed = sum {g in GROUPS} UseGroup[g];
/* declare constraints */
con OneGroupPerObs {i in OBS}:
sum {g in GROUPS} Assign[i,g] <= 1;
con GroupSumZero {g in GROUPS}:
sum {i in OBS} amount[i] * Assign[i,g] = 0;
con AssignImpliesUse {i in OBS, g in GROUPS}:
Assign[i,g] <= UseGroup[g];
con UseImpliesAssign {g in GROUPS}:
2*UseGroup[g] <= sum {i in OBS} Assign[i,g];
con Symmetry {g in GROUPS diff {1}}:
UseGroup[g] <= UseGroup[g-1];
/* call MILP solver */
solve;
/* create output data set */
num assignedGroup {OBS};
for {i in OBS} do;
for {g in GROUPS: Assign[i,g].sol > 0.5} do;
assignedGroup[i] = g;
leave;
end;
end;
create data want from [i] amount assignedGroup;
quit;
The resulting optimal solution has 4 groups:
Obs | i | amount | assignedGroup |
---|---|---|---|
1 | 1 | -56 | 4 |
2 | 2 | 76 | 2 |
3 | 3 | 10 | . |
4 | 4 | -76 | 2 |
5 | 5 | 56 | 4 |
6 | 6 | 20 | 3 |
7 | 7 | -45 | 1 |
8 | 8 | -3 | 1 |
9 | 9 | 15 | 3 |
10 | 10 | -35 | 3 |
11 | 11 | 40 | 1 |
12 | 12 | 4 | 1 |
13 | 13 | 4 | 1 |
See also Solved: Net Groups of Lines in a Table to $0.00 - SAS Support Communities for an alternative greedy approach.
@RobPratt, if I could push the 'like' button more than once, I would.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.