Created
February 16, 2023 17:21
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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