Skip to content

Commit

Permalink
Merge 96e14cc into cd08c70
Browse files Browse the repository at this point in the history
  • Loading branch information
ararslan committed Jan 17, 2019
2 parents cd08c70 + 96e14cc commit 8753cac
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 36 deletions.
67 changes: 31 additions & 36 deletions src/constant.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,49 @@
export Constant
export vexity, evaluate, sign, conic_form!

struct Constant <: AbstractExpr
ispos(x::Real) = x >= 0
ispos(v::AbstractVecOrMat{<:Real}) = all(ispos, v)
isneg(x::Real) = x <= 0
isneg(v::AbstractVecOrMat{<:Real}) = all(isneg, v)

_size(x::Number) = (1, 1)
_size(x::AbstractVector) = (length(x), 1)
_size(x::AbstractMatrix) = size(x)

_sign(x::Union{Complex,AbstractVecOrMat{<:Complex}}) = ComplexSign()
_sign(x::Value) = ispos(x) ? Positive() :
isneg(x) ? Negative() : NoSign()

struct Constant{T<:Value} <: AbstractExpr
head::Symbol
id_hash::UInt64
value::Value
value::T
size::Tuple{Int, Int}
vexity::Vexity
sign::Sign

function Constant(x::Value, sign::Sign)
sz = (size(x, 1), size(x, 2))
return new(:constant, objectid(x), x, sz, ConstVexity(), sign)
end

function Constant(x::Value, check_sign::Bool=true)
if check_sign
if !isreal(x)
return Constant(x, ComplexSign())
elseif all(xi >= 0 for xi in x)
return Constant(x, Positive())
elseif all(xi <= 0 for xi in x)
return Constant(x, Negative())
end
end
return Constant(x, NoSign())
end
Constant(x::Value, sign::Sign) = new{typeof(x)}(:constant, objectid(x), x, _size(x), sign)
Constant(x::Value, check_sign::Bool=true) = Constant(x, check_sign ? _sign(x) : NoSign())
end
#### Constant Definition end #####

function vexity(x::Constant)
return x.vexity
end
#### Constant Definition end #####

function evaluate(x::Constant)
return x.value
end
vexity(::Constant) = ConstVexity()

function sign(x::Constant)
return x.sign
end
evaluate(x::Constant) = x.value

sign(x::Constant) = x.sign

function real_conic_form(x::Constant)
return vec([real(x.value);])
end
# `real(::Real)` is a no-op and should be optimized out for `Constant{<:Real}`
real_conic_form(x::Constant{<:Number}) = [real(x.value)]
real_conic_form(x::Constant{<:AbstractVecOrMat}) = vec(real(x.value))

function imag_conic_form(x::Constant)
return im*vec([imag(x.value);])
end
# `imag(::Real)` always returns 0, so we can avoid the implicit conversion to `Complex`
# by multiplication with `im` and just use an explicit call to `zeros` with the appropriate
# length
imag_conic_form(x::Constant{<:Real}) = zeros(Complex{typeof(x.value)}, 1)
imag_conic_form(x::Constant{<:AbstractVecOrMat{<:Real}}) = zeros(Complex{eltype(x.value)}, length(x))
imag_conic_form(x::Constant{<:Complex}) = [im * imag(x.value)]
imag_conic_form(x::Constant{<:AbstractVecOrMat{<:Complex}}) = im * vec(imag(x.value))

# We can more efficiently get the length of a constant by asking for the length of its
# value, which Julia can get via Core.arraylen for arrays and knows is 1 for scalars
Expand Down
29 changes: 29 additions & 0 deletions test/test_utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,35 @@
@test size(y) == (2, 1)
end

@testset "Parametric constants" begin
z = Constant([1.0 0.0im; 0.0 1.0])
@test z isa Constant{Matrix{Complex{Float64}}}

# Helper functions
@test Convex.ispos(1)
@test Convex.ispos(0)
@test !Convex.ispos(-1)
@test Convex.ispos([0,1,0])
@test !Convex.ispos([0,-1,0])
@test Convex.isneg(-1)
@test Convex.isneg(0)
@test !Convex.isneg(1)
@test Convex.isneg([0,-1,0])
@test !Convex.isneg([0,1,0])
@test Convex._size(3) == (1, 1)
@test Convex._sign(3) == Positive()
@test Convex._size([-1,1,1]) == (3, 1)
@test Convex._sign([-1,1,1]) == NoSign()
@test Convex._sign([-1,-1,-1]) == Negative()
@test Convex._size([0 0; 0 0]) == (2, 2)
@test Convex._sign([0 0; 0 0]) == Positive()
@test Convex._size(0+1im) == (1, 1)
@test Convex._sign(0+1im) == ComplexSign()

@test Convex.imag_conic_form(Constant(1.0)) == [0.0]
@test Convex.imag_conic_form(Constant([1.0, 2.0])) == [0.0, 0.0]
end

# returns [21]; not sure why
# context("iteration") do
# x = Variable(2,3)
Expand Down

0 comments on commit 8753cac

Please sign in to comment.