From 749713a6adf0cba2eda43c25dff2bb93bb6e31cd Mon Sep 17 00:00:00 2001
From: Adrien <adrien.payen@student.uclouvain.be>
Date: Tue, 7 May 2024 00:21:41 +0200
Subject: [PATCH] comments code .py

---
 markovDecision.py       |  60 ++++++-------
 plot.py                 |  76 +++++++++++-----
 strategy_comparison.png | Bin 22221 -> 22200 bytes
 tmc.py                  |  41 ++++-----
 validation.py           | 194 ++++++++++++++--------------------------
 5 files changed, 165 insertions(+), 206 deletions(-)

diff --git a/markovDecision.py b/markovDecision.py
index 5b6e73d..c87b433 100644
--- a/markovDecision.py
+++ b/markovDecision.py
@@ -1,79 +1,79 @@
 import numpy as np
 from tmc import TransitionMatrixCalculator as tmc
 
-class MarkovDecisionSolver:
+class MarkovDecisionProcess :
     def __init__(self, layout: list, circle: bool):
+        # Initialize the Markov Decision Process solver with layout and game mode (circle or not)
         self.Numberk = 15
         self.tmc_instance = tmc()
+
+        # Compute transition matrices for safe, normal, and risky scenarios
         self.safe_dice = self.tmc_instance._compute_safe_matrix()
-        self.normal_dice, _ = self.tmc_instance._compute_normal_matrix(layout, circle)  # Make sure to capture only the normal_dice component
-        self.risky_dice, _ = self.tmc_instance._compute_risky_matrix(layout, circle)    # Make sure to capture only the risky_dice component
+        self.normal_dice, _ = self.tmc_instance._compute_normal_matrix(layout, circle)  
+        self.risky_dice, _ = self.tmc_instance._compute_risky_matrix(layout, circle)    
+
+        # Identify jail states in the layout
         self.jail = [i for i, x in enumerate(layout) if x == 3]
+
+        # Initialize value and dice decision arrays
         self.ValueI = np.zeros(self.Numberk)
-        self.DiceForStates = np.zeros(self.Numberk - 1)
+        self.Dice = np.zeros(self.Numberk - 1)
 
-    def _compute_vi_safe(self, k):
+    def _compute_vi_safe(self, k : int ):
+        # Compute the expected value using safe dice transition matrix for state k
         return np.dot(self.safe_dice[k], self.ValueI) + np.sum(self.normal_dice[k][self.jail])
 
 
-    def _compute_vi_normal(self, k):
+    def _compute_vi_normal(self, k : int ):
+        # Compute the expected value using normal dice transition matrix for state k
         vi_normal = np.dot(self.normal_dice[k], self.ValueI) + np.sum(self.normal_dice[k][self.jail])
         return vi_normal
 
 
-    def _compute_vi_risky(self, k):
+    def _compute_vi_risky(self, k : int ):
+        # Compute the expected value using risky dice transition matrix for state k
         vi_risky = np.dot(self.risky_dice[k], self.ValueI) + np.sum(self.risky_dice[k][self.jail])
         return vi_risky
 
     def solve(self):
+        # Iteratively solve the Markov Decision Process until convergence
         i = 0
         while True:
             ValueINew = np.zeros(self.Numberk)
             i += 1
 
             for k in range(self.Numberk - 1):
+                # Compute expected values for safe, normal, and risky decisions at state k
                 vi_safe = self._compute_vi_safe(k)
                 vi_normal = self._compute_vi_normal(k)
                 vi_risky = self._compute_vi_risky(k)
 
-                # Compute the minimum value among vi_safe, vi_normal, and vi_risky
+                # Determine the minimum value among safe, normal, and risky decisions
                 min_value = min(vi_safe, vi_normal, vi_risky)
 
-                # Find which index (safe, normal, or risky) corresponds to the minimum value
+                # Record the dice decision (safe=1, normal=2, risky=3) corresponding to the minimum value
                 if min_value == vi_safe:
                     ValueINew[k] = 1 + vi_safe
-                    self.DiceForStates[k] = 1
+                    self.Dice[k] = 1
                 elif min_value == vi_normal:
                     ValueINew[k] = 1 + vi_normal
-                    self.DiceForStates[k] = 2
+                    self.Dice[k] = 2
                 else:
                     ValueINew[k] = 1 + vi_risky
-                    self.DiceForStates[k] = 3
-
+                    self.Dice[k] = 3
 
+            # Check for convergence
             if np.allclose(ValueINew, self.ValueI):
                 self.ValueI = ValueINew
                 break
 
             self.ValueI = ValueINew
 
+        # Return the expected values and dice decisions for each state
         Expec = self.ValueI[:-1]
-        return [Expec, self.DiceForStates]
+        return [Expec, self.Dice]
 
 def markovDecision(layout : list, circle : bool):
-    solver = MarkovDecisionSolver(layout, circle)
-    return solver.solve()
-
-"""
-# Exemple d'utilisation de la fonction markovDecision avec les paramètres layout et circle
-layout = [0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 1, 0]
-
-
-# Résolution du problème avec différents modes de jeu
-result_false = markovDecision(layout, circle=False)
-print("\nWin as soon as land on or overstep the final square")
-print(result_false)
-
-result_true = markovDecision(layout, circle=True)
-print("\nStopping on the square to win")
-print(result_true)"""
\ No newline at end of file
+    # Solve the Markov Decision Problem for the given layout and game mode
+    solver = MarkovDecisionProcess(layout, circle)
+    return solver.solve()
\ No newline at end of file
diff --git a/plot.py b/plot.py
index d841495..dd9d81a 100644
--- a/plot.py
+++ b/plot.py
@@ -2,29 +2,24 @@ import matplotlib.pyplot as plt
 from validation import Validation as Val
 import numpy as np
 
-# Example layout and circle settings
-layout = [0, 0, 3, 0, 2, 0, 2, 0, 0, 0, 3, 0, 0, 1, 0]
-circle = False
 
-# Create an instance of validation
-validation_instance = Val(layout, circle)
-
-
-# Plotting function for strategy comparison
-def plot_strategy_comparison(num_games=10000):
+def plot_strategy_comparison(num_games : int):
+    """Plot a bar chart comparing average costs of different strategies over specified number of games."""
+    
+    # Compare strategies and get their costs
     strategy_costs = validation_instance.compare_strategies(num_games=num_games)
 
-    # Bar plot for strategy comparison
+     # Plotting the bar chart
     plt.figure(figsize=(10, 6))
     plt.bar(strategy_costs.keys(), strategy_costs.values(), color=['blue', 'green', 'orange', 'red', 'purple'])
     plt.xlabel('Strategies')
     plt.ylabel('Average Cost')
     plt.title('Comparison of Strategies')
-    plt.savefig('strategy_comparison.png')  # Save the plot
     plt.show()
 
-# Plotting function for state-based average turns for all strategies on the same plot
-def plot_state_based_turns(save=True):
+
+def plot_state_based_turns():
+    """Plot the average number of turns per state for different strategies."""
     strategies = [validation_instance.optimal_policy,
                   validation_instance.safe_strategy,
                   validation_instance.normal_strategy,
@@ -33,8 +28,9 @@ def plot_state_based_turns(save=True):
     strategy_names = ['Optimal', 'SafeDice', 'NormalDice', 'RiskyDice', 'Random']
     
     plt.figure(figsize=(12, 6))
+    # Simulate and plot average turns for each strategy
     for strategy, name in zip(strategies, strategy_names):
-        mean_turns = validation_instance.simulate_state(strategy, layout, circle)
+        mean_turns = validation_instance.simulate_state(strategy, layout, circle, num_games)
         plt.plot(range(len(mean_turns)), mean_turns, marker='o', linestyle='-', label=name)
 
     plt.xlabel('State')
@@ -42,13 +38,35 @@ def plot_state_based_turns(save=True):
     plt.title('Average Turns per State for Different Strategies')
     plt.grid(True)
     plt.legend()
+    plt.show()
+    
+
+def plot_state_based_comparison(num_games_list):
+    """Plot a comparison between optimal turns and empirical turns per state for different num_games."""
+    plt.figure(figsize=(12, 6))  # Create a single figure for all plots
+
+    optimal_turns = None  # Initialize optimal_turns to None
+
+    for num_games in num_games_list:
+        _, empirical_turns = validation_instance.compare_state_based_turns(num_games=num_games)
+
+        # Plotting empirical turns per state for the current num_games
+        plt.plot(range(len(empirical_turns)), empirical_turns, marker='x', linestyle='-', label=f'Empirical (num_games={num_games})')
 
-    #if save:
-         #plt.savefig('state_based_turns_all_strategies.png')  # Save the plot
+        if optimal_turns is None:
+            # Only fetch optimal_turns once (for the first num_games)
+            optimal_turns, _ = validation_instance.compare_state_based_turns(num_games=num_games)
+            plt.plot(range(len(optimal_turns)), optimal_turns, marker='o', linestyle='-', label=f'ValueIteration')
 
+    plt.xlabel('State')
+    plt.ylabel('Average Turns')
+    plt.title('Average Turns per State - ValueIteration vs. Empirical')
+    plt.grid(True)
+    plt.legend()
     plt.show()
 
-def plot_state_based_comparison(validation_instance, num_games=10000):
+
+def plot_state_based_comparison_once(num_games : int):
     optimal_turns, empirical_turns = validation_instance.compare_state_based_turns(num_games=num_games)
 
     # Plotting the state-based average turns comparison
@@ -70,13 +88,23 @@ def plot_state_based_comparison(validation_instance, num_games=10000):
 
 
 
-
-# Main function to generate and save plots
 if __name__ == '__main__':
-    # Example of strategy comparison plot
-    plot_strategy_comparison(num_games=10000)
 
-    # Example of state-based average turns plot for all strategies on the same plot
-    plot_state_based_turns(save=True)
+    ##### Paramètres #####
+
+    # Define the layout of the game board
+    layout = [0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 1, 0]
+    # Indicates whether the board is circular or linear
+    circle = False
+    # Number of games to simulate
+    num_games = 10000
+    # Initialize Validation instance with the specified layout and circle type
+    validation_instance = Val(layout, circle)
+
+     ##### Launch Plots #####
 
-    plot_state_based_comparison(validation_instance, num_games=10000)
\ No newline at end of file
+    # Run the defined plotting functions with specified parameters
+    plot_strategy_comparison(num_games)
+    plot_state_based_turns()
+    plot_state_based_comparison(num_games_list = [10, 100, 1000])
+    plot_state_based_comparison_once(num_games)
\ No newline at end of file
diff --git a/strategy_comparison.png b/strategy_comparison.png
index bcabdaa67b4519b11c1a7cfcc24ba2a35e5327d1..cf7d61d9ba5784ff527eee96c0de4ca903563ab4 100644
GIT binary patch
literal 22200
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
bsdP$eYX-a1IMtl_60*k?k0l*Fd-=ZsSMU-l

literal 22221
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%0AJWuVfN-Dx>F?<K1)+rG{J3jXPMjDQkmRk$o|V-
z8}P+hTaaa_W=n(Ng{3P8jWKe!kMom1=<nebP{g)FeJ5w|h;Boc@nf-u4HD=6v!wW^
zI(;${!C8OlE39sC8fpSPSy%v5);u_TE?PA_3B(9H74RlhtWT&wfxw24bt}i`%mv?Z
z4fZLks>*aToj`ze=tc#z3fYfbcn+)dQEu-11q+T>wY0adb9W!(>SEt}>obWq_768W
zWZP6Mk^k8uHgUZFy*~f-jV~&zu}+Y_gEKQTr!5eSg&z|BBZaHNY^d+2jCk1#=%52T
zZ3*m6>CXM8BzZWu+%#c!)kr7?v!TH2$q-3BTv8znv)Vz?kUlQ$*sTdA_pdT+84F8T
z7<kMdEPtL->zaR3A=En9SfFl+XO?sdGA%U;fNVrR$ARdAe-6m6|570)BOnuqf=4nH
zLG6087`)Yc_w0F)s}e3ZGV3qVPY9Qb%X1wz#fqi%i!vpo*_MrI`<H98?>mbh&v%r^
z6YNq91yHQM^@fkK{(^5`I3OE>boC{GKGG^bb`6767%nfuKy4C;vgWTkuTCUsyQ5g@
z@%QRGcAV{~N=^ptQ)>v^>hK5Qd6;8My&<?dhrQCdvC{uq^8elX^snmVs-FrKS^?D|
zqzN6Q`~EUj`K>tuH12FP@eU3_Vq1N9Hts+<2FW3C9^_lhn$+KzV^(q4I}iyKk&4{*
zT{T*F?%WAM_YjKkNL9ICFaA!gPb*3$eeAv$6?FntGU$Vh^z5vxwdhfh2iFnZDe(6~
zhdjsFtE6=L!OPDnEq-O4o)ZQxalSnqu2IFCswcDU_j?5un<v@KbMn@{0;#7LswO`d
z<>J&i%ft%(0n%Utl&}la=07wO0ki0aI!}p8M2LZrVriU{Cdv9O9*1RV&z$5m@8{K~
zojYc>Kg~YB^clb87eAZ4rlkgF!$7jV4eqT)-<@w3M7tS$G9NaF1qDUpJ{8c#gCsTc
z{@3sRH*Um6L@W!FbJb;+PMj*<c2l=rz`rxSQ}F%GMlg>E7!W~`xW0{HkoLe#h)Pu0
zAj|q`(g+s+v?)_wGykLr)2bj?GdZ<ZbU%T;N?z*q>|6U@ufxBow-o6+H@|Fa%QNNA
zw=Tju2V9=+(50)V2N!;2l0ibuZRfXV{!nP_{3VY0f)XAFG70>vXSCAIyQt$y6}l?S
zwrly#pm_DWx2Q9-(X9;SBGFkO*AD`YzqM|Xym6(%wBq9Im16pq9CaHCSACg>e-jH=
z()W)Gt~{0PXQwM`$$!^%!u<hl16sgzipS+&pMr5;2a45o3;+U`sA8roT8+?Q1fhS8
zV&)aaDg+mJCD5Z3=wg@&(a985$knRzU$cXY&UpR0`Lt1}?$RHZ6U=Jg)MgitV~}|*
z)3P3w$6EAAz@}sN#A6(Y)KXcCHL3Cfz>DcF4zhegk4FYVshbU+bGV|{qpn9wNev`m
z1FJ~XD$d>6txV*6pGD#=NtJO%kMjf<T*3b!#ZqYq|7}Ns$m29U;k9e`5XE!gzz130
zg|@qcg$+Qcl7ERc0BBxtBt<ed-X(zV0~k)Y^uK_ahZ54}v!$UJVEk(kSjc#A+)Fju
zjtY**q#h6?FDejv(v}7%1?s=+vzF&9o!~Z9P+O~q3+kX}YaTzpRi>ajf7tV|LJ^Lw
zS3IufH>4cR*G$xvfRttiC`(m6wJ;$Sbi~EnE`@*jT4I;WsZ(zn8|A&?FI1<QRjGi9
zti<y&;buxakg@}0!sAYUM=~<O4!&#mZlVqv8X6pPd-!CX+hCNZKE)tmgZScNHT$n0
z_Ct+G6AHlGO`16Ibwyx|snlgO<-t&rjCpPSuvtT0-PT;su@gCwMEwk_#w1j*Wa}lQ
zjiS$@;3tR%P&VAToA*#l6-I>2>$!ssE<+#Bac?^EVhZExucZgj&IHLSh77o2jtwQC
z4?!EPVr?sIRBW|j^-kYbxFVt{g_;B*fwp7E>!AMBgb9Ug0HkriEYnx1XT|W}v17-k
z<L`KKzdf5yR=8^`c5OQPimTQEuM3bQ6!`K;it?D<6r-V8#f}Z96cIMmVQ80d?mGdV
zSA*yxBJEMyn!<eIU_TSAxvI?f^Ay?8^{^Jaoja2J1Xn9-7o8;il2<-UB;0;GQFVp_
zg?1j4Dj>rRj8cS0tvfp=f#h6|HI$q?5Q3o>sPDL`#Qg<iJh}I<{8uqhA**AReEIb0
z4uT7eI!2(uQfuA8e-rbITj_YSCcGRKUjI{0{u3}DQ~OucJFkRMs8t$3wqKf>R>Igz
ztqqF4eChAUpjBu>HlwCd^rwcP&OGNloqzi5*|QOT)XdGzg9-%E28!i|CPXc8U7(ze
zx5$t5#y}H75w;)P==_BXW3YM%A*|Pk_ND<KL52EG@iP2AWQwJ`1q9BpAO;bS9RL(C
ze*E~qZRU<LS5a`%-lH*;a`+kx8lBojJL*}P7B}5z+Ni?9dVcC$O$Y;ExriF09tDe0
z(sQ9jH@^?nAx97zy6n;S#&Xj6uG+rR2|_@5wDJ;o_)kDC^A~fQsh@ZHAO=zW%=k$(
zkYFfHeuf4JBQXGHX^_zoQX`Vj321N*1!!^Eh3P`iO=>!dZxS6>?Y*vsPf0)ielhwU
zHIg6wxZHL6o%zLK(0NCO-S0rbBdOM+0nxlX*Ts<<CXob8KRmbt=W=L$=1j*=4y{!v
zoco?l7m3|-Z3RjDkh&sJ>DDB|$mL3dW%cO0CoM1!4-TKDTT3l(qLwE`q`SKtZGq_)
zW9&8y=v!|=2q5!xRHw#tS;aHQ8dEqR2{ok*fC*}2_2iX-|62_PmURjm2kPel7>)&>
ziwZE<eJ1D`fO(+v{g%dZ4>Y~HZ^PykW`syPCSjkMgciQzmj4|AhSC&;2+4}Oy?O2c
zExtyFFDax6$$8|WZ?7_PPfu*>>PiG|<(0JF1`VO&)>gYdP;kwCdS_ieHaAlvAxY6-
zrEUs0eg1qGL{d9g!EmVTG1Ll4Pb?4z2M_$#eo=bk&?#hx&XOQd{_$9Lv2X!^m<T7o
zG{~ZA*ZuGJf)axYB*ta0>IjXEh6l)$dW9Xj>*BzRx8vIWQJ|7e{QUOGdAKW+h(4m9
ziK)Zl>~0l0YuRs@hgY1(Mh3e^!&NfvT2+WV12bJtbd>FvJuhFpFy>h=hhE*<R#hb>
zZvpDkg8eQ813~gDAzstkjKsWOElXT`-){+#ch8eUhoCFkw=%kZletO!xHl$00sE+v
z6u;7Y1+x6a=^MKCYgsfr+FIbjk17&vjO!3L(Ck_apKCO@=<1G(-rm=-S2kPL(Uw5J
z*gnKZo7Yp$D83;k5&po})Z+ZBeT?s~o|Ra1#jJzIx+rKLXdCJ{g$tFMp2&H+bLUP^
zYjMYJedu7jgoO{fCo<6|iK%D)_`<-5i<ccEUx1wJP%OOQHILmNlOzOSSKX3{CUI(<
z11d-WvlkC02fa1>GZb?^HT>@VjV4S_62|ekogh555gGc?+|>y=^PwI>`zeIka!ByR
z;Q64Hae$Y|>ms?~`=Er=ENVBuzb&hWRhFtZ28ka=i0k3u;gl-S8gl}vV$ta4h9XD7
zCz@OzH)hy(YNH_$Axo)M^|nm4pRqn*6M6N~o^fQ$*ss>`E!4ggT4=7fa<{iA60LFQ
z)ytQ~&YnBxQ(msArw1z08<w39(YUjdPR`DY(L43-;Q*+tswv#uMYi%zl4!-A{=BHD
z$lB3y3!e4ZPDRBf5IWx5{=yycV9RB+BfTy0_r|zZ*BG8^o*#)JbLhlSmss1_Y$QDk
z@G}zo;}r&2tX>gMVbR(QrDg`>6-fOV&qcj~AtR|f5|UJOCwgH^e|}9Z`dR}~`>0HR
zxyC`hxepi2pMMM@PmL(ob0-k1K3Lc2jNpNXPP}w%;$t+7Q*UKgr3=!H4>EEs)7tt$
z38EhB7&S@k5xcr{>k+d~G`d_vH+2(axQq<2(S&UdR%W>lJ1F>Dgy9($`FrDeOr%B}
zX(26t^C81R&$CHcNof<H&PK>TN`unwqo*Sg6L$k!CJMm-_wCy^(LA)C2zKt;y?_7y
z-B3Naz~??UO<(NKwQ%9WrYj<OXee!J-G<xs0k3jAC$aAs(98+6kiT|<-sA(t{6mWf
znoGX*_KL%3hl2?YgE=Wf2kI*fm3VzsBbuL!{fq_i9#L;^_e_{*eKH%IH<aaISDg6y
z^XG?w&?GdEz2f9QZJj?jWw1x3Rp&UUNK39oVlOruBpb>$!Ns1TN7C1;2Zx_?Vc-${
z3aNz^S@LLT_~<YH(cBIkrmzX|#2Z%AS~2R2`t<qpkz43>)izT(oj-o*B|hf1hy8wy
zZ^#&OcnI#S!AFk~q-*;(&0DXz2ej-1<<_@>)XwjatBxv28;TTssml=hV9FT@hcn8)
zXn1!axlxFBM;eQTv`!vy@UEtvBl<|#kVc~5K6nk72TQ<1v<gN+jxfo757e_B{?$r_
z9;n@z!F%x2BiTFNe<SKGXtgZ^+nh2xuv4LE5B3nDG+LG{S2WF5T27JaF2dVM8RH6H
zgw_{L++9}<ai_>FtUK*U%LNbKla_(O%xFjWS%=mwG^IFLxQ_`|!}?3o0l{S48q#S%
z)bNlDW9;j@ucxJ*zD3|<1gfNzs*q5UvF26)Y1C#1LBWQ><Xmr;97O1CXfQ275FlSW
zRzo~u`c2_ls0>27X>7ATdj0MorWqe-f!DGasFge)1#nPSHef{qV(i003Sf7^Z$CFV
zqaeq!)uFWjYL7ka{k6A6py;B*JahOo+7l&P3lywby;Ss3n=TL>nIj=Fw<9eUe7gzv
z=Pnl6OKRmp(d$PQ8?2`_En~gXIzz5pGP1H37DS<7v0H2kVY>gFS+xm+2nGo%3;=&N
zx3<Qh`{+xX+t{M3r9Iw5MHzjazsN5I>X?BYUk0;Yy33$tZhxg7*93{FF!@PX)*XN&
zqvqkUD`f1Ly>fRO=~U?M1d|yHWMGOyB4c<#U3a4}To)vvz}ab@Obb9xu0h!Q*lIiz
z8ic{KI7Ro4om!VKKe&N`Hm#J}LCOjcb{pC)p753<Bchl=L7kV}KQ?-AQ+=*mP!#v<
z{_o#QfVV($I_MSWgck+$6&1dFR^3%7fgbt=e0-LUNo28xN1_rN*r_O8rW>O{rVRXJ
zP<uIfso-XmEIS5N8c$YM(Cis%GSIqN$I#;$4gRzp2qewS(auf-k0XJcgZjP=y;T~h
z%DUrU_4TewEs9}nHG-;j>(lA2$ohtW%&Z#u?#8Y{cF!%r2<%rxKPkE&Jjx<D4a>pm
z>jB;UcC$s7Sax2?4|)9fF`a<{WKZ|tU^ENtQZjOWEcQW$(eT(J^$g4Uc=Y^LN8=TX
zs-{2<G<@HMSFm<Qr$9T<_trfAFW!ip1W$-@!-Nyg9hMmDEs}rSG=v;qab^PN*QDG>
zdZaHSji-Lyiepyp5_W-aV#D)=L9|^^CjmC%uEV-dHD;l0{#6`4mr!vc900b9_zE&{
zOa;4X5$N!0_ZT@fFyB-qPMS1{q3*fFtv(TqoCW~VosP=H(01P&_<azd0@d<J8YVZ4
z(oMC{jCTN!c-_~x$hE@b9q=mqaFWT~e7Bl?d2z}IsfB2chB1<toKzu_Hg_%DU^M`F
z91Vy?eK;9DX?{_-;s!xMC8#{*fEWEpJ`E|+pbvqt$hWEk!?oDE!GQs7V1K#;IIfJ@
zcMvA;ZkUvm<XEBS%h?*<T7{9QK+_F1al&}0#}6R}T#sY!dkjE3nr)~(7!xhHuE{Y8
zFTsefLe<O2p=^u@?*D^p^!UQ7d`y{vzbJClodi0`If5I$hx#c2SlPjGDWF6u^}tb!
zG4iDDL*q-6xp)pCh&O+R2)cD>&pn`e^zm!xrk%J(=n+V>+Bx^5Bua91T#~$ddcZ|x
z)S*M2o;O6dlNAC4L?3``J0eaMs_0EfcEBXVS8I9UO{XP8JSbqzWjM0kM|;D$wmi#*
zqD{*U$wCWl8njsZ(5XsiZQOKw8W@GYfcI)Yfk_B<DA$u=&Z_m~ybALP&JrOIIg?-R
zKKfG4P(=b@+YU5}#$qWEP=~AFxY-h%hd=`l=SLg381i>ufNtMW6kjtBMG)-V8FseN
z?Eo>~86>)(V5gZuY@mmy*pALA1JJ5(nWqqW$lFCYoBXM~vd)^g=k)#@id48S9V%;Z
z)B`$7^^tLOAOL5d(wGUMI2SW^Y%uK_6Jt(~&OU;N4zWnXxdANx&@xa4s<6Ijp~j@s
zO7vVn?DTyJP({^q*!k0ig<@SJdCYcy43(915yY215Q*(gzVd}Xykg*9H$`(TjRm#d
znpFvtbHU$IcE%?#7V3yElmiGiQ@}*KXyWkbwW)(WJ*_%$77>|FUKYw{aQDFxdcmc}
z5Ix&;wgGr9^4HYB#$ph2p4lmmrc(pplpz4bbOaT;ZOXA-Edfs=J;0tA(iLHe4_v!{
z2X$_vSG6M5M3t&`Fnp27^(J}_bb3t6Q7<xOVwsS)5@<E;eK=a6(O{4m5fP!}GNoGw
zbQv9e)8AFAgUwzEqR8CQ#<R)k)TuZ?Z0DZbK}}dTE?l@kn4fe|>=I%#$nT5826S)|
z(*nT**0qWj_bAkiVz@i70^&7duKwi*tu+W;Q@{AKA?y%=f(O+JOV3;?8G(J<IFNDz
zC}arTu;?g{0`6IdCUZ&<{n1#P2Gp+%aF~GR;8@^O7zYY$U(0mY!x7r$sg3=nMF-PR
zeFLk)41PI%bOPojOD8lkP&dy*!4C+$7AJH7c&2tr<c7gdK<6!>@fM-@7ELfBXJbaN
zARbM@ldA;xP4-+_*nTrQ<$6I8U?s-lKo2@JhJKU#<Lw4i5R+v)wmw0#5VA)Fs(mq;
zyCv`6D?^yT;U9Mq59yqPljumjX=(ED$r&J}>&P|79TSH(BtN=~Cl&O{RNT2U7Bx5>
z$kcGUR~bXEg1uhwBVVDtQe!RAoyZjN=)j_Uiv_o;ezE^=)W5O7)g3kI30*esXjKxp
zwe?A3QSx#H&sbo8%rBX00Obx1X1!zq7T$%@!S=!fu2GfGnmMPv(&QCM;Y0<4+pV%I
zl8vD=JBIq&w>lYnG#&J2<w`I3b_0h;l{`5!LBjguHpSraIMofz;_iJxf+YwROAV%R
z$f&b5yC()@E~ab_iX#EE0O^=~TiM6D)df;u!Hlx0I#%Wcj&44MKL$3@asR=ly1HQe
zF<41DF@jud9*W~3q<DCJMSZ7%O+&3)U|K-wkx>TD>mUITvPh9KiUXin{=v>>3_8LV
zSPIk$N;9;nb~49D8|q%*;BcxVauL=d3R>hEM2&R<n3FhI1FMyP&ivwj@K)Lm5MkRk
z4+S&yZ0z5`4Jn$t1oM`LSmeVmZ-{nCHIy_cHt(QZ!iVjJBH<qe2=eww%7<t=(Fo7b
zNw!-wSKu@$VFp>3$zw{i5cUC0H8}@sjqrw541kzxa1vogEqdjK+E&sU0k5(iN0}Ti
zymeBi6MI!N+x8gIVz?5SXbh}QA6KZ`Vo?)?s_``_7Z}w$8XrHVk|tCh$B4itqf6I-
zuyEU@JA0|K$v6&cH<~TJ6@dR_Yy>~GS4E{z)E(>5pBxw+U^p^PGKixkHWiVmbb)^|
zj(P#EGy{+zGdieZRLy$8`V4>g^VTp*vEs>XO6JCYkJ}JnpgEhYWJE0iXP<m`V<VcZ
zK3Mp6VV5J~UP6fwgN=3)V?u4`IEHEig9011nBo8{qHAd!35NJM&cy<mPHW8RA`Y)0
z&JSEL_0+<Z8c)_v<hOX#2J3MslmJ;67kT=|0Pi8trwgsDUo1T4NVt()DRB9%6%>4z
zaUaO7et;My)IjakCgFk1gqRU*4WfLhLO?)MLiY>8)-~|S@G;qg<$-%{Wx>%aK0aE2
zS(~tl80rYx;CDA+)2SlUmBwkrd}(i|o?oh=h;3EB_jcs*O`HsNgtpel<q$jm5A_$i
z8nbGX7A{?CzOZoBIypH*kw@RoV%;w1=jX5W`w3WgEISN;+K%yaZVuEjmmNZJv{>5V
zzJ=3o`1mzZPt>Y8GsxC%(TS=i8GQcNj73nyfT$>|!q}vZl}vkqS{%u!hD~V2g0GNo
z4RxV@<iHxDGh+zRqPLCCJOP2B2ITTkKfkO@TtN@@&wQNw0;-lGE{;kAhpqwoAc&d~
z`~}GLfUfGa&|nnS!_pCBne_<paq#9WY9ZDXfC2L!T$yZ?j3y96O6U+`(oqRuuMFl5
zPUm<Mc@`b~9#hYIde-nI2Em#MA8Lb57*v;bED1P*t^%E`Y_C+V85JH;>2Yr~MB4`$
zynp~O_9{0mS>OnU1|N?l!s>t+!g$EylN0|7MT5bO6AZSow+9z>9+`r;ecGl(+gZfQ
z;xq$s>NMddTwI>#>O$Ty+&Gb74qrdq!9i=Wc*#G?&u><u0ZSWrA*jMM5T_1B*TOX$
zfHg(#9%_LjGd;Y7Co`2`<!c7ni#v$J89ER%gW*y~Y`zDE55=VpD7F1CgV6OsftY>!
z_>_)bLcwMg2TI2ooE{+3Iy%j)G_f_!<T#-kP%#xaqmO0?jXP4-A3Z4fBUYQCN(F;`
z1N&wJm~UbP!5?dYakBl!JDKCjDH}TYft$_*q%&9`aj4>fw2<zP963@Bos=wf{+mvg
z3Xoe4aV9hOQplAnfL6Lu;N8{(uEQ-^iW=4|(;L2Nz{F^7xu4tU7#sd^IgUL^zH&o*
zQ0kD>2}~r5Bjc+13R;?)B9rrm_M!sck2|D?I|)|Q-`LS$s1d<_Keg4{LjocW0TGgN
zHZ^IsSNini{r<5}!u*38{;mveEwU++Gu_2%J*I2Q-)Bj3v}EFlFj9HZ5{$MdYvxvL
zIa{93=vEZ#2LnU)d^#G1s89$%)KqpJ$7t})q6vRp4hSl7`lmJFS2BGeO7_F*FP#IU
vH{U@no4+h{|Di?<w&(2s$1_krj!l^Oc;Uj!K`r8>qBC}>>`dBm=<NRhl{F~O

diff --git a/tmc.py b/tmc.py
index cb3b32b..73b496e 100644
--- a/tmc.py
+++ b/tmc.py
@@ -2,12 +2,14 @@ import numpy as np
 
 class TransitionMatrixCalculator:
     def __init__(self):
+        # Initialize the size of the transition matrices
         self.size = 15
         self.matrix_safe = np.zeros((self.size , self.size ))
         self.matrix_normal = np.zeros((self.size , self.size ))
         self.matrix_risky = np.zeros((self.size , self.size ))
 
-    def compute_transition_matrix(self, layout, circle=False):
+    def compute_transition_matrix(self, layout : list , circle : bool):
+        # Compute transition matrices for safe, normal, and risky scenarios
         self.matrix_safe = self._compute_safe_matrix()
         self.matrix_normal, _ = self._compute_normal_matrix(layout, circle)
         self.matrix_risky, _ = self._compute_risky_matrix(layout, circle)
@@ -16,11 +18,12 @@ class TransitionMatrixCalculator:
 
 
     def _compute_safe_matrix(self):
+        # Compute transition matrix for safe scenario
         p = np.zeros((self.size ,self.size ))
         for k in range(self.size  - 1):
             if k == 2:
-                p[k,k+1] = 1/4  # slow lane
-                p[k,k+8] = 1/4  # fast lane
+                p[k,k+1] = 1/4 
+                p[k,k+8] = 1/4  
             elif k == 9:
                 p[k,k+5] = 1/2
             else:
@@ -29,14 +32,15 @@ class TransitionMatrixCalculator:
         p[self.size -1,self.size -1] = 1
         return p
 
-    def _compute_normal_matrix(self, layout, circle=False):
+    def _compute_normal_matrix(self, layout : list , circle : bool):
+        # Compute transition matrix for normal scenario
         p = np.zeros((self.size ,self.size ))
         jail = np.zeros((self.size ,self.size ))
 
         for k in range(self.size  - 1):
             if k == 2:
-                p[k,k+1:k+3] = 1/6  # slow lane # slow lane
-                p[k,k+8:k+10] = 1/6  # fast lane  # fast lane
+                p[k,k+1:k+3] = 1/6  
+                p[k,k+8:k+10] = 1/6 
             elif k == 8:
                 p[k,k+1] = 1/3
                 p[k,k+6] = 1/3
@@ -73,14 +77,15 @@ class TransitionMatrixCalculator:
         p[self.size -1,self.size -1] = 1
         return p, jail
 
-    def _compute_risky_matrix(self, layout, circle=False):
+    def _compute_risky_matrix(self, layout : list , circle : bool):
+        # Compute transition matrix for risky scenario
         p = np.zeros((self.size ,self.size ))
         jail = np.zeros((self.size ,self.size ))
 
         for k in range(self.size -1):
             if k == 2:
-                p[k,k+1:k+4] = 1/8  # slow lane
-                p[k,k+8:k+11] = 1/8  # fast lane
+                p[k,k+1:k+4] = 1/8
+                p[k,k+8:k+11] = 1/8
             elif k == 7:
                 p[k,k+1:k+3] = 1/4
                 p[k,k+7] = 1/4
@@ -131,20 +136,4 @@ class TransitionMatrixCalculator:
                     jail[k,j] = p[k,j]
 
         p[self.size -1,self.size-1] = 1
-        return p, jail
-
-"""
-    def display_matrices(self):
-        print("Safe Matrix:")
-        print(self.matrix_safe)
-        print("\nNormal Matrix:")
-        print(self.matrix_normal)
-        print("\nRisky Matrix:")
-        print(self.matrix_risky)
-
-# Example Usage:
-layout_example = [0]*15
-calculator = TransitionMatrixCalculator()
-calculator.compute_transition_matrix(layout_example, circle=True)
-calculator.display_matrices()
-"""
\ No newline at end of file
+        return p, jail
\ No newline at end of file
diff --git a/validation.py b/validation.py
index 02e656b..7e72b5e 100644
--- a/validation.py
+++ b/validation.py
@@ -1,44 +1,55 @@
 import random as rd
 import numpy as np
 from tmc import TransitionMatrixCalculator as tmc
-from markovDecision import MarkovDecisionSolver as mD
-
+from markovDecision import MarkovDecisionProcess as mD
 
+# Class for performing validation and simulation
 class Validation:
-    def __init__(self, layout, circle=False):
+    def __init__(self, layout : list, circle : bool):
+        # Initialize with layout and circle configuration
         self.layout = layout
         self.circle = circle
+
+        # Initialize TransitionMatrixCalculator instance for transition matrix computation
         self.tmc_instance = tmc()
+
+        # Compute transition matrices for safe, normal, and risky dice
         self.safe_dice = self.tmc_instance._compute_safe_matrix()
         self.normal_dice, _ = self.tmc_instance._compute_normal_matrix(layout, circle)
         self.risky_dice, _ = self.tmc_instance._compute_risky_matrix(layout, circle)
         
+        # Use MarkovDecisionSolver to find optimal policy and expected costs
         solver = mD(self.layout, self.circle)
         self.expec, self.optimal_policy = solver.solve()
 
+        # Predefined strategies for different dice types
         self.safe_strategy = [1] * len(layout)
         self.normal_strategy = [2] * len(layout)
         self.risky_strategy = [3] * len(layout)
         self.random_strategy = [rd.choice([0, 1, 2, 3]) for _ in range(len(layout))]
 
+        # Dictionary to store costs by dice type
         self.costs_by_dice_type = {
             'SafeDice': [0] * len(layout),
             'NormalDice': [0] * len(layout),
             'RiskyDice': [0] * len(layout)
         }
         
-        for i, die_type in enumerate(self.layout):
+        # Assign costs based on dice type to the respective lists in the dictionary
+        for i, die_type in enumerate(self.layout) :
             self.costs_by_dice_type['SafeDice'][i] = 1 if die_type == 3 else 0
             self.costs_by_dice_type['NormalDice'][i] = 2 if die_type == 3 else 0
             self.costs_by_dice_type['RiskyDice'][i] = 3 if die_type == 3 else 0
 
-    def simulate_game(self, strategy, n_iterations=10000):
+
+    def simulate_game(self, strategy: list, n_iterations: int):
+        """Simulate the game using a given strategy over multiple iterations."""
         transition_matrices = [self.safe_dice, self.normal_dice, self.risky_dice]
-        number_turns = []
+        total_turns = np.zeros(n_iterations) 
 
-        for _ in range(n_iterations):
-            total_turns = 0
-            k = 0  # initial state
+        for i in range(n_iterations):
+            k = 0
+            turns = 0
 
             while k < len(self.layout) - 1:
                 action = strategy[k]
@@ -50,32 +61,34 @@ class Validation:
 
                 k = np.random.choice(len(self.layout), p=flattened_probs)
 
-                if self.layout[k] == 3 and action == 2:
-                    total_turns += 1 if np.random.uniform(0, 1) < 0.5 else 2
-                elif self.layout[k] == 3 and action == 3:
-                    total_turns += 2
+                if self.layout[k] == 3:
+                    if action == 2:
+                        turns += np.random.choice([1, 2], p=[0.5, 0.5]) 
+                    elif action == 3:
+                        turns += 2
                 else:
-                    total_turns += 1
+                    turns += 1
+
+            total_turns[i] = turns
 
-            number_turns.append(total_turns)
+        return np.mean(total_turns)
 
-        return np.mean(number_turns)
 
-    def simulate_state(self, strategy, layout, circle, n_iterations=10000):
+    def simulate_state(self, strategy: list, layout: list, circle: bool, n_iterations: int):
+        """Simulate game states using a given strategy."""
         safe_dice = self.tmc_instance._compute_safe_matrix()
         normal_dice = self.tmc_instance._compute_normal_matrix(layout, circle)[0]
         risky_dice = self.tmc_instance._compute_risky_matrix(layout, circle)[0]
 
         transition_matrices = [safe_dice, normal_dice, risky_dice]
-        number_turns = []
-        number_mean = []
+        total_turns = []
 
         for _ in range(n_iterations):
-            number_turns = []
+            state_turns = np.zeros(len(layout) - 1)  # Utiliser un tableau numpy pour stocker les tours par état
 
             for state in range(len(layout) - 1):
-                total_turns = 0
                 k = state
+                turns = 0
 
                 while k < len(layout) - 1:
                     action = strategy[k]
@@ -87,25 +100,27 @@ class Validation:
 
                     k = np.random.choice(len(layout), p=flattened_probs)
 
-                    if layout[k] == 3 and action == 2:
-                        total_turns += 1 if np.random.uniform(0, 1) < 0.5 else 2
-                    elif layout[k] == 3 and action == 3:
-                        total_turns += 2
+                    if layout[k] == 3:
+                        if action == 2:
+                            turns += np.random.choice([1, 2], p=[0.5, 0.5])  # Utiliser numpy pour la randomisation
+                        elif action == 3:
+                            turns += 2
                     else:
-                        total_turns += 1
+                        turns += 1
 
-                number_turns.append(total_turns)
+                state_turns[state] = turns
 
-            number_mean.append(number_turns)
+            total_turns.append(state_turns)
 
-        # calculate the average number of turns for each state
-        mean_turns = np.mean(number_mean, axis=0)
+        mean_turns = np.mean(total_turns, axis=0)
         return mean_turns
 
-    def play_optimal_policy(self, n_iterations=10000):
+    def play_optimal_policy(self, n_iterations : int):
+        """Play using the optimal policy for a number of iterations."""
         return self.simulate_game(self.optimal_policy, n_iterations)
 
-    def play_dice_strategy(self, dice_choice, n_iterations=10000):
+    def play_dice_strategy(self, dice_choice, n_iterations : int):
+        """Play using a specific dice strategy for a number of iterations."""
         strategy = {
             'SafeDice': self.safe_strategy,
             'NormalDice': self.normal_strategy,
@@ -117,33 +132,13 @@ class Validation:
 
         return self.simulate_game(strategy, n_iterations)
 
-    def play_random_strategy(self, n_iterations=10000):
+    def play_random_strategy(self, n_iterations : int ):
+        """Play using a random strategy for a number of iterations."""
         return self.simulate_game(self.random_strategy, n_iterations)
 
-    def play_empirical_strategy(self):
-        k = 0
-        total_turns = 0
-
-        while k < len(self.layout) - 1:
-            action = self.optimal_policy[k]
-            action_index = int(action) - 1
-            transition_matrix = self.normal_dice
-
-            flattened_probs = transition_matrix[k]
-            flattened_probs /= np.sum(flattened_probs)
 
-            k = np.random.choice(len(self.layout), p=flattened_probs)
-
-            if self.layout[k] == 3 and action == 2:
-                total_turns += 1 if np.random.uniform(0, 1) < 0.5 else 2
-            elif self.layout[k] == 3 and action == 3:
-                total_turns += 2
-            else:
-                total_turns += 1
-
-        return total_turns
-
-    def compare_empirical_vs_value_iteration(self, num_games=10000):
+    def compare_empirical_vs_value_iteration(self, num_games : int):
+        """Compare expected value iteration turns with empirical turns."""
         value_iteration_turns = self.expec
         empirical_turns = self.simulate_state(self.optimal_policy, self.layout, self.circle, n_iterations=num_games)
 
@@ -153,14 +148,29 @@ class Validation:
         }
 
         return mean_turns_by_state
+    
+    def empirical_cost_of_square(self, strategy: list, n_iterations: int):
+        """Calculate the empirical cost of a square for a given strategy."""
+        total_square_costs = []
+
+        for _ in range(n_iterations):
+            game_cost = self.simulate_game(strategy, 1)
+            square_cost = game_cost ** 2
+            total_square_costs.append(square_cost)
+
+        empirical_cost = np.mean(total_square_costs)
+        return empirical_cost
 
-    def compare_state_based_turns(self, num_games=10000):
+
+    def compare_state_based_turns(self, num_games : int ):
+         # Compare the expected turns from value iteration with empirical state-based turns
         value_iteration = self.expec
         empirical_turns = self.simulate_state(self.optimal_policy, self.layout, self.circle, n_iterations=num_games)
 
         return value_iteration, empirical_turns
 
-    def compare_strategies(self, num_games=10000):
+    def compare_strategies(self, num_games : int):
+        # Compare the costs of different strategies over a number of games
         optimal_cost = self.simulate_game(self.optimal_policy, n_iterations=num_games)
         dice1_cost = self.simulate_game(self.safe_strategy, n_iterations=num_games)
         dice2_cost = self.simulate_game(self.normal_strategy, n_iterations=num_games)
@@ -174,71 +184,3 @@ class Validation:
             'RiskyDice': dice3_cost,
             'Random': random_cost
         }
-
-"""
-# Exemple d'utilisation
-layout = [0, 0, 3, 0, 2, 0, 2, 0, 0, 0, 3, 0, 0, 1, 0]
-circle = False
-validation_instance = Validation(layout, circle)
-
-# Comparaison entre la stratégie empirique et la value iteration
-turns_by_state = validation_instance.compare_empirical_vs_value_iteration(num_games=1000000)
-
-# Affichage des moyennes de tours pour chaque état
-num_states = len(layout)
-for state in range(num_states - 1):
-    print(f"État {state}:")
-    print(f"   ValueIteration - Tours moyens : {turns_by_state['ValueIteration'][state]:.2f}")
-    print(f"   Empirical - Tours moyens : {turns_by_state['Empirical'][state]:.2f}")
-
-# Exécution de la stratégie empirique une fois
-empirical_strategy_result = validation_instance.play_empirical_strategy()
-print("Coût de la stratégie empirique sur un tour :", empirical_strategy_result)
-
-# Comparaison entre la stratégie empirique et la value iteration sur plusieurs jeux
-comparison_result = validation_instance.compare_empirical_vs_value_iteration(num_games=1000000)
-print("Coût moyen de la stratégie de value iteration :", comparison_result['ValueIteration'])
-print("Coût moyen de la stratégie empirique :", comparison_result['Empirical'])
-
-# Coûts des différentes stratégies
-optimal_cost = validation_instance.play_optimal_policy(n_iterations=1000000)
-print("Optimal Strategy Cost:", optimal_cost)
-
-dice1_cost = validation_instance.play_dice_strategy('SafeDice', n_iterations=1000000)
-print("Safe Dice Strategy Cost:", dice1_cost)
-
-dice2_cost = validation_instance.play_dice_strategy('NormalDice', n_iterations=1000000)
-print("Normal Dice Strategy Cost:", dice2_cost)
-
-dice3_cost = validation_instance.play_dice_strategy('RiskyDice', n_iterations=1000000)
-print("Risky Dice Strategy Cost:", dice3_cost)
-
-random_cost = validation_instance.play_random_strategy(n_iterations=1000000)
-print("Random Strategy Cost:", random_cost)
-
-# Comparaison entre les stratégies
-strategy_comparison = validation_instance.compare_strategies(num_games=1000000)
-print("Strategy Comparison Results:", strategy_comparison)
-
-# Calcul des tours moyens pour différentes stratégies
-optimal_policy = validation_instance.optimal_policy
-mean_turns_optimal = validation_instance.simulate_state(optimal_policy, layout, circle, n_iterations=1000000)
-print("Mean Turns for Optimal Strategy:", mean_turns_optimal)
-
-safe_dice_strategy = validation_instance.safe_strategy
-mean_turns_safe_dice = validation_instance.simulate_state(safe_dice_strategy, layout, circle, n_iterations=1000000)
-print("Mean Turns for Safe Dice Strategy:", mean_turns_safe_dice)
-
-normal_dice_strategy = validation_instance.normal_strategy
-mean_turns_normal_dice = validation_instance.simulate_state(normal_dice_strategy, layout, circle, n_iterations=1000000)
-print("Mean Turns for Normal Dice Strategy:", mean_turns_normal_dice)
-
-risky_dice_strategy = validation_instance.risky_strategy
-mean_turns_risky_dice = validation_instance.simulate_state(risky_dice_strategy, layout, circle, n_iterations=1000000)
-print("Mean Turns for Risky Dice Strategy:", mean_turns_risky_dice)
-
-random_dice_strategy = validation_instance.random_strategy
-mean_turns_random_dice = validation_instance.simulate_state(random_dice_strategy, layout, circle, n_iterations=1000000)
-print("Mean Turns for Random Dice Strategy:", mean_turns_random_dice)
-
-"""
\ No newline at end of file
-- 
GitLab