Skip to content
This repository has been archived by the owner on Jun 14, 2020. It is now read-only.

Add bridges #34

Open
odow opened this issue Jun 30, 2018 · 7 comments
Open

Add bridges #34

odow opened this issue Jun 30, 2018 · 7 comments

Comments

@odow
Copy link
Member

odow commented Jun 30, 2018

We can remove some of the complexity in LQOI by using bridges.
For VectorAffineFunction -> lots of scalaraffinefunctions
For VectorOfVariables-in-Nonpositives -> lots of scalaraffinefunctions-in-greaterthan etc

@blegat
Copy link
Member

blegat commented Jun 30, 2018

What is currently done in LQOI for VectorAffineFunction ? They are transformed into ScalarAffineFunctions or they are passes into the solver as is ?

@odow
Copy link
Member Author

odow commented Jun 30, 2018

We add them as a block so it might be slightly more efficient:

function addlinearconstraint!(m::LinQuadOptimizer, func::VecLin, sense::Cchar)
outputindex = [term.output_index for term in func.terms]
columns = [getcol(m, term.scalar_term.variable_index) for term in func.terms]
coefficients = [term.scalar_term.coefficient for term in func.terms]
# sort into row order
pidx = sortperm(outputindex)
permute!(columns, pidx)
permute!(coefficients, pidx)
# check that there is at least a RHS for each row
@assert maximum(outputindex) <= length(func.constants)
# loop through to get starting position of each row
row_pointers = Vector{Int}(length(func.constants))
row_pointers[1] = 1
row = 1
for i in 2:length(pidx)
if outputindex[pidx[i]] != outputindex[pidx[i-1]]
row += 1
row_pointers[row] = i
end
end
A = CSRMatrix{Float64}(row_pointers, columns, coefficients)
add_linear_constraints!(m, A, fill(sense, length(func.constants)), -func.constants)
end

But the deleting etc happens row by row.

@joaquimg might disagree, but I think the added complexity is outweighed by the additional maintenance. Having bridges allows other solvers to avoid re-implementing.

The vectorofvariables happens here:

function MOI.addconstraint!(m::LinQuadOptimizer, func::VecVar, set::S) where S <: VecLinSets
@assert length(func.variables) == MOI.dimension(set)
m.last_constraint_reference += 1
ref = VVCI{S}(m.last_constraint_reference)
rows = get_number_linear_constraints(m)
n = MOI.dimension(set)
add_linear_constraints!(m,
CSRMatrix{Float64}(collect(1:n), getcol.(m, func.variables), ones(n)),
fill(backend_type(m, set),n),
zeros(n)
)
dict = constrdict(m, ref)
dict[ref] = collect(rows+1:rows+n)
append!(m.constraint_primal_solution, fill(NaN,n))
append!(m.constraint_dual_solution, fill(NaN,n))
append!(m.constraint_constant, fill(0.0,n))
return ref
end

Which is also added maintenance in LQOI for little performance gain.

@IssamT
Copy link
Contributor

IssamT commented Jun 30, 2018

Just adding a precision. If someone needs to pass a block of constraints and only cares about performance, he can still use MOI.add_constraints() with separate constraints.

So keeping it as it is now (without a bridge) is more for people who both care about this little performance gain and want to model their problem in a vectorized way.

@joaquimg
Copy link
Member

joaquimg commented Jul 6, 2018

I hope I am wrong, but we are giving up on efficiency in so many places that we might end up with poor performance. Anyway we will see when there are benchmarks against mpb.
Anyway, the right way to add multiple constraints is MOI.add_constraints as @IssamT mentioned. I agree with this change for vector affine.
Will this be a problem for direct mode?
We will store an extra copy?

@odow
Copy link
Member Author

odow commented Jul 6, 2018

The bridge should probably add them via add_constraints, then it is up to the solver to supply an efficient implementation. Then it is no problem. Direct mode is fine (if you have a bridge), and we won't store an extra copy.

@blegat
Copy link
Member

blegat commented Jul 6, 2018

Agreed, the bridge should use add_constraints.
The bridges can be used in Direct mode, it does not need the CachingOptimizer at all.
It currently stores a copy of every bridged constraint (e.g. so that MOI.ConstraintSet and MOI.ConstraintFunction can be got) but we can add an option to disable that.

@odow
Copy link
Member Author

odow commented Aug 7, 2018

For VectorAffine->ScalarAffine, see jump-dev/MathOptInterface.jl#413

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants