How to specify an equality constraint of decision variables in GA in R?

Viewed 81

Objective and Data

I have disutilities values by percentage for off-peak and peak hours as shown below. I want to optimize the percent values for each hour so that the sum of disutilities (shown in columns with the x prefix e.g. x0506am_td) is the minimum.

## Off-Peak hours
TD_OffPeak2 <- structure(list(percent = c(
  0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06,
  0.07, 0.08, 0.09
), x0506am_td = c(
  0, 6579, 13159, 19738, 26317,
  32896, 39476, 46055, 52634, 59213
), x0607am_td = c(
  272800, 277632,
  282464, 287298, 292132, 296967, 301803, 306639, 311477, 316314
), x0708am_td = c(
  6202903, 6208203, 6213504, 6218807, 6224111,
  6229417, 6234724, 6240033, 6245344, 6250656
), x0910am_td = c(
  4061151,
  4064495, 4067840, 4071185, 4074530, 4077876, 4081222, 4084568,
  4087915, 4091262
), x1011am_td = c(
  599364, 604822, 610281, 615743,
  621206, 626671, 632139, 637608, 643079, 648552
), x1112am_td = c(
  500565,
  507908, 515252, 522597, 529943, 537291, 544640, 551989, 559340,
  566693
)), row.names = c(NA, -10L), class = c(
  "tbl_df", "tbl",
  "data.frame"
))



## Peak Hour
TD_Peak2 <- structure(list(percent = c(
  0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06,
  0.07, 0.08, 0.09, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17,
  0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28,
  0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39,
  0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5,
  0.51, 0.52, 0.53, 0.54
), x0809am_td = c(
  26838281, 26829566, 26820854,
  26812145, 26803439, 26794735, 26786034, 26777336, 26768641, 26759949,
  26751260, 26742573, 26733889, 26725208, 26716530, 26707855, 26699183,
  26690513, 26681846, 26673182, 26664521, 26655862, 26647207, 26638554,
  26629904, 26621257, 26612612, 26603971, 26595332, 26586696, 26578063,
  26569433, 26560805, 26552180, 26543558, 26534939, 26526323, 26517709,
  26509099, 26500491, 26491885, 26483283, 26474683, 26466087, 26457493,
  26448902, 26440313, 26431727, 26423145, 26414565, 26405987, 26397413,
  26388841, 26380272, 26371706
)), row.names = c(NA, -55L), class = c(
  "tbl_df",
  "tbl", "data.frame"
))

Constraint

The sum of percent values for each hour other than 0809am should be equal to mdp.

Attempt at Solution using GA Package

I used the GA package with a fitness function shown below to optimize the percent values for each hour.

# Load Libraries
library(GA)
library(dplyr)

## Fitness Function
fitness_func <- function(offpeak_data,
                               peak_data,
                               mdp,
                               h56p,
                               h67p,
                               h78p,
                               h910p,
                               h1011p,
                               h1112p ){




  mdp <- round(mdp,2)
  h56p <- round(h56p,2)
  h67p <- round(h67p,2)
  h78p <- round(h78p,2)
  h910p <- round(h910p,2)
  h1011p <- round(h1011p, 2)
  h1112p <- round(h1112p, 2)
  h89p <- mdp

## using the constraint 
  if ((h56p + h67p + h78p + h910p + h1011p + h1112p) - mdp <= 0.0001) {



  uval_56 <- offpeak_data$x0506am_td[which(offpeak_data$percent == h56p)]

  uval_67 <-offpeak_data$x0607am_td[which(offpeak_data$percent == h67p)]

  uval_78 <-offpeak_data$x0708am_td[which(offpeak_data$percent == h78p)]

  uval_910 <-offpeak_data$x0910am_td[which(offpeak_data$percent == h910p)]

  uval_1011 <-offpeak_data$x1011am_td[which(offpeak_data$percent == h1011p)]

  uval_1112 <-offpeak_data$x1112am_td[which(offpeak_data$percent == h1112p)]

  uval_89 <-peak_data$x0809am_td[which(peak_data$percent == h89p)]


  total_utility <- uval_56 + uval_67 + uval_78 + uval_910 + uval_1011 + uval_1112 + uval_89

  } else {

    total_utility <- 10000000
  }




  total_utility
}



## Using the GA package:
ga_result2 <- ga(
  type = "real-valued",
  fitness = function(offpeak_data,
                     peak_data,
                     x) {
    total_utility <- -fitness_func(
      offpeak_data,
      peak_data,
      x[1], # mdp,
      x[2], # h56p,
      x[3], # h67p,
      x[4], # h78p,
      x[5], # h910p,
      x[6], # h1011p,
      x[7] # h1112p
    )

    total_utility
  },
  offpeak_data = TD_OffPeak2,
  peak_data = TD_Peak2,
  lower = c(0, 0, 0, 0, 0, 0, 0),
  upper = c(0.54, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09),
  popSize = 50, maxiter = 100,
  monitor = TRUE
)

GA | iter = 1 | Mean = -26971157 | Best = -10000000
GA | iter = 2 | Mean = -17364812 | Best = -10000000
GA | iter = 3 | Mean = -11135468 | Best = -10000000
GA | iter = 4 | Mean = -10567804 | Best = -10000000
GA | iter = 5 | Mean = -10568223 | Best = -10000000
GA | iter = 6 | Mean = -11130456 | Best = -10000000
GA | iter = 7 | Mean = -1e+07 | Best = -1e+07
GA | iter = 8 | Mean = -1e+07 | Best = -1e+07
GA | iter = 9 | Mean = -1e+07 | Best = -1e+07
GA | iter = 10 | Mean = -10563539 | Best = -10000000
GA | iter = 11 | Mean = -11129491 | Best = -10000000
GA | iter = 12 | Mean = -1e+07 | Best = -1e+07
GA | iter = 13 | Mean = -10565386 | Best = -10000000
GA | iter = 14 | Mean = -10564288 | Best = -10000000
GA | iter = 15 | Mean = -1e+07 | Best = -1e+07
GA | iter = 16 | Mean = -1e+07 | Best = -1e+07
GA | iter = 17 | Mean = -1e+07 | Best = -1e+07
GA | iter = 18 | Mean = -11129238 | Best = -10000000
GA | iter = 19 | Mean = -1e+07 | Best = -1e+07
GA | iter = 20 | Mean = -10566658 | Best = -10000000
GA | iter = 21 | Mean = -10566871 | Best = -10000000
GA | iter = 22 | Mean = -1e+07 | Best = -1e+07
GA | iter = 23 | Mean = -1e+07 | Best = -1e+07
GA | iter = 24 | Mean = -1e+07 | Best = -1e+07
GA | iter = 25 | Mean = -10564532 | Best = -10000000
GA | iter = 26 | Mean = -1e+07 | Best = -1e+07
GA | iter = 27 | Mean = -1e+07 | Best = -1e+07
GA | iter = 28 | Mean = -1e+07 | Best = -1e+07
GA | iter = 29 | Mean = -1e+07 | Best = -1e+07
GA | iter = 30 | Mean = -1e+07 | Best = -1e+07
GA | iter = 31 | Mean = -1e+07 | Best = -1e+07
GA | iter = 32 | Mean = -10565518 | Best = -10000000
GA | iter = 33 | Mean = -1e+07 | Best = -1e+07
GA | iter = 34 | Mean = -10564593 | Best = -10000000
GA | iter = 35 | Mean = -1e+07 | Best = -1e+07
GA | iter = 36 | Mean = -10565003 | Best = -10000000
GA | iter = 37 | Mean = -10567136 | Best = -10000000
GA | iter = 38 | Mean = -1e+07 | Best = -1e+07
GA | iter = 39 | Mean = -1e+07 | Best = -1e+07
GA | iter = 40 | Mean = -1e+07 | Best = -1e+07
GA | iter = 41 | Mean = -11132602 | Best = -10000000
GA | iter = 42 | Mean = -1e+07 | Best = -1e+07
GA | iter = 43 | Mean = -1e+07 | Best = -1e+07
GA | iter = 44 | Mean = -1e+07 | Best = -1e+07
GA | iter = 45 | Mean = -1e+07 | Best = -1e+07
GA | iter = 46 | Mean = -11133596 | Best = -10000000
GA | iter = 47 | Mean = -1e+07 | Best = -1e+07
GA | iter = 48 | Mean = -1e+07 | Best = -1e+07
GA | iter = 49 | Mean = -1e+07 | Best = -1e+07
GA | iter = 50 | Mean = -10563668 | Best = -10000000
GA | iter = 51 | Mean = -1e+07 | Best = -1e+07
GA | iter = 52 | Mean = -1e+07 | Best = -1e+07
GA | iter = 53 | Mean = -1e+07 | Best = -1e+07
GA | iter = 54 | Mean = -1e+07 | Best = -1e+07
GA | iter = 55 | Mean = -1e+07 | Best = -1e+07
GA | iter = 56 | Mean = -1e+07 | Best = -1e+07
GA | iter = 57 | Mean = -1e+07 | Best = -1e+07
GA | iter = 58 | Mean = -1e+07 | Best = -1e+07
GA | iter = 59 | Mean = -1e+07 | Best = -1e+07
GA | iter = 60 | Mean = -1e+07 | Best = -1e+07
GA | iter = 61 | Mean = -10564274 | Best = -10000000
GA | iter = 62 | Mean = -1e+07 | Best = -1e+07
GA | iter = 63 | Mean = -10566723 | Best = -10000000
GA | iter = 64 | Mean = -1e+07 | Best = -1e+07
GA | iter = 65 | Mean = -1e+07 | Best = -1e+07
GA | iter = 66 | Mean = -11133478 | Best = -10000000
GA | iter = 67 | Mean = -10565362 | Best = -10000000
GA | iter = 68 | Mean = -1e+07 | Best = -1e+07
GA | iter = 69 | Mean = -1e+07 | Best = -1e+07
GA | iter = 70 | Mean = -1e+07 | Best = -1e+07
GA | iter = 71 | Mean = -1e+07 | Best = -1e+07
GA | iter = 72 | Mean = -10565288 | Best = -10000000
GA | iter = 73 | Mean = -1e+07 | Best = -1e+07
GA | iter = 74 | Mean = -11132318 | Best = -10000000
GA | iter = 75 | Mean = -1e+07 | Best = -1e+07
GA | iter = 76 | Mean = -11701470 | Best = -10000000
GA | iter = 77 | Mean = -11131800 | Best = -10000000
GA | iter = 78 | Mean = -10564773 | Best = -10000000
GA | iter = 79 | Mean = -10567488 | Best = -10000000
GA | iter = 80 | Mean = -1e+07 | Best = -1e+07
GA | iter = 81 | Mean = -1e+07 | Best = -1e+07
GA | iter = 82 | Mean = -1e+07 | Best = -1e+07
GA | iter = 83 | Mean = -1e+07 | Best = -1e+07
GA | iter = 84 | Mean = -10564653 | Best = -10000000
GA | iter = 85 | Mean = -1e+07 | Best = -1e+07
GA | iter = 86 | Mean = -1e+07 | Best = -1e+07
GA | iter = 87 | Mean = -1e+07 | Best = -1e+07
GA | iter = 88 | Mean = -1e+07 | Best = -1e+07
GA | iter = 89 | Mean = -1e+07 | Best = -1e+07
GA | iter = 90 | Mean = -1e+07 | Best = -1e+07
GA | iter = 91 | Mean = -1e+07 | Best = -1e+07
GA | iter = 92 | Mean = -1e+07 | Best = -1e+07
GA | iter = 93 | Mean = -1e+07 | Best = -1e+07
GA | iter = 94 | Mean = -10564223 | Best = -10000000
GA | iter = 95 | Mean = -1e+07 | Best = -1e+07
GA | iter = 96 | Mean = -10567577 | Best = -10000000
GA | iter = 97 | Mean = -10566136 | Best = -10000000
GA | iter = 98 | Mean = -1e+07 | Best = -1e+07
GA | iter = 99 | Mean = -1e+07 | Best = -1e+07
GA | iter = 100 | Mean = -1e+07 | Best = -1e+07

Solution values

ga_result2@solution
              x1         x2         x3         x4         x5         x6         x7
 [1,] 0.16634145 0.04334977 0.03966984 0.04517375 0.04751721 0.04560775 0.05269130
 [2,] 0.16687678 0.04621923 0.05054675 0.04705156 0.04730716 0.04867062 0.05250494

Problem and Questions

I specified the constraint with an if statement in the function. But because of so many number of decimal places, the constraint condition is satisfied rarely. Ideally, the constraint should always be satisfied. How can I make sure that the constraint is satisfied and genetic algorithm ga function picks the values to decimal places only?

0 Answers
Related