Showing posts with label glpk. Show all posts
Showing posts with label glpk. Show all posts

Monday, November 05, 2012

Drawing the presidential Election

Finding all the ways the electoral college votes from each state can be added up to give both candidates 269 votes turns out to be really hard. Political pundits always bring up the spectre of a drawn presidential election.

What happens if the US election ends in a draw?

If There’s an Electoral College Tie, Things Will Get Even Crazier Than You May Know

Where both candidates get 269 of the electoral college votes.

The website 270towin calculates 32 practical combinations that could result in a tie and give the probability of one of these occuring given polling data at 0.2%.

The NYtimes here claims there are 5 practical ways a tie could result.

But how many possible drawing combinations are there in total, including implausible ones?

Elections are much closer than the set of all possible wins a candidate could have. Certain states are similar so tend to vote the same way so some divisions are far more likely than others. Also by the median voter theorem two competing parties will be as similar to each other as possible to get as much of the vote as they can. Roughly the Republicans will be as near the center as they can while getting all the right wing votes and the democrats as near the center while getting all the left wing votes.

But how many total ways are there that two candidates can win 50 states and one district? That is as, ColinTheMathmo pointed out, 2^51 as each state can go to either candidate. I want to find the number of allocations in this 2^51 that give each candidate 269 electoral college votes*.

2^51 is a big number. As Matthew Saltzman said the set partition is an NP-Complete problem and a 'Complete enum at 10M/sec, would take 7 years.'

But instead of complete enum we just want to see the cases where both candidates get 269. The code here calculates this. I took some Minizinc code from Hakan Kjellerstrand who pointed out an error in my previous reading of a result that would calculate all the allocations of states that give 269 electoral votes. The code is written in Minizinc as it can calculate all answers in a way GLPK** doesn't. Hakan also kindly pointed out some inefficiencies in my program so I am linking to his code.

Here are some of the many results it output

Alaska California Delaware Florida Idaho Illinois Iowa Maine Michigan Mississippi Montana Nevada 'New York' Ohio Pennsylvania 'South Dakota' Texas Utah 
----------
Alaska California Delaware Florida Idaho Illinois Iowa Maine Michigan Mississippi Montana Nevada 'New York' Ohio Pennsylvania Texas Utah Vermont 
----------
Alaska California Delaware Florida Idaho Illinois Iowa Maine Michigan Mississippi Montana Nevada 'New York' Ohio Pennsylvania Texas Utah Wyoming 
----------
Alaska California Delaware Florida Idaho Illinois Iowa Maine Michigan Mississippi Nevada 'New York' 'North Dakota' Ohio Pennsylvania 'South Dakota' Texas Utah 
My mac is 2.16 gz and has 2 gigs of RAM so it is not a fast machine. Still after three hours of running it ground to a halt. This means I have no answer for you. If I find out how many of the state allocations result in 269 votes I will let you know.

It is interesting that these sorts of difficult NP-Complete problems pop up in real life and getting solutions for them is not always easy.

* Actually Maine and Nebraska can give out votes proportionately so the search space is even larger than this

**Just in case someone can use it here is GLPK code that will work out one answer

/* sets */
set STATES;
set NEED;

/* parameters */
param VotesTable {i in STATES, j in NEED};
param Pop {i in STATES};
param Need {j in NEED};


/* decision variables: x1: alabama, x2: , x3: , x4:  x51: Wyoming*/
      var x {i in STATES} binary >= 0;

/* objective function 
          z: sum{i in STATES} VotesTable[i,j]*x[i];
     
/* Constraints */
s.t. const{j in NEED} : sum{i in STATES} VotesTable[i,j]*x[i] == Need[j];

/* data section */
data;

set STATES :=  Alaska Delaware "District of Columbia" Montana "North Dakota" "South Dakota" Vermont Wyoming Hawaii Idaho Maine "New Hampshire" "Rhode Island" Nebraska Nevada "New Mexico" Utah "West Virginia" Arkansas Kansas Mississippi Connecticut Iowa Oklahoma Oregon Kentucky "South Carolina" Alabama Colorado Louisiana Arizona Maryland Minnesota Wisconsin Indiana Missouri Tennessee Washington Massachusetts Virginia Georgia "New Jersey" "North Carolina" Michigan Ohio Illinois Pennsylvania Florida "New York" Texas California;
set NEED := Votes;

param VotesTable: Votes:=
 Alabama 9
 Alaska 3
 Arizona 11
 Arkansas 6
 California 55
 Colorado 9
 Connecticut 7
 Delaware 3
 "District of Columbia" 3
 Florida 29
 Georgia 16
 Hawaii 4
 Idaho 4
 Illinois 20
 Indiana 11
 Iowa 6
 Kansas 6
 Kentucky 8
 Louisiana 8
 Maine 4
 Maryland 10
 Massachusetts 11
 Michigan 16
 Minnesota 10
 Mississippi 6
 Missouri 10
 Montana 3
 Nebraska 5
 Nevada 6
 "New Hampshire" 4
 "New Jersey" 14
 "New Mexico" 5
 "New York" 29
 "North Carolina" 15
 "North Dakota" 3
 Ohio 18
 Oklahoma 7
 Oregon 7
 Pennsylvania 20
 "Rhode Island" 4
 "South Carolina" 9
 "South Dakota" 3
 Tennessee 11
 Texas 38
 Utah 6
 Vermont 3
 Virginia 13
 Washington 12
 "West Virginia" 5
 Wisconsin 10
 Wyoming 3;

param Need:=
Votes        269;

end;

Friday, November 02, 2012

Becoming President with 22% of the Votes

Political pundits talk about the possibility of winning the Presidential election with less votes than your opponent. Assuming only two candidates what is the lowest percentage of votes you could get and still win the election? In the case where everyone votes this becomes an interesting question. In America some states have a higher ratio of people to electoral college votes than others. If the ones that are preferentially treated banded together a small percentage of people could decide the election.

In my last post I created a program to work out in an overly complicated way what was the least amount of land a president could be elected from in the US. In this post I want to figure out the best states to win to get you 270+ electoral college seats using the smallest number of voters.

I got the estimated population in July 2011 from the census website here. Using this data in the glpk program below and got the result shown in this map. If everyone voted and the people who get the most power in votes all voted one way then the states on the winning side would have 135936335 voters to get 270 electoral college seats. The total population is 311591917 so 43.67% of the population

The winner would win 40 districts of the 51 states+dc and lose Virginia, Georgia, New Jersey, Michigan, Ohio, Illinois, Pennsylvania, Florida, New York, Texas, California.*

Now if the candidate in these states just squeaked a win by one vote and got zero votes in all the other states that means in a two party election you could win an election, where everyone voted, with under 22% of the vote. If you think of this happening in a senate election where each state has 2 senators (and DC none) then you could control 80% of the senate with under 22% of the vote.

There are all sorts of other questions similar to this. What is the smallest block where all the states touch? What is the shortest distance between all her state capitals a winner could have? I think some analysis that included Senate and Congress seats could be interesting. If you have any ideas please comment. * Thanks to Hakan Kjellerstrand who pointed out here I had read the solution file wrong and North Carolina was not present.

/* sets */
set STATES;
set NEED;

/* parameters */
param VotesTable {i in STATES, j in NEED};
param Pop {i in STATES};
param Need {j in NEED};


/* decision variables: x1: alabama, x2: , x3: , x4:  x51: Wyoming*/
      var x {i in STATES} binary >= 0;

/* objective function */
      minimize z: sum{i in STATES} Pop[i]*x[i];

/* Constraints */
s.t. const{j in NEED} : sum{i in STATES} VotesTable[i,j]*x[i] >= Need[j];


/* data section */
data;

set STATES :=  Alaska Delaware "District of Columbia" Montana "North Dakota" "South Dakota" Vermont Wyoming Hawaii Idaho Maine "New Hampshire" "Rhode Island" Nebraska Nevada "New Mexico" Utah "West Virginia" Arkansas Kansas Mississippi Connecticut Iowa Oklahoma Oregon Kentucky "South Carolina" Alabama Colorado Louisiana Arizona Maryland Minnesota Wisconsin Indiana Missouri Tennessee Washington Massachusetts Virginia Georgia "New Jersey" "North Carolina" Michigan Ohio Illinois Pennsylvania Florida "New York" Texas California;
set NEED := Votes;

param VotesTable: Votes:=
 Alabama 9
 Alaska 3
 Arizona 11
 Arkansas 6
 California 55
 Colorado 9
 Connecticut 7
 Delaware 3
 "District of Columbia" 3
 Florida 29
 Georgia 16
 Hawaii 4
 Idaho 4
 Illinois 20
 Indiana 11
 Iowa 6
 Kansas 6
 Kentucky 8
 Louisiana 8
 Maine 4
 Maryland 10
 Massachusetts 11
 Michigan 16
 Minnesota 10
 Mississippi 6
 Missouri 10
 Montana 3
 Nebraska 5
 Nevada 6
 "New Hampshire" 4
 "New Jersey" 14
 "New Mexico" 5
 "New York" 29
 "North Carolina" 15
 "North Dakota" 3
 Ohio 18
 Oklahoma 7
 Oregon 7
 Pennsylvania 20
 "Rhode Island" 4
 "South Carolina" 9
 "South Dakota" 3
 Tennessee 11
 Texas 38
 Utah 6
 Vermont 3
 Virginia 13
 Washington 12
 "West Virginia" 5
 Wisconsin 10
 Wyoming 3;

param Pop:=
Alabama 4802740
Alaska 722718
Arizona 6482505
Arkansas 2937979
California 37691912
Colorado 5116796
Connecticut 3580709
Delaware 907135
"District of Columbia" 617996
Florida 19057542
Georgia 9815210
Hawaii 1374810
Idaho 1584985
Illinois 12869257
Indiana 6516922
Iowa 3062309
Kansas 2871238
Kentucky 4369356
Louisiana 4574836
Maine 1328188
Maryland 5828289
Massachusetts 6587536
Michigan 9876187
Minnesota 5344861
Mississippi 2978512
Missouri 6010688
Montana 998199
Nebraska 1842641
Nevada 2723322
"New Hampshire" 1318194
"New Jersey" 8821155
"New Mexico" 2082224
"New York" 19465197
"North Carolina" 9656401
"North Dakota" 683932
Ohio 11544951
Oklahoma 3791508
Oregon 3871859
Pennsylvania 12742886
"Rhode Island" 1051302
"South Carolina" 4679230
"South Dakota" 824082
Tennessee 6403353
Texas 25674681
Utah 2817222
Vermont 626431
Virginia 8096604
Washington 6830038
"West Virginia" 1855364
Wisconsin 5711767
Wyoming 568158;

param Need:=
Votes        270;

end;

What is the least amount of land that will make you President?

Matthew Yglesias in the slate calculates what he thinks is the smallest area of land a candidate could win and still win this presidential election. Densely populated states will have more electoral college votes per square kilometer and so you can win the election while winning a relatively small surface area of America.
His reasoning is 'I started with a list of states in order of population density. So you have DC, then New Jersey, then Rhode Island, then Massachusetts, and so forth. Eventually you get a set that wins you the electoral college. Except the bloc of the 18 densest states gives you 282 electoral votes—way more than you need. Eliminate Michigan, the 18th densest, and you have 266 electoral votes. So then you can round things out with little New Hampshire's four electoral votes and you have your winning map'.

I checked this allocation with the GLPK program below. I used the electoral votes listed here and the state areas listed on wikipedia This gets 270 votes with an area of 1625012km². US states + DC is an area of 9826630km² so 16.54% of the US could win an election.

The states are Delaware, District of Columbia, Hawaii, New Hampshire, Rhode Island, Connecticut, Maryland, Indiana, Massachusetts, Virginia, New Jersey, North Carolina, Ohio, Illinois, Pennsylvania, Florida, New York, California. My map is here

Matthew Yglesias' map is the same so he did find the optimal solution by hand.

/*code to find the least land area to get 270 votes. Run with 'glpsol -m election.mod -o out'
*/
/* sets */
set STATES;
set NEED;

/* parameters */
param VotesTable {i in STATES, j in NEED};
param Cost {i in STATES};
param Need {j in NEED};


/* decision variables: x1: alabama, x2: , x3: , x4:  x51: Wyoming*/
      var x {i in STATES} binary >= 0;

/* objective function */
      minimize z: sum{i in STATES} Cost[i]*x[i];

/* Constraints */
s.t. const{j in NEED} : sum{i in STATES} VotesTable[i,j]*x[i] >= Need[j];


/* data section */
data;

set STATES :=  Alaska Delaware "District of Columbia" Montana "North Dakota" "South Dakota" Vermont Wyoming Hawaii Idaho Maine "New Hampshire" "Rhode Island" Nebraska Nevada "New Mexico" Utah "West Virginia" Arkansas Kansas Mississippi Connecticut Iowa Oklahoma Oregon Kentucky "South Carolina" Alabama Colorado Louisiana Arizona Maryland Minnesota Wisconsin Indiana Missouri Tennessee Washington Massachusetts Virginia Georgia "New Jersey" "North Carolina" Michigan Ohio Illinois Pennsylvania Florida "New York" Texas California;
set NEED := Votes;

param VotesTable: Votes:=
 Alabama 9
 Alaska 3
 Arizona 11
 Arkansas 6
 California 55
 Colorado 9
 Connecticut 7
 Delaware 3
 "District of Columbia" 3
 Florida 29
 Georgia 16
 Hawaii 4
 Idaho 4
 Illinois 20
 Indiana 11
 Iowa 6
 Kansas 6
 Kentucky 8
 Louisiana 8
 Maine 4
 Maryland 10
 Massachusetts 11
 Michigan 16
 Minnesota 10
 Mississippi 6
 Missouri 10
 Montana 3
 Nebraska 5
 Nevada 6
 "New Hampshire" 4
 "New Jersey" 14
 "New Mexico" 5
 "New York" 29
 "North Carolina" 15
 "North Dakota" 3
 Ohio 18
 Oklahoma 7
 Oregon 7
 Pennsylvania 20
 "Rhode Island" 4
 "South Carolina" 9
 "South Dakota" 3
 Tennessee 11
 Texas 38
 Utah 6
 Vermont 3
 Virginia 13
 Washington 12
 "West Virginia" 5
 Wisconsin 10
 Wyoming 3;

param Cost:=
 Alabama 135765
 Alaska 1717854
 Arizona 295254
 Arkansas 137732
 California 423970
 Colorado 269601
 Connecticut 14357
 Delaware 6447
 "District of Columbia" 177
 Florida 170304
 Georgia 153909
 Hawaii 28311
 Idaho 216446
 Illinois 149998
 Indiana 94321
 Iowa 145743
 Kansas 213096
 Kentucky 104659
 Louisiana 134264
 Maine 91646
 Maryland 32133
 Massachusetts 27336
 Michigan 250494
 Minnesota 225171
 Mississippi 125434
 Missouri 180533
 Montana 380838
 Nebraska 200345
 Nevada 286351
 "New Hampshire" 24216
 "New Jersey" 22588
 "New Mexico" 314915
 "New York" 141299
 "North Carolina" 139389
 "North Dakota" 183112
 Ohio 116096
 Oklahoma 181035
 Oregon 254805
 Pennsylvania 119283
 "Rhode Island" 4002
 "South Carolina" 82932
 "South Dakota" 199731
 Tennessee 109151
 Texas 695621
 Utah 219887
 Vermont 24901
 Virginia 110785
 Washington 184665
 "West Virginia" 62755
 Wisconsin 169639
 Wyoming 253336;

param Need:=
Votes        270;

end;

Thursday, August 04, 2011

Crowd Sourced Optimal Fantasy Football Team



All my fantasy football attempts have the problem that I know nothing about football. So for example Berbatov is unlikely to do as well this season as last season so picking him would seem unwise. But how does someone who knows nothing about football find out who will play well next season?

The wisdom of the crowds is the James Surowiecki about "the aggregation of information in groups, resulting in decisions that, he argues, are often better than could have been made by any single member of the group." This sort of thing does not work if the crowd has a bias in a particular direction.

I decided to look at the people is the "team selected by %" that fantasy premier league shows you. If I rerun the optimisation described in this post but instead of trying to great a team that has the maximum number of points last season I try and get the team whose players have been selected by the most other fantasy football managers.

The idea is that a team with the right number of defenders, goalkeepers, midfielders and forwards, that has at most three players from one team, that costs less than 100 and whose members have been picked most often should be really good.

The most popular team is

Player Club Pos Price Pts people
7 Al-Habsi WIG GK 45 125 199410
30 Bale TOT MID 80 118 189087
37 Barton NEW MID 60 131 123865
69 Cahill BOL DEF 55 105 180751
184 Given AVL GK 50 0 215091
205 Hangeland FUL DEF 65 154 192333
231 Huth STO DEF 60 138 165684
266 Kompany MCI DEF 60 95 197352
323 N'Gog LIV STR 55 48 279932
334 Odemwingie WBA STR 75 171 218485
421 Suarez LIV STR 95 68 343361
424 Taarabt QPR MID 65 0 141086
452 Vidic MUN DEF 80 148 172773
472 Wilshere ARS MID 65 93 220381
477 Yaya Toure MCI MID 80 146 167706

Some of these players were probably picked for the first few games and will be transfered out when they are about to play tougher games.

The average player is picked 26794 times. These players have been picked 200486 people on average.
This team would have scored 1415 points last season. The best team I could have picked for last season would have scored 2332 points. I have updated the dataset to include this people picked statistic.

Monday, August 01, 2011

Fantasy Football Optimization 2


So it turns out I was thick last post about picking the fantasy football team. As my friend Bren explained to me "you choose 11 players to be "on the pitch" each week, plus a captain who scores double (and a vice captain in case the captain doesn't play). can only have 1 keeper in the first 11, can choose any formation with a minimum of 3 defenders, 3 midfielders and 1 forward."

So the problem is now pick 11 players that will actually play and some really cheap players that won't

So whats the cheapest of each player you could get?
The cheaperst players in each position are about 4 or 4.5 each. For example
Goalkeeper
Moreira SWA 4.0 0
Defenders
Whitbread NOR 4.0 0
Tate SWA 4.0 0
Midfield
Lappin NOR 4.5 0
Gecov FUL 4.5 0
Allen SWA 4.5 0
Strikers
Miller WBA 4.5 6
Hulse QPR 4.5 0
Agyemang QPR 4.5 0

So if you picked from this price of player knowing they would not play that would allow you to spend more money on those that were on the pitch. Now defenders score less points than midfielders and strikers so lets say we only want three of them. And we then buy two cheap ones that we dont play. 2 cheap defenders costs 8 and one goalie for 4 means we now have 88 to pick the remaining 12 players. The case whether you should have 5 midfielders or 3 strikers is less clear. I will try both and see which has a higher score.

Attempt 1. Cheap goalie and 2 defenders and 1 midfielder. Cost 16.5 on 4 non playing players. Trying to have 3 strikers. The constraints would now be
num_goalkeepers <- 1
num_defenders <- 3
num_midfielders <- 4
num_strikers <- 3
max_team_cost <- 835
max_player_from_a_team <- 3

Gives a team of

1 Hart MCI GK 70 175
48 Ivanovic CHE DEF 70 144
49 Huth STO DEF 60 138
51 Hughes FUL DEF 50 129
197 Adam LIV MID 90 192
198 Malouda CHE MID 105 186
200 Dempsey FUL MID 85 168
201 N'Zogbia WIG MID 75 167
210 Jarvis WOL MID 60 133
386 Berbatov MUN STR 95 176
388 Odemwingie WBA STR 75 171

scoring 1779. You would make Adam your captain and he would have double points.

Attempt 2. Cheap non playing goalie and 2 defenders and 1 striker. Trying to have two strikers. Cost 16.5 on 4 non playing players.
num_goalkeepers <- 1
num_defenders <- 3
num_midfielders <- 5
num_strikers <- 2
max_team_cost <- 835
max_player_from_a_team <- 3

1 Hart MCI GK 70 175
48 Ivanovic CHE DEF 70 144
49 Huth STO DEF 60 138
51 Hughes FUL DEF 50 129
197 Adam LIV MID 90 192
198 Malouda CHE MID 105 186
200 Dempsey FUL MID 85 168
201 N'Zogbia WIG MID 75 167
210 Jarvis WOL MID 60 133
386 Berbatov MUN STR 95 176
388 Odemwingie WBA STR 75 171

with a score of 1769. Again Adam would be your captain. It looks like three strikers is a better plan than 5 midfielders. But it is a close run thing.

Just to make things really complicated Bren explained that you should generally have one good player on the subs bench in case one of the rest of the team is injured. "it's quite common for one of the main team to miss a week so you may need to make 1 sub an excellent player (probably defender since they're cheaper)". Having a defender as your good sub has the advantage that you are allowed to play with one forward and three midfielders so if one of your three forwards, four midfielders or three playing defenders gets injured a defender can sub in for any of those.

So assuming we actually want four defenders. We would have one cheap goalie and one cheap defender and one cheap midfielder. At a cost of 12.5 for non playing players.
num_goalkeepers <- 1
num_defenders <- 4
num_midfielders <- 4
num_strikers <- 3
max_team_cost <- 875
max_player_from_a_team <- 3

giving a team of


Player Club Pos Price Pts
1 Hart MCI GK 70 175
46 Cole A CHE DEF 75 150
49 Huth STO DEF 60 138
51 Hughes FUL DEF 50 129
54 Bardsley SUN DEF 50 123
197 Adam LIV MID 90 192
200 Dempsey FUL MID 85 168
201 N'Zogbia WIG MID 75 167
203 Downing LIV MID 85 163
386 Berbatov MUN STR 95 176
388 Odemwingie WBA STR 75 171
393 Davies K BOL STR 65 132


1884 points -123 as Bardley wont play = 1761. Basically Bardsley a Sunderland defender is really cheap at 5. This is one more than you pay for a player you don't want to play but if you do need to lay him he gets 123 points a season.
Davies looks a little low there with 132 points. The worst midfielder has 163 points. So what if we get rid of the third striker and try 5 midfielders?

num_goalkeepers <- 1
num_defenders <- 4
num_midfielders <- 5
num_strikers <- 2
max_team_cost <- 875
max_player_from_a_team <- 3


Player Club Pos Price Pts
1 Hart MCI GK 70 175
46 Cole A CHE DEF 75 150
49 Huth STO DEF 60 138
51 Hughes FUL DEF 50 129
53 Distin EVE DEF 55 124
197 Adam LIV MID 90 192
200 Dempsey FUL MID 85 168
201 N'Zogbia WIG MID 75 167
203 Downing LIV MID 85 163
210 Jarvis WOL MID 60 133
386 Berbatov MUN STR 95 176
388 Odemwingie WBA STR 75 171

1886-124 for Distin who usually wont play = 1762. So this is my best single fantasy football team of last season.

The more I learn about this game the more nuances it has. Off the top of my head
1. Model that the captain gets double points. In this case Adam the highest scoring player is actually quite cheap. But in the case where he was really expensive you would want to take into account that he can earn double points.
2. Take into account who teams are playing. With a full game by game scoring dataset you can investigate really interesting patterns like if playing top five club means less points and bottom five more. And if so make transfers based on upcoming games. This seems to be where a huge amount of the skill in fantasy football is.
3. Change the code so you can have 3->5 defenders, 3-5 midfielders and 1-3 strikers but only 11 total players.
4. Just picking cheap non playing players is probably wrong. You at least want to pick the best cheap players you can. Which I have not. I am told Shane Ferguson is a good buy so I will probably make him one of the cheap players.

If any of the intuitions about having a good substitute or any of my other assumptions are wrong please correct me.
If you predict different points for players this season. If you want to try this method for next season but dont want to run the program linked to in part one


1. Copy the dataset I have here
2. Put this data into a new google docs spreadsheet.
3. Make your predictions on the number of points they will score. So if you think Berbatov won't score 176 points this season but only 160 change that points value. You can delete players you are not interested in as well.
4. Put your new spreadsheet URL in the comments
and I will run a optimization over your predictions for you.

Saturday, July 30, 2011

Fantasy Football Optimisation

Some friends challenged me to a game called fantasy "football" where you pretend to be a Russian billionaire. Not the bit where you steal natural resources off the population but where you buy a bunch of poncy overpaid foreigners who flounce around and earn insane amounts of money.

While I'm ranting about "football". Why do football ads always say it has "the beauty of a dance". If you like dancing that much go to the ballet



Anyway So I have to pretend to know something about this "football" which I dont but I do know a bit about optimization and more about copying stuff. I remembered this old R package article about optimising for fantasy football. This was written by prasoonsharma and I have just reused his code.

I scraped last seasons scores off the fantasy premierleague website. Some parsing turned this into the correct format. You can download the cleaned up data here

The constraints for this version of the game are slightly different than the one prasoonsharma was playing. This means you need more goalies, have more money to spend on players and other such changes.

The best single team for last season would have been

Player Club Pos Price Pts
1 Hart MCI GK 70 175
5 Al-Habsi WIG GK 45 125
48 Ivanovic CHE DEF 70 144
49 Huth STO DEF 60 138
51 Hughes FUL DEF 50 129
54 Bardsley SUN DEF 50 123
55 Johnson WOL DEF 50 120
197 Adam LIV MID 90 192
200 Dempsey FUL MID 85 168
201 N'Zogbia WIG MID 75 167
210 Jarvis WOL MID 60 133
212 Barton NEW MID 60 131
386 Berbatov MUN STR 95 176
388 Odemwingie WBA STR 75 171
393 Davies K BOL STR 65 132

with a total score of 2224 points. You get to change the team every week in the real game. This optimisation is just if you got to pick one team and leave it.

Picking a fantasy football team involves
1. Predicting how many points each player will score that week
2. Optimising based on this prediction so you pick the team that covers all the rule constraints that scores the most points.

This code carries out the second part. If you have a prediction for how many points players will score that is better than
"exactly the same amount they scored last season" you can change the data with your new prediction and run it (or I can run it for you if you want). A web app that allowed you to enter your player score predictions and ran an optimisation so that the best team that could be picked based on your predictions was then created might be useful. If you save the data in a new google doc and change the Pts values to your player predictions. Then post a link to that google doc in the comments I will run the optimisation for you.

Monday, November 30, 2009

Human Nutrient Needs

What nutrients does a person need per day?
I am not a dietician or indeed sober so don't take this as actual advice. But what does ten minutes googling give as a list of the needed nutrients?
This is item 1 of the list of things to do for a modern version of Stigler's diet. Wikipedia the universal source of all truth (TM) italic has an article on this here.

It gives the RDA for an average 25-year old male (for ones that use IU which appears to be nonsense so I have taken some figures from here and here)
all figures are in µg

param RDA:=
Vitamin_A 900
Vitamin_C 90000
Vitamin_D 5
Vitamin_K 120
Vitamin_B6 1300
Vitamin_E 15000
Biotin 30
Calcium 1000000
Chloride 2300000
Chromium 35
Choline 550000
Copper 900
Cyanocobalamin 2.4
Fluoride 4000
Folate 400
Iodine 150
Iron 8000
Magsium 400000
Mangase 2300
Molybdenum 45
Niacin 16000
Nickel 1000
Pantothenic_acid 5000
Phosphorus 700000
Potassium 4700000
Riboflavin 1300
Selenium 55
Sodium 1500000
Thiamin 1200
Zinc 11000
;

And the upper limit as

param UL:=
Vitamin_A 3000
Vitamin_C 2000000
Vitamin_D 50
Vitamin_B6 100000
Vitamin_E 1000000
Boron 20000
Calcium 2500000
Chloride 3600000
Choline 3500000
Copper 10000
Fluoride 10000
Folate 1000
Iodine 1100
Iron 45000
Magsium 350000
Mangase 11000
Molybdenum 2000
Niacin 35000
Nickel 1000
Phosphorus 4000000
Selenium 400
Sodium 2300000
Zinc 40000
;

The figures we are interested in are RDA's which must be met and Tolerable upper intake levels which cannot be exceded.
Macro nutrients are in grams

param Macro:
Waterb 3700
Carbohydrates 130
Proteinc 56
Fiber 38
Linoleic 17
alpha-Linolenic 1.6
end;

Also some nutrients must be minimised Cholesterol, Trans fatty acids, Saturated fatty acids. These will have to be aims of a optimiser for diets.
These are a bit more difficult to deal with so I will ignore them for the moment.
Cholesterol As low as possible
Trans fatty acids As low as possible
Saturated fatty acids As low as possible

Also two types of macro nutrients must be a % of calories.
Added sugar No more than 25% of calories
Fat 20–35% of calories

I am going to guess a 25 year old male needs 2500 calories until I am corrected.
So we have a first approximation of what nutrients people need.

So next up is getting a price and nutrient contents for loads of different foods.

Sunday, November 29, 2009

The Diet Problem

What is the cheapest way to feed yourself? This is not a minor issue our diets and health could be much better if they were optimised to provide the most needed nutrients at the smallest cost and also to provide the most palatable diet that is as healthy as possible.

Stigler in 1939 worked out a near optimal miminum price needed to supply a person with the nutrients they need for a year. The diet consists of five not very pleasant foods so is not intended to be realistic dietry advice.

Still given current knowledge of nutrition a list of prices from various supermarkets could you optimise you shopping basket to provide your family with groceries? Here we want to give people the nutrients they need in a form they will actually eat that is healthy and cheap.

We need a list of
1. What nutrients are needed by a person
2. Foods preferences of people.
3. A price list of foods
4. A Linear program to optimize a shopping basket based on these variables.

All of these requirements need some explanation. I think its best if each gets it's own post. So tomorrow I will have a post on what quantities of nutrients people require. If you have any suggestions please comment.

Wednesday, October 28, 2009

A work sceduling problem

I saw this problem recently
A city authority is considering placing a toll booth on its new bridge. The beginning
times for the shifts are 8am, noon, 4pm, 8pm, midnight and 4am. A collector
beginning a shift at one of the above times works for the next 8 hours.
The following staffing levels during each of the 24-hour periods have been estimated

Hour.................... Minimum Collectors Needed
8am - Noon.............. . 5
Noon – 4pm ................6
4pm – 8pm .................10
8pm - Midnight........... .7
Midnight – 4am ...........4
4am – 8am .................6

Find the minimum number of collectors that need to be hired to begin the 8 hour shifts
at each of the six times.


A GLPK program to calculate this is

var x1 >= 0, integer;
var x2 >= 0, integer;
var x3 >= 0, integer;
var x4 >= 0, integer;
var x5 >= 0, integer;
var x6 >= 0, integer;
/* objective function */
minimize z: x1+x2+x3+x4+x5+x6;

/* Constraints */
s.t. ctr1:x1 + x6 >= 5;
s.t. ctr2:x1+x2>= 6;
s.t. ctr3:x2+x3>= 10;
s.t. ctr4:x3+x4>= 7;
s.t. ctr5:x4+x5>= 4;
s.t. ctr6:x5+x6>= 6;
data;
end;

The answer is 19 and no one starts working at 8am.
This is a simplified version of the program described here. Not a major revelation or anything but always find these puzzle solving programs cool.

Sunday, August 30, 2009

Fair division using a spreadsheet and Ruby

It has taken me a month to get over the idea that someone expected this blog not to be the ranting of an inane balding drunk but actually good. Still it is time to get back to the drunken inane rambling.

There is no point having all these cool algorithms unless people can actually use them. So what is a good way to actually get the data into the program? We'll spreadsheets are used for this sort of thing all the time. Unfortunately I cannot figure out how to get openoffice, excel or gnumeric's solver to carry out this minimax fair division program.

Ruby has a cool library called roo for interacting with spreadsheets. So heres a program to get the data out of a spreadsheet and send it off to GLPK

require 'rubygems'
require 'roo'

#open office version
# oo = Openoffice.new("spreadsheetOO.ods")
# o2 = Openoffice.new("spreadsheetOO.ods")

#excell version
oo = Excel.new("spreadsheetOO.xls")
o2 = Excel.new("spreadsheetOO.xls")
oo.default_sheet = oo.sheets.first

o2.default_sheet ="Sheet2"
st="" #data being written toa file
div= o2.last_column


#start writing data to model file
st<< "data;\n"
st<< "param m := #{oo.last_row-1};\n"

st<< "param n := #{div};\n"
#the non divisible is whatever is left
st<< "param o := #{oo.last_column};\n"

st<< "param c :"
i=1
(oo.last_column).times{st<< "#{i} "
i=i+1}
st<< ":=\n"

# number of people
i=1

2.upto(oo.last_row) do |line|
st<< "#{i} "
1.upto(oo.last_column) do |col|
st<< "#{Integer oo.cell(line,col)} "#Integer

end
st<< "\n";
i=i+1
end
st<< ";\n"
st<< "param d :"
i=1
(o2.last_column).times{st<< "#{i} "
i=i+1}
i=1
st<< ":=\n"
2.upto(o2.last_row) do |line|
st<< "#{i} "
1.upto(o2.last_column) do |col|
st<<"#{Integer o2.cell(line,col)} "
end
st<< "\n";
i=i+1
end


st<< ";\nend;"

#write data to a file
File.open("data","w")do |file|
file.write(st)
end

#call glpk program on the data
system('./glpsol -m fair.mod -d data -o fair.sol');


The input spreadsheets are openoffice and excelin the first row is the list of items.
Every other row is each persons valuation for each item. The first sheet is the indivisible items and the second sheet are the divisible ones. Unfortunately roo does not allow you write to these spreadsheets so I cannot print out the answer to a spreadsheet.

The roo interface to the google docs spreadsheet does allow cells to be written to. So getting that version up and running is the next task.