Skip to content

Commit c67137b

Browse files
Fix deprecations and clean tests & CI (#19)
* Fix deprecations * Use separate test environment and test GLPK as well * Use eachrow and eachcol * Update CI * Fix format Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent b1dba1c commit c67137b

File tree

7 files changed

+71
-46
lines changed

7 files changed

+71
-46
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ jobs:
3838
with:
3939
python-version: '3.9'
4040
architecture: ${{ matrix.arch }}
41-
# Limitation of pip: https://pythonot.github.io/index.html#pip-installation
42-
- run: python -m pip install cython numpy
4341
- run: python -m pip install pot
4442
- uses: julia-actions/setup-julia@v1
4543
with:
@@ -63,7 +61,7 @@ jobs:
6361
PYTHON: python
6462
- uses: julia-actions/julia-processcoverage@v1
6563
if: matrix.version == '1' && matrix.os == 'ubuntu-latest'
66-
- uses: codecov/codecov-action@v1
64+
- uses: codecov/codecov-action@v2
6765
if: matrix.version == '1' && matrix.os == 'ubuntu-latest'
6866
with:
6967
file: lcov.info

.github/workflows/CompatHelper.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: "Run CompatHelper"
2626
run: |
2727
import CompatHelper
28-
CompatHelper.main(; subdirs=["", "docs"], bump_version=true)
28+
CompatHelper.main(; subdirs=["", "docs", "test"], bump_version=true)
2929
shell: julia --color=yes {0}
3030
env:
3131
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/Documentation.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ jobs:
2323
with:
2424
python-version: '3.9'
2525
architecture: ${{ matrix.arch }}
26-
# Limitation of pip: https://pythonot.github.io/index.html#pip-installation
27-
- run: python -m pip install cython numpy
2826
- run: python -m pip install pot
2927
- uses: julia-actions/setup-julia@latest
3028
with:

Project.toml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ExactOptimalTransport"
22
uuid = "24df6009-d856-477c-ac5c-91f668376b31"
33
authors = ["JuliaOptimalTransport"]
4-
version = "0.2.0"
4+
version = "0.2.1"
55

66
[deps]
77
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
@@ -18,19 +18,9 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
1818
Distances = "0.9.0, 0.10"
1919
Distributions = "0.24, 0.25"
2020
FillArrays = "0.12"
21-
MathOptInterface = "0.9, 0.10"
21+
MathOptInterface = "0.10"
2222
PDMats = "0.10, 0.11"
2323
QuadGK = "2"
2424
StatsBase = "0.33.8"
2525
julia = "1.6"
2626

27-
[extras]
28-
HCubature = "19dc6840-f33b-545b-b366-655c7e3ffd49"
29-
PythonOT = "3c485715-4278-42b2-9b5f-8f00e43c12ef"
30-
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
31-
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
32-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
33-
Tulip = "6dd1b50a-3aae-11e9-10b5-ef983d2400fa"
34-
35-
[targets]
36-
test = ["PythonOT", "Random", "SafeTestsets", "Test", "Tulip", "HCubature"]

src/exact.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,21 @@ function emd(μ, ν, C, model::MOI.ModelLike)
7171

7272
# add non-negativity constraints
7373
for xi in x
74-
MOI.add_constraint(model, MOI.SingleVariable(xi), MOI.GreaterThan(zero_T))
74+
MOI.add_constraint(model, xi, MOI.GreaterThan(zero_T))
7575
end
7676

7777
# add constraints for source
78-
for (i, μi) in zip(axes(xmat, 1), μ) # eachrow(xmat) is not available on Julia 1.0
78+
for (xrow, μi) in zip(eachrow(xmat), μ)
7979
f = MOI.ScalarAffineFunction(
80-
[MOI.ScalarAffineTerm(one(μi), xi) for xi in view(xmat, i, :)], zero(μi)
80+
[MOI.ScalarAffineTerm(one(μi), xi) for xi in xrow], zero(μi)
8181
)
8282
MOI.add_constraint(model, f, MOI.EqualTo(μi))
8383
end
8484

8585
# add constraints for target
86-
for (i, νi) in zip(axes(xmat, 2), ν) # eachcol(xmat) is not available on Julia 1.0
86+
for (xcol, νi) in zip(eachcol(xmat), ν)
8787
f = MOI.ScalarAffineFunction(
88-
[MOI.ScalarAffineTerm(one(νi), xi) for xi in view(xmat, :, i)], zero(νi)
88+
[MOI.ScalarAffineTerm(one(νi), xi) for xi in xcol], zero(νi)
8989
)
9090
MOI.add_constraint(model, f, MOI.EqualTo(νi))
9191
end

test/Project.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[deps]
2+
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
3+
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
4+
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
5+
GLPK = "60bf3e95-4087-53dc-ae20-288a0d20c6a6"
6+
HCubature = "19dc6840-f33b-545b-b366-655c7e3ffd49"
7+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
8+
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
9+
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
10+
PythonOT = "3c485715-4278-42b2-9b5f-8f00e43c12ef"
11+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
12+
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
13+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
14+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
15+
Tulip = "6dd1b50a-3aae-11e9-10b5-ef983d2400fa"
16+
17+
[compat]
18+
Distances = "0.9, 0.10"
19+
Distributions = "0.24, 0.25"
20+
FillArrays = "0.12"
21+
GLPK = "0.15"
22+
HCubature = "1.5"
23+
MathOptInterface = "0.10"
24+
PDMats = "0.10, 0.11"
25+
PythonOT = "0.1"
26+
SafeTestsets = "0.0.1"
27+
Tulip = "0.9"
28+
julia = "1.6"

test/exact.jl

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ using ExactOptimalTransport
22

33
using Distances
44
using FillArrays
5+
using GLPK
56
using PythonOT: PythonOT
67
using Tulip
78
using MathOptInterface
@@ -32,30 +33,34 @@ Random.seed!(100)
3233
pot_P = POT.emd(μ, ν, C)
3334
pot_cost = POT.emd2(μ, ν, C)
3435

35-
# compute optimal transport map and cost with Tulip
36-
lp = Tulip.Optimizer()
37-
P = emd(μ, ν, C, lp)
38-
@test size(C) == size(P)
39-
@test MOI.get(lp, MOI.TerminationStatus()) == MOI.OPTIMAL
40-
@test maximum(abs, P .- pot_P) < 1e-2
41-
42-
lp = Tulip.Optimizer()
43-
cost = emd2(μ, ν, C, lp)
44-
@test dot(C, P) cost atol = 1e-5
45-
@test MOI.get(lp, MOI.TerminationStatus()) == MOI.OPTIMAL
46-
@test cost pot_cost atol = 1e-5
36+
# compute optimal transport map and cost with Tulip and GLPK
37+
for T in (Tulip.Optimizer, GLPK.Optimizer)
38+
lp = T()
39+
P = emd(μ, ν, C, lp)
40+
@test size(C) == size(P)
41+
@test MOI.get(lp, MOI.TerminationStatus()) == MOI.OPTIMAL
42+
@test maximum(abs, P .- pot_P) < 1e-2
43+
44+
lp = T()
45+
cost = emd2(μ, ν, C, lp)
46+
@test dot(C, P) cost atol = 1e-5
47+
@test MOI.get(lp, MOI.TerminationStatus()) == MOI.OPTIMAL
48+
@test cost pot_cost atol = 1e-5
49+
end
4750
end
4851

4952
@testset "pre-computed plan" begin
5053
# create random cost matrix
5154
C = pairwise(SqEuclidean(), rand(1, M), rand(1, N); dims=2)
5255

53-
# compute optimal transport map
54-
P = emd(μ, ν, C, Tulip.Optimizer())
56+
# compute optimal transport map with Tulip and GLPK
57+
for T in (Tulip.Optimizer, GLPK.Optimizer)
58+
P = emd(μ, ν, C, T())
5559

56-
# do not use μ and ν to ensure that provided map is used
57-
cost = emd2(similar(μ), similar(ν), C, Tulip.Optimizer(); plan=P)
58-
@test cost emd2(μ, ν, C, Tulip.Optimizer())
60+
# do not use μ and ν to ensure that provided map is used
61+
cost = emd2(similar(μ), similar(ν), C, T(); plan=P)
62+
@test cost emd2(μ, ν, C, T())
63+
end
5964
end
6065

6166
# https://github.com/JuliaOptimalTransport/OptimalTransport.jl/issues/71
@@ -106,8 +111,10 @@ Random.seed!(100)
106111
xs = rand(μ, m)
107112
μdiscrete = fill(1 / m, m)
108113
C = pairwise(Euclidean(), xs', (1:length(νprobs))'; dims=2)
109-
c2 = emd2(μdiscrete, νprobs, C, Tulip.Optimizer())
110-
@test c2 c rtol = 1e-1
114+
for optimizer in (Tulip.Optimizer(), GLPK.Optimizer())
115+
c2 = emd2(μdiscrete, νprobs, C, optimizer)
116+
@test c2 c rtol = 1e-1
117+
end
111118
end
112119

113120
@testset "discrete case" begin
@@ -164,8 +171,10 @@ Random.seed!(100)
164171
# DiscreteNonParametric sorts the support automatically, here we have to sort
165172
# manually
166173
C = pairwise(Euclidean(), μsupport', νsupport'; dims=2)
167-
c2 = emd2(μprobs, νprobs, C, Tulip.Optimizer())
168-
@test c2 c rtol = 1e-5
174+
for optimizer in (Tulip.Optimizer(), GLPK.Optimizer())
175+
c2 = emd2(μprobs, νprobs, C, optimizer)
176+
@test c2 c rtol = 1e-5
177+
end
169178

170179
# compare with POT
171180
# disabled currently since https://github.com/PythonOT/POT/issues/169 causes bounds
@@ -222,8 +231,10 @@ Random.seed!(100)
222231
μprobs = normalize!(pdf(μ, μsupp'), 1)
223232
νprobs = normalize!(pdf(ν, νsupp'), 1)
224233
C = pairwise(SqEuclidean(), μsupp', νsupp'; dims=2)
225-
@test emd2(μprobs, νprobs, C, Tulip.Optimizer()) ot_cost(SqEuclidean(), μ, ν) rtol =
226-
1e-3
234+
for optimizer in (Tulip.Optimizer(), GLPK.Optimizer())
235+
@test emd2(μprobs, νprobs, C, optimizer) ot_cost(SqEuclidean(), μ, ν) rtol =
236+
1e-3
237+
end
227238

228239
# Use hcubature integration to perform ``\\int c(x,T(x)) d\\mu``
229240
T = ot_plan(SqEuclidean(), μ, ν)

0 commit comments

Comments
 (0)