Skip to content
Extraits de code Groupes Projets
validation.py 5,72 ko
Newer Older
  • Learn to ignore specific revisions
  • Adrien Payen's avatar
    Adrien Payen a validé
    import random
    
    import numpy as np
    
    Adrien Payen's avatar
    Adrien Payen a validé
    import matplotlib.pyplot as plt
    
    Adrien Payen's avatar
    Adrien Payen a validé
    from tmc import TransitionMatrixCalculator
    
    Adrien Payen's avatar
    Adrien Payen a validé
    from markovDecision import MarkovDecisionSolver as mD
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
    class Validation:
        def __init__(self, layout, circle=False):
            self.layout = layout
            self.circle = circle
            self.tmc_instance = TransitionMatrixCalculator()
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
            # Compute optimal value iteration results
            solver = mD(self.layout, self.circle)
            self.optimal_values, self.optimal_dice = solver.solve()
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
        def simulate_game(self, strategy='optimal', num_games=1000):
            total_turns = 0
    
            for _ in range(num_games):
    
    Adrien Payen's avatar
    Adrien Payen a validé
                if strategy == 'Optimal':
    
    Adrien Payen's avatar
    Adrien Payen a validé
                    turns = self.play_optimal_strategy()
    
    Adrien Payen's avatar
    Adrien Payen a validé
                elif strategy == 'SafeDice':
    
    Adrien Payen's avatar
    Adrien Payen a validé
                    turns = self.play_dice_strategy(1)
    
    Adrien Payen's avatar
    Adrien Payen a validé
                elif strategy == 'NormalDice':
    
    Adrien Payen's avatar
    Adrien Payen a validé
                    turns = self.play_dice_strategy(2)
    
    Adrien Payen's avatar
    Adrien Payen a validé
                elif strategy == 'RiskyDice':
    
    Adrien Payen's avatar
    Adrien Payen a validé
                    turns = self.play_dice_strategy(3)
    
    Adrien Payen's avatar
    Adrien Payen a validé
                elif strategy == 'Random':
    
    Adrien Payen's avatar
    Adrien Payen a validé
                    turns = self.play_random_strategy()
    
                total_turns += turns
    
            average_turns = total_turns / num_games
            return average_turns
    
        def play_optimal_strategy(self):
    
    Adrien Payen's avatar
    Adrien Payen a validé
            current_state = 0  # Start from the initial state
            turns = 0
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
            while current_state < len(self.layout) - 1:
                optimal_action = int(self.optimal_dice[current_state])  # Get the optimal action for the current state
                current_state += optimal_action  # Move to the next state based on the optimal action
                turns += 1
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
            return turns
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
        def play_dice_strategy(self, dice):
            current_state = 0  # Start from the initial state
            turns = 0
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
            while current_state < len(self.layout) - 1:
                # Always use the specified dice type (1, 2, or 3)
                current_state += dice
                turns += 1
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
            return turns
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
        def play_random_strategy(self):
    
    Adrien Payen's avatar
    Adrien Payen a validé
            current_state = 0  # Start from the initial state
            turns = 0
    
            while current_state < len(self.layout) - 1:
                # Choose a random dice roll between 1 and 3
                dice_roll = np.random.randint(1, 4)
                current_state += dice_roll
                turns += 1
    
            return turns
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
        def compare_strategies(self, num_games=1000):
    
    Adrien Payen's avatar
    Adrien Payen a validé
            optimal_cost = self.simulate_game(strategy='Optimal', num_games=num_games)
            dice1_cost = self.simulate_game(strategy='SafeDice', num_games=num_games)
            dice2_cost = self.simulate_game(strategy='NormalDice', num_games=num_games)
            dice3_cost = self.simulate_game(strategy='RiskyDice', num_games=num_games)
            random_cost = self.simulate_game(strategy='Random', num_games=num_games)
    
    Adrien Payen's avatar
    Adrien Payen a validé
    
            return {
    
    Adrien Payen's avatar
    Adrien Payen a validé
                'Optimal': optimal_cost,
                'SafeDice': dice1_cost,
                'NormalDice': dice2_cost,
                'RiskyDice': dice3_cost,
                'Random': random_cost
    
    Adrien Payen's avatar
    Adrien Payen a validé
            }
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
        def play_one_turn(self, dice_choice, cur_pos, prison):
            if cur_pos == len(self.layout) - 1:
                return len(self.layout) - 1, False
        
            if prison:
                return cur_pos, False
        
            # Convert dice_choice to integer to avoid TypeError
            dice_choice = int(dice_choice)
        
            list_dice_results = [i for i in range(dice_choice + 1)]
            result = random.choice(list_dice_results)
        
            if cur_pos == 2 and result != 0:
                slow_lane = random.choice([0, 1])
                if slow_lane:
                    new_pos = cur_pos + result
                else:
                    new_pos = cur_pos + result + 7
        
            elif ((cur_pos == 9 and result != 0) or ((cur_pos in [7, 8, 9]) and (cur_pos + result >= 10))):
                new_pos = cur_pos + result + 4
        
            else:
                new_pos = cur_pos + result
        
            if new_pos > len(self.layout) - 1:
                if self.circle:
                    new_pos -= len(self.layout)
                else:
                    return len(self.layout) - 1, True
        
            new_square = self.layout[new_pos]
        
            if dice_choice == 1:
                return new_pos, False
        
            elif dice_choice == 2:
                new_square = random.choice([0, new_square])
        
            if new_square == 0:
                return new_pos, False  # nothing happens
            elif new_square == 1:
                return 0, False  # back to square one
            elif new_square == 2:
                if new_pos - 3 < 0:
                    return 0, False  # back to square one
                return new_pos - 3, False  # back 3 squares
            elif new_square == 3:
                return new_pos, True  # prison
        
    
        def play_one_game(self, start=0):
            n_turns = 0
            cur_pos = start
            prison = False
    
            if self.circle:
                while cur_pos != len(self.layout) - 1:
                    new_pos, prison = self.play_one_turn(self.optimal_dice[cur_pos], cur_pos, prison)
                    if new_pos > len(self.layout) - 1:
                        cur_pos = len(self.layout) - new_pos
                    cur_pos = new_pos
                    n_turns += 1
            else:
                while cur_pos < len(self.layout) - 1:
                    new_pos, prison = self.play_one_turn(self.optimal_dice[cur_pos], cur_pos, prison)
                    cur_pos = new_pos
                    n_turns += 1
    
            return n_turns
    
        def empirical_results(self):
            total_turns_played = 0
            for _ in range(10000):
                n_turns = self.play_one_game()
                total_turns_played += n_turns
    
    
    Adrien Payen's avatar
    Adrien Payen a validé
            return total_turns_played / 10000
        
    
    # Utilisation d'exemple
    layout = [0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 1, 0]
    validation = Validation(layout, circle=False)
    results = validation.compare_strategies(num_games=10000)
    print("Coûts moyens :")
    for strategy, cost in results.items():
        print(f"{strategy}: {cost}")