Skip to content

Commit 2ad2b18

Browse files
committed
fixes add changing forms and begin testing
1 parent cd3e963 commit 2ad2b18

File tree

4 files changed

+221
-33
lines changed

4 files changed

+221
-33
lines changed

src/MatrixOptInterface.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ using MathOptInterface
55
const MOI = MathOptInterface
66
const MOIU = MathOptInterface.Utilities
77

8-
export MatrixOptimizer
8+
# export MatrixOptimizer
99

1010
@enum ConstraintSense EQUAL_TO GREATER_THAN LESS_THAN
1111

src/allocate_load.jl

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const CI = MOI.ConstraintIndex
22
const VI = MOI.VariableIndex
33

4-
mutable struct MOISolution{R} where R <: Real
4+
mutable struct MOISolution{R}
55
termination_status::MOI.TerminationStatusCode
66
primal_status::MOI.ResultStatusCode
77
dual_status::MOI.ResultStatusCode
@@ -43,15 +43,28 @@ mutable struct ModelData
4343
c::Vector{Float64}
4444
# variable type
4545
# v_type::Vector{}
46+
# function ModelData()
47+
# new(0,
48+
# 0,
49+
# Int[],
50+
# Int[],
51+
# Float64[],
52+
# Float64[],
53+
# ConstraintSense[],
54+
# NaN,
55+
# Float64[]
56+
# )
57+
# end
4658
end
4759

4860
# This is tied to SCS's internal representation
4961
mutable struct ConeData
62+
nrows::Dict{Int,Int}
5063
eq::Int # number of == constraints
51-
lt::Int # number of <= equality constraints
52-
# gt::Int # number of >= constraints
64+
gt::Int # number of >= constraints
65+
# lt::Int # number of <= equality constraints
5366
function ConeData()
54-
new(0, 0)#, 0)
67+
new(Dict{Int,Int}(), 0, 0)#, 0)
5568
end
5669
end
5770

@@ -63,12 +76,13 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
6376
sol::MOISolution
6477
options
6578
function Optimizer(solve_function = no_solve_function; options...)
66-
new(ConeData(), false, nothing, MOISolution(), options)
79+
new(solve_function, ConeData(), false, nothing, MOISolution(Float64), options)
6780
end
6881
end
6982

7083
function no_solve_function(optimizer::Optimizer)
71-
error("No solver set.")
84+
println("No solver set.")
85+
MOISolution(Float64)
7286
end
7387

7488
MOI.get(::Optimizer, ::MOI.SolverName) = "Matrix optimizer"
@@ -79,7 +93,7 @@ end
7993
function MOI.empty!(optimizer::Optimizer)
8094
optimizer.maxsense = false
8195
optimizer.data = nothing # It should already be nothing except if an error is thrown inside copy_to
82-
optimizer.sol.ret_val = 0
96+
# optimizer.sol.ret_val = 0
8397
end
8498

8599
MOIU.supports_allocate_load(::Optimizer, copy_names::Bool) = !copy_names
@@ -265,9 +279,9 @@ end
265279

266280
function MOI.optimize!(optimizer::Optimizer)
267281
sol = optimizer.solve_function(optimizer)
268-
sol.objval = (optimizer.maxsense ? -1 : 1) *
269-
dot(optimizer.data.c, sol.primal) +
270-
optimizer.objconstant
282+
# sol.objval = (optimizer.maxsense ? -1 : 1) *
283+
# dot(optimizer.data.c, sol.primal) +
284+
# optimizer.objconstant
271285
optimizer.sol = sol
272286
end
273287

@@ -309,4 +323,26 @@ function MOI.get(optimizer::Optimizer, ::MOI.ConstraintDual,
309323
return dual
310324
end
311325

312-
MOI.get(optimizer::Optimizer, ::MOI.ResultCount) = 1
326+
MOI.get(optimizer::Optimizer, ::MOI.ResultCount) = 1
327+
328+
#=
329+
query model data
330+
=#
331+
332+
A_matrix_triplets(data::ModelData) = (data.I, data.J, data.V)
333+
A_matrix_sparse(data::ModelData) = sparse(A_matrix_triplets(data)..., data.m, data.n)
334+
A_matrix_dense(data::ModelData) = Matrix(A_matrix_sparse(data))
335+
336+
337+
function LPSolverForm(optimizer)
338+
data = optimizer.data
339+
raw_lp = LPSolverForm{Float64}(
340+
optimizer.maxsense ? MOI.MAX_SENSE : MOI.MIN_SENSE,
341+
data.c,
342+
A_matrix_dense(data),
343+
data.b,
344+
data.sense,
345+
fill(-Inf, data.n),
346+
fill(Inf, data.n)
347+
)
348+
end

src/matrix_input.jl

Lines changed: 133 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11

22
MOIU.@model(MIPInnerModel,
3-
(MOI.ZeroOne, MOI.Integer),
3+
(),
44
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval),
55
(),
66
(),
7-
(MOI.SingleVariable),
8-
(MOI.ScalarAffineFunction),
7+
(MOI.SingleVariable,),
8+
(MOI.ScalarAffineFunction,),
99
(),
1010
()
1111
)
1212

13-
const Model = MOIU.UniversalFallback{MIPInnerModel{Float64}}
13+
const Model{T} = MOIU.UniversalFallback{MIPInnerModel{T}}
1414

1515
"""
1616
Model()
1717
Create an empty instance of MatrixOptInterface.Model.
1818
"""
19-
function Model()
20-
return MOIU.UniversalFallback(MIPInnerModel{Float64}())
19+
function Model{T}() where T
20+
return MOIU.UniversalFallback(MIPInnerModel{T}())
2121
end
2222

2323
function Base.show(io::IO, ::Model)
2424
print(io, "A MatrixOptInterface Model")
2525
return
2626
end
2727

28-
# abstract type AbstractLPForm{T} end
29-
struct LPMatrixOptInterfaceForm{T}
28+
abstract type AbstractLPForm{T} end
29+
struct LPMatrixOptInterfaceForm{T} <: AbstractLPForm{T}#, V<:AbstractVector{T}, M<:AbstractMatrix{T}}
3030
direction::MOI.OptimizationSense
3131
c::Vector{T}
3232
A::Matrix{T}
@@ -35,19 +35,19 @@ struct LPMatrixOptInterfaceForm{T}
3535
v_lb::Vector{T}
3636
v_ub::Vector{T}
3737
end
38-
struct LPStandardForm{T}# <: AbstractLPForm{T}
38+
struct LPStandardForm{T} <: AbstractLPForm{T}
3939
direction::MOI.OptimizationSense
4040
c::Vector{T}
4141
A::Matrix{T}
4242
b::Vector{T}
4343
end
44-
struct LPCannonicalForm{T}
44+
struct LPCannonicalForm{T} <: AbstractLPForm{T}
4545
direction::MOI.OptimizationSense
4646
c::Vector{T}
4747
A::Matrix{T}
4848
b::Vector{T}
4949
end
50-
struct LPSolverForm{T}
50+
struct LPSolverForm{T} <: AbstractLPForm{T}
5151
direction::MOI.OptimizationSense
5252
c::Vector{T}
5353
A::Matrix{T}
@@ -61,10 +61,11 @@ struct MILP{T}
6161
variable_type
6262
end
6363

64-
function MatrixOptInterfaceForm(lp::MatrixOptInterfaceForm{T}) where T
64+
function change_form(::Type{F}, lp::F) where {F <: AbstractLPForm{T}} where T
6565
return lp
6666
end
67-
function MatrixOptInterfaceForm(lp::LPStandardForm{T}) where T
67+
68+
function change_form(::Type{LPMatrixOptInterfaceForm{T}}, lp::LPStandardForm{T}) where T
6869
return LPMatrixOptInterfaceForm{T}(
6970
lp.direction,
7071
lp.c,
@@ -75,7 +76,7 @@ function MatrixOptInterfaceForm(lp::LPStandardForm{T}) where T
7576
fill(typemax(T), length(lp.c)),
7677
)
7778
end
78-
function MatrixOptInterfaceForm(lp::LPCannonicalForm{T}) where T
79+
function change_form(::Type{LPMatrixOptInterfaceForm{T}}, lp::LPCannonicalForm{T}) where T
7980
return LPMatrixOptInterfaceForm{T}(
8081
lp.direction,
8182
lp.c,
@@ -86,7 +87,7 @@ function MatrixOptInterfaceForm(lp::LPCannonicalForm{T}) where T
8687
fill(typemax(T), length(lp.c)),
8788
)
8889
end
89-
function MatrixOptInterfaceForm(lp::LPSolverForm{T}) where T
90+
function change_form(::Type{LPMatrixOptInterfaceForm{T}}, lp::LPSolverForm{T}) where T
9091
c_lb = fill(typemin(T), length(lp.b))
9192
c_ub = fill(typemax(T), length(lp.b))
9293
for i in eachindex(lp.b)
@@ -112,8 +113,119 @@ function MatrixOptInterfaceForm(lp::LPSolverForm{T}) where T
112113
)
113114
end
114115

116+
function change_form(::Type{LPCannonicalForm{T}}, lp::LPMatrixOptInterfaceForm{T}) where T
117+
has_c_upper = Int[]
118+
has_c_lower = Int[]
119+
sizehint!(has_c_upper, length(lp.c_ub))
120+
sizehint!(has_c_lower, length(lp.c_ub))
121+
for i in eachindex(lp.c_ub)
122+
if lp.c_ub < Inf
123+
push!(has_c_upper, i)
124+
end
125+
if lp.c_lb > -Inf
126+
push!(has_c_lower, i)
127+
end
128+
end
129+
has_v_upper = Int[]
130+
has_v_lower = Int[]
131+
sizehint!(has_v_upper, length(lp.v_ub))
132+
sizehint!(has_v_lower, length(lp.v_ub))
133+
for i in eachindex(lp.v_ub)
134+
if lp.v_ub < Inf
135+
push!(has_v_upper, i)
136+
end
137+
if lp.v_lb > -Inf
138+
push!(has_v_lower, i)
139+
end
140+
end
141+
Id = Matrix{T}(I, length(lp.c), length(lp.c))
142+
new_A = vcat(
143+
lp.A[has_c_upper,:],
144+
-lp.A[has_c_lower,:],
145+
Id[has_v_upper,:],
146+
-Id[has_v_lower,:],
147+
)
148+
new_b = vcat(
149+
lp.c_ub[has_c_upper],
150+
-lp.c_lb[has_c_lower],
151+
lp.v_ub[has_v_upper],
152+
-lp.v_lb[has_v_lower],
153+
)
154+
return LPCannonicalForm{T}(
155+
lp.direction,
156+
lp.c,
157+
new_A,
158+
new_b
159+
)
160+
end
161+
function change_form(::Type{LPCannonicalForm{T}}, lp::F) where {F <: AbstractLPForm{T}} where T
162+
temp_lp = change_form(LPMatrixOptInterfaceForm{T}, lp)
163+
change_form(LPCannonicalForm{T}, lp)
164+
end
165+
166+
function change_form(::Type{LPStandardForm{T}}, lp::LPCannonicalForm{T}) where T
167+
new_A = hcat(
168+
lp.A,
169+
-lp.A,
170+
Matrix{T}(I, length(lp.b), length(lp.b))
171+
)
172+
new_c = vcat(
173+
lp.c,
174+
-lp.c,
175+
fill(0.0, length(lp.b))
176+
)
177+
return LPStandardForm{T}(
178+
lp.direction,
179+
new_c,
180+
new_A,
181+
copy(lp.b)
182+
)
183+
end
184+
function change_form(::Type{LPStandardForm{T}}, lp::F) where {F <: AbstractLPForm{T}} where T
185+
temp_lp = change_form(LPMatrixOptInterfaceForm{T}, lp)
186+
new_lp = change_form(LPCannonicalForm{T}, temp_lp)
187+
change_form(LPStandardForm{T}, new_lp)
188+
end
189+
190+
function change_form(::Type{LPSolverForm{T}}, lp::LPMatrixOptInterfaceForm{T}) where T
191+
new_A = copy(lp.A)
192+
senses = fill(LESS_THAN, length(lp.c_lb))
193+
new_b = fill(NaN, length(lp.c_lb))
194+
for i in eachindex(lp.c_lb)
195+
if lp.c_lb[i] == lp.c_ub[i]
196+
senses[i] = EQUAL_TO
197+
new_b[i] = lp.c_lb[i]
198+
elseif lp.c_lb[i] > -Inf && lp.c_ub[i] < Inf
199+
senses[i] = GREATER_THAN
200+
new_b[i] = lp.c_lb[i]
201+
push!(new_b, lp.c_ub[i])
202+
push!(sense, LESS_THAN)
203+
new_A = vcat(new_A, lp.A[i,:])
204+
elseif lp.c_lb[i] > -Inf
205+
senses[i] = GREATER_THAN
206+
new_b[i] = lp.c_lb[i]
207+
elseif lp.c_ub[i] < Inf
208+
senses[i] = LESS_THAN
209+
new_b[i] = lp.c_ub[i]
210+
end
211+
end
212+
return LPMatrixOptInterfaceForm{T}(
213+
lp.direction,
214+
lp.c,
215+
new_A,
216+
new_b,
217+
senses,
218+
lp.v_lb,
219+
lp.v_ub,
220+
)
221+
end
222+
function change_form(::Type{LPSolverForm{T}}, lp::F) where {F <: AbstractLPForm{T}} where T
223+
temp_lp = change_form(LPMatrixOptInterfaceForm{T}, lp)
224+
change_form(LPSolverForm{T}, temp_lp)
225+
end
226+
115227
"""
116-
reasobale forms:
228+
Possible forms:
117229
118230
A) LP standard form:
119231
@@ -146,20 +258,20 @@ sense = {'<','>','='}
146258
147259
148260
"""
149-
function MatrixOptimizer(raw_lp)
150-
lp = MatrixOptInterfaceForm(raw_lp)
261+
function MatrixOptimizer(raw_lp::F) where {F <: AbstractLPForm{T}} where T
262+
lp = change_form(LPMatrixOptInterfaceForm{T}, raw_lp)
151263
num_variables = length(lp.c)
152264
num_constraints = length(lp.c_lb)
153265

154266
# use caching
155-
optimizer = Model()
267+
optimizer = Model{T}()
156268

157269
x = MOI.add_variables(optimizer, num_variables)
158270

159271
objective_function = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(lp.c, x), 0.0)
160-
MOI.set(optimizer, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
272+
MOI.set(optimizer, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{T}}(),
161273
objective_function)
162-
MOI.set(optimizer, MOI.ObjectiveSense(), lp.sense)
274+
MOI.set(optimizer, MOI.ObjectiveSense(), lp.direction)
163275

164276
# Add constraints
165277
for i in 1:num_constraints

0 commit comments

Comments
 (0)