Skip to content

Instantly share code, notes, and snippets.

@darkopetrovic
Created February 16, 2023 17:21
Show Gist options
  • Select an option

  • Save darkopetrovic/2b1065cf5f597e5ac901a397b4aec65f to your computer and use it in GitHub Desktop.

Select an option

Save darkopetrovic/2b1065cf5f597e5ac901a397b4aec65f to your computer and use it in GitHub Desktop.
Generate a BR (Bischoff and Ratcliff) class instance for the Container Loading Problem (CLP)
import numpy as np
import pandas as pd
from scipy.stats import beta as beta_distribution
def ParkMillerRNG(seed, start, end):
"""Park and Miller Random Number Generator"""
m = 2**31 - 1
a = (end-start)/m
b = start
while True:
seed = (16807*seed) % m
yield a * seed + b
def genBRinstance(c, p, Tc=None, aj=[30, 25, 20], bj=[120, 100, 80], alpha=1, beta=1, Pmax=10000):
"""Generate a BR (Bischoff and Ratcliff) class instance for the Container Loading Problem (CLP).
The function generate furthermore the boxes' weight according to a beta distribution.
Default values (Tc, aj, bj) correspond to the ISO container.
Default values (alpha, beta) correspond an uniform distribution.
Args:
c (int): Class number
p (int): Problem number
Tc (int, optional): Cargo target volume. Defaults to None.
aj (list, optional): Minimal boxes dimensions. Defaults to [30, 25, 20].
bj (list, optional): Maximal boxes dimensions. Defaults to [120, 100, 80].
alpha (int, optional): Beta distribution alpha parameter. Defaults to 1.
beta (int, optional): Beta distribution beta parameter. Defaults to 1.
Pmax (int, optional): Maximal payload weight. Defaults to 10000.
Returns:
Dataframe: List of the generated boxes as pandas dataframe
"""
# Random Number Generator initialization
seed = 2502505+100*(p-1)
rand = ParkMillerRNG(seed, 0, 1)
rng = np.random.default_rng(seed=seed)
def randomGen(a, b, vmin, vmax):
r = rng.beta(a, b)
return vmin + r*(vmax-vmin)
def pseudoRandomGen():
return next(rand)
# ISO Container
Tc = Tc if Tc is not None else 587 * 233 * 220
# number of box types
boxtype = [3, 5, 8, 10, 12, 15, 20]
n = boxtype[c-1]
li = []
wi = []
hi = []
qi = []
vi = []
mi = []
# Discard the first ten random numbers
for i in range(10):
r = pseudoRandomGen()
for i in range(n):
d = []
for j in range(3):
r = pseudoRandomGen()
# Determine box dimensions
dij = int(aj[j] + np.floor(r*(bj[j] - aj[j] + 1)))
d.append(dij)
d.sort(reverse=True)
li.append(d[0])
wi.append(d[1])
hi.append(d[2])
qi.append(1)
vi.append(d[0] * d[1] * d[2])
C = np.sum([qi[i]*vi[i] for i in range(n)])
k = int(np.floor(pseudoRandomGen()*n))
# Determine box quantity
while Tc > C + vi[k]:
qi[k] += 1
C = np.sum([qi[i]*vi[i] for i in range(n)])
k = int(np.floor(pseudoRandomGen()*n))
#### ADD BOX WEIGHT ####
Ex = beta_distribution(alpha, beta).expect()
Dc = Pmax / Tc
Dc_min = 0.5 * Dc
Dc_max = (Dc - Dc_min) / Ex + Dc_min
# Determine box weight
total_mass = 0
for i in range(n):
r = randomGen(alpha, beta, Dc_min, Dc_max)
m = int(r*vi[i])
total_mass += qi[i] * m
mi.append(m)
df = pd.DataFrame({
'quantity': qi,
'length': li,
'width': wi,
'height': hi,
'mass': mi,
})
return df
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment