Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   General Forum (http://www.chiefdelphi.com/forums/forumdisplay.php?f=16)
-   -   OPR (http://www.chiefdelphi.com/forums/showthread.php?t=135182)

KosmicKhaos 25-02-2015 16:12

OPR
 
Does anyone have a an excel document or something where I can plug in match scores and figure out OPR or how I could put an OPR calculator in an Android App

stingray27 25-02-2015 16:20

Re: OPR
 
I will be posting a spreadsheet after Week 1 regarding advanced stats including OPR and a few other metrics.
I have done these spreadsheets the last few years and they can be found here:
http://www.chiefdelphi.com/media/papers/3003
http://www.chiefdelphi.com/media/papers/2967

In addition, I have an app on the google play store called OPRFIRST2014 that was developed to focus specifically on OPR calculations for android. I released the entire source code for it because TheBlueAlliance began to include OPR calculations in their app and it was too hard to gain users with everyone using thebluealliance.com. So feel free to look through here and use the code to calculate OPR. (Although I may warn you, the code may be a little hard to read because I was just beginning android development and this was the first app I created).
https://github.com/mray19027/OPRFIRST2014

The EXACT location of where my OPR calculations take place is here:
https://github.com/mray19027/OPRFIRS...Info.java#L305

saikiranra 25-02-2015 17:38

Re: OPR
 
Ed Law and his team has put together awesome resources for calculating OPR that can be found here.

Calculating OPR isn't actually that hard, although it requires some knowledge about basic linear algebra. Essentially, you are trying to solve a linear system of equations for a certain constant that is what you expect a team to contribute to an alliance each match (OPR). If you have teams a, b, and c playing together in one match, and they score a x amount of points, you are solving

a(OPR) + b(OPR) + c(OPR) = x

As more matches occur, the matrix equations become more complex. In the form of Ax = b, A is the matrix whose values correspond to the amount of matches teams played with each other, x is the OPR vector, and b is the vector of the total score each team made in all the matches they played.

If you don't want to do the hard math/plug in your own match scores, you can use The Blue Alliance's API to get OPRs off their site.

Ether 25-02-2015 19:01

Re: OPR
 
Quote:

Originally Posted by saikiranra (Post 1449844)
b is the vector of the total score each team made in all the matches they played

Not quite.

Each element of |b| corresponds to a team, and the value of that element is the sum of the alliance scores for all alliances that team played with.



GeeTwo 25-02-2015 19:15

Re: OPR
 
Quote:

Originally Posted by saikiranra (Post 1449844)
If you don't want to do the hard math/plug in your own match scores, you can use The Blue Alliance's API to get OPRs off their site.

I don't see the OPR anywhere in their API; am I missing something, or did you just mean that the data required to plug into an OPR calculation is there?

plnyyanks 25-02-2015 19:15

Re: OPR
 
Quote:

Originally Posted by stingray27 (Post 1449820)
I released the entire source code for it because TheBlueAlliance began to include OPR calculations in their app and it was too hard to gain users with everyone using thebluealliance.com

Similarly, you can find the OPR (and DPR, CCWM) calculations done on TBA in this file. The math is based off of this post.

And if you just want to view the data, it is displayed in the TBA Android app, as well (looks like this, but more material. Sorry, old screenshot)

plnyyanks 25-02-2015 19:19

Re: OPR
 
Quote:

Originally Posted by GeeTwo (Post 1449875)
I don't see the OPR anywhere in their API; am I missing something, or did you just mean that the data required to plug into an OPR calculation is there?

The API will return the result of the calculations for OPR, DPR, and CCWM. See here in the docs.

Hit
Code:

/api/v2/event/<event-key>/stats
It'll return an output like:
Spoiler for Lots of data:

Code:

➜  phil@fedora ~  curl --header "X-TBA-App-Id:foo:bar:baz" http://www.thebluealliance.com/api/v2/event/2014cthar/stats
{"oprs": {"558": 61.03862458660732, "571": 25.26315867245658, "1124": 41.56940261999079, "4572": 22.657822140768516, "238": 22.044939318938813, "3146": 12.63390393300261, "178": 46.950456367359891, "177": 92.226404149116206, "4557": 43.334926949271072, "175": 81.334997593159528, "230": 53.027513648529002, "236": 58.096099167356243, "2785": 11.601348126111738, "3555": 7.2284300176004974, "3104": 14.702459074944898, "173": 9.5159523225474345, "839": 19.960465485473357, "2170": 22.066703794171406, "181": 49.492453525796911, "3182": 26.955221924000668, "3634": 34.152969306235953, "4097": 28.571656205234454, "716": 57.420439555814042, "5142": 15.649331351710339, "999": 36.426610246955612, "3525": 50.453711167618096, "5129": 27.586754386014597, "228": 52.10253623902166, "4628": 17.892949898607437, "95": 29.973898403369855, "176": 65.769697919858061, "1991": 53.614388815829997, "4055": 51.617441033456331, "3464": 37.843662949585344, "3566": 31.888458744244957, "4958": 33.821768467384359, "1687": 12.329197344290588, "1740": 7.5272579695618127, "2067": 39.32265324466966}, "ccwms": {"558": 47.714841929054501, "571": -2.2244726240688477, "1124": 32.556983571913001, "4572": -6.0853698077920315, "238": -35.070117174800544, "3146": -36.885966963297193, "178": 14.96298531132085, "177": 71.191849807978272, "4557": -7.7570855600831052, "175": 30.835262590761605, "230": 3.6399453862621081, "236": 20.44387440579483, "2785": -37.350014006119174, "3555": -34.672659512804991, "3104": -28.249324008158332, "173": -37.577530295276226, "839": -19.803791613841952, "2170": -27.524965779988744, "181": 3.7024741266095287, "3182": -8.8673292856880401, "3634": 9.0289537858067348, "4097": -28.403823457387144, "716": 25.671255492674394, "5142": -18.532183768327222, "999": 16.38015834182071, "3525": 27.23416882060123, "5129": -15.548754966962644, "228": 8.7310226121904542, "4628": 7.01561775548765, "95": 5.8413142346092108, "176": 32.851548640364612, "1991": 37.027081101957357, "4055": 13.387511797720734, "3464": 1.4555715944903778, "3566": -15.204361189187283, "4958": -13.407078085909482, "1687": -23.514376735710577, "1740": -21.265070753703672, "2067": 8.2718542816890643}, "dprs": {"558": 13.32378265755275, "571": 27.487631296525407, "1124": 9.0124190480777919, "4572": 28.743191948560586, "238": 57.115056493739317, "3146": 49.519870896299814, "178": 31.987471056039084, "177": 21.034554341137934, "4557": 51.092012509354177, "175": 50.499735002397919, "230": 49.387568262266932, "236": 37.652224761561435, "2785": 48.951362132230891, "3555": 41.901089530405542, "3104": 42.951783083103251, "173": 47.093482617823668, "839": 39.764257099315302, "2170": 49.591669574160193, "181": 45.789979399187374, "3182": 35.822551209688733, "3634": 25.12401552042925, "4097": 56.975479662621588, "716": 31.749184063139648, "5142": 34.181515120037545, "999": 20.046451905134909, "3525": 23.219542347016823, "5129": 43.135509352977216, "228": 43.371513626831245, "4628": 10.877332143119782, "95": 24.13258416876063, "176": 32.918149279493427, "1991": 16.587307713872672, "4055": 38.229929235735582, "3464": 36.388091355095021, "3566": 47.092819933432281, "4958": 47.228846553293849, "1687": 35.843574080001126, "1740": 28.792328723265495, "2067": 31.05079896298054}}


Ether 26-02-2015 11:18

Re: OPR
 
Quote:

Originally Posted by plnyyanks (Post 1449876)
...you can find the OPR (and DPR, CCWM) calculations done on TBA in this file.

Just a minor observation FWIW:

To solve [M][x]=[s], that code uses numpy.linalg.solve which uses LAPACK routine gesv which does LU decomposition.

Since [M] is symmetric positive definite, Cholesky decomposition can be used instead to take advantage of that particular matrix structure.

For OPR computation for single events the difference will likely be negligible, but when computing combined OPR for all events for an entire season Cholesky will be noticeably faster than LU.



plnyyanks 26-02-2015 15:30

Re: OPR
 
Quote:

Originally Posted by Ether (Post 1450136)
Just a minor observation FWIW:

To solve [M][x]=[s], that code uses numpy.linalg.solve which uses LAPACK routine gesv which does LU decomposition.

Since [M] is symmetric positive definite, Cholesky decomposition can be used instead to take advantage of that particular matrix structure.

For OPR computation for single events the difference will likely be negligible, but when computing combined OPR for all events for an entire season Cholesky will be noticeably faster than LU.

Really interesting, thanks for input. This'll be a good offseason hackathon project!

Eugene Fang 26-02-2015 16:23

Re: OPR
 
Quote:

Originally Posted by plnyyanks (Post 1450263)
Really interesting, thanks for input. This'll be a good offseason hackathon project!

It would be a one line change. :p

plnyyanks 26-02-2015 16:44

Re: OPR
 
Quote:

Originally Posted by Eugene Fang (Post 1450294)
It would be a one line change. :p

Low hanging fruit, I call it

saikiranra 26-02-2015 16:46

Re: OPR
 
Quote:

Originally Posted by Eugene Fang (Post 1450294)
It would be a one line change. :p

Code:

x = np.linalg.cho_solve(np.linalg.cho_factor(M) , s)

Ether 27-02-2015 09:05

Re: OPR
 
1 Attachment(s)
Quote:

Originally Posted by saikiranra (Post 1450313)
Code:

x = np.linalg.cho_solve(np.linalg.cho_factor(M) , s)

linalg.cho_factor() and linalg.cho_solve() are in scipy, not numpy.



Attached is a sparse-format "M" matrix generated from this data containing 2,696 teams and 8,921 matches.

Can someone with a Python installation please factor that matrix with LU1 and Cholesky2 and report the times?


1scipy.linalg.lu(M)
2scipy.linalg.cho_factor(M)




Ether 27-02-2015 11:26

Re: OPR
 
Quote:

Originally Posted by plnyyanks (Post 1450311)
Low hanging fruit, I call it

Here's some even tastier fruit:

Code:

Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
>>> import numpy
>>> import time
>>> import scipy
>>> import scipy.sparse
>>> import scipy.sparse.linalg

>>> # Read M & s ...
>>> M = numpy.loadtxt(open('M.dat'))
>>> s = numpy.loadtxt(open('s.dat'))
>>> end = time.time()

>>> # solve...
... start = time.time()
>>> x = numpy.linalg.solve(M,s)
>>> end = time.time()
>>> print "%f seconds" % (end-start)
15.344000 seconds

>>># solve Cholesky...
... start = time.time()
>>> xc = scipy.linalg.cho_solve(scipy.linalg.cho_factor(M),s)
>>> end = time.time()
>>> print "%f seconds" % (end-start)
1.688000 seconds

>>> # Convert to sparse...
... start = time.time()
>>> Msparse = scipy.sparse.csr_matrix(M)
>>> end = time.time()
>>> print "%f seconds" % (end-start)
0.219000 seconds
>>>
>>> # solve sparse...
... start = time.time()
>>> xs = scipy.sparse.linalg.spsolve(Msparse,s)
>>> end = time.time()
>>> print "%f seconds" % (end-start)
0.468000 seconds
>>>

PS: above code was run on single core of 8-year-old Pentium D machine running XP SP3



Spoam 05-03-2015 03:03

Re: OPR
 
Quote:

Originally Posted by saikiranra (Post 1449844)
Ed Law and his team has put together awesome resources for calculating OPR that can be found here.

Calculating OPR isn't actually that hard, although it requires some knowledge about basic linear algebra. Essentially, you are trying to solve a linear system of equations for a certain constant that is what you expect a team to contribute to an alliance each match (OPR). If you have teams a, b, and c playing together in one match, and they score a x amount of points, you are solving

a(OPR) + b(OPR) + c(OPR) = x

As more matches occur, the matrix equations become more complex. In the form of Ax = b, A is the matrix whose values correspond to the amount of matches teams played with each other, x is the OPR vector, and b is the vector of the total score each team made in all the matches they played.

If you don't want to do the hard math/plug in your own match scores, you can use The Blue Alliance's API to get OPRs off their site.

Adding on to this, if anyone truly wants to do the math themselves it's worth mentioning that you'll end up with an over-determined system and a non-invertible matrix. Because of this, |Ax-b|=0 probably doesn't exist (every robot would have to contribute the exact same amount of points every match for that to happen) and you have to settle for minimizing |Ax-b| instead. This is done via a formula called linear least squares, which is essentially just left-multiplying both sides by the pseudo-inverse of A, to pseudo-solve it, if you will.

I think it's useful to understand how OPR works too, because often OPR alone often poorly models the game, or the game includes nonlinear (bins this year) or irrelevant (foul points last year) elements which get lumped into naive OPR equations anyways. You should understand what you're looking at before you take a list of teams ranked by OPR at face value.


All times are GMT -5. The time now is 22:59.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi