[PYTHON] Calculez la solution optimale pour établir un record du monde pour dix types de compétition avec scipy.optimize

introduction

Connaissez-vous le concours appelé "Ten Kinds Competition"? En 2 jours, 10 épreuves de course à pied (100m, 400m, 1500m, 110mH), de saut (course de saut en hauteur, bâton de saut en hauteur, course de saut en longueur), de lancer (lancer d'arme à feu, lancer de disque, lancer de lance) ont été réalisées, et les records de chaque épreuve ont été marqués et le record total C'est une compétition à laquelle participer. Le record du monde actuel (juin 2020) est de 9126 points pour Kevin MAYER.

Au fait, que dois-je faire pour obtenir ce score efficacement? Il semble y avoir une idée de "marquer uniformément dans tous les événements", mais ce n'est pas réaliste. En effet, certains événements permettent de gagner facilement des points et d'autres, il est difficile de gagner des points. Par exemple, le record pour obtenir 900 points dans chaque élément est le suivant. (Pour référence, les records japonais pour chacune des 10 compétitions sont également inclus)

100m 400m 1500m 110mH Courir le saut en hauteur Stick saut en hauteur Long saut Lancer de boulet de canon Lancer de disque Jeter
900 points 10.82 48.19 247.42 14.59 2.10 4.97 7.36 16.79 51.40 70.67
Record japonais pour chacun des dix événements 10.53 47.17 248.24 13.97 2.16 5.30 7.65 15.65 50.23 73.82

Pour obtenir 900 points en lançant une arme à feu ou un disque, il faut battre le record japonais. Ce n’est pas réaliste.

Alors, quel est le moyen le plus simple d'établir un record du monde? Au lieu de n'obtenir que 800 points avec des lancers de balles, obtenons 1000 points dans d'autres épreuves, mais je ne sais pas s'il est plus facile d'obtenir 1000 points en 100m ou 1500m ...

La réponse que j'ai donnée à cette question est ** Le score total minimum sur le "tableau de notation ** (communément appelé tableau hongrois)" ** "**.

Qu'est-ce qu'une table de notation?

Il s'agit d'un tableau créé par la Fédération internationale d'athlétisme (IAAF) qui note les records de chaque élément, et la formule de calcul est différente de celle de la compétition en 10 types. Ceci est fait pour la comparaison par événement, donc vous pouvez l'utiliser comme "Le record de 100m 11.00 (886p) que j'ai fait équivaut à 6m83 (886p) s'il s'agit d'un saut en longueur."

Calculé

Nous avons calculé le "score minimum du 10e événement (restriction: le record de 10 événements dépasse 9126 points)".

Par exemple, disons que vous visez un total de 1000 points dans le deuxième type de 100m et de lancer de balles. Le score total lorsque 500 points sont attribués à chaque épreuve est de 972p, Le score total à 100m14.00 et le lancer de gunball 13.32 est de 945p, et même si le score est le même, il semble que vous puissiez facilement gagner des points. (Le problème réel est différent ...)

Record Dix types de points But : Record Dix types de points But
100m 12.82 500 430 : 14.00 312 221
Lancer de boulet de canon 10.24 500 542 : 13.32 687 724
total 1000 972 : 1000 945

Avec ce genre de sentiment, je cherche comment établir un record du monde avec un petit score.

Méthode de calcul

La méthode d'optimisation utilisée minimiser dans scipy.optimize.

La gamme du record était un score de 1p à un record du monde. (La limite inférieure de l'épreuve sur piste est le record du monde et la limite supérieure de l'épreuve sur le terrain est le record du monde)

100m 400m 1500m 110mH Courir le saut en hauteur Stick saut en hauteur Long saut Lancer de boulet de canon Lancer de disque Jeter
limite inférieure 9.58 43.03 206.00 12.80 0.92 1.16 2.51 1.00 1.57 1.59
limite supérieure 16.79 78.01 380.04 25.43 2.45 6.18 8.95 23.12 74.08 98.48

La formule de calcul du score de la compétition de 10 types est décrite dans [Wikipedia](https://ja.wikipedia.org/wiki/10-kind competition #Score). La formule du tableau de notation n'a pas pu être trouvée officiellement, mais elle semble être calculée à l'aide de la formule ci-dessous.

a × (enregistrement + b) ^ 2 + c (Les coefficients sont listés ci-dessous)

C'est étonnamment simple.

Voici les commandes utilisées dans le calcul.

python


import numpy as np
import pandas as pd
import copy
import sys
from scipy.optimize import minimize, BFGS, LinearConstraint, Bounds
from math import floor
import matplotlib.pyplot as plt

##Facteurs pour le tableau de notation
w_score = np.array([
    [24.64221166,-16.99753156,-0.218662048], #100m
    [1.021013043,-78.99469306,0.0029880052], #400m
    [0.0406599253,-384.9950051,0.001205591], #1500m 
    [7.665206128,-25.79302259,0.0141087786], #110mH
    [32.14570816,11.59368894,-5026.080842],  #HJ
    [3.045719921,39.33586031,-4993.213828],  #PV
    [1.931092873,48.34861905,-4993.807793],  #LJ
    [0.0423461436,684.8281542,-19915.72457], #SP
    [0.0040063129,2232.983411,-20003.52492], #DT
    [0.0024031525,2879.797864,-19950.96836]])#JT

##Dix types de coefficient de concurrence
w_dec = np.array([
    [25.4347,18,1.81],   #100m
    [1.53775,82,1.81],   #400m
    [0.03768,480,1.85],  #1500m
    [5.74352,28.5,1.92], #110mH
    [0.8465,75,1.42],  #HJ
    [0.2797,100,1.35], #PV
    [0.14354,220,1.4], #LJ
    [51.39,1.5,1.05],  #SP
    [12.91,4,1.1],     #DT
    [10.14,7,1.08]])   #JT

##Fonction objectif (tableau de notation)
def calc_score(x):
    total_score = 0
    for i in range(10):
        total_score += w_score[i,0] * (x[i] + w_score[i,1])**2 + w_score[i,2]
    return total_score

##Fonction de contrainte (10 types de score de compétition)
def calc_dec(x):
    n = 0
    total_point = 0
    target_point = 9126

    for i in range(10):
        if i in (0,1,2,3):
            total_point += w_dec[i,0] * (w_dec[i,1] - x[i]) ** w_dec[i,2] #100m, 400m, 1500m, 110mH
        elif i in (4,5,6):
            total_point += w_dec[i,0] * (x[i] *100 - w_dec[i,1]) ** w_dec[i,2] #Courir le saut en hauteur,Long saut,Stick saut en hauteur
        else:
            total_point += w_dec[i,0] * (x[i] - w_dec[i,1]) ** w_dec[i,2] #Lancer de boulet de canon,Lancer de disque,Jeter
        return_point = total_point - target_point
    return return_point

bounds = Bounds(world_rec[0:4] + min_rec[4:10] , min_rec[0:4] + world_rec[4:10])

cons = (
    {'type': 'ineq', 'fun': calc_dec} 
)

x0 = np.array([10, 46.19, 247.42, 13.59, 1.8, 3.5, 6.06, 10.79, 31.40, 53.67]) #La valeur initiale est appropriée

Presque rien n'est décrit sauf pour la création de fonctions. Il est très facile de résoudre le problème d'optimisation avec juste cela ...

résultat

1. 1. Score minimum lors de la réalisation du record du monde (9126 points)

python


result = minimize(calc_score, x0, constraints=cons, method="SLSQP", bounds=bounds)
print(result)
#     fun: 8707.88035324152
#     jac: array([-141.92468262,  -27.99401855,   -5.38891602,  -70.75549316,
#        902.8885498 ,  277.25720215,  221.29797363,   59.95800781,
#         18.4855957 ,   14.31445312])
# message: 'Optimization terminated successfully.'
#    nfev: 569
#     nit: 38
#    njev: 34
#  status: 0
# success: True
#       x: array([ 14.11782497,  65.28575996, 318.7265988 ,  21.17765192,
#         2.45      ,   6.18      ,   8.95      ,  23.12      ,
#        74.08      ,  98.48      ])

100m:14.11 400m:65.28 1500m:318.72 110mH:21.72 Saut en hauteur: 2,45 (record du monde) Saut en hauteur à la barre: 6,18 (record du monde) Saut en longueur: 8,95 (record du monde) Lancer de balle au pistolet: 23,12 (record du monde) Lancer de disque: 74,08 (record du monde) Lancer: 98,48 (record du monde)

Note totale: 8707

Le résultat était! ww Le score augmente de façon exponentielle, donc si vous faites de votre mieux dans un événement sur le terrain avec un taux de croissance élevé Cela signifie-t-il que même si l'épreuve sur piste est appropriée, elle établira un record du monde ...

2. Score minimum lors de l'obtention du record japonais (8308 points)

C'est ennuyeux s'il ne s'agit que du record du monde, alors j'ai aussi essayé la version japonaise. La limite supérieure est «record japonais pour chacun des dix sports».

python


#Seul le résultat est décrit
result = minimize(calc_score, x0, constraints=cons, method="SLSQP", bounds=bounds)
print(result)
#     fun: 8397.295007256867
#     jac: array([-262.33532715,  -58.31018066,   -7.70007324, -130.22009277,
#        884.24414062,  271.89660645,  216.27709961,   59.32495117,
#         18.29467773,   14.19604492])
# message: 'Optimization terminated successfully.'
#    nfev: 521
#     nit: 30
#    njev: 30
#  status: 0
# success: True
#       x: array([ 11.67464597,  50.4396491 , 290.30574658,  17.29878908,
#         2.16      ,   5.3       ,   7.65      ,  15.65      ,
#        50.23      ,  73.82      ])

100m:11.67 400m:50.43 1500m:290.30 110mH:17.29 Saut en hauteur en cours d'exécution: 2,16 (10 types de records japonais) Stick saut en hauteur: 5,30 (10 types de disque japonais) Saut en longueur: 7,65 (10 types de records japonais) Lancer de Gunmaru: 15,65 (10 types de record japonais) Lancer de disque: 50,23 (10 types de disques japonais) Lancer de lance: 73,82 (10 types de record japonais)

Note totale: 8397p

Le résultat était que. La tendance à marquer des points dans les compétitions sur le terrain reste la même ... À propos, le score lorsque le bon joueur a établi un record japonais est de 8609p, donc Avec ce qui précède, il sera possible d'établir efficacement un record japonais d'environ 200p w

prime

Bien que cela n'ait rien à voir avec scipy, j'ai essayé de représenter graphiquement le score des dix types de compétition et la formule de calcul du tableau de notation.

##Sortie graphique
fig, ax = plt.subplots(5, 2, figsize=(14, 25)) 

for i in range(10):
    pltx = np.arange(min(min_rec[i],world_rec[i]), max(min_rec[i],world_rec[i]), 0.01)
    plty = w_score[i,0] * (pltx + w_score[i,1])**2 + w_score[i,2]
    if i in (0,1,2,3):
        plty_p = w_dec[i,0] * (w_dec[i,1] - pltx) ** w_dec[i,2] #100m, 400m, 1500m, 110mH
    elif i in (4,5,6):
        plty_p = w_dec[i,0] * (pltx *100 - w_dec[i,1]) ** w_dec[i,2] #Courir le saut en hauteur,Long saut,Stick saut en hauteur
    else:
        plty_p = w_dec[i,0] * (pltx - w_dec[i,1]) ** w_dec[i,2]
    
    ax[i//2, i%2].set_ylim([0,1400])
    ax[i//2, i%2].plot(pltx, plty, color="blue", label="Scoring")
    ax[i//2, i%2].plot(pltx, plty_p,color="orange", label="Decathlon")
    ax[i//2, i%2].set_title(label[i], size=15)
    ax[i//2, i%2].set_xlabel('Record')
    ax[i//2, i%2].set_ylabel('Score / Point')
    ax[i//2, i%2].axvline(x=world_rec[i], ymin=0, ymax=100, ls="--", color="red", label="World Record")
    ax[i//2, i%2].axvline(x=national_dec_rec[i], ymin=0, ymax=100, ls="--", color="green", label="National Decathlon Record")
    ax[i//2, i%2].grid(which = "major", axis = "both", alpha = 0.8,
        linestyle = "--", linewidth = 0.8)
    ax[i//2, i%2].legend(loc='best')

plt.tight_layout()

img.png

Dans le domaine des scores élevés, j'estime que l'événement sur piste a un score plus faible pour les 10 types de scores que l'événement sur le terrain (= même si un score élevé est donné, il est difficile de se refléter dans le score). J'ai l'impression que vous pouvez comprendre pourquoi nous sommes arrivés à la conclusion que "pour obtenir un score élevé avec le score minimum, obtenir un score élevé sur le terrain". ..

À la fin

scipy.optimize pourrait être utilisé par moi en tant que statisticien amateur. Très pratique ... Nous espérons que cet article augmentera le nombre de personnes (et de personnes intéressées par le concours des 10 types) qui pourront facilement s'attaquer aux problèmes d'optimisation.

Recommended Posts

Calculez la solution optimale pour établir un record du monde pour dix types de compétition avec scipy.optimize
Trouver une solution au problème N-Queen avec un algorithme génétique (2)
Trouver une solution au problème N-Queen avec un algorithme génétique (1)
Écrivez un script pour calculer la distance avec le système Elasticsearch 5 sans douleur
[Apprentissage de Django avec la lame du diable] Comment obtenir un ensemble de requêtes pour une référence avant / arrière
[Introduction à Udemy Python3 + Application] 47. Traitez le dictionnaire avec une instruction for
Un guide pour faire de l'IoT avec MicroPython facilement jusqu'à la dernière minute
Une solution de contournement simple pour que les robots essaient de publier des tweets avec le même contenu
Notez la solution car django n'a pas pu s'installer avec pip
[Introduction à Python] Comment obtenir l'index des données avec l'instruction for
Comment calculer la volatilité d'une marque
Dites bonjour au monde avec Python avec IntelliJ
Enregistrer l'objet dans un fichier avec pickle
Comment définir un dossier partagé avec le système d'exploitation hôte dans CentOS7 sur Virtual BOX
Essayez de créer une table d'enregistrement de bataille avec matplotlib à partir des données de "Schedule-kun"
Trouvez une ligne directrice pour le nombre de processus / threads à définir sur le serveur d'applications
Comment définir l'environnement de développement pour chaque projet avec VSCode + extension Python + Miniconda
Comment créer un sous-menu avec le plug-in [Blender]
Une histoire qui a eu du mal avec l'ensemble commun HTTP_PROXY = ~
Transition vers l'écran de mise à jour avec le Django a tag
Calculer le produit des matrices avec une expression de caractère?
Python> Liste> partitions = [0] * len (all_filepaths) / partitions [: test_set_size] = [1] * Après avoir créé une liste avec test_set_size> 0, définissez la partie avant sur 1.
Définir une tâche pour définir l'environnement de fabric dans YAML
Probablement le moyen le plus simple de créer un pdf avec Python 3
Expérimentez pour créer un PDF indépendant pour Kindle avec Python
La première étape de la création d'une application sans serveur avec Zappa
Créez un Twitter BOT avec le SDK GoogleAppEngine pour Python
Une histoire sur la façon de traiter le problème CORS
La façon habituelle d'ajouter un noyau avec Jupyter Notebook
L'histoire de la définition de la clé privée à 600 avec chmod
Je veux créer un Dockerfile pour le moment.
Essayez de générer une image de veste de type death metal avec DCGAN + grattez le site de base de données de métaux pour cela
"Livre pour former la capacité de programmation à se battre dans le monde" Exemple de solution de code Python --1.6 Compression de chaîne de caractères
"Livre pour former des compétences en programmation pour combattre dans le monde" Exemple de solution de code Python - 1.7 Rotation de matrice
"Un livre pour former les compétences de programmation pour combattre dans le monde" Exemple de solution de code Python --2.8 Détection de boucle
Pour ceux d'entre vous qui ne savent pas comment définir un mot de passe avec Jupyter sur Docker