def benchmark_random_n_nodes(n, k, iterations=3, step=10, plot=False, path=""): """ Benchmarks the classical algorithm for generalized parity games using a random game arenas generator. Arenas of size n with 1 to k priority functions are solved. :param n: number of nodes in generated graph. :param k: number of priority functions in the generated graph. :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. """ y = [] # list for the time recordings n_ = [] # list for the x values total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve" # info about the current benchmark # print first line of output print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "\n" + \ "-" * 108 # games generated are size 1 to n for i in range(2, k + 1, step): g = generators.random_generalized(n, i, n, 1, n/2) temp = [] # #iterations calls to the solver are timed for j in range(iterations): with chrono: generalized_parity_solver(g) # solver call temp.append(chrono.interval) # add time recording min_recording = min(temp) y.append(min_recording) # get the minimum out of #iterations recordings n_.append(i) total_time += min_recording print "Random graph".center(40) + "|" + str(i).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "\n" + "-" * 108 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time print "-" * 108 + "\n" + "Total time".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "\n" + "-" * 108 + "\n" if plot: plt.grid(True) plt.title(u"Random graph of size " + str(100)+" with 1 to "+str(k)+" priority functions") plt.xlabel(u'number of nodes') plt.ylabel(u'time (s)') points, = plt.plot(n_, y, 'g.', label=u"Execution time") plt.legend(loc='upper left', handles=[points]) plt.savefig(path) plt.clf() plt.close()
def benchmark_ladder_wc(n, iterations=3, step=10, plot=False, path="", save_res = False, path_res = "", prt = True): """ Benchmarks the window parity algorithms for strong parity games using the random game generator. Calls window parity partial solver on games generated using the random game generator function. Games of size 1 to n are solved and a timer records the time taken to get the solution.The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result can be plotted using matplotlib. :param n: number of nodes in generated graph (nodes is n due to construction). :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. :param save_res: if True, save the results on a file. :param path_res: path to the file in which to write the result. :param prt: True if the prints are activated. """ y = [] # list for the time recordings n_ = [] # list for the x values (1 to n) per_sol = [] # list for the percentage of the game solved total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s)" # info about the current benchmark not_comp_solved = [] #store the game that are not completely solved # print first line of output if prt: print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "|" + "Percentage solved".center(19) + "|" + "\n" + \ "-" * 115 # games generated are size 1 to n for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings g = generators.ladder(i) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: (w0, w1) = winningcore.partial_solver(g) # winning core call temp.append(chrono.interval) # add time recording min_recording = min(temp) percent_solved = ((float(len(w0)) + len(w1)) /(i)) * 100 if percent_solved != 100: not_comp_solved.append((g, w0, w1)) y.append(min_recording) # get the minimum out of #iterations recordings n_.append(i) per_sol.append(percent_solved) total_time += min_recording if prt: print "Ladder graph".center(40) + "|" + str(i).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "|" + str(percent_solved).center(19) + "|" + "\n" + "-" * 115 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time if prt: print "-" * 115 + "\n" + "Total (s)".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "|" + "\n" + "-" * 115 + "\n" if plot: fig, ax1 = plt.subplots() plt.grid(True) plt.title(u"Graphes Ladder de taille 1 à " + str(n)) plt.xlabel(u'nombre de nœuds') # plt.yscale("log") allows logatithmic y-axis ax1.plot(n_, y, 'g.', label=u"Temps d'exécution", color='b') ax1.tick_params('y', colors='b') ax1.set_ylabel("Temps d'execution (s)", color = 'b') ax2 = ax1.twinx() ax2.plot(n_, per_sol, 'g.', label=u"Pourcentage résolu", color='r') ax2.set_ylim([0, 101]) ax2.set_ylabel("Pourcentage du jeu resolu (%)", color = 'r') ax2.tick_params('y', colors='r') fig.tight_layout() plt.savefig(path+".png", bbox_inches='tight') plt.clf() plt.close() if save_res: #computing the percent solved for each player for the games not solved completely part_solv = 0 comp_solv = 0 percent_solv = [] for (g, w0, w1) in not_comp_solved: #one more game not solved completely part_solv += 1 #checking is the solutions are included to the true solutions. Computing the true sols with Zielonka algorithm (sp_w0, sp_w1) = sp(g) a = all(s in sp_w1 for s in w1) #cheking if included b = all(s in sp_w0 for s in w0) #cheking if included #if not included stop the algorithm if not a or not b: print "Error the solutions found are not included to the true solutions" return -1 #total percentage solved percent_solved_total = ((float(len(w0)) + len(w1)) /(len(sp_w0) + len(sp_w1))) * 100 #percentage solved for player 0 if len(sp_w0) > 0: percent_solved_0 = (float(len(w0)) /len(sp_w0)) * 100 else: percent_solved_0 = 100 #percentage solved for player 1 if len(sp_w1) > 0: percent_solved_1 = (float(len(w1)) /len(sp_w1)) * 100 else: percent_solved_1 = 100 #adding the percentages computed to the list + the size of the game percent_solv.append((len(g.get_nodes()), percent_solved_total, percent_solved_0, percent_solved_1)) comp_solv += n/step - len(not_comp_solved) io.write_benchmark_partial_solver(comp_solv, part_solv, percent_solv, path_res+".txt", n_, y, n, 1, -1, False, "")
def benchmark(n, generator, iterations=3, step=10, plot=False, regression=False, order=1, path="", title=""): """ General benchmarking function. Calls weak parity solver on games generated using the provided generator function. Games of size 1 to n are solved and a timer records the time taken to get the solution. The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result as well as a regression can be plotted using matplotlib. :param n: number of nodes in generated graph. :param generator: graph generator function. :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param regression: if True, plots a polynomial regression along with the data. :param order: order of that regression. :param path: path to the file in which to write the result. :param title: the title to be used in the plot. """ y = [] # list for the time recordings n_ = [] # list for the x values (1 to n) total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s)" # info about the current benchmark # print first line of output print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "\n" + \ "-" * 108 # games generated are size 1 to n with a certain step for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings g = generator(i) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: weak_parity_solver(g) # solver call temp.append(chrono.interval) # add time recording min_recording = min(temp) y.append(min_recording) # get the minimum out of #iterations recordings n_.append(i) total_time += min_recording print generator.__name__.center(40) + "|" + str(i).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "\n" + "-" * 108 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time print "-" * 108 + "\n" + "Total (s)".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "\n" + "-" * 108 + "\n" # if we need to plot if plot: plt.grid(True) if title != "": plt.title(title) else: plt.title(u"Générateur : " + str(generator.__name__).replace("_", " ")) plt.xlabel(u'nombre de nœuds') plt.ylabel(u'temps (s)') if regression: coeficients = np.polyfit(n_, y, order) polynom = np.poly1d(coeficients) points, = plt.plot(n_, y, 'g.', label=u"Temps d'exécution") fit, = plt.plot(n_, polynom(n_), 'b--', alpha=0.6, label=u"Régression polynomiale de degré " + str(order)) plt.legend(loc='upper left', handles=[points, fit]) else: points, = plt.plot(n_, y, 'g.', label=u"Temps d'exécution") plt.legend(loc='upper left', handles=[points]) plt.savefig(path, bbox_inches='tight') plt.clf() plt.close()
def benchmark_worst_case_wp(n, start_lambda = 1, end_lambda = 10, step_lambda = 1, dir = True, v2 = False, iterations=3, step=10, plot=False, path="", save_res = False, path_res = "", prt = True): """ Benchmarks the window parity algorithms for strong parity games using the random game generator. Calls window parity partial solver on games generated using the random game generator function. Games of size 1 to n are solved and a timer records the time taken to get the solution.The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result can be plotted using matplotlib. :param n: number of nodes in generated graph (nodes is n due to construction). :param end_lambda: maximum value of lambda. :param start_lambda: starting value of lambda. :param step_lambda: step to be taken between the different value of lambda. :param dir: if True, uses DirFixWP if not, uses FixWP. :param v2: if True, uses partial_solver2. If False, uses partial_solver. :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. :param save_res: if True, save the results on a file. :param path_res: path to the file in which to write the result. :param prt: True if the prints are activated. :return: Percentage of game solved, size of the games such that we return the time taken to resolve those games. """ y = [] # list for the time recordings n_ = [] # list for the x values (5 to 5n) per_sol = [] # list for the percentage of the game solved total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s)" # info about the current benchmark lam = start_lambda #current lambda used by the algorithme not_comp_solved = [] #store the game that are not completely solved # print first line of output if prt: print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "|" + "Percentage solved".center(19) + "|" + "\n" + \ "-" * 115 #for each value of lambda for lam in range(start_lambda, end_lambda + 1, step_lambda): #print current value of lambda if prt: print "lambda value : ".center(40) + str(lam) + "\n" + "-" * 115 y_temp = [] # stores time recordings for the current value of lambda n_temp = [] # stores the size of the game for the current value of lambda per_sol_temp = [] #stores the resolution percentage of the games for the current value of lambda nbr_generated = 0 # games generated are size 1 to 5*n for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings g = generators.strong_parity_worst_case(i) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: if dir: if v2: (w0, w1) = dirfixwp.partial_solver2(g, lam) # dirfixwp version 2 call else: (w0, w1) = dirfixwp.partial_solver(g, lam) # dirfixwp call else: if v2: (w0, w1) = fixwp.partial_solver2(g, lam) # fixwp version 2 call else: (w0, w1) = fixwp.partial_solver(g, lam) # fixwp call temp.append(chrono.interval) # add time recording min_recording = min(temp) total_time += min_recording percent_solved = ((float(len(w0)) + len(w1)) /(i*5)) * 100 #checking if completely solved if percent_solved != 100: not_comp_solved.append((g, w0, w1)) y_temp.append(min_recording) # get the minimum out of #iterations recordings n_temp.append(5 * i) per_sol_temp.append(percent_solved) if prt: print "Worst-case graph".center(40) + "|" + str(i * 5).center(12) + "|" \ + str(y_temp[nbr_generated]).center(40) + "|" + str(percent_solved).center(19) + "|" + "\n" + "-" * 115 nbr_generated += 1 # updating the number of generated mesures y.append(y_temp) n_.append(n_temp) per_sol.append(per_sol_temp) # at the end, print total time if prt: print "-" * 115 + "\n" + "Total (s)".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "|" + "\n" + "-" * 115 + "\n" if plot: i = 0 for lam in range(start_lambda, end_lambda + 1, step_lambda): fig, ax1 = plt.subplots() plt.grid(True) plt.title(u"Graphes pires cas de taille 1 à " + str(5*n) + " avec lambda = " + str(lam)) plt.xlabel(u'nombre de nœuds') # plt.yscale("log") allows logatithmic y-axis ax1.plot(n_[i], y[i], 'g.', label=u"Temps d'exécution", color='b') ax1.tick_params('y', colors='b') ax1.set_ylabel("Temps d'execution (s)", color = 'b') ax2 = ax1.twinx() ax2.plot(n_[i], per_sol[i], 'g.', label=u"Pourcentage résolu", color='r') ax2.set_ylim([0, 101]) ax2.set_ylabel("Pourcentage du jeu resolu (%)", color = 'r') ax2.tick_params('y', colors='r') fig.tight_layout() plt.savefig(path+str(lam)+".png", bbox_inches='tight') plt.clf() plt.close() i = i + 1 #save the percent solve for each player for each lambda for each size of game in a txt file if save_res: i = 0 for lam in range(start_lambda, end_lambda + 1, step_lambda): #computing the percent solved for each player for the games not solved completely part_solv = 0 comp_solv = 0 percent_solv = [] for (g, w0, w1) in not_comp_solved: #one more game not solved completely part_solv += 1 #checking is the solutions are included to the true solutions. Computing the true sols with Zielonka algorithm (sp_w0, sp_w1) = sp(g) a = all(s in sp_w1 for s in w1) #cheking if included b = all(s in sp_w0 for s in w0) #cheking if included #if not included stop the algorithm if not a or not b: print "Error the solutions found are not included to the true solutions" return -1 #total percentage solved percent_solved_total = ((float(len(w0)) + len(w1)) /(len(sp_w0) + len(sp_w1))) * 100 #percentage solved for player 0 if len(sp_w0) > 0: percent_solved_0 = (float(len(w0)) /len(sp_w0)) * 100 else: percent_solved_0 = 100 #percentage solved for player 1 if len(sp_w1) > 0: percent_solved_1 = (float(len(w1)) /len(sp_w1)) * 100 else: percent_solved_1 = 100 #adding the percentages computed to the list + the size of the game percent_solv.append((len(g.get_nodes()), percent_solved_total, percent_solved_0, percent_solved_1)) comp_solv += 5*n/step - len(not_comp_solved) io.write_benchmark_partial_solver(comp_solv, part_solv, percent_solv, path_res+"_"+str(lam)+".txt", n_[i], y[i], 5*n, 1, lam, False, "")
def benchmark_random_wp(n, start_lambda = 1, end_lambda = 10, step_lambda = 1, dir = True, v2 = False, iterations=3, step=10, ret = False, plot=False, path="", prt = True): """ Benchmarks the window parity algorithms for strong parity games using the random game generator. Calls window parity partial solver on games generated using the random game generator function. Games of size 1 to n are solved and a timer records the time taken to get the solution.The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result can be plotted using matplotlib. :param n: number of nodes in generated graph (nodes is n due to construction). :param end_lambda: maximum value of lambda. :param start_lambda: starting value of lambda. :param step_lambda: step to be taken between the different value of lambda. :param dir: if True, uses DirFixWP if not, uses FixWP. :param v2: if True, uses partial_solver2. If False, uses partial_solver. :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param ret: if True, return the winning region of the games that were not completely solved. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. :param prt: True if the prints are activated. :return: Percentage of game solved, size of the games such that we return the time taken to resolve those games. """ y = [] # list for the time recordings n_ = [] # list for the x values (1 to n) per_sol = [] # list for the percentage of the game solved total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s)" # info about the current benchmark lam = start_lambda #current lambda used by the algorithme not_comp_solved = [] #store the game that are not completely solved # print first line of output if prt: print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "|" + "Percentage solved".center(19) + "|" + "\n" + \ "-" * 115 #for each value of lambda for lam in range(start_lambda, end_lambda + 1, step_lambda): #print current value of lambda if prt: print "lambda value : ".center(40) + str(lam) + "\n" + "-" * 115 y_temp = [] # stores time recordings for the current value of lambda n_temp = [] # stores the size of the game for the current value of lambda per_sol_temp = [] #stores the resolution percentage of the games for the current value of lambda nbr_generated = 0 # games generated are size 1 to n for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings prio = randint(0, i) # number of priorities min_out = randint(1, i) # minimum number of out edges max_out = randint(min_out, i) #maximum number of out edges g = generators.random(i, prio, min_out, max_out) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: if dir: if v2: (w0, w1) = dirfixwp.partial_solver2(g, lam) # dirfixwp version 2 call else: (w0, w1) = dirfixwp.partial_solver(g, lam) # dirfixwp call else: if v2: (w0, w1) = fixwp.partial_solver2(g, lam) # fixwp version 2 call else: (w0, w1) = fixwp.partial_solver(g, lam) # fixwp call temp.append(chrono.interval) # add time recording min_recording = min(temp) percent_solved = ((float(len(w0)) + len(w1)) /(i)) * 100 #checking if completely solved if percent_solved != 100: not_comp_solved.append((g, w0, w1)) y_temp.append(min_recording) # get the minimum out of #iterations recordings n_temp.append(i) per_sol_temp.append(percent_solved) total_time += min_recording if prt: print "Random graph".center(40) + "|" + str(i).center(12) + "|" \ + str(y_temp[nbr_generated]).center(40) + "|" + str(percent_solved).center(19) + "|" + "\n" + "-" * 115 nbr_generated += 1 # updating the number of generated mesures y.append(y_temp) n_.append(n_temp) per_sol.append(per_sol_temp) # at the end, print total time if prt: print "-" * 115 + "\n" + "Total (s)".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "|" + "\n" + "-" * 115 + "\n" if plot: i = 0 for lam in range(start_lambda, end_lambda + 1, step_lambda): fig, ax1 = plt.subplots() plt.grid(True) plt.title(u"Graphes aléatoires de taille 1 à " + str(n) + " avec lambda = " + str(lam)) plt.xlabel(u'nombre de nœuds') # plt.yscale("log") allows logatithmic y-axis ax1.plot(n_[i], y[i], 'g.', label=u"Temps d'exécution", color='b') ax1.tick_params('y', colors='b') ax1.set_ylabel("Temps d'execution (s)", color = 'b') ax2 = ax1.twinx() ax2.plot(n_[i], per_sol[i], 'g.', label=u"Pourcentage résolu", color='r') ax2.set_ylim([0, 101]) ax2.set_ylabel("Pourcentage du jeu resolu (%)", color = 'r') ax2.tick_params('y', colors='r') fig.tight_layout() plt.savefig(path+str(lam)+".png", bbox_inches='tight') plt.clf() plt.close() i = i + 1 if ret: return (not_comp_solved, (n_, y))
def compare_algorithms3(algo1, algo2, algo3, generator, n, preprocess1=None, preprocess2=None, preprocess3=None, iterations=3, step=10, plot=False, path="", title="Comparison", label1="Algorithm 1", label2="Algorithm2", label3="Algorithm3"): """ Benchmarks the recursive algorithm for strong parity games using the worst case generator which yields an exponential complexity. Calls strong parity solver on games generated using the worst case generator function. Games of size 5 to 5*n are solved and a timer records the time taken to get the solution.The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result can be plotted using matplotlib. :param n: number of nodes in generated graph (nodes is 5*n due to construction). :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. """ y1 = [] # list for the time recordings of algorithm 1 n1 = [] # list for the x values of algorithm 1 y2 = [] # list for the time recordings of algorithm 2 n2 = [] # list for the x values of algorithm 2 y3 = [] # list for the time recordings of algorithm 3 n3 = [] # list for the x values of algorithm 3 chrono = timer.Timer(verbose=False) # Timer object # games generated are size 1 to n for i in range(5, n, step): temp1 = [] # temp list for #iterations recordings of algorithm 1 g1 = generator(i) # game generation g2 = copy.deepcopy(g1) g3 = copy.deepcopy(g1) if preprocess1 is not None: g1 = preprocess1(g1) # #iterations calls to the solver are timed for j in range(iterations): with chrono: solution_regular = algo1(g1) temp1.append(chrono.interval) # add time recording min_recording = min(temp1) y1.append( min_recording) # get the minimum out of #iterations recordings n1.append(i) if preprocess2 is not None: g2 = preprocess2(g2) g2, nbr_nodes = transform_graph_into_c_spec(g2) temp2 = [] # #iterations calls to the solver are timed for j in range(iterations): with chrono: #algo2(u[0],u[1],u[2],u[3]) # solver call solution_symbolic = algo2(g2, nbr_nodes, 0) temp2.append(chrono.interval) # add time recording min_recording = min(temp2) y2.append( min_recording) # get the minimum out of #iterations recordings n2.append(i) temp3 = [] # temp list for #iterations recordings of algorithm 1 if preprocess3 is not None: g3 = preprocess3(g3) # #iterations calls to the solver are timed for j in range(iterations): with chrono: solution_third = algo3(g3) temp3.append(chrono.interval) # add time recording min_recording = min(temp3) y3.append( min_recording) # get the minimum out of #iterations recordings n3.append(i) #print("symb "+str(solution_symbolic[0])+" "+str(solution_symbolic[1])) #print("reg "+str(solution_regular[0])+" "+str(solution_regular[1])) if plot: plt.grid(True) plt.title(title) plt.xlabel(u'number of nodes') plt.ylabel(u'time') # plt.yscale("log") allows logatithmic y-axis points, = plt.plot(n1, y1, 'g.', label=label1) points2, = plt.plot(n2, y2, 'r.', label=label2) points3, = plt.plot(n3, y3, 'b.', label=label3) plt.legend(loc='upper left', handles=[points, points2, points3]) plt.savefig(path, bbox_inches='tight') plt.clf() plt.close()
def benchmark_random_wc(n, iterations=3, step=10, ret = False, plot=False, path="", prt = True): """ Benchmarks the window parity algorithms for strong parity games using the random game generator. Calls window parity partial solver on games generated using the random game generator function. Games of size 1 to n are solved and a timer records the time taken to get the solution.The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result can be plotted using matplotlib. :param n: number of nodes in generated graph (nodes is n due to construction). :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param ret: if True, return the winning region of the games that were not completely solved. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. :param prt: True if the prints are activated. """ y = [] # list for the time recordings n_ = [] # list for the x values (1 to n) per_sol = [] # list for the percentage of the game solved total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s)" # info about the current benchmark not_comp_solved = [] #store the game that are not completely solved # print first line of output if prt: print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "|" + "Percentage solved".center(19) + "|" + "\n" + \ "-" * 115 # games generated are size 1 to n for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings prio = randint(0, i) # number of priorities min_out = randint(1, i) # minimum number of out edges max_out = randint(min_out, i) #maximum number of out edges g = generators.random(i, prio, min_out, max_out) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: (w0, w1) = winningcore.partial_solver(g) # winning core call temp.append(chrono.interval) # add time recording min_recording = min(temp) percent_solved = ((float(len(w0)) + len(w1)) /(i)) * 100 if percent_solved != 100: not_comp_solved.append((g, w0, w1)) y.append(min_recording) # get the minimum out of #iterations recordings n_.append(i) per_sol.append(percent_solved) total_time += min_recording if prt: print "Random graph".center(40) + "|" + str(i).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "|" + str(percent_solved).center(19) + "|" + "\n" + "-" * 115 nbr_generated += 1 # updating the number of generated mesures
def benchmark_worst_case(n, iterations=3, step=10, plot=False, path=""): """ Benchmarks the recursive algorithm for strong parity games using the worst case generator which yields an exponential complexity. Calls strong parity solver on games generated using the worst case generator function. Games of size 5 to 5*n are solved and a timer records the time taken to get the solution.The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result can be plotted using matplotlib. :param n: number of nodes in generated graph (nodes is 5*n due to construction). :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. """ y = [] # list for the time recordings n_ = [] # list for the x values (5 to 5n) total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s)" # info about the current benchmark # print first line of output print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "\n" + \ "-" * 108 # games generated are size 1 to n for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings g = generators.strong_parity_worst_case(i) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: strong_parity_solver(g) # solver call temp.append(chrono.interval) # add time recording min_recording = min(temp) y.append( min_recording) # get the minimum out of #iterations recordings n_.append(5 * i) total_time += min_recording print "Worst-case graph".center(40) + "|" + str(i * 5).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "\n" + "-" * 108 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time print "-" * 108 + "\n" + "Total (s)".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "\n" + "-" * 108 + "\n" if plot: plt.grid(True) plt.title(u"Graphes 'pire cas' de taille 5 à " + str(5 * n)) plt.xlabel(u'nombre de nœuds') plt.ylabel(u'temps (s)') # plt.yscale("log") allows logatithmic y-axis points, = plt.plot(n_, y, 'g.', label=u"Temps d'exécution") plt.legend(loc='upper left', handles=[points]) plt.savefig(path, bbox_inches='tight') plt.clf() plt.close()
def benchmark_worst_case_removed_optimization(n, iterations=3, step=10, plot=False, path=""): """ Analyzes the influence of the removed list optimization on the recursive algorithm for worst-case graphs. :param n: number of nodes in generated graph (nodes is 5*n due to construction). :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. """ y = [] # list for the time recordings n_ = [] # list for the x values (5 to 5n) y2 = [] # list for the time recordings n_2 = [] # list for the x values (5 to 5n) total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s)" # info about the current benchmark # print first line of output print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "\n" + \ "-" * 108 # games generated are size 1 to n for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings g = generators.strong_parity_worst_case(i) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: strong_parity_solver(g) # solver call temp.append(chrono.interval) # add time recording min_recording = min(temp) y.append( min_recording) # get the minimum out of #iterations recordings n_.append(5 * i) total_time += min_recording temp = [] # #iterations calls to the solver are timed for j in range(iterations): removed = bitarray([False] + ([False] * len(g.nodes))) with chrono: strong_parity_solver_non_removed(g, removed) # solver call temp.append(chrono.interval) # add time recording min_recording = min(temp) y2.append( min_recording) # get the minimum out of #iterations recordings n_2.append(5 * i) min_recording = min(temp) print "Worst-case graph".center(40) + "|" + str(i * 5).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "\n" + "-" * 108 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time print "-" * 108 + "\n" + "Total (s)".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "\n" + "-" * 108 + "\n" if plot: plt.grid(True) plt.title( u"Recursive algorithm runtime comparison : worst-case graphs of size 1 to " + str(5 * n)) plt.xlabel(u'number of nodes') plt.ylabel(u'time (s)') # plt.yscale("log") allows logatithmic y-axis points, = plt.plot(n_, y, 'g.', label=u"Regular") points2, = plt.plot(n_2, y2, 'r.', label=u"Without sub-game construction") plt.legend(loc='upper left', handles=[points, points2]) plt.savefig(path, bbox_inches='tight') plt.clf() plt.close()
def benchmark_random_reduction(n, iterations=3, step=10, plot=False, path=""): """ Benchmarks the reduction to safety algorithm for strong parity games using a random generator. Games of size 1 to n are solved and a timer records the time taken to get the solution. The solver can be timed several times and the minimum value is selected using optional parameter iterations (to avoid recording time spikes and delays due to system load). The result can be plotted using matplotlib. :param n: number of nodes in generated graph. :param iterations: number of times the algorithm is timed (default is 3). :param step: step to be taken in the generation. :param plot: if True, plots the data using matplotlib. :param path: path to the file in which to write the result. """ y = [] # list for the time recordings n_ = [] # list for the x values total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve" # info about the current benchmark # print first line of output print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "\n" + \ "-" * 108 # games generated are size 1 to n for i in range(5, n + 1, step): temp = [] # temp list for #iterations recordings g = generators.random(i, i, 1, (i / 2)) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: reduction_to_safety_parity_solver(g) # solver call temp.append(chrono.interval) # add time recording min_recording = min(temp) y.append( min_recording) # get the minimum out of #iterations recordings n_.append(i) total_time += min_recording print "Random graphs".center(40) + "|" + str(i).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "\n" + "-" * 108 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time print "-" * 108 + "\n" + "Total time".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "\n" + "-" * 108 + "\n" if plot: plt.grid(True) plt.title(u"Random graphs of size 1 to " + str(n)) plt.xlabel(u'number of nodes') plt.ylabel(u'time (s)') points, = plt.plot(n_, y, 'g.', label=u"Execution time") plt.legend(loc='upper left', handles=[points]) plt.savefig(path, bbox_inches='tight') plt.clf() plt.close()
def benchmark_complete_targetset(n, iterations=3, step=10, plot=False, regression=False, path=""): """ Unused. This was made to compare execution time between players on graphs where the target set is the set of nodes. Calls reachability solver for player 1 on complete graphs where the target set is the set of all nodes. This makes the algorithm add all nodes to the queue and all predecessor lists are iterated over. Games of size 1 to n by step of #step are solved and a timer records the time taken to get the solution. The solver can be timed several times and the minimum value is selected depending on the value of optional parameter iterations (to avoid recording time spikes and delays due to system load). Time to solve the game is recorded and printed to the console in a formatted way. The result can be plotted using matplotlib. :param n: number of nodes in generated graph. :param iterations: number of times the algorithm is timed (default is 3). :param step: step between two sizes of graphs generated. :param plot: if True, plots the data using matplotlib. :param regression: if True, plots a polynomial regression. :param path: path to the file in which to write the result. """ y = [] # list for the time recordings n_ = [] # list for the x values (1 to n) total_time = 0 # accumulator to record total time nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object info = "Time to solve (s), player " + str( 1) + ", target set : V" # info about the current benchmark # print first line of output print u"Generator".center(40) + "|" + u"Nodes (n)".center(12) + "|" + info.center(40) + "\n" + \ "-" * 108 # games generated are size 1 to n for i in range(1, n + 1, step): temp = [] # temp list for #iterations recordings g = generators.complete_graph(i) # generated game # #iterations calls to the solver are timed target = range(1, i + 1) # target set is the set of all nodes for j in range(iterations): with chrono: reachability_solver(g, target, 1) # solver call temp.append(chrono.interval) # add time recording min_recording = min(temp) y.append( min_recording) # get the minimum out of #iterations recordings n_.append(i) total_time += min_recording print "Complete graph".center(40) + "|" + str(i).center(12) + "|" \ + str(y[nbr_generated]).center(40) + "\n" + "-" * 108 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time print "-" * 108 + "\n" + "Total time".center(40) + "|" + "#".center(12) + "|" + \ str(total_time).center(40) + "\n" + "-" * 108 + "\n" if plot: plt.grid(True) plt.title(u"Graphes complets de taille 1 à " + str(n)) plt.xlabel(u'nombre de nœuds') plt.ylabel(u'temps (s)') if regression: coeficients = np.polyfit(n_, y, 2) polynom = np.poly1d(coeficients) points, = plt.plot(n_, y, 'g.', label=u"Temps d'exécution,\nensemble cible : V") fit, = plt.plot(n_, polynom(n_), 'b--', label=u"Régression polynomiale de degré 2") plt.legend(loc='upper left', handles=[points, fit]) else: points, = plt.plot(n_, y, 'g.', label=u"Temps d'exécution,\nensemble cible : V") plt.legend(loc='upper left', handles=[points]) plt.savefig(path + "complete_graph" + "_" + str(n) + "nodes_targetallnodes" + ".png", bbox_inches='tight') plt.clf() plt.close()
def benchmark_worst_case(n, iterations=3, step=10, plot=False, regression=False, path=""): """ Unused. This was made to compare execution time between players on worst case graphs. Calls reachability solver for both players and target set [1] on games generated using the worst case graph generator. Games of size 1 to n by step of #step are solved and a timer records the time taken to get the solution. The solver can be timed several times and the minimum value is selected depending on the value of optional parameter iterations (to avoid recording time spikes and delays due to system load). Time to solve the game for both players is recorded and printed to the console in a formatted way. Both results can be plotted using matplotlib. :param n: number of nodes in generated graph. :param iterations: number of times the algorithm is timed (default is 3). :param step: step between two sizes of graphs generated. :param plot: if True, plots the data using matplotlib. :param regression: if True, plots a polynomial regression. :param path: path to the file in which to write the result. """ y_p0 = [] # list for the time recordings of player 0 y_p1 = [] # list for the time recordings of player 1 acc_p0 = 0 # accumulator for total time of player 0 acc_p1 = 0 # accumulator for total time of player 1 n_ = [] # list for the x values (1 to n) nbr_generated = 0 # conserving the number of generated mesures (used to get the index of a mesure) chrono = timer.Timer(verbose=False) # Timer object # print first line of output print u"Generator".center(30) + "|" + u"Nodes (n)".center(12) + "|" + "Edges (m)".center(10) + "|" \ + u"Time to solve, player 0".center(28) + "|" + u"Time to solve, player 1".center(28) + "\n" + \ "-" * 108 # games generated are size 1 to n for i in range(1, n + 1, step): temp_p0 = [] # temp list for #iterations recordings player 0 temp_p1 = [] # temp list for #iterations recordings player 0 g = generators.reachability_worst_case(i) # generated game # #iterations calls to the solver are timed for j in range(iterations): with chrono: (W_0, sigma_0), (W_1, sigma_1) = reachability_solver( g, [1], 0) # solver call player 0 temp_p0.append(chrono.interval) # add time recording for j in range(iterations): with chrono: (W_1, sigma_1), (W_0, sigma_0) = reachability_solver( g, [1], 1) # solver call player 1 temp_p1.append(chrono.interval) # add time recording min_recording_p0 = min(temp_p0) y_p0.append( min_recording_p0 ) # get the minimum out of #iterations recordings of player 0 acc_p0 += min_recording_p0 min_recording_p1 = min(temp_p1) y_p1.append( min_recording_p1 ) # get the minimum out of #iterations recordings of player 1 acc_p1 += min_recording_p1 n_.append(i) print "Worst-case graph".center(30) + "|" + str(i).center(12) + "|" + str((i * (i + 1)) / 2).center(10) \ + "|" + str(y_p0[nbr_generated]).center(28) + "|" + str(y_p1[nbr_generated]).center(28) + "\n" + "-" * 108 nbr_generated += 1 # updating the number of generated mesures # at the end, print total time print "-" * 108 + "\n" + "Total time".center(30) + "|" + "#".center(12) + "|" + "#".center(10) + "|" + \ str(acc_p0).center(28) + "|" + str(acc_p1).center(28) + "\n" + "-" * 108 + "\n" if plot: if regression: plt.grid(True) plt.title(u"Graphes 'pire cas' de taille 1 à " + str(n)) plt.xlabel(u'nombre de nœuds') plt.ylabel(u'temps (s)') coeficients = np.polyfit(n_, y_p0, 2) polynom = np.poly1d(coeficients) points0, = plt.plot( n_, y_p0, 'g.', label=u"Temps d'exécution, joueur 0,\nensemble cible {v1}") fit0, = plt.plot(n_, polynom(n_), 'b--', label=u"Régression polynomiale de degré 2") plt.legend(loc='upper left', handles=[points0, fit0]) plt.savefig(path + "worstCase_" + str(n) + "nodes_player0.png", bbox_inches='tight') plt.clf() plt.close() plt.grid(True) plt.title(u"Graphes 'pire cas' de taille 1 à " + str(n)) plt.xlabel(u'nombre de nœuds') plt.ylabel(u'temps (s)') coeficients = np.polyfit(n_, y_p1, 1) polynom = np.poly1d(coeficients) points1, = plt.plot( n_, y_p1, 'g.', label=u"Temps d'exécution, joueur 1,\nensemble cible {v1}") fit1, = plt.plot( n_, polynom(n_), 'b--', label=u"Régression linéaire" ) # \\\\"+str(coeficients[0])+u"$x^2 +$"+str(coeficients[1])+u"x +"+str(coeficients[2])) plt.legend(loc='upper left', handles=[points1, fit1]) plt.savefig(path + "worstCase_" + str(n) + "nodes_player1.png", bbox_inches='tight') plt.clf() plt.close() else: plt.grid(True) plt.title(u"Graphes pire cas de taille 1 à " + str(n)) plt.xlabel(u'nombre de nœuds') plt.ylabel(u'temps (s)') points0, = plt.plot( n_, y_p0, 'g.', label=u"Temps d'exécution, joueur 0,\nensemble cible {v1}") plt.legend(loc='upper left', handles=[points0]) plt.savefig(path + "worstCase_" + str(n) + "nodes_player0.png", bbox_inches='tight') plt.clf() plt.close() plt.grid(True) plt.title(u"Graphes pire cas de taille 1 à " + str(n)) plt.xlabel(u'nombre de nœuds') plt.ylabel(u'temps (s)') points1, = plt.plot( n_, y_p1, 'g.', label=u"Temps d'exécution, joueur 1,\nensemble cible {v1}") plt.legend(loc='upper left', handles=[points1]) plt.savefig(path + "worstCase_" + str(n) + "nodes_player1.png", bbox_inches='tight') plt.clf() plt.close()