From 5ff64bd26b1d818605299aaa8d09c2d7e65e7f64 Mon Sep 17 00:00:00 2001
From: Bartolomeo Stellato <bartolomeo.stellato@gmail.com>
Date: Sat, 31 Aug 2019 17:15:19 -0400
Subject: [PATCH 1/5] Updated for OSQP v0.6.0. Fixed #60

---
 .editorconfig       | 12 ++++++++++++
 deps/build.jl       |  2 +-
 src/MOI_wrapper.jl  | 15 +++++++--------
 src/OSQP.jl         |  5 +++--
 src/constants.jl    |  2 +-
 src/interface.jl    | 18 +++++++++++++-----
 test/MOI_wrapper.jl |  1 +
 test/basic.jl       |  6 ++++--
 8 files changed, 42 insertions(+), 19 deletions(-)
 create mode 100644 .editorconfig

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..779f99a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/deps/build.jl b/deps/build.jl
index f86a7ea..223d260 100644
--- a/deps/build.jl
+++ b/deps/build.jl
@@ -5,7 +5,7 @@ const verbose = "--verbose" in ARGS
 const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr")))
 
 # Current version
-version = "0.5.0"
+version = "0.6.0"
 
 # Get current operating system
 osqp_platform =
diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl
index a37531d..ec4c423 100644
--- a/src/MOI_wrapper.jl
+++ b/src/MOI_wrapper.jl
@@ -88,14 +88,13 @@ MOI.get(::Optimizer, ::MOI.SolverName) = "OSQP"
 
 MOI.supports(::Optimizer, ::MOI.Silent) = true
 function MOI.set(optimizer::Optimizer, ::MOI.Silent, value::Bool)
-    if optimizer.silent != value
-        optimizer.silent = value
-        if !MOI.is_empty(optimizer)
-            if optimizer.silent
-                OSQP.update_settings!(optimizer.inner; :verbose => false)
-            else
-                OSQP.update_settings!(optimizer.inner; :verbose => optimizer.settings[:verbose])
-            end
+    optimizer.silent = value
+    optimizer.settings[:verbose] = !value
+    if !MOI.is_empty(optimizer)
+        if optimizer.silent
+            OSQP.update_settings!(optimizer.inner; :verbose => false)
+        else
+            OSQP.update_settings!(optimizer.inner; :verbose => optimizer.settings[:verbose])
         end
     end
 end
diff --git a/src/OSQP.jl b/src/OSQP.jl
index d6aeb2c..4a7f7d5 100644
--- a/src/OSQP.jl
+++ b/src/OSQP.jl
@@ -2,6 +2,7 @@ module OSQP
 
 export OSQPMathProgBaseInterface
 using SparseArrays
+using LinearAlgebra
 
 
 if isfile(joinpath(dirname(@__FILE__), "..", "deps", "deps.jl"))
@@ -19,8 +20,8 @@ function __init__()
 
 
     depsdir = realpath(joinpath(dirname(@__FILE__), "..", "deps"))
-    if (vnum.major != 0 && vnum.minor != 4)
-        error("Current OSQP version installed is $(osqp_version()), but we require version 0.4.*. Delete the contents of the `$depsdir` directory except for the files `build.jl` and `.gitignore`, then rerun Pkg.build(\"OSQP\").")
+    if (vnum.major != 0 && vnum.minor != 6)
+        error("Current OSQP version installed is $(osqp_version()), but we require version 0.6.*. Delete the contents of the `$depsdir` directory except for the files `build.jl` and `.gitignore`, then rerun Pkg.build(\"OSQP\").")
     end
 end
 
diff --git a/src/constants.jl b/src/constants.jl
index 41ab7c3..3f4c215 100644
--- a/src/constants.jl
+++ b/src/constants.jl
@@ -2,7 +2,7 @@ const QDLDL_SOLVER = 0
 const MKL_PARDISO_SOLVER = 1
 
 # Define OSQP infinity constants
-const OSQP_INFTY = 1e20
+const OSQP_INFTY = 1e30
 
 # OSQP return values
 # https://github.com/oxfordcontrol/osqp/blob/master/include/constants.h
diff --git a/src/interface.jl b/src/interface.jl
index 6789df0..89164fd 100644
--- a/src/interface.jl
+++ b/src/interface.jl
@@ -112,6 +112,11 @@ function setup!(model::OSQP.Model;
         A = sparse(A)
     end
 
+    # Constructing upper triangular from P
+    if !istriu(P)
+        P = triu(P)
+    end
+
     # Convert lower and upper bounds from Julia infinity to OSQP infinity
     u = min.(u, OSQP_INFTY)
     l = max.(l, -OSQP_INFTY)
@@ -146,12 +151,16 @@ function setup!(model::OSQP.Model;
                         pointer(q),
                         pointer(l), pointer(u))
 
+
         # Perform setup
-        model.workspace = ccall((:osqp_setup, OSQP.osqp), Ptr{OSQP.Workspace},
-            (Ptr{OSQP.Data}, Ptr{OSQP.Settings}), Ref(data), Ref(stgs))
+	workspace = Ref{Ptr{OSQP.Workspace}}()
+        exitflag = ccall((:osqp_setup, OSQP.osqp), Cc_int,
+	                 (Ptr{Ptr{OSQP.Workspace}}, Ptr{OSQP.Data}, Ptr{OSQP.Settings}),
+			 workspace, Ref(data), Ref(stgs))
+	model.workspace = workspace[]
     end
 
-    if model.workspace == C_NULL
+    if exitflag != 0
         error("Error in OSQP setup")
     end
 
@@ -160,8 +169,7 @@ end
 
 function solve!(model::OSQP.Model, results::Results = Results())
     ccall((:osqp_solve, OSQP.osqp), Cc_int,
-             (Ptr{OSQP.Workspace}, ),
-             model.workspace)
+             (Ptr{OSQP.Workspace}, ), model.workspace)
     workspace = unsafe_load(model.workspace)
     info = results.info
     copyto!(info, unsafe_load(workspace.info))
diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl
index 40327f0..0063b6c 100644
--- a/test/MOI_wrapper.jl
+++ b/test/MOI_wrapper.jl
@@ -342,6 +342,7 @@ term(c, x::MOI.VariableIndex, y::MOI.VariableIndex) = MOI.ScalarQuadraticTerm(c,
 
     # update settings
     @test optimizer.results.info.status_polish == 0
+    print("ERROR STUFF")
     MOI.set(optimizer, OSQPSettings.Polish(), true)
     MOI.optimize!(optimizer)
     @test optimizer.results.info.status_polish == 1
diff --git a/test/basic.jl b/test/basic.jl
index a9e31f3..5a5372a 100644
--- a/test/basic.jl
+++ b/test/basic.jl
@@ -145,14 +145,16 @@ tol = 1e-5
 
         model = OSQP.Model()
         OSQP.setup!(model; P=problem[:P], q=problem[:q],
-                    A=problem[:A], l=problem[:l], u=problem[:u],  options...)
+                    A=problem[:A], l=problem[:l], u=problem[:u], options...)
         results = OSQP.solve!(model)
 
 
         @test results.info.status == :Solved
 
         # Ensure solver will time out
-        OSQP.update_settings!(model, time_limit=1e-6, max_iter=1000000, check_termination=0)
+        OSQP.update_settings!(model,
+			      eps_abs=1e-20, eps_rel=1e-20,
+			      time_limit=1e-6, max_iter=1000000, check_termination=0)
 
         results_time_limit = OSQP.solve!(model)
 

From a8bea98abf91a9a6357dbc96fe745dce813ad29a Mon Sep 17 00:00:00 2001
From: Bartolomeo Stellato <bartolomeo.stellato@gmail.com>
Date: Sat, 31 Aug 2019 20:10:20 -0400
Subject: [PATCH 2/5] Add TimeLimitSec. Fixes #58

---
 src/MOI_wrapper.jl         | 20 ++++++++++++++++++++
 test/MOI_wrapper.jl        |  5 +----
 test/dual_infeasibility.jl |  4 ++--
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl
index ec4c423..4b3e292 100644
--- a/src/MOI_wrapper.jl
+++ b/src/MOI_wrapper.jl
@@ -100,6 +100,26 @@ function MOI.set(optimizer::Optimizer, ::MOI.Silent, value::Bool)
 end
 MOI.get(optimizer::Optimizer, ::MOI.Silent) = optimizer.silent
 
+
+
+MOI.supports(::Optimizer, ::MOI.TimeLimitSec) = true
+function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, limit::Real)
+    MOI.set(model, OSQPSettings.TimeLimit(), limit)
+    return
+end
+
+function MOI.set(model::Optimizer, attr::MOI.TimeLimitSec, ::Nothing)
+    delete!(model.settings, :time_limit)
+    OSQP.update_settings!(model.inner, time_limit=0.0)
+    return
+end
+
+function MOI.get(model::Optimizer, ::MOI.TimeLimitSec)
+    return get(model.settings, :time_limit, nothing)
+end
+
+
+
 hasresults(optimizer::Optimizer) = optimizer.hasresults
 
 function MOI.empty!(optimizer::Optimizer)
diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl
index 0063b6c..8ffe830 100644
--- a/test/MOI_wrapper.jl
+++ b/test/MOI_wrapper.jl
@@ -112,9 +112,7 @@ function bridged_optimizer()
 end
 
 @testset "CachingOptimizer: unit" begin
-    excludes = [# TODO
-                "time_limit_sec",
-                # Quadratic constraints are not supported
+    excludes = [# Quadratic constraints are not supported
                 "solve_qcp_edge_cases",
                 # No method get(::Optimizer, ::MathOptInterface.ConstraintPrimal, ::MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64},MathOptInterface.Nonpositives})
                 "solve_duplicate_terms_vector_affine",
@@ -342,7 +340,6 @@ term(c, x::MOI.VariableIndex, y::MOI.VariableIndex) = MOI.ScalarQuadraticTerm(c,
 
     # update settings
     @test optimizer.results.info.status_polish == 0
-    print("ERROR STUFF")
     MOI.set(optimizer, OSQPSettings.Polish(), true)
     MOI.optimize!(optimizer)
     @test optimizer.results.info.status_polish == 1
diff --git a/test/dual_infeasibility.jl b/test/dual_infeasibility.jl
index 76411ad..5e75cd2 100644
--- a/test/dual_infeasibility.jl
+++ b/test/dual_infeasibility.jl
@@ -2,7 +2,7 @@ function setup_dual_infeasibility()
         options = Dict(:verbose => false,
                        :eps_abs => 1e-05,
                        :eps_rel => 1e-05,
-               :eps_prim_inf => 1e-18,
+               :eps_prim_inf => 1e-15,
                :check_termination => 1)
     return options
 end
@@ -56,7 +56,7 @@ tol = 1e-5
         OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...)
 
         # Warm start to avoid infeasibility detection at first step
-        OSQP.warm_start!(model, x=[25.; 25], y=[-2.; -2; -2; -2])
+        OSQP.warm_start!(model, x=[50.; 30.], y=[-2.; -2; -2; -2])
 
         results = OSQP.solve!(model)
 

From ff9bb43ac89ccd350fc97f51f6e66afd3e7b69a0 Mon Sep 17 00:00:00 2001
From: Bartolomeo Stellato <bartolomeo.stellato@gmail.com>
Date: Sun, 1 Sep 2019 11:07:25 -0400
Subject: [PATCH 3/5] Removed editorconfig

---
 .editorconfig | 12 ------------
 .gitignore    |  1 +
 2 files changed, 1 insertion(+), 12 deletions(-)
 delete mode 100644 .editorconfig

diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index 779f99a..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-root = true
-
-[*]
-indent_style = space
-indent_size = 4
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-
-[*.md]
-trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
index d920beb..fdc0eda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ deps/build.log
 .vscode/
 
 Manifest.toml
+.editorconfig

From aa8f4be9615c5d8ae81c828c10d989897e50bffe Mon Sep 17 00:00:00 2001
From: Bartolomeo Stellato <bartolomeo.stellato@gmail.com>
Date: Sun, 1 Sep 2019 11:17:21 -0400
Subject: [PATCH 4/5] Restored preferred verbose operation. Now silent broken
 again

---
 src/MOI_wrapper.jl | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl
index 4b3e292..3922fc7 100644
--- a/src/MOI_wrapper.jl
+++ b/src/MOI_wrapper.jl
@@ -89,12 +89,11 @@ MOI.get(::Optimizer, ::MOI.SolverName) = "OSQP"
 MOI.supports(::Optimizer, ::MOI.Silent) = true
 function MOI.set(optimizer::Optimizer, ::MOI.Silent, value::Bool)
     optimizer.silent = value
-    optimizer.settings[:verbose] = !value
     if !MOI.is_empty(optimizer)
         if optimizer.silent
             OSQP.update_settings!(optimizer.inner; :verbose => false)
         else
-            OSQP.update_settings!(optimizer.inner; :verbose => optimizer.settings[:verbose])
+            OSQP.update_settings!(optimizer.inner; :verbose => true)
         end
     end
 end

From b7cf688bfef194589c8fa17db1f449a2ee3a0cf3 Mon Sep 17 00:00:00 2001
From: Bartolomeo Stellato <bartolomeo.stellato@gmail.com>
Date: Sun, 1 Sep 2019 12:44:36 -0400
Subject: [PATCH 5/5] Another fix for silent

---
 src/MOI_wrapper.jl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl
index 3922fc7..17c1d78 100644
--- a/src/MOI_wrapper.jl
+++ b/src/MOI_wrapper.jl
@@ -93,7 +93,7 @@ function MOI.set(optimizer::Optimizer, ::MOI.Silent, value::Bool)
         if optimizer.silent
             OSQP.update_settings!(optimizer.inner; :verbose => false)
         else
-            OSQP.update_settings!(optimizer.inner; :verbose => true)
+            OSQP.update_settings!(optimizer.inner; :verbose => optimizer.settings[:verbose])
         end
     end
 end