@@ -36,57 +36,55 @@ function allocateconstraints(m::Optimizer, N::Int)
3636 return id
3737end
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.
4041function 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
9189end
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
0 commit comments