-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1195876
Showing
4 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# charlie_o_mat | ||
Calculating possible results for ifsc combined competitions \ | ||
Uses brute force approach to get possible rankings based on all possible permutations of the last discipline, lead |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Thu Nov 28 16:19:32 2019 | ||
@author: juliaschopp | ||
""" | ||
|
||
import pandas as pd | ||
from itertools import permutations | ||
|
||
|
||
def create_leaderboard(competitors): | ||
""" | ||
Input: a list of competitors (str) | ||
Output: An empty leaderboard (pd Data Frame) with all rankings set to 1. | ||
""" | ||
leaderboard = pd.DataFrame() | ||
possible_placements = [(i+1) for i in list(range(len(competitors)))] | ||
disciplines = ['Speed', 'Boulder', 'Lead'] | ||
leaderboard['Name'] = competitors | ||
for discipline in disciplines: | ||
leaderboard[discipline] = [1 for i in possible_placements] | ||
leaderboard['Score'] = leaderboard.Speed * leaderboard.Boulder * leaderboard.Lead | ||
leaderboard['Rank'] = leaderboard['Score'].rank(method='min') | ||
leaderboard = leaderboard.set_index('Rank') | ||
return leaderboard | ||
|
||
def update_ranking(leaderboard): | ||
""" | ||
Input: the current leaderboard (pd df) | ||
Output: the current leaderboard with scores and rankings updated (pd df) | ||
""" | ||
leaderboard['Score'] = leaderboard.Speed * leaderboard.Boulder * leaderboard.Lead | ||
leaderboard['Rank'] = leaderboard['Score'].rank(method='min') | ||
leaderboard = leaderboard.set_index('Rank') | ||
leaderboard.sort_index(inplace=True) | ||
return leaderboard | ||
|
||
def update_discipline(discipline, results, leaderboard): | ||
""" | ||
Input: The discipline (str), the results of the discipline (dict of format | ||
name (str): ranking (int)), | ||
the leaderboard that is to be updated (pd Data Frame) | ||
Output: The new ranking (pd Data Frame) | ||
""" | ||
leaderboard = leaderboard.copy() | ||
for (key, value) in results.items(): | ||
leaderboard.loc[leaderboard.Name == key, discipline] = value | ||
new_ranking = update_ranking(leaderboard) | ||
return new_ranking | ||
|
||
def get_all_possible_rankings(ranking_after_boulder, given={}): | ||
""" | ||
Brute force aproach to calculating all possible outcomes after second | ||
discipline. Forms the basis of following analysis and calculation of | ||
probabilities | ||
--- | ||
Inputs: | ||
ranking after boulder (pd df); | ||
optional: a dict of assumed results in Lead {str: int}, default empty | ||
--- | ||
Output: | ||
A list of pd Data Frames with all scenarios of final rankings | ||
with every possible permutation of Lead Results (taking into account the | ||
results in given) | ||
""" | ||
competitors = ranking_after_boulder.Name.tolist() # get a list with competitor names | ||
possible_placements = [(i+1) for i in list(range(len(competitors)))] | ||
scenarios = [] | ||
competitors = list(set(competitors)-set(given.keys())) # remove athletes and positions in "given" | ||
possible_placements = list(set(possible_placements)-set(given.values())) | ||
for i in permutations(possible_placements): # create all possible permutations of ranks | ||
x = {n:p for (n,p) in zip(competitors,i)} # create a result table based on permutation | ||
x ={**x, **given} # add the results from the given dict to those created by permutation | ||
leaderboard = update_discipline('Lead', x, ranking_after_boulder) # update the leaderboard | ||
scenarios.append(leaderboard) # add leaderboard to the list of scenarios | ||
return scenarios | ||
|
||
def still_possible(scenarios, athlete, position, given={}): | ||
""" | ||
Tests if a certain position or better is still achievable for one athlete | ||
after boulder | ||
--- | ||
Input: | ||
- scenarios: A list of all possible rankings | ||
- athlete: name of the competitor/athlete (str) to be tested | ||
- position: which is to be tested (int) | ||
- given (optional): A dict of assumed positions, e.g. because someone has | ||
disqualified or testing assumptions (default: empty) | ||
--- | ||
Output: | ||
- scenarios_ok: list of all possible scenarios in which athlete places equal or | ||
better than the input rank (list of pd dfs) | ||
- percentage: percentage of scenarios for which this is the case | ||
- necessary_positoins_mean: Mean position in lead that was required | ||
for athlete to achieve input rank | ||
- necessary_positions_max: Worst position in lead which still allowed the | ||
athlete to reach input position | ||
""" | ||
scenarios_ok = [] | ||
necessary_positions = [] | ||
for i in scenarios: | ||
if (i.loc[i.Name == athlete].index <= position) \ | ||
and sum([(i.loc[i.Name == k].Lead == v).all() for k,v in given.items()]) == len(given): | ||
#test if scenario fulfills: 1) athlete achieves pos 2) given positions apply | ||
scenarios_ok.append(i) | ||
necessary_positions.append(int(i.loc[i.Name == athlete, 'Lead'])) | ||
percentage = 100 * (len(scenarios_ok) / len(scenarios)) | ||
if len(necessary_positions) > 0: | ||
necessary_positions_mean = round(sum(necessary_positions)/len(necessary_positions), 4) | ||
necessary_positions_max = max(necessary_positions) | ||
else: | ||
necessary_positions_mean = "not possible" | ||
necessary_positions_max = "not possible" | ||
return (scenarios_ok, percentage, necessary_positions_mean, necessary_positions_max) | ||
|
||
|
||
def better_than_possible(scenarios, athletes): | ||
""" | ||
Tests if it is still possible for one athlete to place in front of another | ||
--- | ||
Parameters | ||
---------- | ||
scenarios : list of all possible scenarios | ||
athletes : Tuple or list with the name of two athletes (str), with the pos 0 | ||
the one to come up in front of pos 2 | ||
Returns | ||
------- | ||
scenarios_ok : A list of scenarios for which the first athlete positions better | ||
or equal than the second. | ||
percentage : percentage of scenarios for which the condition holds | ||
necessary_positions_mean : mean of the position which athlete 1 has to achieve | ||
to end up in front of the second one | ||
necessary_positions_max : worst possible position that athl. 1 can end up in to | ||
land in front of athlete 2 | ||
""" | ||
scenarios_ok = [] | ||
necessary_positions = [] | ||
for i in scenarios: | ||
if i.loc[i.Name == athletes[0]].index <= i.loc[i.Name == athletes[1]].index: | ||
scenarios_ok.append(i) | ||
necessary_positions.append(int(i.loc[i.Name == athletes[0], 'Lead'])) | ||
percentage = 100 * (len(scenarios_ok) / len(scenarios)) | ||
if len(necessary_positions) > 0: | ||
necessary_positions_mean = round(sum(necessary_positions)/len(necessary_positions), 4) | ||
necessary_positions_max = max(necessary_positions) | ||
else: | ||
necessary_positions_mean = "not possible" | ||
necessary_positions_max = "not possible" | ||
return (scenarios_ok, percentage, necessary_positions_mean, necessary_positions_max) | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Thu Apr 30 19:51:22 2020 | ||
@author: juliaschopp | ||
""" | ||
|
||
# Simulate full round of finals | ||
import pandas as pd | ||
from itertools import permutations | ||
import time | ||
from combined import * | ||
|
||
# --- Competitor and results variables --- | ||
|
||
competitors = ['Mori', 'Condie', 'Rakovec', 'Kaplina', 'Krampel', 'Rogora',\ | ||
'Charnoudie', 'Ito'] | ||
result_dict = {y:x for x,y in dict(enumerate(competitors)).items()} | ||
|
||
speed_results = {'Mori': 8, | ||
'Condie': 2, | ||
'Rakovec': 6, | ||
'Kaplina': 1, | ||
'Krampel': 7, | ||
'Rogora': 5, | ||
'Charnoudie': 3, | ||
'Ito': 4} | ||
|
||
boulder_results = {'Mori': 2, | ||
'Condie': 6, | ||
'Rakovec': 3, | ||
'Kaplina': 8, | ||
'Krampel': 7, | ||
'Rogora': 4, | ||
'Charnoudie': 5, | ||
'Ito': 1} | ||
|
||
lead_results = {'Mori': 3, | ||
'Condie': 7, | ||
'Rakovec': 2, | ||
'Kaplina': 8, | ||
'Krampel': 1, | ||
'Rogora': 4, | ||
'Charnoudie': 2, | ||
'Ito': 6} | ||
|
||
# --- Model leaderboards | ||
|
||
empty_leaderboard = create_leaderboard(competitors) | ||
|
||
ranking_after_speed = update_discipline('Speed', speed_results, empty_leaderboard) | ||
|
||
ranking_after_boulder = update_discipline('Boulder', boulder_results, ranking_after_speed) | ||
|
||
ranking_after_lead = update_discipline('Lead', lead_results, ranking_after_boulder) | ||
|
||
|
||
# --- Create scenarios and calculate probabilities | ||
|
||
given = {} | ||
|
||
athletes = ('Mori', 'Rakovec') | ||
|
||
m1 = time.perf_counter() | ||
|
||
scenarios = get_all_possible_rankings(ranking_after_boulder) | ||
|
||
m2 = time.perf_counter() | ||
|
||
(scenarios_ok, percentage, necessary_positions_mean, necessary_positions_max) = \ | ||
still_possible(scenarios, "Condie", 1) | ||
|
||
m3 = time.perf_counter() | ||
|
||
(test_scenarios, test_percentage, test_necessary_positions_mean, max_position) = \ | ||
better_than_possible(scenarios, athletes) | ||
|
||
m4 = time.perf_counter() | ||
|
||
print("A random scenario: ", scenarios[7]) | ||
print("Necessary_positions_mean for Condie to win: ", necessary_positions_mean) | ||
print("Probability that Mori places in front of Rakovec: ", test_percentage) | ||
print("Time to calc scenarios: {m2-m1:0.4f} seconds") | ||
print("Time to calc still_possible: {m3-m2:0.4f} seconds") | ||
print("Time to calculate better_than: {m4-m3:0.4f} seconds") | ||
print("Total runtime: {m4-m1:0.4f} seconds") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Thu Apr 30 12:59:23 2020 | ||
@author: juliaschopp | ||
""" | ||
|
||
# Simulate test comp with 4 athletes | ||
import pandas as pd | ||
from itertools import permutations | ||
|
||
from combined import * | ||
|
||
# --- Competitor and results variables --- | ||
|
||
competitors = ['Mori', 'Condie', 'Rakovec', 'Kaplina'] | ||
result_dict = {y:x for x,y in dict(enumerate(competitors)).items()} | ||
|
||
speed_results = speed_results = {'Mori': 4, | ||
'Condie': 2, | ||
'Rakovec': 3, | ||
'Kaplina': 1} | ||
|
||
boulder_results = {'Mori': 3, | ||
'Condie': 1, | ||
'Rakovec': 2, | ||
'Kaplina': 4} | ||
|
||
lead_results = {'Mori': 1, | ||
'Condie': 2, | ||
'Rakovec': 3, | ||
'Kaplina': 4} | ||
|
||
# --- Model leaderboards | ||
|
||
empty_leaderboard = create_leaderboard(competitors) | ||
|
||
ranking_after_speed = update_discipline('Speed', speed_results, empty_leaderboard) | ||
|
||
ranking_after_boulder = update_discipline('Boulder', boulder_results, ranking_after_speed) | ||
|
||
ranking_after_lead = update_discipline('Lead', lead_results, ranking_after_boulder) | ||
|
||
|
||
# --- Create scenarios and calculate probabilities | ||
|
||
given = {'Kaplina': 4} | ||
|
||
athletes = ('Mori', 'Rakovec') | ||
|
||
scenarios = get_all_possible_rankings(ranking_after_boulder) | ||
|
||
(scenarios_ok, percentage, necessary_positions_mean, necessary_positions_max) = \ | ||
still_possible(scenarios, "Condie", 3, given) | ||
|
||
(test_scenarios, test_percentage, test_necessary_positions_mean, max_position) = \ | ||
better_than_possible(scenarios, athletes) | ||
|
||
print("necessary_positions_mean: ", necessary_positions_mean) | ||
print("test_percentage: ", test_percentage) | ||
|