Neste post apresento um exemplo de codificação de como um grupo de clientes pode ser atribuído a um armazém cada, considerando um conjunto de armazéns fixos com capacidade ilimitada. O pressuposto subjacente é que não existem custos fixos e que os custos dependem apenas da distância euclidiana entre o cliente e o armazém. Além disso, nenhum requisito de lead time ou outras restrições relacionadas ao nível de serviço são consideradas neste problema.
O algoritmo é muito simples e lembra um dos algoritmos de agrupamento. Ele percorre todos os clientes e atribui cada cliente ao armazém mais próximo, considerando a distância euclidiana e o sistema de latitude-longitude. Abaixo defino esse algoritmo como uma função:
# function for calculating euclidean distances
euclidean_distance <- function(vc,df){
sqrt((as.numeric(rep(vc[1],times=nrow(df)))-df[,1])^2+(as.numeric(rep(vc[2],times=nrow(df)))-df[,2])^2)
}
# function for assigning customers to warehouses
assignment_algorithm <- function(customers,warehouses){
return_df <- as.data.frame(matrix(nrow=nrow(customers),ncol=3))
colnames(return_df)<-c("lat","long","warehouses")
for(i in 1:nrow(customers)){
return_df[i,] <- c(customers[i,1],customers[i,2],which.min(euclidean_distance(customers[i,],warehouses)))
}
return_df
}
Para testar, primeiro construo dois conjuntos, com clientes e armazéns localizados aleatoriamente, respectivamente.
customer_df <- as.data.frame(matrix(nrow=1000,ncol=2))
colnames(customer_df) <- c("lat","long")
warehouse_df <- as.data.frame(matrix(nrow=4,ncol=2))
colnames(warehouse_df) <- c("lat","long")
customer_df[,c(1,2)] <- cbind(runif(n=1000,min=-90,max=90),runif(n=1000,min=-180,max=180))
warehouse_df[,c(1,2)] <- cbind(runif(n=4,min=-90,max=90),runif(n=4,min=-180,max=180))
Abaixo do cabeçalho do dataframe de localização do cliente :
head(customer_df)
## lat long
## 1 -35.42042 -33.68156
## 2 -50.63025 -64.52526
## 3 43.71663 -36.22302
## 4 -53.30511 135.56315
## 5 -46.32125 84.83210
## 6 83.85849 -60.70374
Abaixo do cabeçalho do dataframe de localização do armazém :
head(warehouse_df)
## lat long
## 1 -41.007642 118.5673
## 2 81.968627 116.1495
## 3 11.971601 103.5034
## 4 -6.619224 -103.6206
Agora eu atribuo clientes a armazéns:
# apply function
results_df <- assignment_algorithm(customer_df,warehouse_df)
# display header of result
head(results_df)
## lat long warehouses
## 1 -35.42042 -33.68156 4
## 2 -50.63025 -64.52526 4
## 3 43.71663 -36.22302 4
## 4 -53.30511 135.56315 1
## 5 -46.32125 84.83210 1
## 6 83.85849 -60.70374 4
Além disso, visualizo os resultados no ggplot2:
library(ggplot2)
ggplot(data = results_df) +
geom_point(mapping = aes(x=lat,y=long,color=as.character(warehouses))) +
scale_color_manual(values=c("darkblue","darkgreen","darkred","yellow")) +
xlim(-90,90) + ylim(-180,180)
Os armazéns estão localizados da seguinte forma:
ggplot(data = warehouse_df) + geom_point(mapping = aes(x=lat,y=long)) + xlim(-90,90) + ylim(-180,180)
Em outro post mostro como localizar um armazém no centro de massa, I no centro de demanda do cliente: Problema de armazém único – Locating warehouse at center of mass ( cálculo do centro de massa em R )
Também escrevi postagens sobre como dividir um grupo de clientes em vários grupos menores, com base na proximidade espacial. Esta abordagem pode, por exemplo, ser usada para localizar vários armazéns em cada um de seus centros de massa em R .
Cientista de dados com foco em simulação, otimização e modelagem em R, SQL, VBA e Python
Leave a Reply