Skip to content

Commit

Permalink
Merge branch 'sdp_symmetry'
Browse files Browse the repository at this point in the history
Conflicts:
	src/constraints/sdp_constraints.jl
	src/solution.jl
	src/variable.jl
  • Loading branch information
karanveerm committed Jan 6, 2015
2 parents f51c75b + 2dd5954 commit 161bde6
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 33 deletions.
11 changes: 5 additions & 6 deletions src/constraints/sdp_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ type SDPConstraint <: Constraint
id_hash::Uint64
child::AbstractExpr
size::(Int, Int)
is_symmetric::Bool

function SDPConstraint(child::AbstractExpr; is_symmetric=true)
function SDPConstraint(child::AbstractExpr)
sz = child.size
if sz[1] != sz[2]
error("Positive semidefinite expressions must be square")
end
return new(:sdp, hash(child), child, sz, is_symmetric)
return new(:sdp, hash(child), child, sz)
end
end

Expand All @@ -29,8 +28,7 @@ end

function conic_form!(c::SDPConstraint, unique_conic_forms::UniqueConicForms)
if !has_conic_form(unique_conic_forms, c)
objective = conic_form!(c.child, unique_conic_forms)
if c.is_symmetric
if (isdefined(:SCSSolver) || (isdefined(:SCS) && get_default_solver() == SCS.SCSSolver()))
n,m = size(c.child)
for i=1:n
for j=i+1:m
Expand All @@ -39,10 +37,11 @@ function conic_form!(c::SDPConstraint, unique_conic_forms::UniqueConicForms)
end
end
end
objective = conic_form!(c.child, unique_conic_forms)
cache_conic_form!(unique_conic_forms, c, ConicConstr([objective], :SDP, [c.size[1] * c.size[2]]))
end
return get_conic_form(unique_conic_forms, c)
end

isposdef(x::AbstractExpr; is_symmetric=true) = SDPConstraint(x, is_symmetric=is_symmetric)
isposdef(x::AbstractExpr) = SDPConstraint(x)

10 changes: 4 additions & 6 deletions src/constraints/signs_and_sets.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
export conic_form!

conic_form!(s::Positive, x::Variable, unique_conic_forms) = conic_form!(x>=0, unique_conic_forms)
conic_form!(s::Negative, x::Variable, unique_conic_forms) = conic_form!(x<=0, unique_conic_forms)
conic_form!(s::Positive, x::Variable, unique_conic_forms) = conic_form!(x>=0, unique_conic_forms)
conic_form!(s::Negative, x::Variable, unique_conic_forms) = conic_form!(x<=0, unique_conic_forms)

function conic_form!(set::Symbol, x::Variable, unique_conic_forms)
if set==:Semidefinite
conic_form!(SDPConstraint(x; is_symmetric=true), unique_conic_forms)
elseif set==:AsymSemidefinite
conic_form!(SDPConstraint(x; is_symmetric=false), unique_conic_forms)
conic_form!(SDPConstraint(x), unique_conic_forms)
end
end
end
12 changes: 8 additions & 4 deletions src/solution.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ import MathProgBase
export solve!

function solve!(problem::Problem,
m::MathProgBase.AbstractMathProgModel=get_default_solver();
s::MathProgBase.AbstractMathProgSolver=get_default_solver();
warmstart=true)

m = MathProgBase.model(s)
# TODO: This is a tiny, temporary hack that will be removed once SCS.jl or SCS
# starts to take care of symmetry constraints.
old_solver = get_default_solver()
set_default_solver(s)
c, A, b, cones, var_to_ranges, vartypes = conic_problem(problem)
set_default_solver(old_solver)

if problem.head == :maximize
c = -c
end
Expand Down Expand Up @@ -60,9 +67,6 @@ function solve!(problem::Problem,
end
end

solve!(problem::Problem, m::MathProgBase.AbstractMathProgSolver) =
solve!(problem, MathProgBase.model(m))

function populate_variables!(problem::Problem, var_to_ranges::Dict{Uint64, (Int, Int)})
x = problem.solution.primal
for (id, (start_index, end_index)) in var_to_ranges
Expand Down
13 changes: 5 additions & 8 deletions src/variable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ type Variable <: AbstractExpr
sign::Sign
sets # ::Array{Symbol,1}

# is_symmetric is only needed for Semidefinite atoms. Value is ignored for everything else
# If you wish to force symmetricity for other variables, add x == x' as a constraint
function Variable(size::(Int, Int), sign::Sign=NoSign(), sets::Symbol...)
this = new(:variable, 0, nothing, size, AffineVexity(), sign, sets)
this.id_hash = object_id(this)
Expand All @@ -32,17 +30,16 @@ type Variable <: AbstractExpr
Variable(size::Int, sets::Symbol...) = Variable((size, 1), sets...)
end

# convenience semidefinite matrix constructor
Semidefinite(m::Int; is_symmetric=true) = Variable((m,m), is_symmetric ? :Semidefinite : :AsymSemidefinite)
function Semidefinite(m::Int, n::Int; is_symmetric=true)
Semidefinite(m::Integer) = Variable((m,m), :Semidefinite)
function Semidefinite(m::Integer, n::Integer)
if m==n
return Variable((m,m), is_symmetric ? :Semidefinite : :AsymSemidefinite)
else
return Variable((m,m), :Semidefinite)
else
error("Semidefinite matrices must be square")
end
end

# global map from unique variable ids to variables.
# global map from unique variable ids to variables.
# the expression tree will only utilize variable ids during construction
# full information of the variables will be needed during stuffing
# and after solving to populate the variables with values
Expand Down
2 changes: 1 addition & 1 deletion test/run_tests_all_solvers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ end

if isdir(Pkg.dir("SCS"))
using SCS
push!(solvers, SCSSolver())
push!(solvers, SCSSolver(verbose=0))
end

if isdir(Pkg.dir("Gurobi"))
Expand Down
11 changes: 3 additions & 8 deletions test/test_sdp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ solve!(p)
@test_approx_eq_eps p.optval 0 TOL

# Solution is obtained as y[2,2] -> infinity
# This test fails on Mosek. See
# https://github.com/JuliaOpt/Mosek.jl/issues/29
y = Variable((2, 2), :Semidefinite)
p = minimize(y[1, 1], y[1, 2] == 1)
solve!(p)
Expand All @@ -40,13 +42,6 @@ p = minimize(y[1, 2], y[2, 1] == 1)
solve!(p)
@test_approx_eq_eps p.optval 1 TOL

# Not symmetric
x = Variable(Positive())
y = Semidefinite(3, is_symmetric=false)
p = minimize(y[1, 2], y[2, 1] == 1, y[1, 2] >= -1000)
solve!(p)
@test_approx_eq_eps p.optval -1000 TOL

# trace
y = Variable((3, 3), :Semidefinite)
p = minimize(trace(y), y[2,1]<=4, y[2,2]>=3)
Expand Down Expand Up @@ -81,4 +76,4 @@ solve!(p)
y = Semidefinite(3)
p = maximize(lambda_min(y), trace(y)<=6)
solve!(p)
@test_approx_eq_eps p.optval 2 TOL
@test_approx_eq_eps p.optval 2 TOL

0 comments on commit 161bde6

Please sign in to comment.