Example #1
0
def experiment(results_csv_file: str,
               auction_function: Callable,
               auction_name: str,
               recipe: tuple,
               stocks_prices: list = None,
               stock_names: list = None):
    """
    Run an experiment similar to McAfee (1992) experiment on the given auction.
    :param results_csv_file: the experiment result file.
    :param auction_function: the function for executing the auction under consideration.
    :param auction_name: title 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.
    """
    if stocks_prices is None:
        (stocks_prices, stock_names) = getStocksPrices(recipe)
    results_table = TeeTable(TABLE_COLUMNS, results_csv_file)
    recipe_str = ":".join(map(str, recipe))
    for i in range(len(stocks_prices)):
        market = Market([
            AgentCategory("agent", category) for category in stocks_prices[i]
        ])
        num_of_possible_ps = min([
            len(stocks_prices[i][j]) / recipe[j]
            for j in range(len(stocks_prices[i]))
        ])
        (optimal_trade, _) = market.optimal_trade(recipe)
        auction_trade = auction_function(market, recipe)
        optimal_count = optimal_trade.num_of_deals()
        auction_count = auction_trade.num_of_deals()
        if (auction_trade.num_of_deals() > optimal_trade.num_of_deals()):
            print(
                "Warning!!! the number of deals in action is greater than optimal!"
            )
            print("Optimal num of deals: ", optimal_trade.num_of_deals())
            print("Auction num of deals: ", auction_trade.num_of_deals())
        optimal_gft = optimal_trade.gain_from_trade()
        auction_gft = auction_trade.gain_from_trade(including_auctioneer=True)
        auction_market_gft = auction_trade.gain_from_trade(
            including_auctioneer=False)
        results_table.add(
            OrderedDict((
                ("stock_name", stock_names[i]),
                ("auction_name", auction_name),
                ("recipe", recipe_str),
                ("num_possible_trades", round(num_of_possible_ps)),
                ("optimal_count", round(optimal_count, 2)),
                ("auction_count", round(auction_count, 2)),
                ("count_ratio", 0 if optimal_count == 0 else int(
                    (auction_count / optimal_count) * 100000) / 1000),
                ("optimal_gft", round(optimal_gft, 2)),
                ("auction_gft", round(auction_gft, 2)),
                ("auction_gft_ratio", 0 if optimal_gft == 0 else round(
                    auction_gft / optimal_gft * 100, 3)),
                ("auction_market_gft", round(auction_market_gft, 2)),
                ("market_gft_ratio", 0 if optimal_gft == 0 else round(
                    auction_market_gft / optimal_gft * 100, 3)),
            )))
    results_table.done()
Example #2
0
def experiment(results_csv_file: str,
               auction_functions: list,
               auction_names: str,
               recipe: tuple,
               iterations: int,
               nums_of_agents: list = None,
               stocks_prices: list = None,
               stock_names: list = None):
    """
    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 = [
        "stockname", "recipe", "numpossibletrades", "optimalcount",
        "optimalcountwithgftzero", "optimalgft"
    ]
    AUCTION_COLUMNS = ["auctioncount", "countratio", "gft", "gftratio"]
    print(recipe)
    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)
    if nums_of_agents is None:
        nums_of_agents = [10000000]
    average_total_results = {}
    for num_of_agents_per_category in nums_of_agents:
        average_total_results[str(num_of_agents_per_category)] = []

    for i in range(len(stocks_prices)):
        total_results = {}
        for num_of_agents_per_category in nums_of_agents:
            total_results[str(num_of_agents_per_category)] = []
        stock_prices = stocks_prices[i]
        last_iteration = False
        for num_of_agents_per_category in nums_of_agents:
            for iteration in range(iterations):
                num_of_possible_ps = min(num_of_agents_per_category,
                                         int(len(stock_prices) / recipe_sum))
                if last_iteration and num_of_possible_ps < num_of_agents_per_category:
                    break
                if num_of_possible_ps < num_of_agents_per_category:
                    if last_iteration:
                        break
                last_iteration = True
                categories = []
                buyer_agent_count = recipe[0]
                index = 0
                for category in recipe:
                    next_index = index + num_of_possible_ps * category
                    price_value_multiple = -1 * buyer_agent_count if index > 0 else recipe_sum - buyer_agent_count
                    categories.append(
                        AgentCategory("agent", [
                            int(price * price_value_multiple)
                            for price in stock_prices[index:next_index]
                        ]))
                    index = next_index
                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(
                )

                results = [
                    ("stockname", stock_names[i]), ("recipe", recipe_str),
                    ("numpossibletrades", round(num_of_possible_ps)),
                    ("optimalcount", optimal_count),
                    ("optimalcountwithgftzero", optimal_count_with_gft_zero),
                    ("optimalgft", optimal_gft)
                ]
                for auction_index in range(len(auction_functions)):
                    if 'mcafee' in auction_names[auction_index]:
                        results.append((auction_name + "auctioncount", 0))
                        results.append((auction_name + "countratio", 0))
                        results.append((auction_name + "gft", 0))
                        results.append((auction_name + "gftratio", 0))

                    auction_trade = auction_functions[auction_index](market,
                                                                     recipe)
                    auction_count = auction_trade.num_of_deals()
                    # for j in range(len(stocks_prices[i])):
                    #     print(sorted(stocks_prices[i][j][:num_of_possible_ps*recipe[j]]))
                    if (auction_trade.num_of_deals() >
                            optimal_trade_with_gft_zero.num_of_deals()):
                        # print(sorted(stocks_prices[i][0][:num_of_possible_ps*recipe[0]]))
                        # print(sorted(stocks_prices[i][1][:num_of_possible_ps*recipe[1]]))
                        print(
                            "Warning!!! the number of deals in action is greater than optimal!"
                        )
                        print("Optimal num of deals: ",
                              optimal_trade.num_of_deals())
                        print("Auction num of deals: ",
                              auction_trade.num_of_deals())
                        print("Auction name: ", auction_names[auction_index])
                    gft = auction_trade.gain_from_trade(
                        including_auctioneer=False)
                    auction_name = auction_names[auction_index]
                    results.append((auction_name + "auctioncount",
                                    auction_trade.num_of_deals()))
                    results.append(
                        (auction_name + "countratio",
                         0 if optimal_count_with_gft_zero == 0 else
                         (auction_count / optimal_count_with_gft_zero) * 100))
                    results.append((auction_name + "gft", gft))
                    results.append(
                        (auction_name + "gftratio",
                         0 if optimal_gft == 0 else gft / optimal_gft * 100))

                #results_table.add(OrderedDict(results))
                if len(total_results[str(num_of_agents_per_category)]) == 0:
                    total_results[str(
                        num_of_agents_per_category)] = results[0:len(results)]
                else:
                    sum_result = total_results[str(num_of_agents_per_category)]
                    for index in range(len(results)):
                        if index > 2:
                            sum_result[index] = (results[index][0],
                                                 sum_result[index][1] +
                                                 results[index][1])
        for num_of_agents_per_category in nums_of_agents:
            results = total_results[str(num_of_agents_per_category)]
            if len(results) == 0:
                continue
            for index in range(len(results)):
                if index > 2:
                    if 'ratio' in results[index][0]:
                        results[index] = (results[index][0],
                                          results[index][1] / iterations)
                    else:
                        results[index] = (results[index][0],
                                          results[index][1] / iterations)
                #elif index == 0:
                #    results[index] = (results[index][0], 'Average')
            results_table.add(OrderedDict(results))

            if len(average_total_results[str(
                    num_of_agents_per_category)]) == 0:
                average_total_results[str(
                    num_of_agents_per_category)] = results[0:len(results)]
            else:
                sum_result = average_total_results[str(
                    num_of_agents_per_category)]
                for index in range(len(results)):
                    if index > 2:
                        sum_result[index] = (sum_result[index][0],
                                             sum_result[index][1] +
                                             results[index][1])
    for num_of_agents_per_category in nums_of_agents:
        results = average_total_results[str(num_of_agents_per_category)]
        if len(results) == 0:
            continue
        for index in range(len(results)):
            if index > 2:
                if 'ratio' in results[index][0]:
                    results[index] = (
                        results[index][0],
                        int(results[index][1] / len(stocks_prices) * 1000) /
                        1000)
                else:
                    results[index] = (results[index][0],
                                      round(
                                          results[index][1] /
                                          len(stocks_prices), 1))
            elif index == 0:
                results[index] = (results[index][0], 'Average')
        results_table.add(OrderedDict(results))
    results_table.done()
Example #3
0
def mcafee_trade_reduction(market: Market,
                           ps_recipe: list,
                           price_heuristic=True):
    """
    Calculate the trade and prices using generalized-trade-reduction.
    :param market:   contains a list of k categories, each containing several agents.
    :param ps_recipe:  a list of integers, one integer per category.
                       Each integer i represents the number of agents of category i
                       that should be in each procurement-set.
    :param price_heuristic: whether to use the heuristic of setting the price to (s_{k+1)+b_{k+1})/2.
                            Default is true, as in the original paper.
    :return: Trade object, representing the trade and prices.

    >>> # ONE BUYER, ONE SELLER
    >>> market = Market([AgentCategory("buyer", [9.]),  AgentCategory("seller", [-4.])])
    >>> print(market); print(mcafee_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0], seller: [-4.0]]
    No trade

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.])])
    >>> print(market); print(mcafee_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-4.0]]
    No trade

    >>> market = Market([AgentCategory("seller", [-4.]), AgentCategory("buyer", [9.,8.])])
    >>> print(market); print(mcafee_trade_reduction(market, [1,1]))
    Traders: [seller: [-4.0], buyer: [9.0, 8.0]]
    No trade

    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.])])
    >>> print(market); print(mcafee_trade_reduction(market, [1,1]))
    Traders: [seller: [-3.0, -4.0], buyer: [9.0]]
    No trade

    >>> market = Market([AgentCategory("buyer", [9.]), AgentCategory("seller", [-4.,-3.])])
    >>> print(market); print(mcafee_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0], seller: [-3.0, -4.0]]
    No trade

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.,-3.])])
    >>> print(market); print(mcafee_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    seller: [-3.0]: all 1 agents trade and pay -4.0

    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.,8.])])
    >>> print(mcafee_trade_reduction(market, [1,1]))
    seller: [-3.0]: all 1 agents trade and pay -4.0
    buyer: [9.0]: all 1 agents trade and pay 8.0

    >>> market = Market([AgentCategory("seller", [-8.,-3.]), AgentCategory("buyer", [9.,4.])])
    >>> print(mcafee_trade_reduction(market, [1,1]))
    seller: [-3.0]: all 1 agents trade and pay -6.0
    buyer: [9.0]: all 1 agents trade and pay 6.0

    #
    # >>>
    # >>> # ONE BUYER, ONE SELLER, ONE MEDIATOR
    # >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.])])
    # >>> print(market); print(mcafee_trade_reduction(market, [1,1,1]))
    # Traders: [seller: [-3.0, -4.0], buyer: [9.0, 8.0], mediator: [-1.0, -2.0]]
    # seller: [-3.0]: all 1 agents trade and pay -4.0
    # buyer: [9.0]: all 1 agents trade and pay 8.0
    # mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -4.0
    #
    # >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-10.])])
    # >>> print(market); print(mcafee_trade_reduction(market, [1,1,1]))
    # Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-3.0, -4.0, -10.0]]
    # buyer: [9.0]: all 1 agents trade and pay 8.0
    # mediator: [-1.0]: all 1 agents trade and pay -2.0
    # seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -6.0
    #
    # >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-5.])])
    # >>> print(market); print(mcafee_trade_reduction(market, [1,1,1]))
    # Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-3.0, -4.0, -5.0]]
    # buyer: [9.0]: all 1 agents trade and pay 8.0
    # mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -3.0
    # seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -5.0
    #
    # >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-2.])])
    # >>> print(market); print(mcafee_trade_reduction(market, [1,1,1]))
    # Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-2.0, -3.0, -4.0]]
    # buyer: [9.0]: all 1 agents trade and pay 8.0
    # mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -4.0
    # seller: [-2.0, -3.0]: random 1 out of 2 agents trade and pay -4.0
    #
    # >>> market = Market([AgentCategory("buyer", [9.,8.,7.]), AgentCategory("mediator", [-1.,-2.,-3.]), AgentCategory("seller", [-4.,-3.,-2.])])
    # >>> print(market); print(mcafee_trade_reduction(market, [1,1,1]))
    # Traders: [buyer: [9.0, 8.0, 7.0], mediator: [-1.0, -2.0, -3.0], seller: [-2.0, -3.0, -4.0]]
    # buyer: [9.0, 8.0]: all 2 agents trade and pay 7.0
    # mediator: [-1.0, -2.0]: all 2 agents trade and pay -3.0
    # seller: [-2.0, -3.0]: all 2 agents trade and pay -4.0
    #
    # >>> market = Market([AgentCategory("buyer", [9.,8.,4.]), AgentCategory("mediator", [-1.,-2.,-3.]), AgentCategory("seller", [-4.,-3.,-2.])])
    # >>> print(market); print(mcafee_trade_reduction(market, [1,1,1]))
    # Traders: [buyer: [9.0, 8.0, 4.0], mediator: [-1.0, -2.0, -3.0], seller: [-2.0, -3.0, -4.0]]
    # buyer: [9.0, 8.0]: all 2 agents trade and pay 7.0
    # mediator: [-1.0, -2.0]: all 2 agents trade and pay -3.0
    # seller: [-2.0, -3.0]: all 2 agents trade and pay -4.0

    """
    if len(ps_recipe) != market.num_categories:
        raise ValueError(
            "There are {} categories but {} elements in the PS recipe".format(
                market.num_categories, len(ps_recipe)))

    if any(r != 1 for r in ps_recipe):
        raise ValueError(
            "Currently, the trade-reduction protocol supports only recipes of ones; {} was given"
            .format(ps_recipe))

    logger.info("\n#### McAfee Trade Reduction\n")
    logger.info(market)
    (optimal_trade, remaining_market) = market.optimal_trade(ps_recipe)
    for category in remaining_market.categories:
        if len(category) == 0:
            category.append(-MAX_VALUE)
    logger.info("Optimal trade, by increasing GFT: {}".format(optimal_trade))
    first_negative_ps = remaining_market.get_highest_agents(ps_recipe)
    if price_heuristic:
        price_candidate = sum([abs(x) for x in first_negative_ps
                               ]) / len(first_negative_ps)
        logger.info("First negative PS: {}, candidate price: {}".format(
            first_negative_ps, price_candidate))
    actual_traders = market.empty_agent_categories()

    if optimal_trade.num_of_deals() > 0:
        last_positive_ps = optimal_trade.procurement_sets[0]

        if price_heuristic and is_price_good_for_ps(price_candidate,
                                                    last_positive_ps):
            # All optimal traders trade in the candidate price - no reduction
            prices = [
                price_candidate * (-1 if last_positive_ps[i] < 0 else +1)
                for i in range(market.num_categories)
            ]

        else:
            # Trade reduction
            del optimal_trade.procurement_sets[0]
            prices = last_positive_ps

        for ps in optimal_trade.procurement_sets:
            for i in range(market.num_categories):
                if ps[i] is not None:
                    actual_traders[i].append(ps[i])
    else:
        prices = [0 for i in range(market.num_categories)]

    logger.info("\n")
    return TradeWithSinglePrice(actual_traders, ps_recipe, prices)
Example #4
0
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()
Example #5
0
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()
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_functions: list,
               auction_names: str,
               recipe: tuple,
               nums_of_agents: list = None,
               stocks_prices: list = None,
               stock_names: list = None):
    """
    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 = [
        "stock_name", "recipe", "num_possible_trades", "optimal_count",
        "optimal_count_with_gft_zero", "optimal_gft"
    ]
    AUCTION_COLUMNS = ["auction_count", "count_ratio", "gft", "gft_ratio"]
    print(recipe)
    if stocks_prices is None:
        (stocks_prices, stock_names) = getStocksPrices(recipe)
    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))
    if nums_of_agents is None:
        nums_of_agents = [10000000]

    for i in range(len(stocks_prices)):
        last_iteration = False
        for num_of_agents_per_category in nums_of_agents:
            num_of_possible_ps = min(num_of_agents_per_category,
                                     len(stocks_prices[i][0]))
            if last_iteration is True and num_of_possible_ps < num_of_agents_per_category:
                break
            if num_of_possible_ps < num_of_agents_per_category:
                if last_iteration is True:
                    break
                else:
                    last_iteration = True
                    market = Market([
                        AgentCategory("agent", stocks_prices[i][j])
                        for j in range(len(stocks_prices[i]))
                    ])
            else:
                market = Market([
                    AgentCategory(
                        "agent",
                        stocks_prices[i][j][0:num_of_possible_ps * recipe[j]])
                    for j in range(len(stocks_prices[i]))
                ])
            (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(
            )

            results = [("stock_name", stock_names[i]), ("recipe", recipe_str),
                       ("num_possible_trades", round(num_of_possible_ps)),
                       ("optimal_count", round(optimal_count, 2)),
                       ("optimal_count_with_gft_zero",
                        round(optimal_count_with_gft_zero, 2)),
                       ("optimal_gft", round(optimal_gft, 2))]
            for auction_index in range(len(auction_functions)):
                auction_trade = auction_functions[auction_index](market,
                                                                 recipe)
                auction_count = auction_trade.num_of_deals()
                if (auction_trade.num_of_deals() >
                        optimal_trade_with_gft_zero.num_of_deals()):
                    # print(sorted(stocks_prices[i][0][:num_of_possible_ps*recipe[0]]))
                    # print(sorted(stocks_prices[i][1][:num_of_possible_ps*recipe[1]]))
                    print(
                        "Warning!!! the number of deals in action is greater than optimal!"
                    )
                    print("Optimal num of deals: ",
                          optimal_trade.num_of_deals())
                    print("Auction num of deals: ",
                          auction_trade.num_of_deals())
                    print("Auction name: ", auction_names[auction_index])
                gft = auction_trade.gain_from_trade(including_auctioneer=False)
                auction_name = auction_names[auction_index]
                results.append((auction_name + "_auction_count",
                                round(auction_trade.num_of_deals(), 2)))
                results.append(
                    (auction_name + "_count_ratio",
                     0 if optimal_count_with_gft_zero == 0 else int(
                         (auction_count / optimal_count_with_gft_zero) *
                         100000) / 1000))
                results.append((auction_name + "_gft", round(gft, 2)))
                results.append(
                    (auction_name + "_gft_ratio",
                     0 if optimal_gft == 0 else round(gft / optimal_gft *
                                                      100, 3)))

            results_table.add(OrderedDict(results))
    results_table.done()
Example #8
0
def budget_balanced_ascending_auction(
        market: Market,
        ps_recipe: list,
        max_iterations=999999999) -> TradeWithSinglePrice:
    """
    Calculate the trade and prices using generalized-ascending-auction.
    :param market:   contains a list of k categories, each containing several agents.
    :param ps_recipe:  a list of integers, one integer per category.
                       Each integer i represents the number of agents of category i
                       that should be in each procurement-set.
    :return: Trade object, representing the trade and prices.

    >>> # ONE BUYER, ONE SELLER

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-4.0]]
    No trade

    >>> market = Market([AgentCategory("seller", [-4.]), AgentCategory("buyer", [9.,8.])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [1,1]))
    Traders: [seller: [-4.0], buyer: [9.0, 8.0]]
    seller: [-4.0]: all 1 agents trade and pay -8.0
    buyer: [9.0]: all 1 agents trade and pay 8.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.,-3.])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -8.0

    >>> # ONE BUYER, ONE SELLER, ONE MEDIATOR

    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [1,1,1]))
    Traders: [seller: [-3.0, -4.0], buyer: [9.0, 8.0], mediator: [-1.0, -2.0]]
    seller: [-3.0]: all 1 agents trade and pay -4.0
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.,7.]), AgentCategory("mediator", [-1.,-2.,-3.]), AgentCategory("seller", [-4.,-3.,-2.])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0, 7.0], mediator: [-1.0, -2.0, -3.0], seller: [-2.0, -3.0, -4.0]]
    buyer: [9.0, 8.0]: all 2 agents trade and pay 7.0
    mediator: [-1.0, -2.0]: all 2 agents trade and pay -3.0
    seller: [-2.0, -3.0, -4.0]: random 2 out of 3 agents trade and pay -4.0


    >>> # ONE BUYER, TWO SELLERS

    >>> market = Market([AgentCategory("buyer", [9., 8., 7., 6.]),  AgentCategory("seller", [-6., -5., -4.,-3.,-2.,-1.])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [1,2]))
    Traders: [buyer: [9.0, 8.0, 7.0, 6.0], seller: [-1.0, -2.0, -3.0, -4.0, -5.0, -6.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    seller: [-1.0, -2.0, -3.0, -4.0]: random 2 out of 4 agents trade and pay -4.0

    >>> market = Market([AgentCategory("seller", [-4.,-3.,-2.,-1.]), AgentCategory("buyer", [9.,8.])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [2,1]))
    Traders: [seller: [-1.0, -2.0, -3.0, -4.0], buyer: [9.0, 8.0]]
    seller: [-1.0, -2.0, -3.0]: random 2 out of 3 agents trade and pay -4.0
    buyer: [9.0, 8.0]: random 1 out of 2 agents trade and pay 8.0


    >>> # ONE SELLER, ONE BUYER, ZERO MEDIATORS

    >>> market = Market([AgentCategory("seller", [-4.]), AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-5, -7])])
    >>> print(market); print(budget_balanced_ascending_auction(market, [1,1,0]))
    Traders: [seller: [-4.0], buyer: [9.0, 8.0], mediator: [-5, -7]]
    seller: [-4.0]: all 1 agents trade and pay -8.0
    buyer: [9.0]: all 1 agents trade and pay 8.0

    """
    num_categories = market.num_categories
    if len(ps_recipe) != num_categories:
        raise ValueError(
            "There are {} categories but {} elements in the PS recipe".format(
                num_categories, len(ps_recipe)))

    relevant_category_indices = [
        i for i in range(num_categories) if ps_recipe[i] > 0
    ]

    logger.info("\n#### Budget-Balanced Ascending Auction\n")
    logger.info(market)
    logger.info("Procurement-set recipe: {}".format(ps_recipe))

    optimal_trade = market.optimal_trade(ps_recipe,
                                         max_iterations=max_iterations)[0]
    logger.info("For comparison, the optimal trade is: %s\n", optimal_trade)

    remaining_market = market.clone()
    prices = AscendingPriceVector(ps_recipe, -MAX_VALUE)

    # Functions for calculating the number of potential PS that can be supported by a category:
    fractional_potential_ps = lambda category_index: remaining_market.categories[
        category_index].size() / ps_recipe[category_index]
    integral_potential_ps = lambda category_index: math.floor(
        remaining_market.categories[category_index].size() / ps_recipe[
            category_index])

    while True:
        # find a category with a largest number of potential PS, and increase its price
        main_category_index = max(relevant_category_indices,
                                  key=fractional_potential_ps)
        main_category = remaining_market.categories[main_category_index]
        logger.info("Chosen category: {} with {} agents and ratio {}".format(
            main_category.name, main_category.size(),
            fractional_potential_ps(main_category_index)))

        if main_category.size() == 0:
            logger.info("\nThe %s category became empty - no trade!",
                        main_category.name)
            logger.info("  Final price-per-unit vector: %s", prices)
            break

        prices.increase_price_up_to_balance(main_category_index,
                                            main_category.lowest_agent_value(),
                                            main_category.name)
        if prices.status == PriceStatus.STOPPED_AT_ZERO_SUM:
            logger.info("\nPrice crossed zero.")
            logger.info("  Final price-per-unit vector: %s", prices)
            break

        main_category.remove_lowest_agent()
        logger.info(
            "  {} price increases to {}: {} agents and ratio {}".format(
                main_category.name, prices[main_category_index],
                main_category.size(),
                fractional_potential_ps(main_category_index)))

    logger.info(remaining_market)
    return TradeWithSinglePrice(remaining_market.categories, ps_recipe,
                                prices.prices)
def budget_balanced_trade_reduction(market:Market, ps_recipe:list, including_gft_0:bool = True):
    """
    Calculate the trade and prices using generalized-trade-reduction.
    :param market:   contains a list of k categories, each containing several agents.
    :param ps_recipe:  a list of integers, one integer per category.
                       Each integer i represents the number of agents of category i
                       that should be in each procurement-set.
    :return: Trade object, representing the trade and prices.

    >>> market = Market([AgentCategory("seller", [-1, -2, -3, -4, -5, -7, -8, -10, -11]),AgentCategory("buyer", [17, 14, 13, 9, 6])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [2, 1]))
    Traders: [seller: [-1, -2, -3, -4, -5, -7, -8, -10, -11], buyer: [17, 14, 13, 9, 6]]
    seller: [-1, -2, -3, -4]: all 4 agents trade and pay -5
    buyer: [17, 14, 13]: random 2 out of 3 agents trade and pay 10.0

    >>> market = Market([AgentCategory("mediator", [-3, -4, -5, -6, -7, -8, -9, -10]),AgentCategory("seller", [-1, -2, -3, -4, -5, -6, -7, -8]),AgentCategory("buyer", [17, 16, 15, 14, 13, 12, 10, 6])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [2,3,2]))
    Traders: [mediator: [-3, -4, -5, -6, -7, -8, -9, -10], seller: [-1, -2, -3, -4, -5, -6, -7, -8], buyer: [17, 16, 15, 14, 13, 12, 10, 6]]
    mediator: [-3, -4]: all 2 agents trade and pay -5
    seller: [-1, -2, -3, -4, -5]: random 3 out of 5 agents trade and pay -5.333333333333333
    buyer: [17, 16, 15, 14]: random 2 out of 4 agents trade and pay 13


    >>> market = Market([AgentCategory("seller", [-2, -4, -6, -8, -10, -12, -14]),AgentCategory("buyer", [20, 18, 16, 9, 2, 1])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [2,3]))
    Traders: [seller: [-2, -4, -6, -8, -10, -12, -14], buyer: [20, 18, 16, 9, 2, 1]]
    seller: [-2, -4]: all 2 agents trade and pay -6
    buyer: [20, 18, 16, 9]: random 3 out of 4 agents trade and pay 4.0

    >>> # Multi trade
    >>> market = Market([AgentCategory("buyer", [17, 14, 13, 9, 6]),AgentCategory("seller", [-1, -2, -3, -4, -5, -7, -8, -10, -11])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1, 2]))
    Traders: [buyer: [17, 14, 13, 9, 6], seller: [-1, -2, -3, -4, -5, -7, -8, -10, -11]]
    buyer: [17, 14]: all 2 agents trade and pay 13
    seller: [-1, -2, -3, -4, -5]: random 4 out of 5 agents trade and pay -6.5

    >>> market = Market([AgentCategory("buyer", [17, 16, 15, 14, 13, 12, 10, 6]),AgentCategory("mediator", [-3, -4, -5, -6, -7, -8, -9, -10]),AgentCategory("seller", [-1, -2, -3, -4, -5, -6, -7, -8])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [2,2,3]))
    Traders: [buyer: [17, 16, 15, 14, 13, 12, 10, 6], mediator: [-3, -4, -5, -6, -7, -8, -9, -10], seller: [-1, -2, -3, -4, -5, -6, -7, -8]]
    buyer: [17, 16]: all 2 agents trade and pay 15
    mediator: [-3, -4]: all 2 agents trade and pay -5
    seller: [-1, -2, -3, -4, -5, -6]: random 3 out of 6 agents trade and pay -6.666666666666667

    >>> market = Market([AgentCategory("buyer", [20, 18, 16, 9, 2, 1]),AgentCategory("seller", [-2, -4, -6, -8, -10, -12, -14])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [3,2]))
    Traders: [buyer: [20, 18, 16, 9, 2, 1], seller: [-2, -4, -6, -8, -10, -12, -14]]
    buyer: [20, 18, 16, 9]: random 3 out of 4 agents trade and pay 6.666666666666667
    seller: [-2, -4, -6, -8]: random 2 out of 4 agents trade and pay -10

    >>> # Multi trade
    >>> market = Market([AgentCategory("seller", [-1, -2, -2, -3]),AgentCategory("buyer", [2, 2, 2, 3])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1, 1]))
    Traders: [seller: [-1, -2, -2, -3], buyer: [3, 2, 2, 2]]
    seller: [-1, -2, -2]: all 3 agents trade and pay -2.0
    buyer: [3, 2, 2]: all 3 agents trade and pay 2

    >>> # Multi trade
    >>> market = Market([AgentCategory("buyer", [2, 2, 2, 3]),AgentCategory("seller", [-1, -2, -2, -3])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1, 1]))
    Traders: [buyer: [3, 2, 2, 2], seller: [-1, -2, -2, -3]]
    buyer: [3, 2]: all 2 agents trade and pay 2
    seller: [-1, -2, -2]: random 2 out of 3 agents trade and pay -2.0

    >>> market = Market([AgentCategory("buyer", [17, 16, 15, 14, 13, 12, 10, 6]),AgentCategory("mediator", [-3, -4, -5, -6, -7, -8, -9, -10]),AgentCategory("seller", [-1, -2, -3, -4, -5, -6, -7, -8])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [2,2,3]))
    Traders: [buyer: [17, 16, 15, 14, 13, 12, 10, 6], mediator: [-3, -4, -5, -6, -7, -8, -9, -10], seller: [-1, -2, -3, -4, -5, -6, -7, -8]]
    buyer: [17, 16]: all 2 agents trade and pay 15
    mediator: [-3, -4]: all 2 agents trade and pay -5
    seller: [-1, -2, -3, -4, -5, -6]: random 3 out of 6 agents trade and pay -6.666666666666667

    >>> # ONE BUYER, ONE SELLER
    >>> market = Market([AgentCategory("buyer", [9.]),  AgentCategory("seller", [-4.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0], seller: [-4.0]]
    No trade

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-4.0]]
    No trade

    >>> market = Market([AgentCategory("seller", [-4.]), AgentCategory("buyer", [9.,8.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [seller: [-4.0], buyer: [9.0, 8.0]]
    seller: [-4.0]: all 1 agents trade and pay -8.0
    buyer: [9.0]: all 1 agents trade and pay 8.0

    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [seller: [-3.0, -4.0], buyer: [9.0]]
    No trade

    >>> market = Market([AgentCategory("buyer", [9.]), AgentCategory("seller", [-4.,-3.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0], seller: [-3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 4.0
    seller: [-3.0]: all 1 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.,-3.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -8.0

    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.,8.])])
    >>> print(budget_balanced_trade_reduction(market, [1,1]))
    seller: [-3.0]: all 1 agents trade and pay -4.0
    buyer: [9.0, 8.0]: random 1 out of 2 agents trade and pay 4.0

    >>> # ALL POSITIVE VALUES
    >>> market = Market([AgentCategory("buyer1", [4.,3.]), AgentCategory("buyer2", [9.,8.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer1: [4.0, 3.0], buyer2: [9.0, 8.0]]
    buyer1: [4.0]: all 1 agents trade and pay 3.0
    buyer2: [9.0, 8.0]: random 1 out of 2 agents trade and pay -3.0

    >>> # ALL NEGATIVE VALUES
    >>> market = Market([AgentCategory("seller1", [-4.,-3.]), AgentCategory("seller2", [-9.,-8.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [seller1: [-3.0, -4.0], seller2: [-8.0, -9.0]]
    No trade

    >>>
    >>> # ONE BUYER, ONE SELLER, ONE MEDIATOR
    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [seller: [-3.0, -4.0], buyer: [9.0, 8.0], mediator: [-1.0, -2.0]]
    seller: [-3.0]: all 1 agents trade and pay -4.0
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-10.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-3.0, -4.0, -10.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0]: all 1 agents trade and pay -2.0
    seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -6.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-5.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-3.0, -4.0, -5.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -3.0
    seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -5.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-2.0, -3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -4.0
    seller: [-2.0, -3.0]: random 1 out of 2 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.,7.]), AgentCategory("mediator", [-1.,-2.,-3.]), AgentCategory("seller", [-4.,-3.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0, 7.0], mediator: [-1.0, -2.0, -3.0], seller: [-2.0, -3.0, -4.0]]
    buyer: [9.0, 8.0]: all 2 agents trade and pay 7.0
    mediator: [-1.0, -2.0]: all 2 agents trade and pay -3.0
    seller: [-2.0, -3.0, -4.0]: random 2 out of 3 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.,4.]), AgentCategory("mediator", [-1.,-2.,-3.]), AgentCategory("seller", [-4.,-3.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0, 4.0], mediator: [-1.0, -2.0, -3.0], seller: [-2.0, -3.0, -4.0]]
    buyer: [9.0, 8.0]: all 2 agents trade and pay 7.0
    mediator: [-1.0, -2.0]: all 2 agents trade and pay -3.0
    seller: [-2.0, -3.0]: all 2 agents trade and pay -4.0

    """
    if len(ps_recipe) != market.num_categories:
        raise ValueError(
            "There are {} categories but {} elements in the PS recipe".
                format(market.num_categories, len(ps_recipe)))

    logger.info("\n#### Budget-Balanced Trade Reduction\n")
    logger.info(market)
    (optimal_trade, remaining_market) = market.optimal_trade(ps_recipe)
    if len(optimal_trade.procurement_sets) == 0:
        return TradeWithSinglePrice(market.empty_agent_categories(), ps_recipe, [0] * len(ps_recipe))

    highest_negative_ps = remaining_market.get_highest_agents(ps_recipe)
    list_ps_to_compete = optimal_trade.procurement_sets
    if highest_negative_ps:
        list_ps_to_compete = [highest_negative_ps] + list_ps_to_compete
        remaining_market.remove_highest_agents(ps_recipe)

    for category in remaining_market.categories:
        if len(category)==0:
            category.append(-MAX_VALUE)
    logger.info("Optimal trade including one highest non-positive trade, by increasing GFT: {}".format(optimal_trade))
    logger.info("Remaining market: {}".format(remaining_market))

    actual_traders = market.empty_agent_categories()

    # Preparing the order of pivot index for trade_reduction
    pivot_indexes = []
    pivot_index_to_category_index = []
    total = 0
    index = 0
    for agent in ps_recipe:
        pivot_indexes += [total+i for i in range(agent-1, -1, -1)]
        pivot_index_to_category_index += [index for _ in range(agent)]
        total += agent
        index += 1
    found_external = False

    latest_prices = None
    for ps in list_ps_to_compete:
        ps = list(ps)
        if latest_prices is None:
            logger.info("\nCalculating prices for PS {}:".format(ps))
            for pivot_index in pivot_indexes:
                pivot_value = ps[pivot_index]
                if found_external:
                    actual_traders[pivot_index_to_category_index[pivot_index]].append(pivot_value)
                    continue
                pivot_category_index = convert_category_index(ps_recipe, pivot_index)
                pivot_category = market.categories[pivot_category_index]
                logger.info("  Looking for external competition to {} with value {}:".
                            format(pivot_category.name, pivot_value))
                best_containing_PS = remaining_market.best_containing_PS(pivot_category_index, pivot_value)
                best_containing_GFT = sum([best_containing_PS[i]*ps_recipe[i] for i in range(len(best_containing_PS))])
                if best_containing_GFT > 0 or (including_gft_0 and best_containing_GFT == 0):  # EXTERNAL COMPETITION - KEEP TRADER
                    found_external = True
                    logger.info("    best PS is {},{} with GFT {}. It is positive so it is an external competition.".
                                format(best_containing_PS, ps_recipe, best_containing_GFT))
                    prices = market.calculate_prices_by_external_competition(pivot_category_index, pivot_value, best_containing_PS, ps_recipe)
                    logger.info("    Prices are {}".format(prices))
                    latest_prices = prices
                    actual_traders[pivot_index_to_category_index[pivot_index]].append(pivot_value)
                    #for i in range(len(prices)):
                    #    agent_prices = market.categories[i].values
                    #    for value in agent_prices:
                    #        #TODO: should we check if value is greater or equal?
                    #        if value >= prices[i]:
                    #            actual_traders[i].append(value)
                    #break  # done with current PS - move to next PS
                else:  # NO EXTERNAL COMPETITION - REMOVE TRADER
                    logger.info("    Best PS is {},{} with GFT {}. It is negative so it is not an external competition.".
                                format(best_containing_PS, ps_recipe, best_containing_GFT))
                    logger.info("    Remove {} {} from trade and add to remaining market".
                                format(pivot_category.name, pivot_value))
                    ps[pivot_index] = None
                    remaining_market.append_trader(pivot_category_index, pivot_value)
                    logger.info("    Remaining market is now: {}".format(remaining_market))
        else:
            logger.info("\nPrices for PS {} are {}".format(ps, latest_prices))
            #print(pivot_index_to_category_index)
            for pivot_index in pivot_indexes:
                pivot_value = ps[pivot_index]
                actual_traders[pivot_index_to_category_index[pivot_index]].append(pivot_value)
    logger.info("\n")
    result = TradeWithSinglePrice(actual_traders, ps_recipe, latest_prices)
    logger.info(result)
    return result
Example #10
0
def budget_balanced_trade_reduction(market: Market, ps_recipe: list):
    """
    Calculate the trade and prices using generalized-trade-reduction.
    :param market:   contains a list of k categories, each containing several agents.
    :param ps_recipe:  a list of integers, one integer per category.
                       Each integer i represents the number of agents of category i
                       that should be in each procurement-set.
    :return: Trade object, representing the trade and prices.

    >>> # ONE BUYER, ONE SELLER
    >>> market = Market([AgentCategory("buyer", [9.]),  AgentCategory("seller", [-4.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0], seller: [-4.0]]
    No trade

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-4.0]]
    No trade

    >>> market = Market([AgentCategory("seller", [-4.]), AgentCategory("buyer", [9.,8.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [seller: [-4.0], buyer: [9.0, 8.0]]
    seller: [-4.0]: all 1 agents trade and pay -8.0
    buyer: [9.0]: all 1 agents trade and pay 8.0

    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [seller: [-3.0, -4.0], buyer: [9.0]]
    No trade

    >>> market = Market([AgentCategory("buyer", [9.]), AgentCategory("seller", [-4.,-3.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0], seller: [-3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 4.0
    seller: [-3.0]: all 1 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]),  AgentCategory("seller", [-4.,-3.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer: [9.0, 8.0], seller: [-3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -8.0

    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.,8.])])
    >>> print(budget_balanced_trade_reduction(market, [1,1]))
    seller: [-3.0]: all 1 agents trade and pay -4.0
    buyer: [9.0, 8.0]: random 1 out of 2 agents trade and pay 4.0

    >>> # ALL POSITIVE VALUES
    >>> market = Market([AgentCategory("buyer1", [4.,3.]), AgentCategory("buyer2", [9.,8.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [buyer1: [4.0, 3.0], buyer2: [9.0, 8.0]]
    buyer1: [4.0]: all 1 agents trade and pay 3.0
    buyer2: [9.0, 8.0]: random 1 out of 2 agents trade and pay -3.0

    >>> # ALL NEGATIVE VALUES
    >>> market = Market([AgentCategory("seller1", [-4.,-3.]), AgentCategory("seller2", [-9.,-8.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1]))
    Traders: [seller1: [-3.0, -4.0], seller2: [-8.0, -9.0]]
    No trade

    >>>
    >>> # ONE BUYER, ONE SELLER, ONE MEDIATOR
    >>> market = Market([AgentCategory("seller", [-4.,-3.]), AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [seller: [-3.0, -4.0], buyer: [9.0, 8.0], mediator: [-1.0, -2.0]]
    seller: [-3.0]: all 1 agents trade and pay -4.0
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-10.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-3.0, -4.0, -10.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0]: all 1 agents trade and pay -2.0
    seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -6.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-5.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-3.0, -4.0, -5.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -3.0
    seller: [-3.0, -4.0]: random 1 out of 2 agents trade and pay -5.0

    >>> market = Market([AgentCategory("buyer", [9.,8.]), AgentCategory("mediator", [-1.,-2.]), AgentCategory("seller", [-4.,-3.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0], mediator: [-1.0, -2.0], seller: [-2.0, -3.0, -4.0]]
    buyer: [9.0]: all 1 agents trade and pay 8.0
    mediator: [-1.0, -2.0]: random 1 out of 2 agents trade and pay -4.0
    seller: [-2.0, -3.0]: random 1 out of 2 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.,7.]), AgentCategory("mediator", [-1.,-2.,-3.]), AgentCategory("seller", [-4.,-3.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0, 7.0], mediator: [-1.0, -2.0, -3.0], seller: [-2.0, -3.0, -4.0]]
    buyer: [9.0, 8.0]: all 2 agents trade and pay 7.0
    mediator: [-1.0, -2.0]: all 2 agents trade and pay -3.0
    seller: [-2.0, -3.0]: all 2 agents trade and pay -4.0

    >>> market = Market([AgentCategory("buyer", [9.,8.,4.]), AgentCategory("mediator", [-1.,-2.,-3.]), AgentCategory("seller", [-4.,-3.,-2.])])
    >>> print(market); print(budget_balanced_trade_reduction(market, [1,1,1]))
    Traders: [buyer: [9.0, 8.0, 4.0], mediator: [-1.0, -2.0, -3.0], seller: [-2.0, -3.0, -4.0]]
    buyer: [9.0, 8.0]: all 2 agents trade and pay 7.0
    mediator: [-1.0, -2.0]: all 2 agents trade and pay -3.0
    seller: [-2.0, -3.0]: all 2 agents trade and pay -4.0

    """
    if len(ps_recipe) != market.num_categories:
        raise ValueError(
            "There are {} categories but {} elements in the PS recipe".format(
                market.num_categories, len(ps_recipe)))

    if any(r != 1 for r in ps_recipe):
        raise ValueError(
            "Currently, the trade-reduction protocol supports only recipes of ones; {} was given"
            .format(ps_recipe))

    logger.info("\n#### Budget-Balanced Trade Reduction\n")
    logger.info(market)
    (optimal_trade, remaining_market) = market.optimal_trade(ps_recipe)
    for category in remaining_market.categories:
        if len(category) == 0:
            category.append(-MAX_VALUE)
    logger.info("Optimal trade, by increasing GFT: {}".format(optimal_trade))
    logger.info("Remaining market: {}".format(remaining_market))

    actual_traders = market.empty_agent_categories()

    latest_prices = None
    for ps in optimal_trade.procurement_sets:
        ps = list(ps)
        if latest_prices is None:
            logger.info("\nCalculating prices for PS {}:".format(ps))
            for pivot_index in range(len(ps)):
                pivot_value = ps[pivot_index]
                pivot_category = market.categories[pivot_index]
                logger.info(
                    "  Looking for external competition to {} with value {}:".
                    format(pivot_category.name, pivot_value))
                best_containing_PS = remaining_market.best_containing_PS(
                    pivot_index, pivot_value)
                best_containing_GFT = sum(best_containing_PS)
                if best_containing_GFT > 0:  # EXTERNAL COMPETITION - KEEP TRADER
                    logger.info(
                        "    best PS is {} with GFT {}. It is positive so it is an external competition."
                        .format(best_containing_PS, best_containing_GFT))
                    prices = market.calculate_prices_by_external_competition(
                        pivot_index, pivot_value, best_containing_PS)
                    logger.info("    Prices are {}".format(prices))
                    latest_prices = prices
                    for i in range(market.num_categories):
                        if ps[i] is not None:
                            actual_traders[i].append(ps[i])
                    break  # done with current PS - move to next PS
                else:  # NO EXTERNAL COMPETITION - REMOVE TRADER
                    logger.info(
                        "    Best PS is {} with GFT {}. It is negative so it is not an external competition."
                        .format(best_containing_PS, best_containing_GFT))
                    logger.info(
                        "    Remove {} {} from trade and add to remaining market"
                        .format(pivot_category.name, pivot_value))
                    ps[pivot_index] = None
                    remaining_market.append_trader(pivot_index, pivot_value)
                    logger.info("    Remaining market is now: {}".format(
                        remaining_market))
        else:
            logger.info("\nPrices for PS {} are {}".format(ps, latest_prices))
            for i in range(market.num_categories):
                if ps[i] is not None:
                    actual_traders[i].append(ps[i])

    logger.info("\n")
    return TradeWithSinglePrice(actual_traders, ps_recipe, latest_prices)
Example #11
0
        -0.1523, -0.1445, -11.2, -11.2, -3.1406, -11.2, -11.2, -2.6875, -11.2
    ]

    random.shuffle(buyers)
    random.shuffle(sellers)

    reduce_number += 1
    print(reduce_number)
    buyers = removeSeconds(buyers, reduce_number)
    sellers = removeSeconds(sellers, reduce_number)

    # buyers1 = [4]*10 + [8]*20 + [12]*30
    # sellers1 = [-2]*40 + [-2]*80 + [-3]*120

    market = Market([
        AgentCategory("buyer", buyers),
        AgentCategory("seller", sellers),
    ])
    auction_trade = budget_balanced_ascending_auction(market, [1, 4])
    (optimal_trade, _) = market.optimal_trade([1, 4])
    auction_trade_num_of_deals = auction_trade.num_of_deals()
    optimal_trade_num_of_deals = optimal_trade.num_of_deals()
    print(auction_trade_num_of_deals)
    print("Optimal:", optimal_trade_num_of_deals)
    # print(len(buyers), ",", len(sellers))
    # print("max buyer: ", max(buyers), ", min buyer: ", min(buyers), ", max seller: ", max(sellers), ", min seller: ", min(sellers))
# buyers.sort()
# sellers.sort()
print("buyers =", buyers)
print("sellers =", sellers)