Skip to content

Instantly share code, notes, and snippets.

@tyleransom
Last active December 9, 2018 03:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tyleransom/3738fa6cd1b3b5602e0621b08d068380 to your computer and use it in GitHub Desktop.
Save tyleransom/3738fa6cd1b3b5602e0621b08d068380 to your computer and use it in GitHub Desktop.
MWE for linear programming problem
using DataFrames
using HTTP
using uCSV
using JuMP
using GLPK
using Cbc
# read in the data
fname = "https://gist.githubusercontent.com/tyleransom/3738fa6cd1b3b5602e0621b08d068380/raw/5c4b139639d7b3c16716289b0232b8528d1bf494/mwe.csv"
data = DataFrame(uCSV.read(IOBuffer(HTTP.get(fname).body), quotes='"', header=1))
data = Matrix(data)
# id = data[:,1]
# val = data[:,2]
# score = data[:,3]
# id1 = data[:,4]
# take a subset of the data just to compare (can figure out by hand on smaller data)
data = data[1:14,:]
#solver = GLPKSolverLP()
solver = CbcSolver()
# Solve model
function SolveModel(data)
N = size(data,1)
m = Model(solver=solver)
@variable(m, is_good[1:N], Bin)
@variable(m, is_bad[1:N], Bin)
@objective(m, Max, data[i,3] * is_good[i] - data[i,3] * is_bad[i] for i in 1:N)
@constraints m begin
# Constraint 1 - sum of good vals >= sum of bad vals
data[i,2] * is_good[i] .>= data[i,2] * is_bad[i]
# Constraint 2 - can't choose the same id for both good and bad
is_good[1:N] .+ is_bad[1:N] .<= 1
end
# Solve it
status = solve(m)
println(getvalue(is_good))
println(getvalue(is_bad))
end
@time SolveModel(data)
julia> include("jump_mwe.jl")
ERROR: LoadError: MethodError: no method matching *(::Float64, ::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##9#10")){Array{Int64,2},Array{Variable,1},Array{Variable,1}}})
Closest candidates are:
*(::Any, ::Any, ::Any, ::Any...) at operators.jl:502
*(::Float64, ::Float64) at float.jl:399
*(::AbstractFloat, ::Bool) at bool.jl:120
...
Stacktrace:
[1] addtoexpr(::JuMP.GenericAffExpr{Float64,Variable}, ::Float64, ::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##9#10")){Array{Int64,2},Array{Variable,1},Array{Variable,1}}}) at /home/ransom/.julia/packages/JuMP/Xvn0n/src/parseExpr_staged.jl:289
[2] macro expansion at /home/ransom/.julia/packages/JuMP/Xvn0n/src/parseExpr_staged.jl:296 [inlined]
[3] addtoexpr_reorder(::JuMP.GenericAffExpr{Float64,Variable}, ::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##9#10")){Array{Int64,2},Array{Variable,1},Array{Variable,1}}}) at /home/ransom/.julia/packages/JuMP/Xvn0n/src/parseExpr_staged.jl:296
[4] macro expansion at /home/ransom/.julia/packages/JuMP/Xvn0n/src/macros.jl:232 [inlined]
[5] SolveModel(::Array{Int64,2}) at /home/ransom/jump_mwe.jl:29
[6] top-level scope at util.jl:156
[7] include at ./boot.jl:317 [inlined]
[8] include_relative(::Module, ::String) at ./loading.jl:1038
[9] include(::Module, ::String) at ./sysimg.jl:29
[10] include(::String) at ./client.jl:388
[11] top-level scope at none:0
in expression starting at /home/ransom/jump_mwe.jl:65
id val score id1
1 9 0 64
2 4 0 7
3 11 12 53
4 7 0 8
5 4 35 11
6 14 0 31
7 13 29 2
8 10 11 4
9 2 18 18
10 5 6 38
11 13 0 5
12 8 0 23
13 15 0 44
14 12 0 24
15 2 7 21
16 6 7 59
17 9 0 32
18 15 0 9
19 4 5 61
20 6 0 48
21 15 0 15
22 1 5 42
23 9 33 12
24 5 6 14
25 15 0 39
26 16 0 68
27 11 25 29
28 13 0 66
29 6 0 27
30 3 15 33
31 3 15 6
32 8 9 17
33 14 0 30
34 12 0 65
35 16 0 68
36 9 0 49
37 7 0 55
38 12 0 10
39 2 7 25
40 5 55 47
41 10 0 46
42 16 0 22
43 10 11 56
44 2 18 13
45 16 0 62
46 7 8 41
47 12 0 40
48 11 12 20
49 8 9 36
50 14 0 57
51 11 0 68
52 11 0 68
53 6 0 3
54 3 4 67
55 10 11 37
56 7 0 43
57 3 9 50
58 16 0 68
59 11 0 16
60 16 0 63
61 13 0 19
62 1 2 45
63 1 2 60
64 8 30 1
65 5 6 34
66 4 11 28
67 14 0 54
68 1 5 58
Pwin team1 team2 round_face game_number game_draw game_played underdog1 underdog2 potential_score1 potential_score2 winnerNum loserNum
0.219431922565201 7 2 1 1 0.8731271249006383 true true false 0 10 2 7
0.428321777404977 6 3 1 2 0.8259745103159322 true true false 0 11 3 6
0.855427626374035 1 8 1 3 0.9227457166433748 true false true 0 16 8 1
0.593642689873469 5 4 1 4 0.9277263978497581 true true false 0 12 4 5
0.392189867110385 7 6 2 5 0.46520655315720205 false true false 0 19 6 7
0.323058209843327 7 3 2 5 0.3095865006255485 false true false 20 0 7 3
0.314695962253744 6 2 2 5 0.36384712333820723 false true false 0 15 2 6
0.61735737701594 2 3 2 5 0.28367704682852657 true false true 15 0 2 3
0.735644394458733 1 5 2 6 0.8892309704845145 false false true 0 18 5 1
0.805433797752599 1 4 2 6 0.5865761505823821 false false true 14 0 1 4
0.331556538123172 8 5 2 6 0.9849133208327021 false true false 0 18 5 8
0.421965786339032 8 4 2 6 0.06951775089275669 true true false 21 0 8 4
0.125734665623416 7 1 3 7 0.8663918779867097 false true false 0 22 1 7
0.470769473270697 7 8 3 7 0.5523356463291214 false false true 0 29 8 7
0.303341033270792 7 5 3 7 0.9329328452798897 false true false 0 26 5 7
0.392594884301928 7 4 3 7 0.08806065034710131 false true false 28 0 7 4
0.201234598969552 6 1 3 7 0.9841275514728216 false true false 0 22 1 6
0.578986095316038 6 8 3 7 0.06746086317442801 false false true 27 0 6 8
0.410724193540738 6 5 3 7 0.7071320843976836 false true false 0 26 5 6
0.502557208876912 6 4 3 7 0.7420025781455908 false true false 0 25 4 6
0.365197687525855 2 1 3 7 0.1897901283429657 false true false 23 0 2 1
0.755942236276598 2 8 3 7 0.556190992764551 true false true 23 0 2 8
0.60658119075765 2 5 3 7 0.5813570879039913 false false true 23 0 2 5
0.691194550797902 2 4 3 7 0.1514442293496121 false false true 23 0 2 4
0.258806638451577 3 1 3 7 0.9815133430127434 false true false 0 22 1 3
0.649098777414991 3 8 3 7 0.7368557023496518 false false true 0 29 8 3
0.484683179132226 3 5 3 7 0.17940598906049554 false false true 24 0 3 5
0.575687618671595 3 4 3 7 0.7697864650844537 false false true 0 25 4 3
using DataFrames
using HTTP
using uCSV
using JuMP
using Cbc
solver = CbcSolver()
# read in the data
fname = "https://gist.githubusercontent.com/tyleransom/3738fa6cd1b3b5602e0621b08d068380/raw/1664e3d0d5cb8973ab5eb23fa406667ab4b7e9ca/mwe_all.csv"
mwe = DataFrame(uCSV.read(IOBuffer(HTTP.get(fname).body), quotes='"', header=1))
mwe[:game_played] = convert(Array{Bool},mwe[:game_played].=="true")
mwe[:underdog1] = convert(Array{Bool},mwe[:underdog1].=="true")
mwe[:underdog2] = convert(Array{Bool},mwe[:underdog2].=="true")
function SolveModelMWE(data)
N = size(data,1)
m = Model(solver=solver)
r1idx = findall(data[:,2].==1)
r2idx = findall(data[:,2].==2)
r3idx = findall(data[:,2].==3)
r1u1idx = findall((data[:,7].==1) .& (data[:,2].==1))
r1u2idx = findall((data[:,8].==1) .& (data[:,2].==1))
r2u1idx = findall((data[:,7].==1) .& (data[:,2].==2))
r2u2idx = findall((data[:,8].==1) .& (data[:,2].==2))
r3u1idx = findall((data[:,7].==1) .& (data[:,2].==3))
r3u2idx = findall((data[:,8].==1) .& (data[:,2].==3))
gnums = [findall(data[:,9].==j) for j=1:7]
@variable(m, picks[1:N,1:2], Bin)
# data matrix: game_played, round_face, points1, points2, team1, team2, underdog1, underdog2, game_number
@objective(m, Max, sum(data[i,1] * sum(data[i,2+j] * picks[i,j] for j in 1:2) for i in 1:N))
@constraints m begin
# Constraint 1 - must pick sufficient number of lower-ranked teams
sum(picks[i,1] for i in r1u1idx) + sum(picks[i,2] for i in r1u2idx) >= 2
sum(picks[i,1] for i in r2u1idx) + sum(picks[i,2] for i in r2u2idx) >= 1
sum(picks[i,1] for i in r3u1idx) + sum(picks[i,2] for i in r3u2idx) >= 1
# Constraint 2 - must have picked 7 winners, and appropriate number from each round
sum(sum(picks[i,j] for j in 1:2) for i in 1:N ) == 7
sum(sum(picks[i,j] for j in 1:2) for i in r1idx) == 4
sum(sum(picks[i,j] for j in 1:2) for i in r2idx) == 2
sum(sum(picks[i,j] for j in 1:2) for i in r3idx) == 1
# Constraint 3 - can only pick one team per game
sum(picks[:,j] for j in 1:2) .<=1
# Constraint 4 - can't pick teams eliminated in prior rounds
# ????
# Constraint 5 - can't pick more than one game per set of potential matchups in a given round
sum(sum(picks[i,j] for j in 1:2) for i in gnums[1 ]) == 1
sum(sum(picks[i,j] for j in 1:2) for i in gnums[2 ]) == 1
sum(sum(picks[i,j] for j in 1:2) for i in gnums[3 ]) == 1
sum(sum(picks[i,j] for j in 1:2) for i in gnums[4 ]) == 1
sum(sum(picks[i,j] for j in 1:2) for i in gnums[5 ]) == 1
sum(sum(picks[i,j] for j in 1:2) for i in gnums[6 ]) == 1
sum(sum(picks[i,j] for j in 1:2) for i in gnums[7 ]) == 1
end
# Solve it
status = solve(m)
picked = getvalue(picks)
points = getobjectivevalue(m)
return picked,points
end
picked_test,points_test = SolveModelMWE(Matrix(mwe[:,[:game_played,:round_face,:potential_score1,:potential_score2,:team1,:team2,:underdog1,:underdog2,:game_number]]))
mwe[:picked1] = picked_test[:,1].==1
mwe[:picked2] = picked_test[:,2].==1
println(mwe[:,[:team1,:team2,:round_face,:game_number,:winnerNum,:loserNum,:picked1,:picked2]])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment