Skip to content

Commit b152d83

Browse files
authored
Remove Core.Box from split_scalar_matrix (#206)
1 parent fe15ea9 commit b152d83

File tree

2 files changed

+45
-51
lines changed

2 files changed

+45
-51
lines changed

src/constraint.jl

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -36,57 +36,55 @@ function allocateconstraints(m::Optimizer, N::Int)
3636
return id
3737
end
3838

39-
# `putbaraij` and `putbarcj` need the whole matrix as a sum of sparse mat at once
39+
# `putbaraij` and `putbarcj` need the whole matrix as a sum of sparse matrix at
40+
# once.
4041
function split_scalar_matrix(
42+
set_sd_fn::F,
4143
m::Optimizer,
4244
terms::Vector{MOI.ScalarAffineTerm{Float64}},
43-
set_sd::Function,
44-
)
45-
cols = Int32[]
46-
values = Float64[]
45+
) where {F<:Function}
46+
cols, values = Int32[], Float64[]
4747
# `terms` is in canonical form so the variables belonging to the same
4848
# matrix appear adjacent to each other so we can reuse the vector for all
4949
# matrices. Allocating one vector for each matrix can cause performance
5050
# issues; see https://github.com/jump-dev/MosekTools.jl/issues/135
51-
current_matrix = -1
52-
sd_row = Int32[]
53-
sd_col = Int32[]
54-
sd_coef = Float64[]
55-
function add(col::ColumnIndex, coefficient::Float64)
56-
push!(cols, col.value)
57-
return push!(values, coefficient)
58-
end
59-
function add_sd()
60-
if current_matrix != -1
61-
@assert !isempty(sd_row)
62-
id = Mosek.appendsparsesymmat(
63-
m.task,
64-
m.sd_dim[current_matrix],
65-
sd_row,
66-
sd_col,
67-
sd_coef,
68-
)
69-
set_sd(current_matrix, [id], [1.0])
51+
current_matrix = Int32(-1)
52+
sd_row, sd_col, sd_coef = nothing, nothing, nothing
53+
for term in terms
54+
index = mosek_index(m, term.variable)
55+
if index isa ColumnIndex
56+
push!(cols, index.value)
57+
push!(values, term.coefficient)
58+
continue
7059
end
71-
end
72-
function add(mat::MatrixIndex, coefficient::Float64)
73-
@assert mat.matrix != -1
74-
if current_matrix != mat.matrix
75-
add_sd()
76-
current_matrix = mat.matrix
60+
@assert index isa MatrixIndex
61+
@assert index.matrix != -1
62+
if sd_row === sd_col === sd_coef === nothing
63+
sd_row, sd_col, sd_coef = Int32[], Int32[], Float64[]
64+
end
65+
if index.matrix != current_matrix && current_matrix != Int32(-1)
66+
# This marks the start of a new matrix variable. We can flush the
67+
# previous matrix by calling set_sd_fn and empty the associated
68+
# vectors
69+
@assert !isempty(sd_row)
70+
dim = m.sd_dim[current_matrix]
71+
id = Mosek.appendsparsesymmat(m.task, dim, sd_row, sd_col, sd_coef)
72+
set_sd_fn(current_matrix, [id], [1.0])
7773
empty!(sd_row)
7874
empty!(sd_col)
7975
empty!(sd_coef)
8076
end
81-
coef = mat.row == mat.column ? coefficient : coefficient / 2
82-
push!(sd_row, mat.row)
83-
push!(sd_col, mat.column)
84-
return push!(sd_coef, coef)
77+
push!(sd_row, index.row)
78+
push!(sd_col, index.column)
79+
scale = (index.row == index.column ? 1.0 : 0.5)
80+
push!(sd_coef, scale * term.coefficient)
81+
current_matrix = index.matrix
8582
end
86-
for term in terms
87-
add(mosek_index(m, term.variable), term.coefficient)
83+
if current_matrix != Int32(-1)
84+
dim = m.sd_dim[current_matrix]
85+
id = Mosek.appendsparsesymmat(m.task, dim, sd_row, sd_col, sd_coef)
86+
set_sd_fn(current_matrix, [id], [1.0])
8887
end
89-
add_sd()
9088
return cols, values
9189
end
9290

@@ -483,11 +481,9 @@ function MOI.add_constraint(
483481
conid = allocateconstraints(m, 1)
484482
ci = MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},S}(conid)
485483
r = row(m, ci)
486-
cols, values = split_scalar_matrix(
487-
m,
488-
f.terms,
489-
(j, ids, coefs) -> Mosek.putbaraij(m.task, r, j, ids, coefs),
490-
)
484+
cols, values = split_scalar_matrix(m, f.terms) do j, ids, coefs
485+
return Mosek.putbaraij(m.task, r, j, ids, coefs)
486+
end
491487
Mosek.putarow(m.task, r, ColumnIndices(cols).values, values)
492488
_putconbound(m, r, set)
493489
return ci

src/objective.jl

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,18 @@ function MOI.set(
5454
msg = "Cannot set a different objective if a previous objective was set including the contribution of the entry of a PSD variable."
5555
throw(MOI.SetAttributeNotAllowed(attr, msg))
5656
end
57-
cols, values = split_scalar_matrix(
58-
m,
59-
MOI.Utilities.canonical(func).terms,
60-
(j, ids, coefs) -> begin
61-
m.has_psd_in_objective = true
62-
Mosek.putbarcj(m.task, j, ids, coefs)
63-
end,
64-
)
57+
f = MOI.Utilities.canonical(func)
58+
cols, values = split_scalar_matrix(m, f.terms) do j, ids, coefs
59+
m.has_psd_in_objective = true
60+
Mosek.putbarcj(m.task, j, ids, coefs)
61+
return
62+
end
6563
c = zeros(Float64, Mosek.getnumvar(m.task))
6664
for (col, val) in zip(cols, values)
6765
c[col] += val
6866
end
6967
Mosek.putclist(m.task, convert(Vector{Int32}, 1:length(c)), c)
70-
Mosek.putcfix(m.task, func.constant)
68+
Mosek.putcfix(m.task, f.constant)
7169
m.has_objective = true
7270
return
7371
end

0 commit comments

Comments
 (0)