<gh_stars>10-100
import unittest
import numpy as np
import os
import matplotlib.pyplot as plt
from tqdm import tqdm

import acpc_python_client as acpc

from tools.constants import Action
from weak_agents.action_tilted_agent import create_agent_strategy_from_trained_strategy, TiltType
from tools.io_util import read_strategy_from_file
from evaluation.exploitability import Exploitability


FIGURES_FOLDER = 'verification/action_tilted_agents'

KUHN_EQUILIBRIUM_STRATEGY_PATH = 'strategies/kuhn.limit.2p-equilibrium.strategy'
LEDUC_EQUILIBRIUM_STRATEGY_PATH = 'strategies/leduc.limit.2p-equilibrium.strategy'

TILT_TYPES = [
    ('FOLD-ADD', Action.FOLD, TiltType.ADD),
    ('CALL-ADD', Action.CALL, TiltType.ADD),
    ('RAISE-ADD', Action.RAISE, TiltType.ADD),
    ('FOLD-MULTIPLY', Action.FOLD, TiltType.MULTIPLY),
    ('CALL-MULTIPLY', Action.CALL, TiltType.MULTIPLY),
    ('RAISE-MULTIPLY', Action.RAISE, TiltType.MULTIPLY),
]


class ActionTiltedAgentsExploitabilityTest(unittest.TestCase):
    def test_plot_kuhn_agent_exploitabilities(self):
        self.create_agents_and_plot_exploitabilities({
            'title': 'Kuhn poker action tilted agents exploitability',
            'figure_filename': 'kuhn_action_tilted_agents',
            'base_strategy_path': KUHN_EQUILIBRIUM_STRATEGY_PATH,
            'game_file_path': 'games/kuhn.limit.2p.game',
            'tilt_probabilities': [-0.5, 0.5], #[i * 0.1 - 1 for i in range(21)],
            'plot_exploitabilities': False,
            'plot_agent_comparison': True,
        })

    def test_plot_leduc_agent_exploitabilities(self):
        self.create_agents_and_plot_exploitabilities({
            'title': 'Leduc Hold\'em action tilted agents exploitability',
            'figure_filename': 'leduc_action_tilted_agents',
            'base_strategy_path': LEDUC_EQUILIBRIUM_STRATEGY_PATH,
            'game_file_path': 'games/leduc.limit.2p.game',
            'tilt_probabilities': [-0.5, 0.5], #[i * 0.1 - 1 for i in range(21)],
            'plot_equilibrium': False,
            'plot_exploitabilities': False,
            'plot_agent_comparison': True,
        })

    def create_agents_and_plot_exploitabilities(self, test_spec):
        base_strategy, _ = read_strategy_from_file(
            test_spec['game_file_path'],
            test_spec['base_strategy_path'])

        game = acpc.read_game_file(test_spec['game_file_path'])
        exploitability = Exploitability(game)

        plot_equilibrium = test_spec['plot_equilibrium'] if 'plot_equilibrium' in test_spec else True
        if plot_equilibrium:
            equilibrium_exploitability = exploitability.evaluate(base_strategy)

        tilt_probabilities = test_spec['tilt_probabilities']
        exploitability_values = np.zeros([len(TILT_TYPES), len(tilt_probabilities)])

        plot_exploitabilities = test_spec['plot_exploitabilities'] if 'plot_exploitabilities' in test_spec else True
        if plot_exploitabilities:
            for i, tilt_type in enumerate(TILT_TYPES):
                for j, tilt_probability in enumerate(tilt_probabilities):
                    tilted_agent = create_agent_strategy_from_trained_strategy(
                        test_spec['game_file_path'],
                        base_strategy,
                        tilt_type[1],
                        tilt_type[2],
                        tilt_probability)
                    exploitability_values[i, j] = exploitability.evaluate(tilted_agent)

                plt.figure(dpi=160)
                for j in range(i + 1):
                    plt.plot(
                        tilt_probabilities,
                        exploitability_values[j],
                        label=TILT_TYPES[j][0],
                        linewidth=0.8)

                if plot_equilibrium:
                    plt.plot(
                        tilt_probabilities,
                        [equilibrium_exploitability] * len(tilt_probabilities),
                        'r--',
                        label='Equilibrium',
                        linewidth=1.5)

                # plt.title(test_spec['title'])
                plt.xlabel('Tilt amount')
                plt.ylabel('Agent exploitability [mbb/g]')
                plt.grid()
                plt.legend()

                figure_output_path = '%s/%s.png' % (FIGURES_FOLDER, test_spec['figure_filename'])

                figures_directory = os.path.dirname(figure_output_path)
                if not os.path.exists(figures_directory):
                    os.makedirs(figures_directory)

                plt.savefig(figure_output_path)

        plot_agent_comparison = test_spec['plot_agent_comparison'] if 'plot_agent_comparison' in test_spec else False
        if plot_agent_comparison:
            agents_strategies = []
            agent_names = []
            for i, tilt_type in enumerate(TILT_TYPES):
                for j, tilt_probability in enumerate(tilt_probabilities):
                    agent_names += ['%s %s %s' % (str(tilt_type[1]).split('.')[1], str(tilt_type[2]).split('.')[1], tilt_probability)]
                    agents_strategies += [create_agent_strategy_from_trained_strategy(
                        test_spec['game_file_path'],
                        base_strategy,
                        tilt_type[1],
                        tilt_type[2],
                        tilt_probability)]

            num_agents = len(agent_names)
            scores_table = np.zeros([num_agents, num_agents])

            num_comparisons = 0
            for i in range(num_agents):
                for j in range(i, num_agents):
                    num_comparisons += 1

            with tqdm(total=num_comparisons) as pbar:
                for i in range(num_agents):
                    for j in range(i, num_agents):
                        scores_table[i, j] = exploitability.evaluate(agents_strategies[j], agents_strategies[i])
                        scores_table[j, i] = -scores_table[i, j]
                        pbar.update(1)

            max_score = scores_table.max()
            min_score = scores_table.min()

            # plt.figure(dpi=160)
            fig, ax = plt.subplots()

            cax = plt.imshow(scores_table, cmap=plt.cm.RdYlGn)
            plt.xticks(np.arange(num_agents), agent_names)
            plt.setp(ax.xaxis.get_majorticklabels(), rotation=45, ha="right", rotation_mode="anchor")
            plt.yticks(np.arange(num_agents), agent_names)
            # plt.yticks(rotation=35)

            # plt.tick_params(
            #     axis='x',
            #     which='both',
            #     bottom=False,
            #     top=False,
            #     labelbottom=False)

            cbar = fig.colorbar(cax, ticks=[min_score, 0, max_score])
            cbar.ax.set_yticklabels([round(min_score), '0', round(max_score)])

            plt.tight_layout()
            plt.gcf().subplots_adjust(left=0.1)

            figure_output_path = '%s/%s-comparison.png' % (FIGURES_FOLDER, test_spec['figure_filename'])

            figures_directory = os.path.dirname(figure_output_path)
            if not os.path.exists(figures_directory):
                os.makedirs(figures_directory)

            plt.savefig(figure_output_path, dpi=160)

import unittest
import numpy as np
import os
import matplotlib.pyplot as plt
from tqdm import tqdm

import acpc_python_client as acpc

from tools.constants import Action
from weak_agents.action_tilted_agent import create_agent_strategy_from_trained_strategy, TiltType
from tools.io_util import read_strategy_from_file
from evaluation.exploitability import Exploitability


FIGURES_FOLDER = 'verification/action_tilted_agents'

KUHN_EQUILIBRIUM_STRATEGY_PATH = 'strategies/kuhn.limit.2p-equilibrium.strategy'
LEDUC_EQUILIBRIUM_STRATEGY_PATH = 'strategies/leduc.limit.2p-equilibrium.strategy'

TILT_TYPES = [
    ('FOLD-ADD', Action.FOLD, TiltType.ADD),
    ('CALL-ADD', Action.CALL, TiltType.ADD),
    ('RAISE-ADD', Action.RAISE, TiltType.ADD),
    ('FOLD-MULTIPLY', Action.FOLD, TiltType.MULTIPLY),
    ('CALL-MULTIPLY', Action.CALL, TiltType.MULTIPLY),
    ('RAISE-MULTIPLY', Action.RAISE, TiltType.MULTIPLY),
]


class ActionTiltedAgentsExploitabilityTest(unittest.TestCase):
    def test_plot_kuhn_agent_exploitabilities(self):
        self.create_agents_and_plot_exploitabilities({
            'title': 'Kuhn poker action tilted agents exploitability',
            'figure_filename': 'kuhn_action_tilted_agents',
            'base_strategy_path': KUHN_EQUILIBRIUM_STRATEGY_PATH,
            'game_file_path': 'games/kuhn.limit.2p.game',
            'tilt_probabilities': [-0.5, 0.5], #[i * 0.1 - 1 for i in range(21)],
            'plot_exploitabilities': False,
            'plot_agent_comparison': True,
        })

    def test_plot_leduc_agent_exploitabilities(self):
        self.create_agents_and_plot_exploitabilities({
            'title': 'Leduc Hold\'em action tilted agents exploitability',
            'figure_filename': 'leduc_action_tilted_agents',
            'base_strategy_path': LEDUC_EQUILIBRIUM_STRATEGY_PATH,
            'game_file_path': 'games/leduc.limit.2p.game',
            'tilt_probabilities': [-0.5, 0.5], #[i * 0.1 - 1 for i in range(21)],
            'plot_equilibrium': False,
            'plot_exploitabilities': False,
            'plot_agent_comparison': True,
        })

    def create_agents_and_plot_exploitabilities(self, test_spec):
        base_strategy, _ = read_strategy_from_file(
            test_spec['game_file_path'],
            test_spec['base_strategy_path'])

        game = acpc.read_game_file(test_spec['game_file_path'])
        exploitability = Exploitability(game)

        plot_equilibrium = test_spec['plot_equilibrium'] if 'plot_equilibrium' in test_spec else True
        if plot_equilibrium:
            equilibrium_exploitability = exploitability.evaluate(base_strategy)

        tilt_probabilities = test_spec['tilt_probabilities']
        exploitability_values = np.zeros([len(TILT_TYPES), len(tilt_probabilities)])

        plot_exploitabilities = test_spec['plot_exploitabilities'] if 'plot_exploitabilities' in test_spec else True
        if plot_exploitabilities:
            for i, tilt_type in enumerate(TILT_TYPES):
                for j, tilt_probability in enumerate(tilt_probabilities):
                    tilted_agent = create_agent_strategy_from_trained_strategy(
                        test_spec['game_file_path'],
                        base_strategy,
                        tilt_type[1],
                        tilt_type[2],
                        tilt_probability)
                    exploitability_values[i, j] = exploitability.evaluate(tilted_agent)

                plt.figure(dpi=160)
                for j in range(i + 1):
                    plt.plot(
                        tilt_probabilities,
                        exploitability_values[j],
                        label=TILT_TYPES[j][0],
                        linewidth=0.8)

                if plot_equilibrium:
                    plt.plot(
                        tilt_probabilities,
                        [equilibrium_exploitability] * len(tilt_probabilities),
                        'r--',
                        label='Equilibrium',
                        linewidth=1.5)

                # plt.title(test_spec['title'])
                plt.xlabel('Tilt amount')
                plt.ylabel('Agent exploitability [mbb/g]')
                plt.grid()
                plt.legend()

                figure_output_path = '%s/%s.png' % (FIGURES_FOLDER, test_spec['figure_filename'])

                figures_directory = os.path.dirname(figure_output_path)
                if not os.path.exists(figures_directory):
                    os.makedirs(figures_directory)

                plt.savefig(figure_output_path)

        plot_agent_comparison = test_spec['plot_agent_comparison'] if 'plot_agent_comparison' in test_spec else False
        if plot_agent_comparison:
            agents_strategies = []
            agent_names = []
            for i, tilt_type in enumerate(TILT_TYPES):
                for j, tilt_probability in enumerate(tilt_probabilities):
                    agent_names += ['%s %s %s' % (str(tilt_type[1]).split('.')[1], str(tilt_type[2]).split('.')[1], tilt_probability)]
                    agents_strategies += [create_agent_strategy_from_trained_strategy(
                        test_spec['game_file_path'],
                        base_strategy,
                        tilt_type[1],
                        tilt_type[2],
                        tilt_probability)]

            num_agents = len(agent_names)
            scores_table = np.zeros([num_agents, num_agents])

            num_comparisons = 0
            for i in range(num_agents):
                for j in range(i, num_agents):
                    num_comparisons += 1

            with tqdm(total=num_comparisons) as pbar:
                for i in range(num_agents):
                    for j in range(i, num_agents):
                        scores_table[i, j] = exploitability.evaluate(agents_strategies[j], agents_strategies[i])
                        scores_table[j, i] = -scores_table[i, j]
                        pbar.update(1)

            max_score = scores_table.max()
            min_score = scores_table.min()

            # plt.figure(dpi=160)
            fig, ax = plt.subplots()

            cax = plt.imshow(scores_table, cmap=plt.cm.RdYlGn)
            plt.xticks(np.arange(num_agents), agent_names)
            plt.setp(ax.xaxis.get_majorticklabels(), rotation=45, ha="right", rotation_mode="anchor")
            plt.yticks(np.arange(num_agents), agent_names)
            # plt.yticks(rotation=35)

            # plt.tick_params(
            #     axis='x',
            #     which='both',
            #     bottom=False,
            #     top=False,
            #     labelbottom=False)

            cbar = fig.colorbar(cax, ticks=[min_score, 0, max_score])
            cbar.ax.set_yticklabels([round(min_score), '0', round(max_score)])

            plt.tight_layout()
            plt.gcf().subplots_adjust(left=0.1)

            figure_output_path = '%s/%s-comparison.png' % (FIGURES_FOLDER, test_spec['figure_filename'])

            figures_directory = os.path.dirname(figure_output_path)
            if not os.path.exists(figures_directory):
                os.makedirs(figures_directory)

            plt.savefig(figure_output_path, dpi=160)
#[i * 0.1 - 1 for i in range(21)], #[i * 0.1 - 1 for i in range(21)], # plt.title(test_spec['title']) # plt.figure(dpi=160) # plt.yticks(rotation=35) # plt.tick_params( #     axis='x', #     which='both', #     bottom=False, #     top=False, #     labelbottom=False)