Turn on suggestions

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

Showing results for

Options

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

🔒 This topic is **solved** and **locked**.
Need further help from the community? Please
sign in and ask a **new** question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 04-16-2017 02:51 PM
(1241 views)

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;

1 ACCEPTED SOLUTION

Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;
```

12 REPLIES 12

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Thank you rob

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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 ;
```

**Available on demand!**

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

Multiple Linear Regression in SAS

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.