ICEACE Model: Closed Economy  1.0.0
Design Documentation of ICEACE Model
 All Data Structures Files Functions Variables Typedefs Macros Pages
mall_functions_consumption.c
Go to the documentation of this file.
1 #include "../header.h"
2 #include "../mall_agent_header.h"
3 #include "../library_header.h"
4 
5 
6 /*
7  * \fn: int mall_consumption_shopping()
8  * \brief:
9  */
11 {
12  /* Allocate local buyer queues and seller lists. */
13  seller_array sellers_list;
14  buyer_array buyers_list;
15  /* Initialize arrays. */
16  init_seller_array(&sellers_list);
17  init_buyer_array(&buyers_list);
18 
19  /* Collect supply */
20  int firm_id, inventory;;
21  double price, inv_price;
22  double denominator = 0;
23  double min_price = 5;
24  double max_price = 0;
25 
27  firm_id = sell_message->id;
28  price = sell_message->price;
29  if (price < min_price) {
30  min_price = price;
31  }
32  if (price > max_price) {
33  max_price = price;
34  }
35  inventory = sell_message->inventory;
36  if (price > 0 && inventory > 0) {
37  /* Add to the shelve */
38  inv_price = 1/price;
39  denominator += inv_price;
40  add_seller(&sellers_list, firm_id, price, inventory, inv_price);
41  }
42  else if (inventory <= 0){
43  if (WARNING_MODE) {
44  printf("Warning @mall_consumption_shopping(): An invalid inventory = %d is received from Firm ID = %d\n", inventory, firm_id);
45  }
46  }
47  else{
48  if (WARNING_MODE) {
49  printf("Warning @mall_consumption_shopping(): An invalid price = %f is received from Firm ID = %d\n", price, firm_id);
50  }
51  }
52 
54 
55  //printf("IT_NO = %d, Mall max = %f , min = %f\n", IT_NO, max_price, min_price);
56 
57 
58  /* Queue the households */
59  int hh_id;
60  double budget;
62  hh_id = buy_message->id;
63  budget = buy_message->budget;
64  if (budget > 0) {
65  /* Add household to the queue */
66  add_buyer(&buyers_list, hh_id, budget);
67  }
68  else{
69  if (WARNING_MODE) {
70  printf("Warning @mall_consumption_shopping(): An invalid budget = %f is received from Household ID = %d\n", budget, hh_id);
71  }
72  }
74 
75  /* Do the matching *
76  * Input assumptions:
77  * sellers are sorted ascendingly by price.
78  * buyers are randomly queued
79  * this is done at message filtering stage.
80  */
81  double select_prob;
82  double inv_price_cum;
83  double denominator_temp;
84  int ind,i;
85  int transaction_size;
86  double transaction_volume;
87 
88  /* Identifiers below are used to hold weekly transaction summary.
89  */
90  int total_sold = 0;
91  double total_volume = 0;
92  int transaction_occured;
93  do {
94 
95  if (sellers_list.size == 0 || buyers_list.size == 0) {break;}
96 
97  hh_id = buyers_list.array[0].id;
98  budget = buyers_list.array[0].budget;
99  price = sellers_list.array[0].price;
100 
101  /* The household in the turn does not have enough money to buy even
102  the cheapest available good.
103  */
104  if (budget < price) {
105  remove_buyer(&buyers_list,0);
106  continue;
107  }
108 
109  /* Determining the probability of picking a random seller. */
110  select_prob = (double) random_int(0, 99) / 100;
111  inv_price_cum = 0;
112  transaction_size = 0;
113  transaction_volume = 0;
114  transaction_occured = 0;
115  for (ind = 0; ind < sellers_list.size; ind++) {
116  inventory = sellers_list.array[ind].inventory;
117  firm_id = sellers_list.array[ind].id;
118  if (inventory <= 0) {
119  remove_seller(&sellers_list, ind);
120  if (WARNING_MODE) {
121  printf("Warning @mall_consumption_shopping(): An invalid inventory = %d is detected while processing Firm ID = %d\n", inventory, firm_id);
122  }
123  break;
124  }
125  inv_price_cum += sellers_list.array[ind].inv_price;
126  price = sellers_list.array[ind].price;
127 
128  /* Household with current budget does not afford to buy further goods in the list.
129  The household buys from the ones he/she affords to buy.
130  */
131  if (budget <= price) {
132  denominator_temp = inv_price_cum;
133  if (denominator_temp <= 0) {
134  if (WARNING_MODE) {
135  printf("Warning @mall_consumption_shopping(): An invalid state is detected while processing Household ID = %d\n", hh_id);
136  }
137  remove_buyer(&buyers_list, 0);
138  break;
139  }
140  inv_price_cum = 0;
141  for (i = 0; i <= ind; i++) {
142  inventory = sellers_list.array[i].inventory;
143  inv_price_cum += sellers_list.array[i].inv_price;
144  if ((inv_price_cum / denominator_temp - select_prob) >= 0) {
145  transaction_size = (int) floor(budget / price);
146  if (transaction_size > inventory){
147  transaction_size = inventory;
148  }
149  /* Update household budget and send out message.*/
150  transaction_volume = transaction_size * price;
151  budget -= transaction_volume;
152  buyers_list.array[0].budget = budget;
153  add_bought_message(hh_id, transaction_volume, transaction_size);
154  /* Send out sales info. */
155  add_sold_message(firm_id, transaction_size);
156  total_sold += transaction_size;
157  total_volume += transaction_volume;
158  /* Update sellers inventory to go */
159  inventory -= transaction_size;
160  if (inventory == 0) {
161  denominator -= sellers_list.array[i].inv_price;
162  remove_seller(&sellers_list, i);
163  }
164  else{
165  sellers_list.array[i].inventory = inventory;
166  }
167  transaction_occured = 1;
168  break;
169  }
170  }
171  break;
172  }
173 
174  /* Household decides to buy from the current shelf he/she is examining.
175  */
176  if ((inv_price_cum / denominator - select_prob) >= 0) {
177  transaction_size = (int) floor(budget / price);
178  if (transaction_size > inventory){
179  transaction_size = inventory;
180  }
181  /* Update household budget and send out message.*/
182  transaction_volume = transaction_size * price;
183  budget -= transaction_volume;
184  buyers_list.array[0].budget = budget;
185  add_bought_message(hh_id, transaction_volume, transaction_size);
186  /* Send out sales info. */
187  add_sold_message(firm_id, transaction_size);
188  total_sold += transaction_size;
189  total_volume += transaction_volume;
190  /* Update sellers inventory to go */
191  inventory -= transaction_size;
192  if (inventory == 0) {
193  denominator -= sellers_list.array[ind].inv_price;
194  remove_seller(&sellers_list, ind);
195  }
196  else{
197  sellers_list.array[ind].inventory = inventory;
198  }
199  transaction_occured = 1;
200  }
201  /* Household is eager to buy from a more expensive shelf.
202  */
203 
204  }/* Sellers Loop End */
205  if (transaction_occured == 0) {
206  if (WARNING_MODE) {
207  printf("Warning @mall_consumption_shopping(): Transaction did not take place while processing Household ID = %d\n", hh_id);
208  remove_buyer(&buyers_list, 0);
209  }
210  }
211  } while (1);
212 
213  /* Finish */
214  GOODS_TRANSACTIONS.quantity = total_sold;
215  if (total_sold > 0) {
216  GOODS_TRANSACTIONS.avg_price = total_volume / total_sold;
217  }
218 
219  /* Free seller list */
220  free_seller_array(&sellers_list);
221  /* Free buyer queues */
222  free_buyer_array(&buyers_list);
223  return 0; /* Returning zero means the agent is not removed */
224 }
225 
227 // * \fn: int mall_consumption_shopping()
228 // * \brief:
229 // */
230 //int mall_consumption_shopping_old()
231 //{
232 // /* Initialize **
233 // */
234 //
235 // int firm_id, hh_id;
236 // double price, budget;
237 // int quantity, total_sold;
238 //
239 // double denominator;
240 //
241 // double min_price;
242 // int min_price_index;
243 // int min_price_is_picked;
244 //
245 // /* identifiers used to hold weekly transaction summary
246 // */
247 //
248 // int transaction_quantity = 0;
249 // double transaction_volume = 0;
250 //
251 // /* Allocate local buyer queues and seller lists.
252 // */
253 // seller_array sellers_list;
254 // buyer_array buyers_list;
255 //
256 // /* Initialize */
257 // init_seller_array(&sellers_list);
258 // init_buyer_array(&buyers_list);
259 //
260 // denominator = 0;
261 // min_price_is_picked = 0;
262 // /* Collect supply */
263 // START_SELL_MESSAGE_LOOP
264 // firm_id = sell_message->id;
265 // price = sell_message->price;
266 //
267 // if ( min_price_is_picked == 0){
268 // min_price = price;
269 // min_price_is_picked = 1;
270 // min_price_index = 0;
271 // }
272 //
273 // denominator += 1 / price;
274 // quantity = sell_message->inventory;
275 // /* Add to the shelve */
276 // add_seller(&sellers_list, firm_id, price, quantity);
277 // FINISH_SELL_MESSAGE_LOOP
278 //
279 // /* Queue the households */
280 // START_BUY_MESSAGE_LOOP
281 // hh_id = buy_message->id;
282 // budget = buy_message->budget;
283 // /* Add household to the queue */
284 // add_buyer(&buyers_list, hh_id, budget, 0);
285 // FINISH_BUY_MESSAGE_LOOP
286 //
287 //
288 // if (sellers_list.size == 0 || buyers_list.size == 0) {
289 // /* Free seller list */
290 // free_seller_array(&sellers_list);
291 // /* Free buyer queues */
292 // free_buyer_array(&buyers_list);
293 // return 0;
294 // }
295 //
296 //
297 // /* Do the matching *
298 // * Input assumptions:
299 // * sellers are sorted ascendingly by price.
300 // * buyers are randomly queued
301 // * this is done at message filtering stage.
302 // */
303 // double select_prob;
304 // double firm_select_prob, firm_select_prob_cum;
305 // int tmp,i,j;
306 // int sold_out = 0;
307 // for (i = 0; i < buyers_list.size; i++) {
308 //
309 // if (sold_out == sellers_list.size) { break; }
310 //
311 // budget = buyers_list.array[i].budget;
312 // if (budget < min_price || budget < 0 || min_price < 0){ continue; }
313 // /* Filtering out households with initially insufficient budgets.
314 // */
315 //
316 //
317 // select_prob = (double) random_int(0, sellers_list.size) / sellers_list.size;
318 // firm_select_prob_cum = 0;
319 // j = min_price_index;
320 // do {
321 // /* Filtering out households those who have spent their budget down below min price. */
322 // if (budget < min_price) { break; }
323 //
324 // /* No goods left to buy more. */
325 // if (sold_out == sellers_list.size) { break; }
326 //
327 // quantity = sellers_list.array[j].inventory;
328 //
329 // if (quantity <= 0) {
330 // /* This is the case when goods right after min price goods have already been sold out. */
331 // if (j == min_price_index) {
332 // min_price_index = j+1;
333 // }
334 // j++;
335 // continue;
336 // }
337 //
338 // price = sellers_list.array[j].price;
339 // if (budget < price) {
340 // /* Houshold (select_prob) desires something she/he cannot afford (any more).
341 // Try finding a cheaper product by starting over.
342 // Make sure that an affordable good is targeted.
343 // */
344 // tmp = (int)firm_select_prob_cum * 100;
345 // select_prob = (double)random_int(0, tmp) / (tmp + 1);
346 // firm_select_prob_cum = 0;
347 // j = min_price_index;
348 // continue;
349 // }
350 //
351 // firm_select_prob = (1 / price) / denominator;
352 // firm_select_prob_cum += firm_select_prob;
353 // if ((firm_select_prob_cum - select_prob) >= 0){
354 // quantity = (int) floor(budget / price);
355 //
356 // if (quantity >= sellers_list.array[j].inventory) {
357 // quantity = sellers_list.array[j].inventory;
358 // sold_out++;
359 // denominator -= 1/price;
360 // if (j == min_price_index){
361 // min_price_index = j+1;
362 // min_price = sellers_list.array[j+1].price;
363 // }
364 // }
365 //
366 // if (quantity < 0) {
367 // if (WARNING_MODE) {
368 // printf("Warning @mall_consumption_shopping(): Seller = %d, Buyer = %d, Vars: quantity = %d, budget = %f, price = %f, inventory = %d\n", sellers_list.array[j].id,buyers_list.array[i].id, quantity, budget, price, sellers_list.array[j].inventory);
369 // }
370 // quantity = 0;
371 // }
372 //
373 // buyers_list.array[i].recieved_quantity += quantity;
374 // sellers_list.array[j].inventory -= quantity;
375 // buyers_list.array[i].budget -= quantity * price;
376 // budget = buyers_list.array[i].budget;
377 //
378 // transaction_quantity += quantity;
379 // transaction_volume += quantity * price;
380 //
381 // j = min_price_index;
382 // select_prob = (double)random_int(0, sellers_list.size) / sellers_list.size;
383 // continue;
384 // }
385 // j++;
386 // } while (1);
387 // }
388 //
389 //
390 // /* Indeed keeps unsold quantities. */
391 // total_sold = 0;
392 // quantity = 0;
393 // /* Send out revenue information. */
394 // for (i =0; i < sellers_list.size; i++) {
395 // firm_id = sellers_list.array[i].id;
396 // quantity = sellers_list.array[i].inventory;
397 // add_sold_message(firm_id, quantity);
398 // total_sold += quantity;
399 // }
400 // quantity = 0;
401 // /* Send out goods information. */
402 // for (i =0; i < buyers_list.size; i++) {
403 // hh_id = buyers_list.array[i].id;
404 // budget = buyers_list.array[i].budget;
405 // quantity = buyers_list.array[i].recieved_quantity;
406 // add_bought_message(hh_id, budget, quantity);
407 // }
408 //
409 // /* Finish */
410 // GOODS_TRANSACTIONS.quantity = transaction_quantity;
411 // if (transaction_quantity > 0) {
412 // GOODS_TRANSACTIONS.avg_price = transaction_volume / transaction_quantity;
413 // }
414 //
415 // /* Free seller list */
416 // free_seller_array(&sellers_list);
417 // /* Free buyer queues */
418 // free_buyer_array(&buyers_list);
419 // return 0; /* Returning zero means the agent is not removed */
420 //}
421 
422 /*
423  * \fn: int mall_consumption_summary()
424  * \brief:
425  */
427 {
428  double price;
429  int quantity;
430 
431  price = GOODS_TRANSACTIONS.avg_price;
432  quantity = GOODS_TRANSACTIONS.quantity;
433 
434  if (DATA_COLLECTION_MODE) {
435  char * filename;
436  FILE * file1;
437  filename = malloc(100*sizeof(char));
438  filename[0]=0;
439  strcpy(filename, "./outputs/data/Mall_snapshot.txt");
440 
441  file1 = fopen(filename,"a");
442  fprintf(file1,"%d %d %f\n",IT_NO, quantity, price);
443  fclose(file1);
444  free(filename);
445  }
446 
448 
449  if (PRINT_DEBUG_MODE) {
450  printf("Mall posts weekly transaction summaries. \n");
451  }
452 
453 
454  return 0; /* Returning zero means the agent is not removed */
455 }
456 
457 
458