SAS Optimization, and SAS Simulation Studio

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-16-2017 02:51 PM

Hi Folks,

I am new to Sas trying to solve below simple facility location, Please advice what I am missing,

Data | Wgt | X | Y |

Boston | 425 | 100 | 80 |

Providence | 320 | 86 | 40 |

Springfield | 220 | 20 | 60 |

Proc optmodel;

set city = {'BO','PR','SP'};

set Geo = {'X','Y'};

number Cor{city,Geo} =[100 80 86 40 20 60];

number Wgt{City}=[425 320 220];

var x{city,Geo} integer >= 0;

var y{city,Geo} integer >= 0;

Minimize MinWgtDis = sum{i in City}sum {j in Geo}

(sqrt((cor[i,j] - x[i,j])^2 + (cor[i,j] - y[i,j])^2 ))* Wgt[i];

/*

con x{i in city,j in Geo}: X[i,j]<=200;

con y{i in city,j in Geo}: y[i,j]<=200;*/

solve;

print MinWgtDis x y;

quit;

Accepted Solutions

Solution

04-17-2017
01:34 AM

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-16-2017 05:38 PM

You can use the EXPAND statement to see how the objective function you defined gets populated:

```
Var x >= 0
Var y >= 0
Minimize MinWgtDis=SQRT((-x + 100)**2 + (-y + 100)**2)*425 + SQRT((-x + 80)**2 + (-y + 80)
**2)*425 + SQRT((-x + 86)**2 + (-y + 86)**2)*320 + SQRT((-x + 40)**2 + (-y + 40)**2)*320
+ SQRT((-x + 20)**2 + (-y + 20)**2)*220 + SQRT((-x + 60)**2 + (-y + 60)**2)*220
```

You can see that the formula for MinWgtDis is not really what you intended. Here's a modification of your code that instead does what you want:

```
Proc optmodel;
set city = {'BO','PR','SP'};
set Geo = {'Xi','Yi'};
number Cor{city,Geo} =[100 80 86 40 20 60];
number Wgt{city}=[425 320 220];
var x {Geo} >= 0 ;
Minimize MinWgtDis = sum{i in city} sqrt(sum {j in Geo} (cor[i,j] - x[j])^2)* Wgt[i];
solve;
print MinWgtDis x;
quit;
```

All Replies

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-16-2017 05:19 PM

Here's one way to solve it as an unconstrained problem with nonlinear objective and two variables:

```
data indata;
input city $12. Wgt X Y;
datalines;
Boston 425 100 80
Providence 320 86 40
Springfield 220 20 60
;
proc sgplot data=indata;
bubble x=x y=y size=wgt / datalabel=city;
run;
proc optmodel;
set <str> CITIES;
num wgt {CITIES};
num xc {CITIES};
num yc {CITIES};
read data indata into CITIES=[city] wgt xc=x yc=y;
var X, Y;
min MinWgtDis = sum {i in CITIES} (sqrt((xc[i] - X)^2 + (yc[i] - Y)^2)) * wgt[i];
solve;
print MinWgtDis X Y;
create data sganno from function='text' drawspace='datavalue' label='facility' x1=X y1=Y;
quit;
proc sgplot data=indata sganno=sganno;
bubble x=x y=y size=wgt / datalabel=city;
run;
```

The resulting plot provides a sanity check on the optimal solution returned.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RobPratt

04-16-2017 05:28 PM

Wow, that's super! Thanks

I am trying to solve it without defining data table, started to get some numbers but am still missing something, can you help me figuring out the error. I think coz I don't have a seperate variable for Xi and Yi it's not working right

Proc optmodel;

set city = {'BO','PR','SP'};

set Geo = {'Xi','Yi'};

number Cor{city,Geo} =[100 80 86 40 20 60];

number Wgt{city}=[425 320 220];

var x >= 0 ;

var y >= 0;

Minimize MinWgtDis = sum{i in city} sum {j in Geo}

((sqrt((cor[i,j] - x)^2 + (cor[i,j] - y)^2 ))* Wgt[i]);

solve;

print MinWgtDis x y ;

quit;

Solution

04-17-2017
01:34 AM

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-16-2017 05:38 PM

You can use the EXPAND statement to see how the objective function you defined gets populated:

```
Var x >= 0
Var y >= 0
Minimize MinWgtDis=SQRT((-x + 100)**2 + (-y + 100)**2)*425 + SQRT((-x + 80)**2 + (-y + 80)
**2)*425 + SQRT((-x + 86)**2 + (-y + 86)**2)*320 + SQRT((-x + 40)**2 + (-y + 40)**2)*320
+ SQRT((-x + 20)**2 + (-y + 20)**2)*220 + SQRT((-x + 60)**2 + (-y + 60)**2)*220
```

You can see that the formula for MinWgtDis is not really what you intended. Here's a modification of your code that instead does what you want:

```
Proc optmodel;
set city = {'BO','PR','SP'};
set Geo = {'Xi','Yi'};
number Cor{city,Geo} =[100 80 86 40 20 60];
number Wgt{city}=[425 320 220];
var x {Geo} >= 0 ;
Minimize MinWgtDis = sum{i in city} sqrt(sum {j in Geo} (cor[i,j] - x[j])^2)* Wgt[i];
solve;
print MinWgtDis x;
quit;
```

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RobPratt

04-17-2017 02:26 PM

how to use the expand statment to see how the function is populated ?

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-17-2017 02:33 PM

What I showed above came from the simplest invocation, which expands the whole model:

`expand;`

But you can also expand just the objective as follows:

`expand MinWgtDis;`

The full documentation for the EXPAND statement is here:

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RobPratt

04-17-2017 02:45 PM

I actually added two addional lines, but when I write expand, it expands only the optmization formula

number SumCOG = sum(of Wgt[*]);

number xcog{geo} = sum{i in city} (sum{j in Geo} (Wgt[i]/SumCOG)*cor[i,j]);

expand ;

XCOG is not calculated right and want trace it, but it doesn't show up in the expand result.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-17-2017 04:25 PM

EXPAND does not apply here, but you can use the PRINT statement to inspect parts of your expression. For example,

```
print SumCOG;
```

returns the correct value 965.

The issue with your NUM declaration is that you have used Geo both as an index set on the left-hand side and as a summation index set on the right-hand side. I think what you intended is this:

`num xcog{j in geo} = sum{i in city} ((Wgt[i]/SumCOG)*cor[i,j]);`

print xcog;

SAS Output

[1] | xcog |
---|---|

Xi | 77.119 |

Yi | 62.176 |

By the way, the value of MinWgtDis is higher than the minimum value returned by the solver, which you can confirm as follows:

```
for {j in Geo} x[j] = xcog[j];
print MinWgtDis;
```

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RobPratt

04-17-2017 05:45 PM

that's extremly helpful Rob,I need to work on the summation notation.

when you added

"for {j in Geo} x[j] = xcog[j];

print MinWgtDis;"

it means untill j holds a value, go back and use the new xcog instead of x to calculate the minimum cost, right ?

and to print each and every indvidual X,Y, not the summed one.

I have to put this"sqrt(sum {j in Geo} (cor[i,j] - x[j])^2)* Wgt[i];" in avariable and then print it

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-17-2017 05:59 PM

The FOR loop sets x[j] to xcog[j] for each j in Geo. The subsequent PRINT statement prints the new value of MinWgtDis, which gets automatically updated whenever any part of its definition gets updated.

A good source for learning about PROC OPTMODEL is SAS/OR 14.2 User's Guide: Mathematical Programming Examples.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RobPratt

04-18-2017 03:17 PM

Thank you rob

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-22-2017 11:32 AM

Hi Rob,

I added this code to your solution, it works fine, is there is a better way to do ?

/*Calculating CoG Coordinates */

num SumCOG = sum(of Wgt[*]);

for {i in CITIES} X = sum{i in CITIES} (Wgt[i]*xc[i])/SumCOG ;

for {i in CITIES} Y = sum{i in CITIES} (Wgt[i]*yc[i])/SumCOG ;

print MinWgtDis SumCOG X Y;

expand;

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-25-2017 02:24 PM

The FOR loop over CITIES is unnecessary, and you are performing the exact same calculation multiple times. Instead, you can just do this:

```
X = sum{i in CITIES} (Wgt[i]*xc[i])/SumCOG ;
Y = sum{i in CITIES} (Wgt[i]*yc[i])/SumCOG ;
```