diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml new file mode 100644 index 0000000..0f66259 --- /dev/null +++ b/.github/workflows/CompatHelper.yml @@ -0,0 +1,22 @@ +name: CompatHelper + +on: + schedule: + - cron: '00 00 * * *' + workflow_dispatch: + +jobs: + CompatHelper: + runs-on: ${{ matrix.os }} + strategy: + matrix: + julia-version: [1.2.0] + julia-arch: [x86] + os: [ubuntu-latest] + steps: + - name: Pkg.add("CompatHelper") + run: julia -e 'using Pkg; Pkg.add("CompatHelper")' + - name: CompatHelper.main() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml new file mode 100644 index 0000000..f49313b --- /dev/null +++ b/.github/workflows/TagBot.yml @@ -0,0 +1,15 @@ +name: TagBot +on: + issue_comment: + types: + - created + workflow_dispatch: +jobs: + TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..10f299a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI +on: + push: + branches: [master] + pull_request: + types: [opened, synchronize, reopened] +jobs: + test: + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - version: '1.0' + os: ubuntu-latest + arch: x64 + - version: '1' + os: ubuntu-latest + arch: x64 + - version: '1' + os: ubuntu-latest + arch: x86 + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: actions/cache@v1 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 + with: + depwarn: error + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v1 + with: + file: lcov.info diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index af2e7b0..0000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -# Documentation: http://docs.travis-ci.com/user/languages/julia/ -language: julia -codecov: true -os: - - linux -julia: - - 1 -notifications: - email: false diff --git a/Project.toml b/Project.toml index 35958c2..9ffa747 100644 --- a/Project.toml +++ b/Project.toml @@ -9,8 +9,8 @@ MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" [compat] -MathOptInterface = "0.9.18" -MutableArithmetics = "0.2.10" +MathOptInterface = "0.10" +MutableArithmetics = "0.3" julia = "1" [extras] diff --git a/README.md b/README.md index 850fa93..26f1972 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ There are two types of complex sets: For instance, `[x y+zim; y-zim w]` is vectorized as `[x, y, w, z]`. -Sets with complex entries **should not** be used with `Single` or `VectorOfVariables` constraints +Sets with complex entries **should not** be used with `VariableIndex` or `VectorOfVariables` constraints as the variables in MathOptInterface are assumed to be real. Indeed, for instance doing ```julia @@ -25,7 +25,7 @@ x, cx = MOI.add_constrained_variable(model, MOI.EqualTo(1 + 2im)) fallbacks to ```julia x = MOI.add_variable(model) -cx = MOI.add_constraint(model, MOI.SingleVariable(x), MOI.EqualTo(1 + 2im)) +cx = MOI.add_constraint(model, x, MOI.EqualTo(1 + 2im)) ``` In the first line, the solvers create a real variable. Moreover, in the bridge from `MOI.ScalarAffineFunction{Complex{T}}`-in-`EqualTo{Complex{T}}` diff --git a/src/Bridges/Variable/psd.jl b/src/Bridges/Variable/psd.jl index ee7f1e8..94c8d9a 100644 --- a/src/Bridges/Variable/psd.jl +++ b/src/Bridges/Variable/psd.jl @@ -54,15 +54,15 @@ function MOIB.Variable.bridge_constrained_variable( k12 = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(n)) k21 = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(2n)) + 1 k22 = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(n)) - X11() = MOI.SingleVariable(variables[k11]) - X12() = MOI.SingleVariable(variables[k12]) + X11() = variables[k11] + X12() = variables[k12] function X21(i, j) I = j J = n + i k21 = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(J - 1)) + I - return MOI.SingleVariable(variables[k21]) + return variables[k21] end - X22() = MOI.SingleVariable(variables[k22]) + X22() = variables[k22] con_11_22 = EQ{T}[] con12diag = EQ{T}[] con_12_21 = EQ{T}[] @@ -159,7 +159,7 @@ function _matrix_indices(k) return i, j end -function _variable_map(idx::MOIB.Variable.IndexInVector, n) +function _variable_map(idx::MOIB.IndexInVector, n) N = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(n)) if idx.value <= N return idx.value @@ -168,7 +168,7 @@ function _variable_map(idx::MOIB.Variable.IndexInVector, n) return N + j * n + MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(j)) + i end end -function _variable(bridge::HermitianToSymmetricPSDBridge, i::MOIB.Variable.IndexInVector) +function _variable(bridge::HermitianToSymmetricPSDBridge, i::MOIB.IndexInVector) return bridge.variables[_variable_map(i, length(bridge.con12diag))] end @@ -177,7 +177,7 @@ function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintPrimal, values = MOI.get(model, attr, bridge.psd_constraint) M = MOI.dimension(MOI.get(model, MOI.ConstraintSet(), bridge)) n = length(bridge.con12diag) - return [values[_variable_map(MOIB.Variable.IndexInVector(i), n)] for i in 1:M] + return [values[_variable_map(MOIB.IndexInVector(i), n)] for i in 1:M] end # See docstring of bridge for why we ignore the dual of the constraints @@ -217,16 +217,16 @@ function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintDual, end function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal, - bridge::HermitianToSymmetricPSDBridge{T}, i::MOIB.Variable.IndexInVector) where T + bridge::HermitianToSymmetricPSDBridge{T}, i::MOIB.IndexInVector) where T value = MOI.get(model, attr, _variable(bridge, i)) end -function MOIB.bridged_function(bridge::HermitianToSymmetricPSDBridge{T}, i::MOIB.Variable.IndexInVector) where T - func = MOI.SingleVariable(_variable(bridge, i)) +function MOIB.bridged_function(bridge::HermitianToSymmetricPSDBridge{T}, i::MOIB.IndexInVector) where T + func = _variable(bridge, i) return convert(MOI.ScalarAffineFunction{T}, func) end function MOIB.Variable.unbridged_map(bridge::HermitianToSymmetricPSDBridge{T}, vi::MOI.VariableIndex, - i::MOIB.Variable.IndexInVector) where T - func = convert(MOI.ScalarAffineFunction{T}, MOI.SingleVariable(vi)) + i::MOIB.IndexInVector) where T + func = convert(MOI.ScalarAffineFunction{T}, vi) return (_variable(bridge, i) => func,) end diff --git a/src/ComplexOptInterface.jl b/src/ComplexOptInterface.jl index c1242d3..04b1706 100644 --- a/src/ComplexOptInterface.jl +++ b/src/ComplexOptInterface.jl @@ -19,7 +19,7 @@ function MOI.Utilities.set_dot(x::AbstractVector, y::AbstractVector, sym = MOI.PositiveSemidefiniteConeTriangle(set.side_dimension) result = MOI.Utilities.set_dot(x, y, sym) for k in (MOI.dimension(sym) + 1):MOI.dimension(set) - result = MA.add_mul!(result, 2, x[k], y[k]) + result = MA.add_mul!!(result, 2, x[k], y[k]) end return result end diff --git a/test/runtests.jl b/test/runtests.jl index 5bc0887..8e67a20 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -31,12 +31,11 @@ function projection_test(optimizer, config) MOI.empty!(optimizer) set = COI.HermitianPositiveSemidefiniteConeTriangle(2) x, cx = MOI.add_constrained_variables(optimizer, set) - fx = MOI.SingleVariable.(x) - x11 = fx[1:3] - x12 = fx[4] + x11 = x[1:3] + x12 = x[4] t = MOI.add_variable(optimizer) ft = MOI.SingleVariable(t) - MOI.add_constraint(optimizer, MOI.Utilities.operate(vcat, Float64, ft, fx[1] - 1.0, √2 * (fx[2] + 1.0), fx[3] + 1.0, √2 * (fx[4] - 1.0)), + MOI.add_constraint(optimizer, MOI.Utilities.operate(vcat, Float64, ft, x[1] - 1.0, √2 * (x[2] + 1.0), x[3] + 1.0, √2 * (x[4] - 1.0)), MOI.SecondOrderCone(5)) MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MIN_SENSE) MOI.set(optimizer, MOI.ObjectiveFunction{typeof(ft)}(), ft) @@ -56,8 +55,7 @@ function hermitian_psd_test(optimizer, config) MOI.empty!(optimizer) set = COI.HermitianPositiveSemidefiniteConeTriangle(3) x, cx = MOI.add_constrained_variables(optimizer, set) - fx = MOI.SingleVariable.(x) - MOI.add_constraints(optimizer, fx, MOI.EqualTo.([1.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0])) + MOI.add_constraints(optimizer, x, MOI.EqualTo.([1.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0])) MOI.optimize!(optimizer) primal = [1.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0] @test MOI.get(optimizer, MOI.VariablePrimal(), x) ≈ primal atol=atol rtol=rtol @@ -71,8 +69,7 @@ function zero_1_test(optimizer, config) MOI.empty!(optimizer) x, cx = MOI.add_constrained_variables(optimizer, MOI.Nonnegatives(2)) - fx = MOI.SingleVariable.(x) - func = (1.0 + 2.0im) * fx[1] + (1.0 - 1.0im) * fx[2] + (-1.0 + -1.0im) + func = (1.0 + 2.0im) * x[1] + (1.0 - 1.0im) * x[2] + (-1.0 + -1.0im) c = MOI.add_constraint( optimizer, MOI.Utilities.operate(vcat, Complex{Float64}, func), @@ -93,8 +90,7 @@ function zero_2_test(optimizer, config) MOI.empty!(optimizer) x, cx = MOI.add_constrained_variables(optimizer, MOI.Nonnegatives(1)) - fx = MOI.SingleVariable.(x) - func = (1.0 + 0.0im) * fx[1] + 1.0im * fx[1] - 2.0im - (1.0 + 0.0im) * fx[1] + func = (1.0 + 0.0im) * x[1] + 1.0im * x[1] - 2.0im - (1.0 + 0.0im) * x[1] c = MOI.add_constraint( optimizer, MOI.Utilities.operate(vcat, Complex{Float64}, func), @@ -111,7 +107,7 @@ end import CSDP @testset "CSDP" begin - config = MOI.Test.TestConfig(atol=1e-4, rtol=1e-4) + config = MOI.Test.Config(atol=1e-4, rtol=1e-4) bridged = MOI.instantiate(CSDP.Optimizer, with_bridge_type=Float64) MOI.Bridges.add_bridge(bridged, COI.Bridges.Variable.HermitianToSymmetricPSDBridge{Float64}) projection_test(bridged, config)