BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Santha
Pyrite | Level 9

Rob. 

This NLP from the old thread worked fine. It gave me 1 solution with latitude and longitude. Here is the code:

set DIMS=1..2;
set <str> CUSTOMERS;
read data STDOPT.COGModelingData into CUSTOMERS=[Sitename];

num demand {CUSTOMERS};
read data STDOPT.COGModelingData into [Sitename] Demand=SiteParameter1;

NUM Latitude {CUSTOMERS};
read data STDOPT.COGModelingData into [Sitename] Latitude=SiteLatitude;

NUM Longitude {CUSTOMERS};
read data STDOPT.COGModelingData into [Sitename] Longitude=SiteLongitude;

var X {DIMS};

min Z = sum {i in CUSTOMERS} demand[i]*GEODIST(Latitude[i],Longitude[i],X[1],X[2]);
solve;
print X;

I want to expand the logic so that the model gives me "p" number of possible facilities. I am thinking of the logic below. We need to minimize the weighted distance from "p" points to all customers.So, Here is what I did  and I know that this is not correct. Your insight would be helpful. set p=1..3; (meaning to say how many sites I want model to find out as answer): here is my code /logic below. 

var X {DIMS,p}; -- am sure this is not the right way. 

min Z = sum {i in CUSTOMERS,p} demand[i]*GEODIST(Latitude[i],Longitude[i],X[1,p],X[2,p]);

solve; print X;

Also, should we not make sure by way of constraint to make sure the model finds exactly "p" answers.?

1 ACCEPTED SOLUTION

Accepted Solutions
Santha
Pyrite | Level 9

Rob.

The read data statement reads the lat and lon  and demand. 

I have few columns like SiteState, SiteBusiness etc that I want to use it for my outputs. I understand that this is not needed for the proc optmodel. So the question is , is it good to create columns in the "create data" step like sitestate, SiteBusines and update it using lat, lon and demand from the original table. But there could be 2 sites with same lat, lon and demand but only thing that is different could be it could be different SiteBusiness.  What would you recommend?

View solution in original post

6 REPLIES 6
RobPratt
SAS Super FREQ

Here is code to solve the multisource Weber problem, where m is the number of facilities.  It is based on the code I posted in the other thread, but you can modify as needed for your data and distance function.  Because the multisource problem is nonconvex, I used the multistart option for the NLP solver and also added optional code to post-process the solution to make further local improvements.

 

%let m = 3;
proc optmodel;
   set DIMS = 1..2;
   set CUSTOMERS;
   set FACILITIES = 1..&m;
   num a {CUSTOMERS, DIMS};
   num demand {CUSTOMERS};
   read data cdata into CUSTOMERS=[_N_] {d in DIMS} <a[_N_,d]=col('a'||d)> demand;

   num Xlb {d in DIMS} = min {i in CUSTOMERS} a[i,d];
   num Xub {d in DIMS} = max {i in CUSTOMERS} a[i,d];
   var X {FACILITIES, d in DIMS} >= Xlb[d] <= Xub[d];
   var W {CUSTOMERS, FACILITIES} >= 0;
   impvar Distance {i in CUSTOMERS, j in FACILITIES} = 
      sqrt(sum {d in DIMS}(a[i,d]-X[j,d])^2);
   min Z = sum {i in CUSTOMERS, j in FACILITIES} W[i,j]*Distance[i,j];
   con DemandCon {i in CUSTOMERS}:
      sum {j in FACILITIES} W[i,j] = demand[i];

   solve with nlp / ms;
   print X;
   put _OBJ_=;

   /* post-processing: assign each customer to closest facility */
   set CUSTOMERS_j {FACILITIES} init {};
   num minDistance, argminDistance;
   for {i in CUSTOMERS} do;
      minDistance = constant('BIG');
      argminDistance = .;
      for {j in FACILITIES} do;
         if minDistance > Distance[i,j] then do;
            minDistance = Distance[i,j];
            argminDistance = j;
         end;
      end;
      for {j in FACILITIES} W[i,j] = 0;
      W[i,argminDistance] = demand[i];
      CUSTOMERS_j[argminDistance] = CUSTOMERS_j[argminDistance] union {i};
   end;
   put _OBJ_=;

   /* post-processing: solve each facility separately */
   min SingleFacilityObjective {j in FACILITIES} = 
      sum {i in CUSTOMERS_j[j]} demand[i]*Distance[i,j];
   problem SingleFacilityProblem {j in FACILITIES} include
      {d in DIMS} X[j,d]
      SingleFacilityObjective[j];
   for {j in FACILITIES} do;
      put j=;
      use problem SingleFacilityProblem[j];
      solve;
   end;
   put (sum {j in FACILITIES} SingleFacilityObjective[j])=;
   print X;

   create data Xdata from [j]=FACILITIES {d in DIMS} <col('X'||d)=X[j,d].sol>;
   create data assignments from [j i]={j in FACILITIES, i in CUSTOMERS_j[j]} W[i,j]
      x1=a[i,1] y1=a[i,2] x2=X[j,1] y2=X[j,2];
quit;

proc sgplot data=assignments;
   vector x=x2 y=y2 / xorigin=x1 yorigin=y1 group=j;
run;
Santha
Pyrite | Level 9

Rob. 

Thank you once again. I will look into it and will understand completely. 

you are awesome

 

 

Santha
Pyrite | Level 9

Rob.

The read data statement reads the lat and lon  and demand. 

I have few columns like SiteState, SiteBusiness etc that I want to use it for my outputs. I understand that this is not needed for the proc optmodel. So the question is , is it good to create columns in the "create data" step like sitestate, SiteBusines and update it using lat, lon and demand from the original table. But there could be 2 sites with same lat, lon and demand but only thing that is different could be it could be different SiteBusiness.  What would you recommend?

RobPratt
SAS Super FREQ

You have this code:

set <str> CUSTOMERS;
read data STDOPT.COGModelingData into CUSTOMERS=[Sitename];
num demand {CUSTOMERS};
read data STDOPT.COGModelingData into [Sitename] Demand=SiteParameter1;
NUM Latitude {CUSTOMERS};
read data STDOPT.COGModelingData into [Sitename] Latitude=SiteLatitude;
NUM Longitude {CUSTOMERS};
read data STDOPT.COGModelingData into [Sitename] Longitude=SiteLongitude;

It would be simpler to use one READ DATA statement:

set <str> CUSTOMERS;
num demand {CUSTOMERS};
NUM Latitude {CUSTOMERS};
NUM Longitude {CUSTOMERS};
read data STDOPT.COGModelingData into CUSTOMERS=[Sitename]
Demand=SiteParameter1 Latitude=SiteLatitude Longitude=SiteLongitude;

If you have additional customer attributes, you can declare them as additional (string or numeric) parameters:

str SiteState {CUSTOMERS};
str SiteBusiness {CUSTOMERS};

You can then populate these parameters however you want and use them in a CREATE DATA statement.  Alternatively, you can populate the value of a column by evaluating an expression in the CREATE DATA statement itself, without explicitly declaring new parameters, as demonstrated in the documentation.

Santha
Pyrite | Level 9

Rob

THANK YOU. it worked. 

RobPratt
SAS Super FREQ

Glad to help, but it looks like you accepted your second question as the solution to your first question.

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

Discussion stats
  • 6 replies
  • 965 views
  • 2 likes
  • 2 in conversation