diff --git a/.idea/ANAC.iml b/.idea/ANAC.iml new file mode 100644 index 0000000..0070e87 --- /dev/null +++ b/.idea/ANAC.iml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..9c4cdb9 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,173 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..fb13a18 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ANAC/DetReg.py b/ANAC/DetReg.py new file mode 100644 index 0000000..adcc94d --- /dev/null +++ b/ANAC/DetReg.py @@ -0,0 +1,194 @@ +import random +import warnings + +import numpy as np +from negmas import SAOState +from scipy.stats import pearsonr + +from ANAC.learner import Learner + + +def correlation_to_probability(correlation_coefficient): + return (1 + correlation_coefficient) / 2 + + +def fill_with_mean(x, y): + # Find the length of the longest array + max_length = max(len(x), len(y)) + if len(x) < max_length: + mean_value = np.mean(x) + x = np.concatenate([x, np.full(max_length - len(x), mean_value)]) + else: + mean_value = np.mean(y) + y = np.concatenate([y, np.full(max_length - len(y), mean_value)]) + return x, y + + +def calc_corr(x, y): + with warnings.catch_warnings(record=True) as w: + pearson_corr, _ = pearsonr(x, y) + if np.isnan(pearson_corr): + return 0.1 + return pearson_corr + + +class DetectingRegion: + def __init__(self, T: int, Nt: int, Np: int): + self.T = T # Deadline + self.current_time = 0 # Current negotiation time + self.Nt = Nt # Number of columns + self.Np = Np # Number of rows + self.n_cells = Nt * Np + self.cells = [] # List to store detecting cells + self.random_reservation_points = [] # List to store random reservation points + self.regression_curves = [] # List to store regression curves + self.fitted_offers = [] # List to store fitted offers + self.correlations = [] # List to store non-linear correlations + self.probs = [] + self.initialize_detecting_region() + + def initialize_detecting_region(self): + # Define detecting region + self.detecting_region = (0, self.T, 0, 100) # Initial detecting region + + # Initialize detecting cells and generate random reservation points + self.update_detecting_region() + + def update_detecting_region(self, state: SAOState = None, max_price=100): + # Update the detecting region with the current negotiation time + # TODO: current price as min price + if state is not None: + self.current_time = state.step + else: + self.current_time = 0 + max_price = max_price + if self.current_time == 0: + max_price = 100 + self.detecting_region = (self.current_time, self.T, 0, max_price) + + # Clear previous random reservation points and detecting cells + self.random_reservation_points.clear() + self.cells.clear() + self.regression_curves.clear() + self.fitted_offers.clear() + self.correlations.clear() + self.probs.clear() + + # Initialize detecting cells and generate random reservation points + for t_idx in range(self.Nt): + t_low = ( + self.detecting_region[0] + + t_idx + * (self.detecting_region[1] - self.detecting_region[0]) + / self.Nt + ) + t_high = ( + self.detecting_region[0] + + (t_idx + 1) + * (self.detecting_region[1] - self.detecting_region[0]) + / self.Nt + ) + for p_idx in range(self.Np): + p_low = ( + self.detecting_region[2] + + p_idx + * (self.detecting_region[3] - self.detecting_region[2]) + / self.Np + ) + p_high = ( + self.detecting_region[2] + + (p_idx + 1) + * (self.detecting_region[3] - self.detecting_region[2]) + / self.Np + ) + tx = random.uniform(t_low, t_high) + px = random.uniform(p_low, p_high) + self.cells.append((t_low, t_high, p_low, p_high)) + self.random_reservation_points.append((tx, px)) + # Initialize the cell's prior probability + for i in range(len(self.cells)): + prob = Learner(prior=1 / self.n_cells) + self.probs.append(prob) + + def print_detecting_region(self): + print(f"Detecting region: {self.detecting_region}") + for idx, cell in enumerate(self.cells): + print(f"Cell {idx}: {cell}") + for idx, point in enumerate(self.random_reservation_points): + print(f"Random reservation point {idx}: {point}") + + def generate_regression_curve(self, history: list[float]): + print("Generating random regression curve") + # init price + init_price = history[0] if history[0] != 0 else 100 + + for reservation_point in self.random_reservation_points: + # claculate the beta coefficient + beta = 0 + up = 0 + down = 0 + t_i_x, p_i_x = reservation_point[0], reservation_point[1] + # print(f"t_i_x: {t_i_x}") + # print(f"p_i_x: {p_i_x}") + + for i in range(1, self.current_time): + history[i] = history[i] if history[i] != init_price else init_price - 1 + p_star_i = np.log((init_price - history[i]) / (init_price - p_i_x)) + t_star_i = np.log(i / t_i_x) + t_star_i_current = np.log(self.current_time / t_i_x) + up += (p_star_i - p_i_x) * (t_star_i - t_i_x) + down += (t_star_i - t_i_x) ** 2 + + beta = up / down + self.regression_curves.append((init_price, p_i_x, t_i_x, beta)) + + def clalculate_fitted_offers(self): + for curve in self.regression_curves: + index = 0 + offer_list = [] # List to store fitted offers + init_price, p_i_x, t_i_x, beta = curve + for i in range(self.current_time): + offer = init_price + (p_i_x - init_price) * (i / t_i_x) ** beta + offer_list.append(offer) + # print(f"for cell: {index} at time: {i} offer: {offer}") + index += 1 + self.fitted_offers.append(offer_list) + + def get_non_linear_correlation(self, history: list[float]): + # Calculate the correlation coefficient + index = 0 + for fitted_offer in self.fitted_offers: + # up = 0 + # + # for i in range(len(fitted_offer)): + # p_hat_gag = np.mean(fitted_offer[:i + 1]) + # p_gag = np.mean(history[:i + 1]) + # + # up += ((history[i] - p_gag) * (fitted_offer[i] - p_hat_gag)) + # + # down = 0 + # down_left = 0 + # down_right = 0 + # + # for i in range(len(fitted_offer)): + # p_hat_gag = np.mean(fitted_offer[:i + 1]) + # p_gag = np.mean(history[:i + 1]) + # down_left += (history[i] - p_gag) ** 2 + # down_right += (fitted_offer[i] - p_hat_gag) ** 2 + # down += np.sqrt(down_left * down_right) + + # gamma = up / down + x = np.array(history) + y = np.array(fitted_offer) + + if len(x) != len(y): + x, y = fill_with_mean(x, y) + + corr = calc_corr(x, y) + gamma = correlation_to_probability(corr) + + print(f"for cell: {index} reservation point: {self.random_reservation_points[index]} gamma: {gamma}") + self.correlations.append(gamma) + self.probs[index].learn(likelihood=gamma) + + index += 1 diff --git a/ANAC/a.ipynb b/ANAC/a.ipynb deleted file mode 100644 index 5302f7d..0000000 --- a/ANAC/a.ipynb +++ /dev/null @@ -1,235 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "outputs": [], - "source": [ - "from sklearn.cluster import DBSCAN" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:10:42.205206Z", - "start_time": "2024-03-15T10:10:42.189764Z" - } - }, - "id": "b4efda482cb75365", - "execution_count": 24 - }, - { - "cell_type": "code", - "outputs": [], - "source": [ - "import numpy as np" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:10:42.622002Z", - "start_time": "2024-03-15T10:10:42.613485Z" - } - }, - "id": "c998d917776f1da6", - "execution_count": 25 - }, - { - "cell_type": "code", - "outputs": [], - "source": [ - "X = np.array([[1, 2], [2, 2], [2, 3], [8, 7], [8, 8], [25, 80]])" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:10:43.075296Z", - "start_time": "2024-03-15T10:10:43.063670Z" - } - }, - "id": "be177bfb7bed84e9", - "execution_count": 26 - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "initial_id", - "metadata": { - "collapsed": true, - "ExecuteTime": { - "end_time": "2024-03-15T10:10:43.635177Z", - "start_time": "2024-03-15T10:10:43.513058Z" - } - }, - "outputs": [], - "source": [ - "clustering = DBSCAN(eps=3, min_samples=2).fit(X)" - ] - }, - { - "cell_type": "code", - "outputs": [ - { - "data": { - "text/plain": "array([ 0, 0, 0, 1, 1, -1], dtype=int64)" - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "clustering.labels_" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:10:43.961390Z", - "start_time": "2024-03-15T10:10:43.930499Z" - } - }, - "id": "1a09edbfa67e630d", - "execution_count": 28 - }, - { - "cell_type": "code", - "outputs": [], - "source": [ - "from sklearn.cluster import KMeans\n", - "\n", - "kmeans = KMeans(n_clusters=len(set(clustering.labels_)))" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:14:39.598531Z", - "start_time": "2024-03-15T10:14:39.530786Z" - } - }, - "id": "db660be13d15ae92", - "execution_count": 30 - }, - { - "cell_type": "code", - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\Users\\adina\\anaconda3\\envs\\m\\lib\\site-packages\\sklearn\\cluster\\_kmeans.py:1412: FutureWarning: The default value of `n_init` will change from 10 to 'auto' in 1.4. Set the value of `n_init` explicitly to suppress the warning\n", - " super()._check_params_vs_input(X, default_n_init=10)\n", - "C:\\Users\\adina\\anaconda3\\envs\\m\\lib\\site-packages\\sklearn\\cluster\\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.\n", - " warnings.warn(\n" - ] - }, - { - "data": { - "text/plain": "array([0, 0, 0, 2, 2, 1])" - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "kmeans.fit_predict(X)" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:14:56.044367Z", - "start_time": "2024-03-15T10:14:53.595427Z" - } - }, - "id": "ef5a6675ff889f00", - "execution_count": 31 - }, - { - "cell_type": "code", - "outputs": [], - "source": [ - "y_pred = np.array([8, 80])\n", - "y_pred = kmeans.predict(X)" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:19:47.911601Z", - "start_time": "2024-03-15T10:19:47.803102Z" - } - }, - "id": "2697f38cf3ac2262", - "execution_count": 35 - }, - { - "cell_type": "code", - "outputs": [], - "source": [ - "y_pred = np.array([8, 80])\n", - "y_pred = kmeans.predict([y_pred])" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:20:32.662988Z", - "start_time": "2024-03-15T10:20:32.613634Z" - } - }, - "id": "faf868bc680cbf6a", - "execution_count": 38 - }, - { - "cell_type": "code", - "outputs": [ - { - "data": { - "text/plain": "array([1])" - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y_pred " - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2024-03-15T10:20:38.965023Z", - "start_time": "2024-03-15T10:20:38.955023Z" - } - }, - "id": "19fc35d21b6b924", - "execution_count": 39 - }, - { - "cell_type": "code", - "outputs": [], - "source": [], - "metadata": { - "collapsed": false - }, - "id": "4bb84f340b79d3c9" - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/ANAC/helper_func.py b/ANAC/helper_func.py new file mode 100644 index 0000000..e69de29 diff --git a/ANAC/learner.py b/ANAC/learner.py new file mode 100644 index 0000000..d619182 --- /dev/null +++ b/ANAC/learner.py @@ -0,0 +1,18 @@ +class Learner: + def __init__(self, prior): + self.prior = prior + self.likelihood = 0. + self.posterior = 0. + + def learn(self, likelihood, sum_of_probs=1): + self.likelihood = likelihood + posterior = ((self.likelihood * self.prior) / sum_of_probs) * 10 + + if posterior >= 1: + self.posterior = posterior / 10 + else: + self.posterior = posterior + + self.prior = self.posterior + print(f"likelihood: {self.likelihood}," + f"\nposterior: {self.posterior}") diff --git a/ANAC/myagent.py b/ANAC/myagent.py index ddf8f87..1a2efac 100644 --- a/ANAC/myagent.py +++ b/ANAC/myagent.py @@ -1,174 +1,12 @@ -import random -from typing import List from negmas.gb.common import GBState from negmas.outcomes import Outcome from negmas.sao import ResponseType, SAONegotiator, SAOResponse, SAOState -import math -import numpy as np - - -class DetectingRegion: - def __init__(self, T: int, Nt: int, Np: int): - self.T = T # Deadline - self.current_time = 0 # Current negotiation time - self.Nt = Nt # Number of columns - self.Np = Np # Number of rows - self.cells = [] # List to store detecting cells - self.random_reservation_points = [] # List to store random reservation points - self.regression_curves = [] # List to store regression curves - self.fitted_offers = [] # List to store fitted offers - self.correlations = [] # List to store non-linear correlations - - self.initialize_detecting_region() - - def initialize_detecting_region(self): - # Define detecting region - self.detecting_region = (0, self.T, 0, 100) # Initial detecting region - - # Initialize detecting cells and generate random reservation points - self.update_detecting_region() - - def update_detecting_region(self, state: SAOState = None, max_price=100): - # Update the detecting region with the current negotiation time - # TODO: current price as min price - if state is not None: - self.current_time = state.step - else: - self.current_time = 0 - max_price = max_price - if self.current_time == 0: - max_price = 100 - self.detecting_region = (self.current_time, self.T, 0, max_price) - - # Clear previous random reservation points and detecting cells - self.random_reservation_points.clear() - self.cells.clear() - self.regression_curves.clear() - self.fitted_offers.clear() - self.correlations.clear() - - # Initialize detecting cells and generate random reservation points - for t_idx in range(self.Nt): - t_low = ( - self.detecting_region[0] - + t_idx - * (self.detecting_region[1] - self.detecting_region[0]) - / self.Nt - ) - t_high = ( - self.detecting_region[0] - + (t_idx + 1) - * (self.detecting_region[1] - self.detecting_region[0]) - / self.Nt - ) - for p_idx in range(self.Np): - p_low = ( - self.detecting_region[2] - + p_idx - * (self.detecting_region[3] - self.detecting_region[2]) - / self.Np - ) - p_high = ( - self.detecting_region[2] - + (p_idx + 1) - * (self.detecting_region[3] - self.detecting_region[2]) - / self.Np - ) - tx = random.uniform(t_low, t_high) - px = random.uniform(p_low, p_high) - self.cells.append((t_low, t_high, p_low, p_high)) - self.random_reservation_points.append((tx, px)) - - def print_detecting_region(self): - print(f"Detecting region: {self.detecting_region}") - for idx, cell in enumerate(self.cells): - print(f"Cell {idx}: {cell}") - for idx, point in enumerate(self.random_reservation_points): - print(f"Random reservation point {idx}: {point}") - - def generate_regression_curve(self, history: List[float]): - print("Generating random regression curve") - # init price - init_price = history[0] if history[0] != 0 else 100 - - for reservation_point in self.random_reservation_points: - # claculate the beta coefficient - beta = 0 - up = 0 - down = 0 - t_i_x, p_i_x = reservation_point[0], reservation_point[1] - # print(f"t_i_x: {t_i_x}") - # print(f"p_i_x: {p_i_x}") - - for i in range(1, self.current_time): - history[i] = history[i] if history[i] != init_price else init_price - 1 - # print(f"------------i: {i}-----------") - # print(f"init_price: {init_price}") - # print(f"history[i]: {history[i]}") - # print(f"p_i_x: {p_i_x}") - p_star_i = np.log((init_price - history[i]) / (init_price - p_i_x)) - # print(f"p_star_i: {p_star_i}") - t_star_i = np.log(i / t_i_x) - # print(f"t_star_i: {t_star_i}") - t_star_i_current = np.log(self.current_time / t_i_x) - # print(f"t_star_i_current: {t_star_i_current}") - up += (p_star_i - p_i_x) * (t_star_i - t_i_x) - # print(f"up: {up}") - down += (t_star_i - t_i_x) ** 2 - # print(f"down: {down}") - - beta = up / down - # print(f"beta: {beta}") - # offer = init_price + (p_i_x - init_price) * (self.current_time / t_i_x) ** beta - # print(f"offer: {offer}") - self.regression_curves.append((init_price, p_i_x, t_i_x, beta)) - - def clalculate_fitted_offers(self): - for curve in self.regression_curves: - index = 0 - offer_list = [] # List to store fitted offers - init_price, p_i_x, t_i_x, beta = curve - for i in range(0, self.current_time): - offer = init_price + (p_i_x - init_price) * (i / t_i_x) ** beta - offer_list.append(offer) - # print(f"for cell: {index} at time: {i} offer: {offer}") - index += 1 - self.fitted_offers.append(offer_list) - - def get_non_linear_correlation(self, history: List[float]): - # Calculate the correlation coefficient - index = 0 - p_gag = np.mean(history) - for fitted_offer in self.fitted_offers: - p_hat_gag = np.mean(fitted_offer) - up = 0 - # print(f"p_gag: {p_gag}") - # print(f"p_hat_gag: {p_hat_gag}") - - for i in range(len(fitted_offer)): - # print(f"fitted_avg: {p_hat_gag}, fitted_offer: {fitted_offer[i]}") - # print(f"history_avg: {p_gag}, history: {history[i]}") - up += ((history[i] - p_gag) * (fitted_offer[i] - p_hat_gag)) - # print(f"up: {up}") - - down = 0 - down_left = 0 - down_right = 0 - - for i in range(len(fitted_offer)): - down_left += (history[i] - p_gag) ** 2 - down_right += (fitted_offer[i] - p_hat_gag) ** 2 - down += np.sqrt((down_left) * (down_right)) - # print(f"down: {down}") - - gamma = up / down - print(f"for cell: {index} reseravtion point: {self.random_reservation_points[index]} gamma: {gamma}") - index += 1 - self.correlations.append(gamma) + +from ANAC.DetReg import DetectingRegion class AwesomeNegotiator(SAONegotiator): - IP = 0 # Initial price will be set during negotiation start + IP = 0 # The Initial price will be set during negotiation start RP = 0 # Reserve price T = 0 # Deadline beta = 0 # Concession parameter @@ -192,17 +30,18 @@ def on_negotiation_start(self, state: GBState) -> None: # self.detecting_region.print_detecting_region() def on_preferences_changed(self, changes): - # If there a no outcomes (should in theory never happen) + # If their a no outcomes (should in theory never happen) if self.ufun is None: return self.rational_outcomes = [ _ - for _ in self.nmi.outcome_space.enumerate_or_sample() # enumerates outcome space when finite, samples when infinite + for _ in self.nmi.outcome_space.enumerate_or_sample() + # enumerates outcome space when finite, samples when infinite if self.ufun(_) > self.ufun.reserved_value ] - # Estimate the reservation value, as a first guess, the opponent has the same reserved_value as you + # Estimate the reservation value; as a first guess, the opponent has the same reserved_value as you self.partner_reserved_value = self.ufun.reserved_value def __call__(self, state: SAOState) -> SAOResponse: @@ -228,7 +67,7 @@ def __call__(self, state: SAOState) -> SAOResponse: if self.acceptance_strategy(state): return SAOResponse(ResponseType.ACCEPT_OFFER, offer) - # If it's not acceptable, determine the counter offer in the bidding_strategy + # If it's not acceptable, determine the counter-offer in the bidding_strategy return SAOResponse(ResponseType.REJECT_OFFER, self.bidding_strategy(state)) def acceptance_strategy(self, state: SAOState) -> bool: @@ -285,14 +124,6 @@ def update_partner_reserved_value(self, state: SAOState) -> None: if self.opponent_ufun(_) > self.partner_reserved_value ] - # def _on_negotiation_end(self, state: GBState) -> None: - # print( - # f"Final score: {self.ufun(state.agreement) - self.reserved_value * self.opponent_ufun(state.agreement)-0.2}" - # ) - - # def on_round_start(self, state: SAOState) -> None: - # print(f"offer: {state.current_offer} with utility: {self.ufun(state.current_offer)} and opponent utility: {self.opponent_ufun(state.current_offer)}") - def isFinalRound(self, state: SAOState) -> bool: if state.step == self.T - 1: return True @@ -303,4 +134,4 @@ def isFinalRound(self, state: SAOState) -> bool: if __name__ == "__main__": from helpers.runner import run_a_tournament - run_a_tournament(AwesomeNegotiator, small=True) + run_a_tournament(AwesomeNegotiator, small=True, nologs=True) diff --git a/helpers/__init__.py b/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/helpers/runner.py b/helpers/runner.py new file mode 100644 index 0000000..709d173 --- /dev/null +++ b/helpers/runner.py @@ -0,0 +1,79 @@ +""" +A helper function to run a tournament with your agent. + +You only need to change the name of the class implementing your agent at the top of this file. +""" + + +def run_a_tournament( + TestedNegotiator, + n_repetitions=5, + n_outcomes=1000, + n_scenarios=10, + debug=False, + nologs=False, + small=False, +): + """ + **Not needed for submission.** You can use this function to test your agent. + + Args: + TestedNegotiator: Negotiator type to be tested + n_repetitions: The number of repetitions of each scenario tested + n_outcomes: Number of outcomes in the domain (makes sure this is between 900 and 1100) + n_scenarios: Number of different scenarios generated + debug: Pass True here to run the tournament in serial, increase verbosity, and fails on any exception + nologs: If passed, no logs will be stored + small: if set to True, the tournament will be very small and run in a few seconds. + + Returns: + None + + Remarks: + + - This function will take several minutes to run. + - To speed it up, use a smaller `n_repetitions` value + + """ + import time + + from anl.anl2024 import ( + DEFAULT_AN2024_COMPETITORS, + DEFAULT_TOURNAMENT_PATH, + anl2024_tournament, + ) + from anl.anl2024.negotiators import Conceder + from negmas.helpers import humanize_time, unique_name + from rich import print + + start = time.perf_counter() + name = ( + unique_name(f"test{TestedNegotiator().type_name.split('.')[-1]}", sep="") + if not nologs + else None + ) + if small: + anl2024_tournament( + competitors=tuple([TestedNegotiator, Conceder]), + n_scenarios=1, + n_outcomes=n_outcomes, + n_repetitions=1, + njobs=-1 if debug else 0, + verbosity=2 if debug else 1, + plot_fraction=0, + name=name, + ).final_scores + else: + anl2024_tournament( + competitors=tuple([TestedNegotiator] + list(DEFAULT_AN2024_COMPETITORS)), + n_scenarios=n_scenarios, + n_outcomes=n_outcomes, + n_repetitions=n_repetitions, + njobs=-1 if debug else 0, + verbosity=2 if debug else 1, + plot_fraction=0, + name=name, + ).final_scores + print(f"Finished in {humanize_time(time.perf_counter() - start)}") + if name is not None: + print(f"You can see all logs at {DEFAULT_TOURNAMENT_PATH / name}")