diff --git a/src/Convex.jl b/src/Convex.jl index daecf542a..bc1f24d9e 100644 --- a/src/Convex.jl +++ b/src/Convex.jl @@ -56,6 +56,7 @@ export Positive, Negative, ComplexSign, NoSign # Problems export add_constraints!, maximize, minimize, Problem, satisfy, solve! +export write_to_file # Module level globals diff --git a/src/problems.jl b/src/problems.jl index f7f83bd3c..e5ee28e7c 100644 --- a/src/problems.jl +++ b/src/problems.jl @@ -235,3 +235,32 @@ end function add_constraint!(p::Problem, constraint::Constraint) return add_constraints!(p, constraint) end + +""" + write_to_file(problem::Problem{Float64}, filename::String) + +Write the current problem to the file at `filename`. + +Requires solving the problem at least once using [`solve!`](@ref) to ensure that +the problem is loaded into a MathOptInterface model. + +The file format is inferred from the filename extension. Supported file +types depend on the model type. + +Currently, `Float64` is the only supported coefficient type. This may be +relaxed in future if file formats support other types. +""" +function write_to_file(p::Problem{T}, filename::String) where {T<:Float64} + if isnothing(p.model) + msg = """ + Problem has not been loaded into a MathOptInterface model; + call `solve!(problem, optimizer)` before writing problem to file. + """ + throw(ArgumentError(msg)) + end + dest = MOI.FileFormats.Model(; filename) + model = MOI.Bridges.full_bridge_optimizer(dest, T) + MOI.copy_to(model, p.model) + MOI.write_to_file(dest, filename) + return +end diff --git a/test/test_utilities.jl b/test/test_utilities.jl index b113e39ad..197a29e09 100644 --- a/test/test_utilities.jl +++ b/test/test_utilities.jl @@ -922,6 +922,20 @@ function test_ProbabilityVectors() return end +function test_write_to_file() + x = Variable(3) + p = minimize(logsumexp(x)) + dir = mktempdir() + filename = joinpath(dir, "test.mof.json") + @test_throws ArgumentError write_to_file(p, filename) + solve!(p, SCS.Optimizer; silent_solver = true) + write_to_file(p, filename) + @test occursin("ExponentialCone", read(filename, String)) + p_int = minimize(logsumexp(x); numeric_type = Int) + @test_throws MethodError write_to_file(p_int, filename) + return +end + end # TestUtilities TestUtilities.runtests()