├── README.md ├── demand.txt ├── shale.py ├── shale_with_sympy.py └── supply.txt /README.md: -------------------------------------------------------------------------------- 1 | # SHALE 2 | SHALE: An Efficient Algorithm for Allocation of Guaranteed Display Advertising 3 | 4 | Online allocation for Guaranteed Display Advertising 5 | 6 | supply: 7 | 8 | supply_node inventory satisfy_demand 9 | 10 | 0 40 a 11 | 12 | 1 40 b 13 | 14 | 2 40 a,c 15 | 16 | 3 40 c,b 17 | 18 | demand: 19 | 20 | demand_node demand penalty target_supply 21 | 22 | a 40 1.000000 0,2 23 | 24 | b 40 1.000000 1,3 25 | 26 | c 70 1.000000 2,3 27 | 28 | allocation: 29 | 30 | demand_node demand allocation 31 | 32 | a 40 43 33 | 34 | b 40 37 35 | 36 | c 70 65 37 | 38 | remaind: 39 | 40 | supply_node inventory remaind 41 | 42 | 0 40 6 43 | 44 | 1 40 9 45 | 46 | 2 40 0 47 | 48 | 3 40 0 49 | 50 | 51 | Any question mail to wangjie5@xiaomi.com 52 | -------------------------------------------------------------------------------- /demand.txt: -------------------------------------------------------------------------------- 1 | #demand_node demand penalty target_supply 2 | a 40 1.0 0,2 3 | b 40 1.0 1,3 4 | c 70 1.0 2,3 5 | #d 79 1.0 2,3 6 | -------------------------------------------------------------------------------- /shale.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from sympy import * 4 | from random import random 5 | from copy import copy 6 | 7 | class Supply: 8 | def __init__(self, file): 9 | self.pair = {} 10 | self.satisfy_demand = {} 11 | with open(file, 'r') as f: 12 | for line in f: 13 | line = line.strip() 14 | if line.startswith('#'): 15 | continue 16 | i, s = line.split('\t') 17 | self.pair[i] = int(s) 18 | 19 | def get_supply(self, i): 20 | return self.pair[i] 21 | 22 | def get_satisfy_demand(self, i): 23 | return self.satisfy_demand[i] 24 | 25 | def get_all_i(self): 26 | return self.pair.keys() 27 | 28 | 29 | class Demand: 30 | def __init__(self, file, supply): 31 | self.demand = {} 32 | self.penalty = {} 33 | self.target_supply = {} 34 | with open(file, 'r') as f: 35 | for line in f: 36 | line = line.strip() 37 | if line.startswith('#'): 38 | continue 39 | j, d, p, ii = line.split('\t') 40 | self.demand[j] = int(d) 41 | self.penalty[j] = float(p) 42 | self.target_supply[j] = ii.split(',') 43 | self._set_supply_satisfy_demand(supply) 44 | 45 | def _set_supply_satisfy_demand(self, supply): 46 | for (j, ii) in self.target_supply.items(): 47 | for i in ii: 48 | if i not in supply.satisfy_demand: 49 | supply.satisfy_demand[i] = [] 50 | supply.satisfy_demand[i].append(j) 51 | 52 | def get_demand(self, j): 53 | return self.demand[j] 54 | 55 | def get_penalty(self, j): 56 | return self.penalty[j] 57 | 58 | def get_target_supply(self, j): 59 | return self.target_supply[j] 60 | 61 | def get_all_j(self): 62 | return self.demand.keys() 63 | 64 | def get_v(self, j): 65 | return 1.0 66 | 67 | 68 | class Shale: 69 | def __init__(self, supply, demand): 70 | self.supply = supply 71 | self.demand = demand 72 | self.solve = Solve() 73 | 74 | def initialize(self): 75 | self.alpha_j = {} 76 | self.beta_i = {} 77 | self.theta_ij = {} 78 | self.sigma_j = {} 79 | for j in self.demand.get_all_j(): 80 | self.alpha_j[j] = 0.0 81 | sum = 0.0 82 | for i in self.demand.get_target_supply(j): 83 | sum += self.supply.get_supply(i) 84 | self.theta_ij[j] = self.demand.get_demand(j) / sum 85 | 86 | 87 | def stage_one(self, iters): 88 | while iters > 0: 89 | for i in self.supply.get_all_i(): 90 | self.update_beta(i) 91 | for j in self.demand.get_all_j(): 92 | self.update_alpha(j) 93 | iters -= 1 94 | print 'stage one alpha --->', sorted(self.alpha_j.iteritems(), key=lambda d:d[0]) 95 | print 'stage one beta --->', sorted(self.beta_i.iteritems(), key=lambda d:d[0]) 96 | 97 | def stage_two(self): 98 | self.s_i = {} 99 | for i in self.supply.get_all_i(): 100 | self.s_i[i] = self.supply.get_supply(i) 101 | self.update_beta(i) 102 | print 'stage two beta --->', sorted(self.beta_i.iteritems(), key=lambda d:d[0]) 103 | sigma = {} 104 | for j in self.demand.get_all_j(): 105 | #self.find_sigma(j) 106 | self.find_sigma2(j) 107 | #self.update_sigma(j) 108 | for i in self.demand.get_target_supply(j): 109 | g = max(0.0, self.theta_ij[j] * (1.0+(self.sigma_j[j]-self.beta_i[i])/self.demand.get_v(j))) 110 | self.s_i[i] -= min(self.s_i[i], self.supply.get_supply(i) * g) 111 | 112 | def output(self): 113 | print 'output alpha_j --->', sorted(self.alpha_j.iteritems(), key=lambda d:d[0]) 114 | print 'output sigma_j --->', sorted(self.sigma_j.iteritems(), key=lambda d:d[0]) 115 | 116 | def update_beta(self, i): 117 | coef = [] 118 | for j in self.supply.get_satisfy_demand(i): 119 | a = self.theta_ij[j] * (1.0 + self.alpha_j[j] / self.demand.get_v(j)) 120 | b = self.theta_ij[j] / self.demand.get_v(j) 121 | coef.append((a / b, a, b)) 122 | result = self.solve.max(coef, 1.0) 123 | if len(result) == 0 or result[0] < 0.0: 124 | self.beta_i[i] = 0.0 125 | else: 126 | self.beta_i[i] = result[0] 127 | 128 | def update_alpha(self, j): 129 | coef = [] 130 | for i in self.demand.get_target_supply(j): 131 | s = self.supply.get_supply(i) 132 | a = -1.0 * s * self.theta_ij[j] * (1.0 - self.beta_i[i] / self.demand.get_v(j)) 133 | b = -1.0 * s * self.theta_ij[j] /self.demand.get_v(j) 134 | coef.append((a / b, a, b)) 135 | result = self.solve.max(coef, -1.0 * self.demand.get_demand(j)) 136 | if len(result) == 0 or -1.0 * result[0] > self.demand.get_penalty(j): 137 | self.alpha_j[j] = self.demand.get_penalty(j) 138 | #if len(result) == 0 or result[0] < 0.0: 139 | # self.alpha_j[j] = 0.0 140 | else: 141 | self.alpha_j[j] = -1.0 * result[0] 142 | 143 | def find_sigma(self, j): 144 | sigma = Symbol('sigma') 145 | flag = True 146 | for i in self.demand.get_target_supply(j): 147 | s = self.supply.get_supply(i) 148 | f = self.theta_ij[j] * (1.0 + (sigma - self.beta_i[i]) / self.demand.get_v(j)) 149 | f_max = s * Piecewise((f, f >= 0), (0, f < 0)) 150 | f_min = Piecewise((self.s_i[i], self.s_i[i] <= f_max), (f_max, self.s_i[i] > f_max)) 151 | if flag: 152 | sum = f_min 153 | flag = False 154 | else: 155 | sum += f_min 156 | result = solve(sum - self.demand.get_demand(j), sigma) 157 | if len(result) == 0: 158 | self.sigma_j[j] = float('inf') 159 | else: 160 | self.sigma_j[j] = result[0] 161 | 162 | def find_sigma2(self, j): 163 | result = self.update_sigma(j) 164 | if len(result) == 0: 165 | self.sigma_j[j] = float('inf') 166 | else: 167 | self.sigma_j[j] = -1.0 * result[0] 168 | #self.sigma_j[j] = result[0] 169 | 170 | def update_sigma(self, j): 171 | solutions = [] 172 | coef = [] 173 | for i in self.demand.get_target_supply(j): 174 | s = self.supply.get_supply(i) 175 | a = s * self.theta_ij[j] * (1.0 - self.beta_i[i] / self.demand.get_v(j)) 176 | b = s * self.theta_ij[j] / self.demand.get_v(j) 177 | coef.append(((self.s_i[i] - a) / b, a / b, a, b, self.s_i[i])) 178 | coef = sorted(coef, key=lambda t:t[1]) 179 | 180 | for k in range(len(coef)): 181 | temp = copy(coef[k:]) 182 | temp = sorted(temp, key=lambda t:t[0]) 183 | sum_remained = 0.0 184 | sum_cons = 0.0 185 | sum_coef = 0.0 186 | for t in range(len(temp)): 187 | sum_cons += temp[t][2] 188 | sum_coef += temp[t][3] 189 | sum_remained += temp[t][4] 190 | res = (sum_cons - self.demand.get_demand(j)) / sum_coef 191 | if sum_remained < self.demand.get_demand(j): 192 | continue 193 | if k == 0: 194 | if res <=temp[0][0] and res <= coef[k][1]: 195 | solutions.append(res) 196 | else: 197 | if res <=temp[0][0] and res <= coef[k][1] and res >= coef[k-1][1]: 198 | solutions.append(res) 199 | sum_remained = 0.0 200 | for t in range(1, len(temp)): 201 | sum_cons -= temp[t-1][2] 202 | sum_coef -= temp[t-1][3] 203 | sum_remained += temp[t-1][4] 204 | res = (sum_cons + sum_remained - self.demand.get_demand(j)) / sum_coef 205 | if k == 0: 206 | if res <= temp[t][0] and res >= temp[t-1][0] and res <= coef[k][1]: 207 | solutions.append(res) 208 | else: 209 | if res <= temp[t][0] and res >= temp[t-1][0] and res <= coef[k][1] and res >= coef[k-1][1]: 210 | solutions.append(res) 211 | return solutions 212 | 213 | 214 | class Online: 215 | def __init__(self, supply, demand, alpha_j, sigma_j): 216 | self.supply = supply 217 | self.demand = demand 218 | self.alpha_j = alpha_j 219 | self.sigma_j = sigma_j 220 | self.theta_ij = {} 221 | self.beta_i = {} 222 | self.allocation_j = {} 223 | self.remaind_i = {} 224 | for i in self.supply.get_all_i(): 225 | self.remaind_i[i] = supply.get_supply(i) 226 | for j in self.demand.get_all_j(): 227 | sum = 0.0 228 | for i in self.demand.get_target_supply(j): 229 | sum += self.supply.get_supply(i) 230 | self.theta_ij[j] = self.demand.get_demand(j) / sum 231 | self.allocation_j[j] = 0 232 | self.solve = Solve() 233 | 234 | 235 | def allocation(self, i): 236 | s = 1.0 237 | x_ij = {} 238 | if i not in self.beta_i: 239 | self.update_beta(i) 240 | for j in self.supply.get_satisfy_demand(i): 241 | g = max(0.0, self.theta_ij[j] * (1.0+(self.sigma_j[j]-self.beta_i[i])/self.demand.get_v(j))) 242 | x_ij[j] = min(s, g) 243 | s -= x_ij[j] 244 | 245 | sum = 0.0 246 | for (j, p) in x_ij.items(): 247 | sum += p 248 | if sum < 1.0: 249 | print 'there is %f chance that no conract is selected' % (1.0 - sum) 250 | 251 | r = random() 252 | sum = 0.0 253 | for (j, p) in x_ij.items(): 254 | sum += p 255 | if r < sum: 256 | self.allocation_j[j] += 1 257 | self.remaind_i[i] -= 1 258 | break 259 | 260 | 261 | def update_beta(self, i): 262 | coef = [] 263 | for j in self.supply.get_satisfy_demand(i): 264 | a = self.theta_ij[j] * (1.0 + self.alpha_j[j] / self.demand.get_v(j)) 265 | b = self.theta_ij[j] / self.demand.get_v(j) 266 | coef.append((a / b, a, b)) 267 | result = self.solve.max(coef, 1.0) 268 | if len(result) == 0 or result[0] < 0.0: 269 | self.beta_i[i] = 0.0 270 | else: 271 | self.beta_i[i] = result[0] 272 | 273 | 274 | class Solve: 275 | # http://math.stackexchange.com/questions/145458/solve-equations-using-the-max-function 276 | def max(self, coef, y): 277 | solutions = [] 278 | sum_cons = 0.0 279 | sum_coef = 0.0 280 | for i in range(len(coef)): 281 | sum_cons += coef[i][1] 282 | sum_coef += coef[i][2] 283 | coef = sorted(coef, key=lambda t:t[0]) 284 | res = (sum_cons - y) / sum_coef 285 | if res <= coef[0][0]: 286 | solutions.append(res) 287 | for i in range(1, len(coef)): 288 | sum_cons -= coef[i-1][1] 289 | sum_coef -= coef[i-1][2] 290 | res = (sum_cons - y) / sum_coef 291 | if res <= coef[i]: 292 | solutions.append(res) 293 | break 294 | return solutions 295 | 296 | def max2(self): 297 | pass 298 | 299 | 300 | #http://www.bitsofpancake.com/math/minimum-and-maximum-of-two-functions/ 301 | #http://math.stackexchange.com/questions/602553/how-to-invert-max-and-min-operators-in-equations 302 | def minmax(self): 303 | pass 304 | 305 | 306 | 307 | class Debug: 308 | def __init__(self, shale, online): 309 | self.shale = shale 310 | self.online = online 311 | 312 | def print_supply(self): 313 | ii = self.shale.supply.get_all_i() 314 | ii.sort() 315 | print "\nsupply:" 316 | print "supply_node\tinventory\tsatisfy_demand" 317 | for i in ii: 318 | print '%s\t\t%d\t\t%s' % (i, self.shale.supply.get_supply(i), ','.join(self.shale.supply.get_satisfy_demand(i))) 319 | 320 | def print_demand(self): 321 | jj = self.shale.demand.get_all_j() 322 | jj.sort() 323 | print "\ndemand:" 324 | print "demand_node\tdemand\tpenalty\ttarget_supply" 325 | for j in jj: 326 | print '%s\t\t%d\t%f\t%s' % (j, self.shale.demand.get_demand(j), self.shale.demand.get_penalty(j), \ 327 | ','.join(self.shale.demand.get_target_supply(j))) 328 | 329 | def print_online_allocation(self): 330 | jj = self.online.demand.get_all_j() 331 | jj.sort() 332 | print "\nallocation:" 333 | print "demand_node\tdemand\t\tallocation" 334 | for j in jj: 335 | print '%s\t\t%d\t\t%d' % (j, self.online.demand.get_demand(j), self.online.allocation_j[j]) 336 | 337 | def print_online_remaind(self): 338 | ii = self.online.supply.get_all_i() 339 | ii.sort() 340 | print "\nremaind:" 341 | print "supply_node\tinventory\tremaind" 342 | for i in ii: 343 | print '%s\t\t%d\t\t%s' % (i, self.online.supply.get_supply(i), self.online.remaind_i[i]) 344 | 345 | 346 | def main(): 347 | supply = Supply('./supply.txt') 348 | demand = Demand('./demand.txt', supply) 349 | 350 | shale = Shale(supply, demand) 351 | shale.initialize() 352 | shale.stage_one(5) 353 | shale.stage_two() 354 | shale.output() 355 | 356 | online = Online(supply, demand, shale.alpha_j, shale.sigma_j) 357 | for i in supply.get_all_i(): 358 | inventory = supply.get_supply(i) 359 | while inventory > 0: 360 | online.allocation(i) 361 | inventory -= 1 362 | 363 | debug = Debug(shale, online) 364 | debug.print_supply() 365 | debug.print_demand() 366 | debug.print_online_allocation() 367 | debug.print_online_remaind() 368 | 369 | 370 | 371 | if __name__ == '__main__' : 372 | main() 373 | -------------------------------------------------------------------------------- /shale_with_sympy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from sympy import * 4 | from random import random 5 | 6 | class Supply: 7 | def __init__(self, file): 8 | self.pair = {} 9 | self.satisfy_demand = {} 10 | with open(file, 'r') as f: 11 | for line in f: 12 | line = line.strip() 13 | if line.startswith('#'): 14 | continue 15 | i, s = line.split('\t') 16 | self.pair[i] = int(s) 17 | 18 | def get_supply(self, i): 19 | return self.pair[i] 20 | 21 | def get_satisfy_demand(self, i): 22 | return self.satisfy_demand[i] 23 | 24 | def get_all_i(self): 25 | return self.pair.keys() 26 | 27 | 28 | class Demand: 29 | def __init__(self, file, supply): 30 | self.demand = {} 31 | self.penalty = {} 32 | self.target_supply = {} 33 | with open(file, 'r') as f: 34 | for line in f: 35 | line = line.strip() 36 | if line.startswith('#'): 37 | continue 38 | j, d, p, ii = line.split('\t') 39 | self.demand[j] = int(d) 40 | self.penalty[j] = float(p) 41 | self.target_supply[j] = ii.split(',') 42 | self._set_supply_satisfy_demand(supply) 43 | 44 | def _set_supply_satisfy_demand(self, supply): 45 | for (j, ii) in self.target_supply.items(): 46 | for i in ii: 47 | if i not in supply.satisfy_demand: 48 | supply.satisfy_demand[i] = [] 49 | supply.satisfy_demand[i].append(j) 50 | 51 | def get_demand(self, j): 52 | return self.demand[j] 53 | 54 | def get_penalty(self, j): 55 | return self.penalty[j] 56 | 57 | def get_target_supply(self, j): 58 | return self.target_supply[j] 59 | 60 | def get_all_j(self): 61 | return self.demand.keys() 62 | 63 | def get_v(self, j): 64 | return 1.0 65 | 66 | 67 | class Shale: 68 | def __init__(self, supply, demand): 69 | self.supply = supply 70 | self.demand = demand 71 | 72 | def initialize(self): 73 | self.alpha_j = {} 74 | self.beta_i = {} 75 | self.theta_ij = {} 76 | self.sigma_j = {} 77 | for j in self.demand.get_all_j(): 78 | self.alpha_j[j] = 0.0 79 | sum = 0.0 80 | for i in self.demand.get_target_supply(j): 81 | sum += self.supply.get_supply(i) 82 | self.theta_ij[j] = self.demand.get_demand(j) / sum 83 | 84 | 85 | def stage_one(self, iters): 86 | while iters > 0: 87 | for i in self.supply.get_all_i(): 88 | self.update_beta(i) 89 | for j in self.demand.get_all_j(): 90 | self.update_alpha(j) 91 | iters -= 1 92 | print 'stage one alpha --->', sorted(self.alpha_j.iteritems(), key=lambda d:d[0]) 93 | print 'stage one beta --->', sorted(self.beta_i.iteritems(), key=lambda d:d[0]) 94 | 95 | def stage_two(self): 96 | self.s_i = {} 97 | for i in self.supply.get_all_i(): 98 | self.s_i[i] = self.supply.get_supply(i) 99 | self.update_beta(i) 100 | print 'stage two beta --->', sorted(self.beta_i.iteritems(), key=lambda d:d[0]) 101 | sigma = {} 102 | for j in self.demand.get_all_j(): 103 | self.find_sigma(j) 104 | for i in self.demand.get_target_supply(j): 105 | g = max(0.0, self.theta_ij[j] * (1.0+(self.sigma_j[j]-self.beta_i[i])/self.demand.get_v(j))) 106 | self.s_i[i] -= min(self.s_i[i], self.supply.get_supply(i) * g) 107 | 108 | def output(self): 109 | print 'output alpha_j --->', sorted(self.alpha_j.iteritems(), key=lambda d:d[0]) 110 | print 'output sigma_j --->', sorted(self.sigma_j.iteritems(), key=lambda d:d[0]) 111 | 112 | def update_beta(self, i): 113 | beta = Symbol('beta') 114 | flag = True 115 | for j in self.supply.get_satisfy_demand(i): 116 | f = self.theta_ij[j] * (1.0+(self.alpha_j[j]-beta)/self.demand.get_v(j)) 117 | if flag: 118 | sum = Piecewise((f, f >= 0), (0, f < 0)) 119 | flag = False 120 | else: 121 | sum += Piecewise((f, f >= 0), (0, f < 0)) 122 | result = solve(sum - 1, beta) 123 | if len(result) == 0 or result[0] < 0.0: 124 | self.beta_i[i] = 0.0 125 | else: 126 | self.beta_i[i] = result[0] 127 | 128 | def update_alpha(self, j): 129 | alpha = Symbol('alpha') 130 | flag = True 131 | for i in self.demand.get_target_supply(j): 132 | s = self.supply.get_supply(i) 133 | f = self.theta_ij[j] * (1.0+(alpha-self.beta_i[i])/self.demand.get_v(j)) 134 | if flag: 135 | sum = s * Piecewise((f, f >= 0), (0, f < 0)) 136 | flag = False 137 | else: 138 | sum += s * Piecewise((f, f >= 0), (0, f < 0)) 139 | result = solve(sum - self.demand.get_demand(j), alpha) 140 | if len(result) == 0 or result[0] > self.demand.get_penalty(j): 141 | self.alpha_j[j] = self.demand.get_penalty(j) 142 | #if len(result) == 0 or result[0] < 0.0: 143 | # self.alpha_j[j] = 0.0 144 | else: 145 | self.alpha_j[j] = result[0] 146 | 147 | 148 | def find_sigma(self, j): 149 | sigma = Symbol('sigma') 150 | flag = True 151 | for i in self.demand.get_target_supply(j): 152 | s = self.supply.get_supply(i) 153 | f = self.theta_ij[j] * (1.0+(sigma-self.beta_i[i])/self.demand.get_v(j)) 154 | f_max = s * Piecewise((f, f >= 0), (0, f < 0)) 155 | f_min = Piecewise((self.s_i[i], self.s_i[i] <= f_max), (f_max, self.s_i[i] > f_max)) 156 | if flag: 157 | sum = f_min 158 | flag = False 159 | else: 160 | sum += f_min 161 | result = solve(sum - self.demand.get_demand(j), sigma) 162 | if len(result) == 0: 163 | self.sigma_j[j] = float('inf') 164 | else: 165 | self.sigma_j[j] = result[0] 166 | 167 | class Online: 168 | def __init__(self, supply, demand, alpha_j, sigma_j): 169 | self.supply = supply 170 | self.demand = demand 171 | self.alpha_j = alpha_j 172 | self.sigma_j = sigma_j 173 | self.theta_ij = {} 174 | self.beta_i = {} 175 | self.allocation_j = {} 176 | self.remaind_i = {} 177 | for i in self.supply.get_all_i(): 178 | self.remaind_i[i] = supply.get_supply(i) 179 | for j in self.demand.get_all_j(): 180 | sum = 0.0 181 | for i in self.demand.get_target_supply(j): 182 | sum += self.supply.get_supply(i) 183 | self.theta_ij[j] = self.demand.get_demand(j) / sum 184 | self.allocation_j[j] = 0 185 | 186 | 187 | def allocation(self, i): 188 | s = 1.0 189 | x_ij = {} 190 | if i not in self.beta_i: 191 | self.update_beta(i) 192 | for j in self.supply.get_satisfy_demand(i): 193 | g = max(0.0, self.theta_ij[j] * (1.0+(self.sigma_j[j]-self.beta_i[i])/self.demand.get_v(j))) 194 | x_ij[j] = min(s, g) 195 | s -= x_ij[j] 196 | 197 | sum = 0.0 198 | for (j, p) in x_ij.items(): 199 | sum += p 200 | if sum < 1.0: 201 | print 'there is %f chance that no conract is selected' % (1.0 - sum) 202 | 203 | r = random() 204 | sum = 0.0 205 | for (j, p) in x_ij.items(): 206 | sum += p 207 | if r < sum: 208 | self.allocation_j[j] += 1 209 | self.remaind_i[i] -= 1 210 | break 211 | 212 | 213 | def update_beta(self, i): 214 | beta = Symbol('beta') 215 | flag = True 216 | for j in self.supply.get_satisfy_demand(i): 217 | f = self.theta_ij[j] * (1.0+(self.alpha_j[j]-beta)/self.demand.get_v(j)) 218 | if flag: 219 | sum = Piecewise((f, f >= 0), (0, f < 0)) 220 | flag = False 221 | else: 222 | sum += Piecewise((f, f >= 0), (0, f < 0)) 223 | result = solve(sum - 1, beta) 224 | if len(result) == 0 or result[0] < 0.0: 225 | self.beta_i[i] = 0.0 226 | else: 227 | self.beta_i[i] = result[0] 228 | 229 | 230 | class Debug: 231 | def __init__(self, shale, online): 232 | self.shale = shale 233 | self.online = online 234 | 235 | def print_supply(self): 236 | ii = self.shale.supply.get_all_i() 237 | ii.sort() 238 | print "\nsupply:" 239 | print "supply_node\tinventory\tsatisfy_demand" 240 | for i in ii: 241 | print '%s\t\t%d\t\t%s' % (i, self.shale.supply.get_supply(i), ','.join(self.shale.supply.get_satisfy_demand(i))) 242 | 243 | def print_demand(self): 244 | jj = self.shale.demand.get_all_j() 245 | jj.sort() 246 | print "\ndemand:" 247 | print "demand_node\tdemand\tpenalty\ttarget_supply" 248 | for j in jj: 249 | print '%s\t\t%d\t%f\t%s' % (j, self.shale.demand.get_demand(j), self.shale.demand.get_penalty(j), \ 250 | ','.join(self.shale.demand.get_target_supply(j))) 251 | 252 | def print_online_allocation(self): 253 | jj = self.online.demand.get_all_j() 254 | jj.sort() 255 | print "\nallocation:" 256 | print "demand_node\tdemand\t\tallocation" 257 | for j in jj: 258 | print '%s\t\t%d\t\t%d' % (j, self.online.demand.get_demand(j), self.online.allocation_j[j]) 259 | 260 | def print_online_remaind(self): 261 | ii = self.online.supply.get_all_i() 262 | ii.sort() 263 | print "\nremaind:" 264 | print "supply_node\tinventory\tremaind" 265 | for i in ii: 266 | print '%s\t\t%d\t\t%s' % (i, self.online.supply.get_supply(i), self.online.remaind_i[i]) 267 | 268 | 269 | def main(): 270 | supply = Supply('./supply.txt') 271 | demand = Demand('./demand.txt', supply) 272 | 273 | shale = Shale(supply, demand) 274 | shale.initialize() 275 | shale.stage_one(5) 276 | shale.stage_two() 277 | shale.output() 278 | 279 | online = Online(supply, demand, shale.alpha_j, shale.sigma_j) 280 | for i in supply.get_all_i(): 281 | inventory = supply.get_supply(i) 282 | while inventory > 0: 283 | online.allocation(i) 284 | inventory -= 1 285 | 286 | debug = Debug(shale, online) 287 | debug.print_supply() 288 | debug.print_demand() 289 | debug.print_online_allocation() 290 | debug.print_online_remaind() 291 | 292 | 293 | 294 | if __name__ == '__main__' : 295 | main() 296 | -------------------------------------------------------------------------------- /supply.txt: -------------------------------------------------------------------------------- 1 | #supply_node inventory 2 | 0 40 3 | 1 40 4 | 2 40 5 | 3 40 6 | --------------------------------------------------------------------------------