Skip to content

Commit 79797ea

Browse files
authored
Support artifact downloading and reading (#50)
1 parent 7dd6ebc commit 79797ea

File tree

13 files changed

+94
-63
lines changed

13 files changed

+94
-63
lines changed
File renamed without changes.

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ authors = ["Jin-Guo Liu", "Martin Roa Villescas"]
44
version = "0.1.0"
55

66
[deps]
7+
Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
78
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
89
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
910
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1011
OMEinsum = "ebe7aa44-baf0-506c-a96f-8464559b3922"
12+
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
1113
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
1214
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
1315
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"

docs/src/api/public.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ most_probable_config
5757
probability
5858
read_evidence_file
5959
read_instance
60+
read_instance_from_artifact
6061
read_model_file
6162
read_solution_file
6263
read_td_file

src/TensorInference.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ using OMEinsum, LinearAlgebra
1111
using DocStringExtensions, TropicalNumbers
1212
# The Tropical GEMM support
1313
using StatsBase
14+
import Pkg
1415

1516
# reexport OMEinsum functions
1617
export RescaledArray
1718
export contraction_complexity, TreeSA, GreedyMethod, KaHyParBipartite, SABipartite, MergeGreedy, MergeVectors
1819

1920
# read and load uai files
20-
export read_model_file, read_td_file, read_evidence_file, read_solution_file, read_instance, UAIInstance
21+
export read_model_file, read_td_file, read_evidence_file, read_solution_file
22+
export read_instance, read_instance_from_artifact, UAIInstance
2123
export set_evidence!, set_query!
2224

2325
# marginals

src/utils.jl

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
$(TYPEDSIGNATURES)
33
44
Parse the problem instance found in `model_filepath` defined in the UAI model
5-
format.
5+
format. If the provided file path is empty, return `nothing`.
66
77
The UAI file formats are defined in:
88
https://uaicompetition.github.io/uci-2022/file-formats/
99
"""
10-
function read_model_file(model_filepath; factor_eltype = Float64)
10+
function read_model_file(model_filepath::AbstractString; factor_eltype = Float64)
1111
# Read the uai file into an array of lines
1212
str = open(model_filepath) do file
1313
read(file, String)
@@ -244,10 +244,79 @@ function read_instance(
244244
return UAIInstance(nvars, ncliques, cards, factors, obsvars, obsvals, queryvars, reference_solution)
245245
end
246246

247-
function read_instance_from_string(uai::AbstractString; eltype = Float64)::UAIInstance
248-
nvars, cards, ncliques, factors = read_model_string(uai; factor_eltype = eltype)
247+
function read_instance_from_string(model::AbstractString; eltype = Float64)::UAIInstance
248+
nvars, cards, ncliques, factors = read_model_string(model; factor_eltype = eltype)
249249
return UAIInstance(nvars, ncliques, cards, factors, Int[], Int[], Int[], nothing)
250250
end
251251

252252
# patch to get content by broadcasting into array, while keep array size unchanged.
253253
broadcasted_content(x) = asarray(content.(x), x)
254+
255+
"""
256+
$(TYPEDSIGNATURES)
257+
258+
Load a specific instance, identified by `task/name`, from the provided
259+
artifact.
260+
"""
261+
function read_instance_from_artifact(
262+
artifact_name::AbstractString,
263+
problem_name::AbstractString,
264+
task::AbstractString;
265+
eltype = Float64
266+
)
267+
model_filepath, evidence_filepath, query_filepath, solution_filepath = get_instance_filepaths(
268+
artifact_name,
269+
problem_name,
270+
task
271+
)
272+
read_instance(model_filepath; evidence_filepath, query_filepath, solution_filepath, eltype)
273+
end
274+
275+
"""
276+
Helper function to obtain the filepaths for an instance's model, evidence, and
277+
solution files within the provided artifact, corresponding to the provided
278+
task. If a given file path does not exist in the instance's directory, an
279+
empty file path is returned.
280+
"""
281+
function get_instance_filepaths(
282+
artifact_name::AbstractString,
283+
problem_name::AbstractString,
284+
task::AbstractString
285+
)
286+
artifact_toml = pkgdir(TensorInference, "Artifacts.toml")
287+
Pkg.ensure_artifact_installed(artifact_name, artifact_toml)
288+
artifact_hash = Pkg.Artifacts.artifact_hash(artifact_name, artifact_toml)
289+
artifact_path = Pkg.Artifacts.artifact_path(artifact_hash)
290+
model_filepath = joinpath(artifact_path, task, problem_name * ".uai") |> topath
291+
evidence_filepath = joinpath(artifact_path, task, problem_name * ".uai.evid") |> topath
292+
query_filepath = joinpath(artifact_path, task, problem_name * ".uai.query") |> topath
293+
solution_filepath = joinpath(artifact_path, task, problem_name * ".uai." * task) |> topath
294+
return model_filepath, evidence_filepath, query_filepath, solution_filepath
295+
end
296+
297+
"""
298+
This function returns the provided file path if it exists on disk, otherwise it
299+
returns an empty string.
300+
"""
301+
topath(filepath::AbstractString) = isfile(filepath) ? filepath : ""
302+
303+
"""
304+
Helper function that captures the problem names that belong to `problem_set`
305+
for the given task.
306+
"""
307+
function get_problem_names(
308+
artifact_name::AbstractString,
309+
problem_set::AbstractString,
310+
task::AbstractString
311+
)
312+
artifact_toml = pkgdir(TensorInference, "Artifacts.toml")
313+
Pkg.ensure_artifact_installed(artifact_name, artifact_toml)
314+
artifact_hash = Pkg.Artifacts.artifact_hash(artifact_name, artifact_toml)
315+
artifact_path = Pkg.Artifacts.artifact_path(artifact_hash)
316+
317+
regex = Regex("($(problem_set)_\\d*)(\\.uai)\$")
318+
return readdir(joinpath(artifact_path, task); sort = false) |>
319+
x -> map(y -> match(regex, y), x) |> # apply regex
320+
x -> filter(!isnothing, x) |> # filter out `nothing` values
321+
x -> map(first, x) # get the first capture of each element
322+
end

test/Project.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
[deps]
2-
Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
32
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
43
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
54
KaHyPar = "2a6221f6-aa48-11e9-3542-2d9e0ef01880"

test/cuda.jl

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ using TensorInference, CUDA
44
CUDA.allowscalar(false)
55

66
@testset "gradient-based tensor network solvers" begin
7-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths("Promedus_14", "MAR")
8-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
7+
instance = read_instance_from_artifact("uai2014", "Promedus_14", "MAR")
98

109
# does not optimize over open vertices
1110
tn = TensorNetworkModel(instance; optimizer = TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40))
@@ -21,8 +20,7 @@ CUDA.allowscalar(false)
2120
end
2221

2322
@testset "map" begin
24-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths("Promedus_14", "MAR")
25-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
23+
instance = read_instance_from_artifact("uai2014", "Promedus_14", "MAR")
2624

2725
# does not optimize over open vertices
2826
tn = TensorNetworkModel(instance; optimizer = TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40))
@@ -36,8 +34,7 @@ end
3634
end
3735

3836
@testset "mmap" begin
39-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths("Promedus_14", "MAR")
40-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
37+
instance = read_instance_from_artifact("uai2014", "Promedus_14", "MAR")
4138

4239
optimizer = TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40)
4340
tn_ref = TensorNetworkModel(instance; optimizer)

test/map.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ using OMEinsum
33
using TensorInference
44

55
@testset "gradient-based tensor network solvers" begin
6-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths("Promedus_14", "MAR")
7-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
6+
instance = read_instance_from_artifact("uai2014", "Promedus_14", "MAR")
87

98
# does not optimize over open vertices
109
tn = TensorNetworkModel(instance; optimizer = TreeSA(ntrials = 3, niters = 2, βs = 1:0.1:80))
@@ -18,8 +17,7 @@ end
1817
@testset "UAI Reference Solution Comparison" begin
1918
problem_name = "Promedas_70"
2019
@info "Testing: $problem_name"
21-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths(problem_name, "MAP")
22-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
20+
instance = read_instance_from_artifact("uai2014", problem_name, "MAP")
2321
tn = TensorNetworkModel(instance; optimizer = TreeSA(ntrials = 1, niters = 5, βs = 0.1:0.1:100))
2422
_, solution = most_probable_config(tn)
2523
@test solution == instance.reference_solution

test/mar.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Test, Artifacts
1+
using Test
22
using OMEinsum
33
using KaHyPar
44
using TensorInference
@@ -12,8 +12,7 @@ using TensorInference
1212
end
1313

1414
@testset "cached, rescaled contract" begin
15-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths("Promedus_14", "MAR")
16-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
15+
instance = read_instance_from_artifact("uai2014", "Promedus_14", "MAR")
1716
ref_sol = instance.reference_solution
1817
optimizer = TreeSA(ntrials = 1, niters = 5, βs = 0.1:0.1:100)
1918
tn = TensorNetworkModel(instance; optimizer)
@@ -50,12 +49,11 @@ end
5049
for (problem_set, optimizer) in problem_sets
5150
@testset "$(problem_set) problem set" begin
5251
# Capture the problem names that belong to the current problem set
53-
problem_names = get_problem_names(problem_set, "MAR")
52+
problem_names = TensorInference.get_problem_names("uai2014", problem_set, "MAR")
5453
for problem_name in problem_names
5554
@info "Testing: $problem_name"
5655
@testset "$(problem_name)" begin
57-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths(problem_name, "MAR")
58-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
56+
instance = read_instance_from_artifact("uai2014", problem_name, "MAR")
5957
ref_sol = instance.reference_solution
6058
obsvars = instance.obsvars
6159

test/mmap.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ using TensorInference
88
end
99

1010
@testset "gradient-based tensor network solvers" begin
11-
model_filepath, evidence_filepath, _, solution_filepath = get_instance_filepaths("Promedus_14", "MAR")
12-
instance = read_instance(model_filepath; evidence_filepath, solution_filepath)
11+
instance = read_instance_from_artifact("uai2014", "Promedus_14", "MAR")
1312

1413
optimizer = TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40)
1514
tn_ref = TensorNetworkModel(instance; optimizer)
@@ -43,10 +42,9 @@ end
4342
]
4443
for (problem_name, optimizer) in problems
4544
@info "Testing: $problem_name"
46-
model_filepath, evidence_filepath, query_filepath, solution_filepath = get_instance_filepaths(problem_name, "MMAP")
47-
instance = read_instance(model_filepath; evidence_filepath, query_filepath, solution_filepath)
45+
instance = read_instance_from_artifact("uai2014", problem_name, "MMAP")
4846
model = MMAPModel(instance; optimizer)
4947
_, solution = most_probable_config(model)
5048
@test solution == instance.reference_solution
5149
end
52-
end
50+
end

0 commit comments

Comments
 (0)