def experiment(results_csv_file: str, recipe: list, value_ranges: list, nums_of_agents: list, num_of_iterations: int, agent_counts: list, agent_values: list, recipe_tree_agent_counts: list, num_recipes: int): """ Run an experiment similar to McAfee (1992) experiment on the given auction. :param results_csv_file: the experiment result file. :param auction_functions: list of functions for executing the auction under consideration. :param auction_names: titles of the experiment, for printouts. :param recipe: can be any vector of ones, e.g. (1,1,1), for our trade-reduction mechanism, or any vector of positive integers for our ascending-auction mechanism. :param nums_of_agents: list of n(s) for number of possible trades to make the calculations. :param stocks_prices: list of prices for each stock and each agent. :param stock_names: list of stocks names which prices are belongs, for naming only. """ TABLE_COLUMNS = [ "iterations", "recipe", "numofagents", "optimalcount", "optimalkmin", "optimalkmax", "gftformula", "auctioncount", "auctionkmin", "auctionkmax", "countratio", "optimalgft", "auctiongft", "gftratio" ] print('recipe:', recipe, 'size:', num_recipes) GFT_ROUND = 1 - 1 K_ROUND = 2 - 1 RATIO_ROUND = 3 - 1 results_table = TeeTable(TABLE_COLUMNS, results_csv_file) recipe_str = str(recipe).replace(',', '-') is_binary = len(set(recipe_tree_agent_counts)) == 1 for i in range(len(nums_of_agents)): now = datetime.now() sum_optimal_count = sum_auction_count = sum_optimal_kmin = sum_optimal_kmax = 0 # count the number of deals done in the optimal vs. the actual auction. sum_optimal_gft = sum_auction_total_gft = sum_auction_kmin = sum_auction_kmax = 0 for iteration in range(num_of_iterations): #if iteration % 10000 == 0: # print('iteration:', iteration) agents = [] for category in range(len(recipe_tree_agent_counts)): sign = 0 if category == 0 else 1 agents.append( AgentCategory.uniformly_random( "agent", int(nums_of_agents[i] * agent_counts[category]), value_ranges[sign][0] * agent_values[category], value_ranges[sign][1] * agent_values[category])) #agents.append(AgentCategory.uniformly_random("agent", nums_of_agents[i], value_ranges[sign][0], value_ranges[sign][1])) market = Market(agents) #print(market) #print(agents) recipe_tree = RecipeTree(market.categories, recipe, recipe_tree_agent_counts) optimal_trade, optimal_count, optimal_gft, kmin, kmax, categories_optimal_counters = recipe_tree.optimal_trade_with_counters( ) #print('counters:' + str(categories_counters)) #print('optimal trade:', optimal_trade, optimal_count, optimal_gft) auction_trade = budget_balanced_ascending_auction( market, recipe, recipe_tree_agent_counts) auction_count = auction_trade.num_of_deals() auction_kmin = auction_trade.min_num_of_deals() auction_kmax = auction_trade.max_num_of_deals() path_counters = auction_trade.path_counters gft = auction_trade.gain_from_trade() #print('Compare:', categories_optimal_counters, path_counters) for counter in categories_optimal_counters.keys(): if categories_optimal_counters[ counter] > path_counters[counter] + 1 and False: print(market) print('Compare:', categories_optimal_counters, path_counters) print('Warning counters', str(counter), 'are not in same size!', categories_optimal_counters[counter], '!=', path_counters[counter]) #for i in range(len(path_counters)): # print('Compare:', categories_optimal_counters, path_counters) #if optimal_count > 0 and gft < optimal_gft * (kmin - 1)/(kmin + 2): #the auction count is less more than 1 than the optimal count. # print('Warning GFT!!!', 'optimal_count:', optimal_count, 'auction_count:', auction_count, # 'num_of_possible_ps:', nums_of_agents[i], 'optimal_gft:', optimal_gft, 'gft:', gft, 'lower bound:', optimal_gft * (1 - 1/optimal_count)) # if nums_of_agents[i] < 20: # print(market.categories) sum_optimal_count += optimal_count sum_auction_count += auction_count sum_optimal_kmin += kmin sum_optimal_kmax += kmax sum_auction_kmin += auction_kmin sum_auction_kmax += auction_kmax sum_optimal_gft += optimal_gft sum_auction_total_gft += gft #if auction_count < optimal_count - 2: #the auction count is less more than 1 than the optimal count. #print('Warning!!!', 'optimal_count:', optimal_count, 'auction_count:', auction_count, 'num_of_possible_ps:', nums_of_agents[i]) #if nums_of_agents[i] < 10: # print(market.categories) # print("Num of times {} attains the maximum GFT: {} / {} = {:.2f}%".format(title, count_optimal_gft, num_of_iterations, count_optimal_gft * 100 / num_of_iterations)) # print("GFT of {}: {:.2f} / {:.2f} = {:.2f}%".format(title, sum_auction_gft, sum_optimal_gft, 0 if sum_optimal_gft==0 else sum_auction_gft * 100 / sum_optimal_gft)) kmin_mean = sum_optimal_kmin / num_of_iterations if is_binary: gft_formula = int_round( (kmin_mean - 1) / kmin_mean * 100 if kmin_mean - 1 > 0 else 0, RATIO_ROUND) else: gft_formula = int_round( (kmin_mean - num_recipes) / (kmin_mean + num_recipes) * 100 if kmin_mean - num_recipes > 0 else 0, RATIO_ROUND) results_table.add( OrderedDict([ ("iterations", num_of_iterations), ("recipe", recipe_str), ("numofagents", nums_of_agents[i]), ("optimalcount", int_round(sum_optimal_count / num_of_iterations, K_ROUND)), ("optimalkmin", int_round(kmin_mean, K_ROUND)), ("optimalkmax", int_round(sum_optimal_kmax / num_of_iterations, K_ROUND)), ("gftformula", gft_formula), ("auctioncount", int_round(sum_auction_count / num_of_iterations, K_ROUND)), ("auctionkmin", int_round(sum_auction_kmin / num_of_iterations, K_ROUND)), ("auctionkmax", int_round(sum_auction_kmax / num_of_iterations, K_ROUND)), ("countratio", int_round( 0 if sum_optimal_count == 0 else (sum_auction_count / sum_optimal_count) * 100, RATIO_ROUND)), ("optimalgft", int_round(sum_optimal_gft / num_of_iterations, GFT_ROUND)), ("auctiongft", int_round(sum_auction_total_gft / num_of_iterations, GFT_ROUND)), ("gftratio", '0.00' if sum_optimal_gft == 0 else int_round( sum_auction_total_gft / sum_optimal_gft * 100, RATIO_ROUND)), ])) print('took', (datetime.now() - now).seconds) results_table.done()
def experiment(results_csv_file: str, recipe: list, value_ranges: list, nums_of_agents: list, num_of_iterations: int, agent_counts: list, agent_values: list, agent_counts_integer: list): """ Run an experiment similar to McAfee (1992) experiment on the given auction. :param results_csv_file: the experiment result file. :param auction_functions: list of functions for executing the auction under consideration. :param auction_names: titles of the experiment, for printouts. :param recipe: can be any vector of ones, e.g. (1,1,1), for our trade-reduction mechanism, or any vector of positive integers for our ascending-auction mechanism. :param nums_of_agents: list of n(s) for number of possible trades to make the calculations. :param stocks_prices: list of prices for each stock and each agent. :param stock_names: list of stocks names which prices are belongs, for naming only. """ TABLE_COLUMNS = [ "iterations", "recipe", "numofagents", "optimalcount", "optimalkmin", "optimalkmax", "gftformula", "auctioncount", "auctionkmin", "auctionkmax", "countratio", "optimalgft", "auctiongft", "gftratio" ] GFT_ROUND = 1 K_ROUND = 2 RATIO_ROUND = 3 print('recipe:', recipe) results_table = TeeTable(TABLE_COLUMNS, results_csv_file) results_table_integer = TeeTable(TABLE_COLUMNS, results_csv_file[0:-4] + '_integer.csv') recipe_str = str(recipe).replace(',', '-') category_size_list = get_agents_analyze(recipe) for i in range(len(nums_of_agents)): sum_optimal_count = sum_auction_count = sum_optimal_kmin = sum_optimal_kmax = 0 # count the number of deals done in the optimal vs. the actual auction. sum_optimal_gft = sum_auction_total_gft = sum_auction_kmin = sum_auction_kmax = 0 sum_optimal_count_integer = sum_auction_count_integer = sum_optimal_kmin_integer = sum_optimal_kmax_integer = 0 # count the number of deals done in the optimal vs. the actual auction. sum_optimal_gft_integer = sum_auction_total_gft_integer = sum_auction_kmin_integer = sum_auction_kmax_integer = 0 for iteration in range(num_of_iterations): if iteration % 10000 == 0: print('iteration:', iteration) agents = [] agents_integer = [] for category in range(len(category_size_list)): sign = 0 if category == 0 else 1 agent_category = AgentCategory.uniformly_random( "agent", int(nums_of_agents[i] * agent_counts[category]), value_ranges[sign][0] * agent_values[category], value_ranges[sign][1] * agent_values[category]) agents.append(agent_category) agents_integer.append( AgentCategory( agent_category.name, agent_category.values + agent_category.values)) #agents.append(AgentCategory.uniformly_random("agent", nums_of_agents[i], value_ranges[sign][0], value_ranges[sign][1])) market = Market(agents) market_integer = Market(agents_integer) #print(agents) recipe_tree = RecipeTree(market.categories, recipe) recipe_tree_integer = RecipeTree(market_integer.categories, recipe, agent_counts_integer) optimal_trade, optimal_count, optimal_gft, kmin, kmax = recipe_tree.optimal_trade_with_counters( ) optimal_trade_integer, optimal_count_integer, optimal_gft_integer, kmin_integer, kmax_integer = recipe_tree_integer.optimal_trade_with_counters( ) #print('optimal trade:', optimal_trade, optimal_count, optimal_gft) auction_trade = budget_balanced_ascending_auction(market, recipe) auction_trade_integer = budget_balanced_ascending_auction( market_integer, recipe, agent_counts_integer) auction_count = auction_trade.num_of_deals() auction_count_integer = auction_trade_integer.num_of_deals() auction_kmin = auction_trade.min_num_of_deals() auction_kmin_integer = auction_trade_integer.min_num_of_deals() auction_kmax = auction_trade.max_num_of_deals() auction_kmax_integer = auction_trade_integer.max_num_of_deals() gft = auction_trade.gain_from_trade() gft_integer = auction_trade_integer.gain_from_trade() #if optimal_count > 0 and gft < optimal_gft * (1 - 1/optimal_count): #the auction count is less more than 1 than the optimal count. # print('Warning GFT!!!', 'optimal_count:', optimal_count, 'auction_count:', auction_count, # 'num_of_possible_ps:', nums_of_agents[i], 'optimal_gft:', optimal_gft, 'gft:', gft) # if nums_of_agents[i] < 20: # print(market.categories) sum_optimal_count += optimal_count sum_optimal_count_integer += optimal_count_integer sum_auction_count += auction_count sum_auction_count_integer += auction_count_integer sum_optimal_kmin += kmin sum_optimal_kmin_integer += kmin_integer sum_optimal_kmax += kmax sum_optimal_kmax_integer += kmax_integer sum_auction_kmin += auction_kmin sum_auction_kmin_integer += auction_kmin_integer sum_auction_kmax += auction_kmax sum_auction_kmax_integer += auction_kmax_integer sum_optimal_gft += optimal_gft sum_optimal_gft_integer += optimal_gft_integer sum_auction_total_gft += gft sum_auction_total_gft_integer += gft_integer if auction_count < optimal_count - 2: #the auction count is less more than 1 than the optimal count. print('Warning!!!', 'optimal_count:', optimal_count, 'auction_count:', auction_count, 'num_of_possible_ps:', nums_of_agents[i]) if nums_of_agents[i] < 10: print(market.categories) # print("Num of times {} attains the maximum GFT: {} / {} = {:.2f}%".format(title, count_optimal_gft, num_of_iterations, count_optimal_gft * 100 / num_of_iterations)) # print("GFT of {}: {:.2f} / {:.2f} = {:.2f}%".format(title, sum_auction_gft, sum_optimal_gft, 0 if sum_optimal_gft==0 else sum_auction_gft * 100 / sum_optimal_gft)) kmin_mean = sum_optimal_kmin / num_of_iterations kmin_mean_integer = sum_optimal_kmin_integer / num_of_iterations results_table.add( OrderedDict([ ("iterations", num_of_iterations), ("recipe", recipe_str), ("numofagents", nums_of_agents[i]), ("optimalcount", int_round(sum_optimal_count / num_of_iterations, K_ROUND)), ("optimalkmin", int_round(kmin_mean, K_ROUND)), ("optimalkmax", int_round(sum_optimal_kmax / num_of_iterations, K_ROUND)), ("gftformula", int_round((1 - 1 / kmin_mean) * 100 if kmin_mean > 1 else 0, RATIO_ROUND)), ("auctioncount", int_round(sum_auction_count / num_of_iterations, K_ROUND)), ("auctionkmin", int_round(sum_auction_kmin / num_of_iterations, K_ROUND)), ("auctionkmax", int_round(sum_auction_kmax / num_of_iterations, K_ROUND)), ("countratio", int_round( 0 if sum_optimal_count == 0 else (sum_auction_count / sum_optimal_count) * 100, RATIO_ROUND)), ("optimalgft", int_round(sum_optimal_gft / num_of_iterations, GFT_ROUND)), ("auctiongft", int_round(sum_auction_total_gft / num_of_iterations, GFT_ROUND)), ("gftratio", '0.00' if sum_optimal_gft == 0 else int_round( sum_auction_total_gft / sum_optimal_gft * 100, RATIO_ROUND)), ])) results_table_integer.add( OrderedDict([ ("iterations", num_of_iterations), ("recipe", recipe_str), ("numofagents", nums_of_agents[i]), ("optimalcount", int_round(sum_optimal_count_integer / num_of_iterations, K_ROUND)), ("optimalkmin", int_round(kmin_mean_integer, K_ROUND)), ("optimalkmax", int_round(sum_optimal_kmax_integer / num_of_iterations, K_ROUND)), ("gftformula", int_round((1 - 1 / kmin_mean_integer) * 100 if kmin_mean_integer > 1 else 0, RATIO_ROUND)), ("auctioncount", int_round(sum_auction_count_integer / num_of_iterations, K_ROUND)), ("auctionkmin", int_round(sum_auction_kmin_integer / num_of_iterations, K_ROUND)), ("auctionkmax", int_round(sum_auction_kmax_integer / num_of_iterations, K_ROUND)), ("countratio", int_round( 0 if sum_optimal_count_integer == 0 else (sum_auction_count_integer / sum_optimal_count_integer) * 100, RATIO_ROUND)), ("optimalgft", int_round(sum_optimal_gft_integer / num_of_iterations, GFT_ROUND)), ("auctiongft", int_round(sum_auction_total_gft_integer / num_of_iterations, GFT_ROUND)), ("gftratio", '0.00' if sum_optimal_gft_integer == 0 else int_round( sum_auction_total_gft_integer / sum_optimal_gft_integer * 100, RATIO_ROUND)), ])) results_table.done()
def experiment(results_csv_file: str, auction_functions: list, auction_names: str, recipe: tuple, nums_of_agents=None, stocks_prices: list = None, stock_names: list = None, num_of_iterations=1000, run_with_stock_prices=True, report_diff=False): """ Run an experiment similar to McAfee (1992) experiment on the given auction. :param results_csv_file: the experiment result file. :param auction_functions: list of functions for executing the auction under consideration. :param auction_names: titles of the experiment, for printouts. :param recipe: can be any vector of ones, e.g. (1,1,1), for our trade-reduction mechanism, or any vector of positive integers for our ascending-auction mechanism. :param stocks_prices: list of prices for each stock and each agent. :param stock_names: list of stocks names which prices are belongs, for naming only. """ TABLE_COLUMNS = [ "iterations", "stockname", "recipe", "numpossibletrades", "optimalcount", "gftratioformula", "optimalcountwithgftzero", "optimalgft", "optimalgftwithgftzero" ] AUCTION_COLUMNS = [ "count", "countratio", "totalgft", "totalgftratio", "withoutgftzerocountratio", "withoutgftzerototalgft", "withoutgftzerototalgftratio", "marketgft", "marketgftratio" ] if path.exists(results_csv_file): print('The file', results_csv_file, 'already exists, skipping') return else: print('Running for the file', results_csv_file) if stocks_prices is None: (stocks_prices, stock_names) = getStocksPricesShuffled() column_names = TABLE_COLUMNS column_names += [ auction_name + column for auction_name in auction_names for column in AUCTION_COLUMNS ] results_table = TeeTable(column_names, results_csv_file) recipe_str = ":".join(map(str, recipe)) recipe_sum = sum(recipe) recipe_sum_for_buyer = (recipe_sum - recipe[0]) / recipe[0] if nums_of_agents is None: nums_of_agents = [10000000] #print(nums_of_agents) total_results = {} for num_of_agents_per_category in nums_of_agents: total_results[str(num_of_agents_per_category)] = [] #print(total_results) for i in range(len(stocks_prices)): stock_prices = stocks_prices[i] for num_of_possible_ps in nums_of_agents: for iteration in range(num_of_iterations): categories = [] if run_with_stock_prices: while len(stock_prices) < num_of_possible_ps * recipe_sum: stock_prices = stock_prices + stock_prices random.shuffle(stock_prices) index = 0 for category in recipe: next_index = index + num_of_possible_ps * category price_sign = recipe_sum_for_buyer if index == 0 else -1 #price_value_multiple = -1 * buyer_agent_count if index > 0 else recipe_sum - buyer_agent_count categories.append( AgentCategory("agent", [ int(price * price_sign) for price in stock_prices[index:next_index] ])) index = next_index else: #prices from random. for index in range(len(recipe)): #for category in recipe: min_value = -100000 if index > 0 else recipe_sum_for_buyer max_value = -1 if index > 0 else 100000 * recipe_sum_for_buyer categories.append( AgentCategory.uniformly_random( "agent", num_of_possible_ps * recipe[index], min_value, max_value)) market = Market(categories) (optimal_trade, _) = market.optimal_trade(ps_recipe=list(recipe), max_iterations=10000000, include_zero_gft_ps=False) optimal_count = optimal_trade.num_of_deals() optimal_gft = optimal_trade.gain_from_trade() (optimal_trade_with_gft_zero, _) = market.optimal_trade(ps_recipe=list(recipe), max_iterations=10000000) optimal_count_with_gft_zero = optimal_trade_with_gft_zero.num_of_deals( ) optimal_gft_with_gft_zero = optimal_trade_with_gft_zero.gain_from_trade( ) results = [ ("iterations", num_of_iterations), ("stockname", stock_names[i]), ("recipe", recipe_str), ("numpossibletrades", int(num_of_possible_ps)), ("optimalcount", optimal_count), ("gftratioformula", (optimal_count - 1) * 100 / (optimal_count if min(recipe) == max(recipe) and recipe[0] == 1 else optimal_count + 1) if optimal_count > 1 else 0), ("optimalcountwithgftzero", optimal_count_with_gft_zero), ("optimalgft", optimal_gft), ("optimalgftwithgftzero", optimal_gft_with_gft_zero) ] for auction_index in range(len(auction_functions)): auction_trade = auction_functions[auction_index](market, recipe) count = auction_trade.num_of_deals() total_gft = auction_trade.gain_from_trade( including_auctioneer=True) market_gft = auction_trade.gain_from_trade( including_auctioneer=False) auction_name = auction_names[auction_index] results.append( (auction_name + "count", auction_trade.num_of_deals())) results.append( (auction_name + "countratio", 0 if optimal_count == 0 else (count / optimal_count_with_gft_zero) * 100)) results.append((auction_name + "totalgft", total_gft)) results.append((auction_name + "totalgftratio", 0 if optimal_gft == 0 else total_gft / optimal_gft_with_gft_zero * 100)) results.append((auction_name + "marketgft", market_gft)) results.append((auction_name + "marketgftratio", 0 if optimal_gft == 0 else market_gft / optimal_gft_with_gft_zero * 100)) results.append((auction_name + "withoutgftzerocountratio", 0 if optimal_count == 0 else (count / optimal_count) * 100)) results.append( (auction_name + "withoutgftzerototalgft", total_gft)) results.append( (auction_name + "withoutgftzerototalgftratio", 0 if optimal_gft == 0 else total_gft / optimal_gft * 100)) #We check which auction did better and print the market and their results. if report_diff: gft_to_compare = -1 k_to_compare = -1 gft_found = False k_found = False for (label, value) in results: if 'SBB' in label: if gft_found is False and label.endswith( 'totalgft'): if gft_to_compare < 0: gft_to_compare = value elif gft_to_compare != value: with open('diff_in_sbbs_gft.txt', 'a') as f: f.write( 'There is diff in gft between two auctions: ' + str(gft_to_compare) + ' ' + str(value) + '\n') f.write(str(results) + '\n') if num_of_possible_ps < 10: f.write(str(market) + '\n') gft_found = True elif k_found is False and label.endswith('count'): if k_to_compare < 0: k_to_compare = value elif k_to_compare != value: with open('diff_in_sbbs_k.txt', 'a') as f: f.write( 'There is diff in gft between two auctions: ' + str(k_to_compare) + ' ' + str(value) + '\n') f.write(str(results) + '\n') if num_of_possible_ps < 10: f.write(str(market) + '\n') k_found = True compare_sbbs = True if compare_sbbs: gft_to_compare = -1 k_to_compare = -1 gft_found = False k_found = False for (label, value) in results: if 'SBB' in label: if gft_found is False and label.endswith( 'totalgft'): if gft_to_compare < 0: gft_to_compare = value elif gft_to_compare > value: with open('diff_in_sbbs_gft.txt', 'a') as f: f.write( 'There is diff in gft between two auctions: ' + str(gft_to_compare) + ' ' + str(value) + '\n') f.write(str(results) + '\n') if num_of_possible_ps < 10: f.write(str(market) + '\n') gft_found = True elif k_found is False and label.endswith('count'): if k_to_compare < 0: k_to_compare = value elif k_to_compare > value: with open('diff_in_sbbs_k.txt', 'a') as f: f.write( 'There is diff in gft between two auctions: ' + str(k_to_compare) + ' ' + str(value) + '\n') f.write(str(results) + '\n') if num_of_possible_ps < 10: f.write(str(market) + '\n') k_found = True #results_table.add(OrderedDict(results)) #print(results) if len(total_results[str(num_of_possible_ps)]) == 0: total_results[str( num_of_possible_ps)] = results[0:len(results)] else: sum_result = total_results[str(num_of_possible_ps)] for index in range(len(results)): if index > 3: sum_result[index] = (results[index][0], sum_result[index][1] + results[index][1]) #print(total_results) print(stock_names[i], end=',') #break print() division_number = num_of_iterations * len(stocks_prices) #division_number = num_of_iterations for num_of_possible_ps in nums_of_agents: results = total_results[str(num_of_possible_ps)] for index in range(len(results)): if 'gftratio' in results[index][0]: results[index] = (results[index][0], padding_zeroes( results[index][1] / division_number, 3)) elif index > 3: results[index] = (results[index][0], padding_zeroes( results[index][1] / division_number, 2)) elif index == 1: results[index] = (results[index][0], 'Average') #print(results) results_table.add(OrderedDict(results)) results_table.done()
def experiment(results_csv_file: str, auction_function: Callable, auction_name: str, recipe: tuple, value_ranges: list, nums_of_agents: list, num_of_iterations: int): """ Run an experiment similar to McAfee (1992) experiment on the given auction. :param auction_function: the function for executing the auction under consideration. :param auction_name: title of the experiment, for printouts. :param nums_of_agents: a list of the numbers of agents with which to run the experiment. :param value_ranges: for each category, a pair (min_value,max_value). The value for each agent in this category is selected uniformly at random between min_value and max_value. :param num_of_iterations: how many times to repeat the experiment for each num of agents. """ results_table = TeeTable(TABLE_COLUMNS, results_csv_file) recipe_str = ":".join(map(str, recipe)) num_of_categories = len(recipe) for num_of_agents_per_category in nums_of_agents: sum_optimal_count = sum_auction_count = 0 # count the number of deals done in the optimal vs. the actual auction. sum_optimal_gft = sum_auction_total_gft = sum_auction_market_gft = 0 for _ in range(num_of_iterations): market = Market([ AgentCategory.uniformly_random( "agent", num_of_agents_per_category * recipe[category], value_ranges[category][0], value_ranges[category][1]) for category in range(num_of_categories) ]) (optimal_trade, _) = market.optimal_trade(recipe) auction_trade = auction_function(market, recipe) sum_optimal_count += optimal_trade.num_of_deals() sum_auction_count += auction_trade.num_of_deals() sum_optimal_gft += optimal_trade.gain_from_trade() sum_auction_total_gft += auction_trade.gain_from_trade( including_auctioneer=True) sum_auction_market_gft += auction_trade.gain_from_trade( including_auctioneer=False) # print("Num of times {} attains the maximum GFT: {} / {} = {:.2f}%".format(title, count_optimal_gft, num_of_iterations, count_optimal_gft * 100 / num_of_iterations)) # print("GFT of {}: {:.2f} / {:.2f} = {:.2f}%".format(title, sum_auction_gft, sum_optimal_gft, 0 if sum_optimal_gft==0 else sum_auction_gft * 100 / sum_optimal_gft)) results_table.add( OrderedDict(( ("iterations", num_of_iterations), ("auction_name", auction_name), ("recipe", recipe_str), ("num_of_agents", num_of_agents_per_category), ("mean_optimal_count", round(sum_optimal_count / num_of_iterations, 2)), ("mean_auction_count", round(sum_auction_count / num_of_iterations, 2)), ("count_ratio", 0 if sum_optimal_count == 0 else int( (sum_auction_count / sum_optimal_count) * 10000) / 100), ("mean_optimal_gft", round(sum_optimal_gft / num_of_iterations, 2)), ("mean_auction_total_gft", round(sum_auction_total_gft / num_of_iterations, 2)), ("total_gft_ratio", 0 if sum_optimal_gft == 0 else round( sum_auction_total_gft / sum_optimal_gft * 100, 2)), ("mean_auction_market_gft", round(sum_auction_market_gft / num_of_iterations, 2)), ("market_gft_ratio", 0 if sum_optimal_gft == 0 else round( sum_auction_market_gft / sum_optimal_gft * 100, 2)), ))) results_table.done()
def experiment(results_csv_file: str, recipes: tuple, value_ranges: list, nums_of_agents: list, num_of_iterations: int): """ Run an experiment similar to McAfee (1992) experiment on the given auction. :param recipes: list of recipes. :param nums_of_agents: a list of the numbers of agents with which to run the experiment. :param value_ranges: for each category, a pair (min_value,max_value). The value for each agent in this category is selected uniformly at random between min_value and max_value. :param num_of_iterations: how many times to repeat the experiment for each num of agents. """ results_table = TeeTable(TABLE_COLUMNS, results_csv_file) for recipe in recipes: recipe_str = ":".join(map(str, recipe)) num_of_categories = len(recipe) external_wins_gft = tie_gft = ascending_wins_gft = 0 external_wins_k = tie_k = ascending_wins_k = 0 for num_of_agents_per_category in nums_of_agents: external_sum_auction_count = ascending_sum_auction_count = 0 # count the number of deals done the ascending auction. external_sum_auction_gft = ascending_sum_auction_gft = 0 agents_recipe_values = [sum(recipe) - recipe[0]] + [ recipe[0] for _ in range(1, len(recipe)) ] for _ in range(num_of_iterations): market = Market([ AgentCategory.uniformly_random( "agent", num_of_agents_per_category * recipe[category], value_ranges[category][0] * agents_recipe_values[category], value_ranges[category][1] * agents_recipe_values[category]) for category in range(num_of_categories) ]) (optimal_trade, _) = market.optimal_trade(recipe) external_auction_trade = budget_balanced_trade_reduction( market, recipe) ascending_auction_trade = budget_balanced_ascending_auction( market, recipe) external_sum_auction_count += external_auction_trade.num_of_deals( ) ascending_sum_auction_count += ascending_auction_trade.num_of_deals( ) external_sum_auction_gft += external_auction_trade.gain_from_trade( ) ascending_sum_auction_gft += ascending_auction_trade.gain_from_trade( ) if external_sum_auction_count > ascending_sum_auction_count: external_wins_k += 1 elif external_sum_auction_count == ascending_sum_auction_count: tie_k += 1 else: ascending_wins_k += 1 if external_sum_auction_gft > ascending_sum_auction_gft: external_wins_gft += 1 elif external_sum_auction_gft == ascending_sum_auction_gft: tie_gft += 1 else: ascending_wins_gft += 1 num_agents = len(nums_of_agents) results_table.add( OrderedDict(( ("recipe", recipe), ("external_wins_gft", int(external_wins_gft * 100 / num_agents)), ("tie_gft", int(tie_gft * 100 / num_agents)), ("ascending_wins_gft", int(ascending_wins_gft * 100 / num_agents)), ("external_wins_k", int(external_wins_k * 100 / num_agents)), ("tie_k", int(tie_k * 100 / num_agents)), ("ascending_wins_k", int(ascending_wins_k * 100 / num_agents)), ("external_wins", external_wins_gft), ("tie", tie_gft), ("ascending_wins", ascending_wins_gft), ))) results_table.done()