Skip to content

Commit

Permalink
High-level ops and tests, close #118
Browse files Browse the repository at this point in the history
  • Loading branch information
IainNZ committed Mar 10, 2014
1 parent 6287e2a commit 249a449
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 39 deletions.
57 changes: 39 additions & 18 deletions src/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,10 @@ end
(*)(q::QuadExpr, a::AffExpr) = error("Cannot multiply a quadratic expression by an aff. expression")
(/)(q::QuadExpr, a::AffExpr) = error("Cannot divide a quadratic expression by an aff. expression")
# QuadExpr--QuadExpr
(+)(q1::QuadExpr, q2::QuadExpr) = QuadExpr(vcat(q1.qvars1, q2.qvars1),
vcat(q1.qvars2, q2.qvars2),
vcat(q1.qcoeffs, q2.qcoeffs),
q1.aff + q2.aff)
(-)(q1::QuadExpr, q2::QuadExpr) = QuadExpr(vcat(q1.qvars1, q2.qvars1),
vcat(q1.qvars2, q2.qvars2),
vcat(q1.qcoeffs, -q2.qcoeffs),
q1.aff - q2.aff)
(+)(q1::QuadExpr, q2::QuadExpr) = QuadExpr( vcat(q1.qvars1, q2.qvars1), vcat(q1.qvars2, q2.qvars2),
vcat(q1.qcoeffs, q2.qcoeffs), q1.aff + q2.aff)
(-)(q1::QuadExpr, q2::QuadExpr) = QuadExpr( vcat(q1.qvars1, q2.qvars1), vcat(q1.qvars2, q2.qvars2),
vcat(q1.qcoeffs, -q2.qcoeffs), q1.aff - q2.aff)
(*)(q1::QuadExpr, q2::QuadExpr) = error("Cannot multiply two quadratic expressions")
(/)(q1::QuadExpr, q2::QuadExpr) = error("Cannot divide a quadratic expression by a quadratic expression")

Expand Down Expand Up @@ -198,45 +194,70 @@ for sgn in (:<=, :(==), :>=)
end
end


#############################################################################
# High-level operators
# Currently supported
# - sum
# - dot
#############################################################################

sum{T<:Real}(j::JuMPDict{T}) = sum(j.innerArray)
sum(j::JuMPDict{Variable}) = AffExpr(vec(j.innerArray), ones(length(j.innerArray)), 0.0)
sum(j::Array{Variable}) = AffExpr(vec(j), ones(length(j)), 0.0)
function sum(affs::Array{AffExpr})
n = 0
for aff in affs
n += length(aff.vars)
end
new_aff = AffExpr()
sizehint(new_aff.vars, n)
sizehint(new_aff.coeffs, n)
for aff in affs
for i in 1:length(aff.vars)
push!(new_aff.vars, aff.vars[i])
push!(new_aff.coeffs, aff.coeffs[i])
end
new_aff.constant += aff.constant
end
return new_aff
end


#Vectorization Stuff
function dot{T<:Real}(lhs::Array{T}, rhs::JuMP.JuMPDict{Variable})
function dot{T<:Real}(lhs::Array{T}, rhs::JuMPDict{Variable})
sz = size(lhs)
if length(rhs.indexsets) == 1
# Single dimension version
if length(sz) == 2
@assert sz[1] == 1 || sz[2] == 1
@assert sz[1] == 1 && sz[2] == length(rhs.indexsets[1]) ||
sz[2] == 1 && sz[1] == length(rhs.indexsets[1])
return AffExpr(rhs.innerArray, float(lhs[:]), 0.0)
sz[2] == 1 && sz[1] == length(rhs.indexsets[1])
elseif length(sz) == 1
@assert sz[1] == length(rhs.indexsets[1])
return AffExpr(rhs.innerArray,float(lhs),0.0)
end
elseif length(rhs.indexsets) == 2
# 2D JuMPDict
@assert length(rhs.indexsets[1]) == sz[1] &&
length(rhs.indexsets[2]) == sz[2]
return AffExpr(vec(rhs.innerArray), vec(float(lhs)), 0.0)
elseif length(rhs.indexsets) == 3
#3D JuMPDict
@assert length(rhs.indexsets[1]) == sz[1] &&
length(rhs.indexsets[2]) == sz[2] &&
length(rhs.indexsets[3]) == sz[3]
return AffExpr(vec(rhs.innerArray),vec(float(lhs)),0.0)
else
error("Dot products of matrices higher than 3D not supported.")
end

dot(lhs,rhs.innerArray)
end
dot{T<:Real}(lhs::JuMPDict{Variable},rhs::Array{T}) = dot(rhs,lhs)
dot{T<:Real}(lhs::Array{T}, rhs::JuMPDict{Float64}) = dot(vec(lhs), vec(rhs.innerArray))
dot{T<:Real}(lhs::JuMPDict{Float64}, rhs::Array{T}) = dot(vec(rhs), vec(lhs.innerArray))
dot{T<:Real}(lhs::Array{T}, rhs::Array{Variable}) = AffExpr(vec(rhs), vec(float(lhs)), 0.0)
dot{T<:Real}(rhs::Array{Variable}, lhs::Array{T}) = AffExpr(vec(rhs), vec(float(lhs)), 0.0)

############################################

#############################################################################
# JuMPDict comparison operators (all errors)

for sgn in (:<=, :(==), :>=)
for term in (:Real, :Variable, :AffExpr)
@eval $(sgn)(a::JuMPDict, b::$(term)) = error("Cannot construct constraint with a JuMPDict term")
Expand Down
45 changes: 41 additions & 4 deletions test/operator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,44 @@ q3 = 2.0 * x * x + 1.0 * y * y + z + 3.0


# Higher-level operators
@defVar(m, matrix[1:3,1:3])
@test affToStr(sum(matrix)) == "1.0 matrix[1,1] + 1.0 matrix[2,1] + 1.0 matrix[3,1] + 1.0 matrix[1,2] + 1.0 matrix[2,2] + 1.0 matrix[3,2] + 1.0 matrix[1,3] + 1.0 matrix[2,3] + 1.0 matrix[3,3]"
@setObjective(m, Min, sum(matrix))
@test quadToStr(m.obj) == "1.0 matrix[1,1] + 1.0 matrix[2,1] + 1.0 matrix[3,1] + 1.0 matrix[1,2] + 1.0 matrix[2,2] + 1.0 matrix[3,2] + 1.0 matrix[1,3] + 1.0 matrix[2,3] + 1.0 matrix[3,3]"
# sum
let
sum_m = Model()
@defVar(sum_m, 0 <= matrix[1:3,1:3] <= 1)
# sum(j::JuMPDict{Variable})
@test affToStr(sum(matrix)) == "1.0 matrix[1,1] + 1.0 matrix[2,1] + 1.0 matrix[3,1] + 1.0 matrix[1,2] + 1.0 matrix[2,2] + 1.0 matrix[3,2] + 1.0 matrix[1,3] + 1.0 matrix[2,3] + 1.0 matrix[3,3]"
# sum(j::JuMPDict{Variable}) in a macro
@setObjective(sum_m, Max, sum(matrix))
@test quadToStr(sum_m.obj) == "1.0 matrix[1,1] + 1.0 matrix[2,1] + 1.0 matrix[3,1] + 1.0 matrix[1,2] + 1.0 matrix[2,2] + 1.0 matrix[3,2] + 1.0 matrix[1,3] + 1.0 matrix[2,3] + 1.0 matrix[3,3]"
solve(sum_m)
# sum{T<:Real}(j::JuMPDict{T})
@test_approx_eq_eps sum(getValue(matrix)) 9.0 1e-6
# sum(j::Array{Variable})
@test affToStr(sum(matrix[1:3,1:3])) == affToStr(sum(matrix))
# sum(affs::Array{AffExpr})
@test affToStr(sum([2.0*matrix[i,j] for i in 1:3, j in 1:3])) == "2.0 matrix[1,1] + 2.0 matrix[2,1] + 2.0 matrix[3,1] + 2.0 matrix[1,2] + 2.0 matrix[2,2] + 2.0 matrix[3,2] + 2.0 matrix[1,3] + 2.0 matrix[2,3] + 2.0 matrix[3,3]"
end

# dot
let
dot_m = Model()
@defVar(dot_m, 0 <= x[1:3] <= 1)
c = [1:3]
@test affToStr(dot(c,x)) == "1.0 x[1] + 2.0 x[2] + 3.0 x[3]"
@test affToStr(dot(x,c)) == "1.0 x[1] + 2.0 x[2] + 3.0 x[3]"

A = [1 3 ; 2 4]
@defVar(dot_m, 1 <= y[1:2,1:2] <= 1)
@test affToStr(dot(A,y)) == "1.0 y[1,1] + 2.0 y[2,1] + 3.0 y[1,2] + 4.0 y[2,2]"
@test affToStr(dot(y,A)) == "1.0 y[1,1] + 2.0 y[2,1] + 3.0 y[1,2] + 4.0 y[2,2]"

B = ones(2,2,2)
@defVar(dot_m, 0 <= z[1:2,1:2,1:2] <= 1)
@test affToStr(dot(B,z)) == "1.0 z[1,1,1] + 1.0 z[2,1,1] + 1.0 z[1,2,1] + 1.0 z[2,2,1] + 1.0 z[1,1,2] + 1.0 z[2,1,2] + 1.0 z[1,2,2] + 1.0 z[2,2,2]"
@test affToStr(dot(z,B)) == "1.0 z[1,1,1] + 1.0 z[2,1,1] + 1.0 z[1,2,1] + 1.0 z[2,2,1] + 1.0 z[1,1,2] + 1.0 z[2,1,2] + 1.0 z[1,2,2] + 1.0 z[2,2,2]"

@setObjective(dot_m, Max, dot(x, ones(3)) - dot(y, ones(2,2)) )
solve(dot_m)
@test_approx_eq_eps dot(c, getValue(x)) 6.0 1e-6
@test_approx_eq_eps dot(A, getValue(y)) 10.0 1e-6
end
3 changes: 1 addition & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ tests = ["expr.jl",
"model.jl",
"probmod.jl",
"callback.jl",
"sosmodel.jl",
"vector_validity.jl"]
"sosmodel.jl"]

println("Running tests:")

Expand Down
15 changes: 0 additions & 15 deletions test/vector_validity.jl

This file was deleted.

0 comments on commit 249a449

Please sign in to comment.