@@ -80,29 +80,51 @@ function MOI.eval_constraint_jacobian(moiproblem::MOIOptimizationProblem, j, x)
80
80
)
81
81
end
82
82
moiproblem. f. cons_j (moiproblem. J, x)
83
- for i in eachindex (j)
84
- j[i] = moiproblem. J[i]
83
+ if moiproblem. J isa SparseMatrixCSC
84
+ nnz = nonzeros (moiproblem. J)
85
+ @assert length (j) == length (nnz)
86
+ for (i, Ji) in zip (eachindex (j), nnz)
87
+ j[i] = Ji
88
+ end
89
+ else
90
+ for i in eachindex (j)
91
+ j[i] = moiproblem. J[i]
92
+ end
85
93
end
86
94
return
87
95
end
88
96
89
- # Because the Hessian is symmetrical, we choose to store the upper-triangular
90
- # component. We also assume that it is dense.
91
97
function MOI. hessian_lagrangian_structure (moiproblem:: MOIOptimizationProblem )
92
- if moiproblem. H isa SparseMatrixCSC
98
+ sparse_obj = moiproblem. H isa SparseMatrixCSC
99
+ sparse_constraints = all (H -> H isa SparseMatrixCSC, moiproblem. cons_H)
100
+ if ! sparse_constraints && any (H -> H isa SparseMatrixCSC, moiproblem. cons_H)
101
+ # Some constraint hessians are dense and some are sparse! :(
102
+ error (" Mix of sparse and dense constraint hessians are not supported" )
103
+ end
104
+ N = length (moiproblem. u0)
105
+ inds = if sparse_obj
93
106
rows, cols, _ = findnz (moiproblem. H)
94
- inds = Tuple{Int,Int}[(i, j) for (i,j) in zip (rows, cols)]
95
- for ind in 1 : length (moiproblem. cons_H)
96
- r,c,_ = findnz (moiproblem. cons_H[ind])
97
- for (i,j) in zip (r,c)
98
- push! (inds, (i,j))
107
+ Tuple{Int,Int}[(i, j) for (i, j) in zip (rows, cols) if i <= j]
108
+ else
109
+ Tuple{Int,Int}[(row, col) for col in 1 : N for row in 1 : col]
110
+ end
111
+ if sparse_constraints
112
+ for Hi in moiproblem. cons_H
113
+ r, c, _ = findnz (Hi)
114
+ for (i, j) in zip (r, c)
115
+ if i <= j
116
+ push! (inds, (i, j))
117
+ end
99
118
end
100
119
end
101
- return inds
120
+ elseif ! sparse_obj
121
+ # Performance optimization. If both are dense, no need to repeat
102
122
else
103
- num_vars = length (moiproblem. u0)
104
- return Tuple{Int,Int}[(row, col) for col in 1 : num_vars for row in 1 : col]
123
+ for col in 1 : N, row in 1 : col
124
+ push! (inds, (row, col))
125
+ end
105
126
end
127
+ return inds
106
128
end
107
129
108
130
function MOI. eval_hessian_lagrangian (
@@ -112,43 +134,47 @@ function MOI.eval_hessian_lagrangian(
112
134
σ,
113
135
μ,
114
136
) where {T}
115
- if iszero (σ )
116
- fill! (h, zero (T))
117
- else
118
- moiproblem. f . hess (moiproblem . H, x)
119
- k = 0
120
- if moiproblem. H isa SparseMatrixCSC
121
- rows, cols, _ = findnz (moiproblem . H )
122
- for (i, j) in zip (rows, cols)
137
+ fill! (h, zero (T) )
138
+ k = 0
139
+ moiproblem . f . hess (moiproblem . H, x)
140
+ sparse_objective = moiproblem. H isa SparseMatrixCSC
141
+ if sparse_objective
142
+ rows, cols, _ = findnz ( moiproblem. H)
143
+ for (i, j) in zip ( rows, cols)
144
+ if i <= j
123
145
k += 1
124
146
h[k] = σ * moiproblem. H[i, j]
125
147
end
126
- else
127
- for i in 1 : size (moiproblem. H, 1 )
128
- for j in 1 : i
129
- k += 1
130
- h[k] = σ * moiproblem. H[i, j]
131
- end
132
- end
148
+ end
149
+ else
150
+ for i in 1 : size (moiproblem. H, 1 ), j in 1 : i
151
+ k += 1
152
+ h[k] = σ * moiproblem. H[i, j]
133
153
end
134
154
end
155
+ # A count of the number of non-zeros in the objective Hessian is needed if
156
+ # the constraints are dense.
157
+ nnz_objective = k
135
158
if ! isempty (μ) && ! all (iszero, μ)
136
159
moiproblem. f. cons_h (moiproblem. cons_H, x)
137
160
for (μi, Hi) in zip (μ, moiproblem. cons_H)
138
- k = 0
139
161
if Hi isa SparseMatrixCSC
140
162
rows, cols, _ = findnz (Hi)
141
163
for (i, j) in zip (rows, cols)
142
- k += 1
143
- h[k] += μi * Hi[i, j]
144
- end
145
- else
146
- for i in 1 : size (Hi, 1 )
147
- for j in 1 : i
164
+ if i <= j
148
165
k += 1
149
166
h[k] += μi * Hi[i, j]
150
167
end
151
168
end
169
+ else
170
+ # The constraints are dense. We only store one copy of the
171
+ # Hessian, so reset `k` to where it starts. That will be
172
+ # `nnz_objective` if the objective is sprase, and `0` otherwise.
173
+ k = sparse_objective ? nnz_objective : 0
174
+ for i in 1 : size (Hi, 1 ), j in 1 : i
175
+ k += 1
176
+ h[k] += μi * Hi[i, j]
177
+ end
152
178
end
153
179
end
154
180
end
0 commit comments