0

In this particular issue, I have an imaginary city divided into squares - basically a MxN grid of squares covering the city. M and N can be relatively big, so I have cases with more than 40,000 square cells overall.

I have a number of customers Z distributed in this grid, some cells will contain many customers while others will be empty. I would like to find a way to place the minimum number of shops (only one per cell) to be able to serve all customers, with the restriction that all customers must be “in reach” of one shop and all customers need to be included.

As an additional couple of twist, I have these constraints/issues:

  1. There is a maximum distance that a customer can travel - if the shop is in a cell too far away then the customer cannot be associated with that shop. Edit: it’s not really a distance, it’s a measure of how easy it is for a customer to reach a shop, so I can’t use circles...
  2. While respecting the condition (1) above, there may well be multiple shops in reaching distance of the same customer. In this case, the closest shop should win.

At the moment I’m trying to ignore the issue of costs - many customers means bigger shops and larger costs - but maybe at some point I’ll think about that too. The problem is, I have no idea of the name of the problem I’m looking at nor about possible algorithmic solutions for it: can this be solved as a Linear Programming problem?

I normally code in Python, so any suggestions on a possible algorithmic approach and/or some code/libraries to solve it would be very much appreciated.

Thank you in advance.

Edit: as a follow up, I kind of found out I could solve this problem as a MINLP “uncapacitated facility problem”, but all the information I have found are way too complex: I don’t care to know which customer is served by which shop, I only care to know if and where a shop is built. I have a secondary way - as post processing - to associate a customer to the most appropriate shop.

All the codes I found set up this monstrous linear system associating a constraint per customer per shop (as “explained” here: https://en.m.wikipedia.org/wiki/Facility_location_problem#Uncapacitated_facility_location), so in a situation like mine I could easily end up with a linear system with millions of rows and columns, which with integer/binary variables will take about the age of the universe to solve.

There must be an easier way to handle this...

Infinity77
  • 1,317
  • 10
  • 17
  • Perhaps similar to https://stackoverflow.com/questions/15882202/minimum-number-of-circles-with-radius-r-to-cover-n-points ? – Peter de Rivaz Jun 06 '20 at 11:49
  • "There must be an easier way to handle this". Famous last words. – n. m. could be an AI Jun 07 '20 at 07:59
  • Thank you for the link. I have edited my question a bit, sorry for the poorly worded original one. It’s not really a distance, it’s a measure of how easy is for a customer to reach a shop, so I cant use circles... – Infinity77 Jun 07 '20 at 08:02

1 Answers1

3

I think this can be formulated as a set covering problem link.

You say:

in a situation like mine I could easily end up with a linear system with millions of rows and columns, which with integer/binary variables will take about the age of the universe to solve

So let's see if that is even remotely true.

Step 1: generate some data

I generated a grid of 200 x 200, yielding 40,000 cells. I place at random M=500 customers. This looks like:

----     22 PARAMETER cloc  customer locations

                  x           y

cust1            35          75
cust2           169          84
cust3           111          18
cust4            61         163
cust5            59         102
...
cust497         196         148
cust498         115         136
cust499          63         101
cust500          92          87

Step 2: calculate reach of each customer

The next step is to determine for each customer c the allowed locations (i,j) within reach. I created a large sparse boolean matrix reach(c,i,j) for this. I used the rule: if the manhattan distance is

  |i-cloc(c,'x')|+|j-cloc(c,'y')| <= 10

then the store at (i,j) can service customer c. My data looks like:

enter image description here

(zeros are not stored). This data structure has 106k elements.

Step 3: Form MIP model

We form a simple MIP model:

enter image description here

The inequality constraint says: we need at least one store that is within reach of each customer. This is a very simple model to formulate and to implement.

Step 4: Solve

This is a large but easy MIP. It has 40,000 binary variables. It solves very fast. On my laptop it took less than 1 second with a commercial solver (3 seconds with open-source solver CBC).

The solution looks like:

----     47 VARIABLE numStores.L           =          113  number of stores

----     47 VARIABLE placeStore.L  store locations

              j1          j6          j7          j8          j9         j15         j16         j17         j18

i4                                                                                                             1
i18                                                            1
i40                                                                                    1
i70            1
i79                                                                                                1
i80                        1
i107                                                                                   1
i118                                   1
i136                                                                       1
i157                                               1
i167                                                                       1
i193                                               1

   +         j21         j23         j26         j28         j29         j31         j32         j36         j38

i10                                    1
i28                                                                        1
i54                                                            1
i72                                                                                    1
i96                                                1
i113                       1
i147                                                           1
i158                                                                                                           1
i179                                                                                               1
i184                       1
i198           1

   +         j39         j44         j45         j46         j49         j50         j56         j58         j59

i5                                                                                                             1
i18                                                1
i39            1
i62                                                            1
i85                        1
i102                                                                       1
i104                                   1
i133                                               1
i166                                                                                               1
i195                                                                                   1

   +         j62         j66         j67         j68         j69         j73         j74         j76         j80

i11                                                                                                1
i16                                                1
i36                                                            1
i61                                                                                    1
i76                                                                        1
i105                                                                       1
i112           1
i117                                                                                                           1
i128                                   1
i146                                               1
i190                       1

   +         j82         j84         j85         j88         j90         j92         j95         j96         j97

i17                                    1
i26            1
i35                                                                                                1
i48                                    1
i68                                                                        1
i79                                                                                                            1
i97            1
i136                       1
i156                                               1
i170                                   1
i183                                                                                   1
i191                                                           1

   +         j98        j102        j107        j111        j112        j114        j115        j116        j118

i4                                                                         1
i22                                                                                    1
i36                                                            1
i56                        1
i63                                                1
i68                                                                                                            1
i88                                                                                                1
i100                                                                                   1
i101           1
i111                                                                                                           1
i129                                                           1
i140                                   1

   +        j119        j121        j126        j127        j132        j133        j134        j136        j139

i11                                                            1
i30                                    1
i53                                                1
i72                                                                                                1
i111                                                                                                           1
i129                                                                                   1
i144                                                                       1
i159           1
i183                                                                                               1
i191                       1

   +        j140        j147        j149        j150        j152        j153        j154        j156        j158

i14                                                            1
i35                        1
i48                                                                        1
i83                                                                                                1
i98                                                1
i117                                                                                                           1
i158                                                                                   1
i174                                   1
i194           1

   +        j161        j162        j163        j164        j166        j170        j172        j174        j175

i5                                                                         1
i32            1
i42                                                                                                1
i61                                                                                    1
i69                                                                        1
i103                                                           1
i143                                   1
i145                                                                                                           1
i158                                                                                               1
i192                       1
i198                                               1

   +        j176        j178        j179        j180        j182        j183        j184        j188        j191

i6                                                                         1
i13                                                                                                            1
i23                                                1
i47                                                                                                            1
i61                                                                                    1
i81                        1
i93            1
i103                                                                                                           1
i125                                   1
i182                                                           1
i193                                                                                               1

   +        j192        j193        j196

i73                                    1
i120           1
i138           1
i167                       1

I think we have debunked your statement that a MIP model is not a feasible approach to this problem.

Note that the age of the universe is 13.7 billion years or 4.3e17 seconds. So we have achieved a speed-up of about 1e17. This is a record for me.

Note that this model does not find the optimal locations for the stores, but only a configuration that minimizes the number of stores needed to service all customers. It is optimal in that sense. But the solution will not minimize the distances between customers and stores.

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39
  • Thank you Erwin, that looks like a potential approach: one thing I’m unclear about: does this guarantee that there is a one-to-one correspondence between stores and customers? One of the requirements i have is that there cannot be two stores servicing the same customer. If that’s the case - I am not sure as I am no expert in this, I’ll have to find a way to translate your approach to Python and lpsolve, as I am not sure CBC is a supported tool in our setup, much less a commercial software... – Infinity77 Jun 07 '20 at 14:02
  • There may be more than one store in reach. The customer can pick the best one. Note that LpSolve is not a very strong MIP solver. – Erwin Kalvelagen Jun 07 '20 at 14:05
  • Thanks, it seems to be doing the right thing with the appropriate solver (CBC). On my problem it takes a bit longer - 55 seconds - but better than the age of the universe for sure. lpsolve takes hours just find something. – Infinity77 Jun 08 '20 at 04:49
  • Out of curiosity, what graphical user interface are you showing in your answer? I’m trying to use CBC from the command line, it’s a bit of a pain to try and understand what I can output and what I can’t... – Infinity77 Jun 08 '20 at 04:50
  • I used GAMS as modeling tool. – Erwin Kalvelagen Jun 08 '20 at 05:40