Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize ExpAtom #613

Closed
wants to merge 8 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions src/atoms/ExpAtom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,37 @@ function new_conic_form!(context::Context{T}, e::ExpAtom) where {T}
x = e.children[1]
m, n = size(x)
z = Variable(m, n)
for i in 1:m, j in 1:n
f = vcat(x[i, j], 1, z[i, j])
add_constraint!(context, GenericConstraint{MOI.ExponentialCone}(f))
# Naive implementation:
# for i in 1:m, j in 1:n
# f = vcat(x[i, j], 1, z[i, j])
# add_constraint!(context, GenericConstraint{MOI.ExponentialCone}(f))
# end
# return conic_form!(context, z)
# This is slow, since we are indexing on the Convex side, and convex is based around
# vector/matrix operations. We don't want to produce n*m IndexAtoms!
# Instead, we will drop to the MOI level to implement this in terms of scalar operations.
# First, we will get `x` as an MOI.VectorAffineFunction
x_tape = conic_form!(context, x)
ericphanson marked this conversation as resolved.
Show resolved Hide resolved
vaf = to_vaf(x_tape)
# Next, we can extract the individual components of `x` via `MOI.Utilities.scalarize`
xs = MOI.Utilities.scalarize(vaf)
# Now we have a vector of `m*n` ScalarAffineFunctions in order.
# We can likewise lower `z` to a vector of `MOI.VariableIndex`
z_tape = conic_form!(context, z)
zs = z_tape.variables
for i in eachindex(xs, zs)
# Now, we wish to add the constraint `(x[i], 1, z[i]) ∈ MOI.ExponentialCone()`
# however, we have 3 different types: x[i] is a ScalarAffineFunction, 1 is a constant,
# and `z` is a VariableIndex.
# So we can't use `MOI.Utilities.vectorize`. Instead, we will construct a VectorAffineFunction manually.
# First, we construct the VectorAffineTerm's for the first and third components.
terms = [
[MOI.VectorAffineTerm(Int64(1), sat) for sat in xs[i].terms]
MOI.VectorAffineTerm(Int64(3), MOI.ScalarAffineTerm(T(1), zs[i]))
]
# Then we can add in the constants, and we are good to go.
vaf_i = MOI.VectorAffineFunction(terms, [xs[i].constant, T(1), T(0)])
MOI.add_constraint(context.model, vaf_i, MOI.ExponentialCone())
end
return conic_form!(context, z)
return z_tape
end
Loading