在整数规划约束

问题描述

我正在尝试在 lpsolveAPI 中制定货架优化整数编程算法,并希望添加一个约束,从而使每个选定货架 (S) 上的每种产品的数量相同:

f

constraint

我的困难是访问和使用总和作为约束(特别是 Xij

我可以重新编写使其线性而不会有太多问题(请原谅伪代码):

sum(X_ij)*F_ij - sum(F_ij) = 0

此操作可能会影响 X 本身的选择,因此我需要它是动态的(否则我只能在求解后更改值)如何访问这些值,或将 F 值编码为相等?

>

线性程序通过一系列约束创建了一个二元解决方案,将产品放在货架上(目前可能放在一个或两个货架上),有四个货架。然后是第二组,它允许那些货架上的许多产品不是零,受产品宽度与货架长度的限制,所有货架上的产品数量给定最大(大多数为 8 个,虽然这有点武断),最大限度地提高产品利润。所有这些都按预期工作。但是,我希望添加一个约束,使两个或多个货架上的产品数量相同,即一个货架上有四个,另一个货架上有四个。鉴于使用的货架数量可以是 1 或 2,我不能简单地划分这些值。此外,由于哪些货架被占用是由约束决定的,我不能简单地使用 P1S1 = P1S2(除非我可以选择被占用的货架,但我没有这样做)

这是我尝试做的一个最小的例子(请原谅我第一次这样做的不雅代码)数据集是here

library(lpSolveAPI)

shelves <- data.frame(Sl_i = c(151,200,180,218),Sh_i = c(30,30,36))

datatable <- read.csv("~/Desktop/sales/datatable.txt",sep="")

S = 4  # number of shelves
P = 40 # number of products

Shelf_choice <-
  make.lp(0,nrow(mydata) * 2) # create the lp object with decision variables == longitude of data.frame

#### SET OBJECTIVE FUNCTION ####


#### Set controls for the model ####

lp.control(Shelf_choice,sense = "max",timeout = 10,presolve = "none") ## timeout prevents getting stuck
set.objfn(Shelf_choice,c(rep(rep(0,nrow(
  mydata
)),1),mydata$Pu_j)) # maximize profit (Pu_j)

set.type(Shelf_choice,1:nrow(mydata),"binary") # present on shelf or not
set.type(Shelf_choice,1:nrow(mydata) + nrow(mydata),"integer") # number of product j on shelf


### Assure that each product appears on minimum number of shelves (1 in this case)
Add_productShelf_constraint <- function (prod_index) {
  cargo_cols <-
    (0:(S - 1)) * P + prod_index  # # index of products by column (eg. 1,41,81,121)
  add.constraint(
    Shelf_choice,rep(1,S),# repeat value the same number of times as shelves
    indices = cargo_cols,type = ">=",rhs = mydata$smin_j[prod_index]
  ) # value of minimum number of shelves
}

lapply(1:P,Add_productShelf_constraint) # list apply this for every product

### Assure that product appears no more than the number of shelves permitted (2 in this case)
Add_productShelfMAX_constraint <- function (prod_index) {
  cargo_cols <-
    (0:(S - 1)) * P + prod_index   # index of products by column (eg. 1,type = "<=",rhs = mydata$smax_j[prod_index]
  ) # value of minimum number of shelves
}

lapply(1:P,Add_productShelfMAX_constraint) # list apply this for every product



### Third Constraint: Products too tall for a shelf are excluded

Add_height_constraint <-
  function (prod_index) {
    # this needs to be improved
    add.constraint(Shelf_choice,1,indices = prod_index,type = "=",rhs = 0)
  }
lapply(which(mydata$height == 0),Add_height_constraint) # Here we select the colums which have 0 (don't fit),and set the value to 0


## Products are on consecutive shelves - this currently only works for two shelves
Add_nextshelf_constraint <- function (prod_index) {
  mat1 <- combn(1:S,2)[,which(combn(1:S,2)[2,] - combn(1:S,2)[1,] != 1)]
  cargo_cols <- (0:(S - 1)) * P + prod_index
  result <- matrix(cargo_cols[mat1],nrow = 2)
  
  for (i in 1:ncol(result)) {
    add.constraint(
      Shelf_choice,c(1,indices = result[,i],rhs = 1
    )
  }
}
lapply(1:P,Add_nextshelf_constraint)




### Product facings only appear on selected shelves (where Xij = 1)

Add_FF_constraint1 <- function (prod_index) {
  Y01col <- prod_index
  print(Y01col)
  FF_col <- prod_index + nrow(mydata)
  add.constraint(
    Shelf_choice,-100),indices = c(FF_col,Y01col),rhs = 0
  )
}
lapply(1:nrow(mydata),Add_FF_constraint1) #

Add_FF_constraint2 <- function (prod_index) {
  Y01col <- prod_index
  FF_col <- prod_index + nrow(mydata)
  add.constraint(
    Shelf_choice,-1),Add_FF_constraint2) #



#### Sum of product widths on shelves does not exceed shelf length
Add_FijShelflength_constraint <- function (shelf_index) {
  shelf_cols_mydata <- ((1:(P)) + (shelf_index - 1) * P)
  FF_shelf_cols <- ((1:(P)) + (shelf_index - 1) * P)  + nrow(mydata)
  
  add.constraint(
    Shelf_choice,c(mydata$Pw_j[shelf_cols_mydata]),# width of each product
    indices = c(FF_shelf_cols),# indices of products per shelf in Fij Matrix
    rhs = shelves$Sl_i[shelf_index]
  ) # length of each shelf
  
}
lapply(1:S,Add_FijShelflength_constraint) # list apply this by shelf index

## add minimum number of total facings
Add_min_facings_constraint <- function (prod_index) {
  FjSi_cols <-
    (0:(S - 1)) * P + prod_index + nrow(mydata) # index of the products by column in out table
  add.constraint(
    Shelf_choice,# repeat value the same number of times as shelves
    indices = FjSi_cols,# index of products by column (eg. 1,121)
    type = ">=",rhs = mydata$Fmin_j[prod_index]
  ) # value of minimum number of products
}
lapply(1:P,Add_min_facings_constraint) # list apply this for every product

## add maximum number of facings
Add_max_facings_constraint <- function (prod_index) {
  FjSi_cols <-
    (0:(S - 1)) * P + prod_index + nrow(mydata)
  add.constraint(
    Shelf_choice,121)
    type = "<=",rhs = mydata$Fmax_j[prod_index]
  ) # value of maximum number of products
}
lapply(1:P,Add_max_facings_constraint) # list apply this for every product

solve(Shelf_choice)

get.objective(Shelf_choice) # gives the total value of the facings

### Tabulates the results ####
test <- matrix(get.variables(Shelf_choice),ncol = S * 2,byrow = F)
rownames(test) <- paste0("Product",1:40)
colnames(test) <- c(rep(paste0("Shelf",1:4),2))

test[,5:8] # shows the product placements (uneven products between shelves)
#

结果:

产品 货架 1 货架 2 货架 3 货架 4
P1 0 0 0 2
- - - - -
P11 1 7 0 0
P16 2 2 0 0

例如,我需要产品 11 在每个货架上有相同数量的产品(每个货架 4 个)

我试图创建一个约束,例如:

Sum_Xshelf_constraint <- function (prod_index) {
  binary_sum <-
    sum(get.variables(Shelf_choice)[(0:(S - 1)) * P + prod_index])
  total_Fij <-
    sum(get.variables(Shelf_choice)[(0:(S - 1)) * P + prod_index + nrow(df)])
  
  total_cols <-
    (0:(S - 1)) * P + prod_index + nrow(df) # index of the products in Fij
  
  for (i in 1:length(total_cols)) {
    add.constraint(
      Shelf_choice,c(binary_sum),indices = c(total_cols[i]),rhs = total_Fij
    )                  # value of minimum number which is Fmin_j
  }
}
### At least one product on a shelf
lapply(1:P,Sum_Xshelf_constraint) 

不出所料,这在解决之前不起作用,一旦解决就没有效果

任何想法如何实现这一目标?提前致谢。

解决方法

如果你的决策变量是 PiSj(#ith Product on jth Shelf),那么一系列链式方程就可以工作:

P1S1 = P1S2
P1S2 = P1S3
P1S3 = P1S4

这种简单有时可以显着提高性能。

,

我必须在这里回答我自己的问题:

这是不可能的。

仔细阅读,似乎这个特定约束是二次的... (http://lpsolve.sourceforge.net/5.5/)

"假设 xj 必须取一个整数值 i:

yj / y0 = i

yj = i * y0

不幸的是,这个约束不能被 lpsolve 处理,因为它是二次的。”

完成后,我将使用二次解法编辑此答案。我想我最好现在发布这个,这样其他人就不会花太多精力去尝试解决它。​​

谢谢!