From e91a0a5e6323f0c1243d1ce249ad0c84428a20a3 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Wed, 9 Sep 2026 03:13:44 +0800 Subject: [PATCH 1/4] Fix MMAP reference validation tests --- README.md | 1 + test/mmap.jl | 43 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b089bb6..ee55a32 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Build Status](https://github.com/TensorBFS/TensorInference.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/TensorBFS/TensorInference.jl/actions/workflows/CI.yml?query=branch%3Amain) [![Coverage](https://codecov.io/gh/TensorBFS/TensorInference.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/TensorBFS/TensorInference.jl) [![status](https://joss.theoj.org/papers/a6792845b2522b07898cd35e246ec4d2/status.svg)](https://joss.theoj.org/papers/a6792845b2522b07898cd35e246ec4d2) +![Agent maintained](https://img.shields.io/badge/maintenance-agent%20maintained-blue)

TensorInference is an open source   diff --git a/test/mmap.jl b/test/mmap.jl index 89d7fee..a3a9040 100644 --- a/test/mmap.jl +++ b/test/mmap.jl @@ -1,6 +1,8 @@ using Test +using Random using OMEinsum using TensorInference +using TensorInference: Factor, UAIModel, get_vars @testset "clustering" begin ixs = [[1, 2, 3], [2, 3, 4], [4, 5, 6]] @@ -31,20 +33,51 @@ end @test log_probability(mmap3, config) ≈ logp end -@testset "UAI Reference Solution Comparison" begin +@testset "MMAP exhaustive small independent oracle" begin + rng = MersenneTwister(4279) + for trial in 1:12 + f = trial == 1 ? [1.0 0.0; 0.0 1.0] : rand(rng, 2, 2) + g = trial == 1 ? [0.0 1.0; 1.0 0.0] : rand(rng, 2, 2) + model = UAIModel(3, [2, 2, 2], [Factor((1, 2), f), Factor((2, 3), g)]) + for queryvars in ([1], [1, 3]), evidence in (Dict{Int,Int}(), Dict(3 => 1)) + mmap = MMAPModel(model; queryvars, evidence) + scores = Dict{Tuple,Float64}() + outputvars = get_vars(mmap) + for x in 0:1, y in 0:1, z in 0:1 + assignment = [x, y, z] + all(assignment[k] == value for (k, value) in evidence) || continue + key = Tuple(assignment[k] for k in outputvars) + scores[key] = get(scores, key, 0.0) + f[x + 1, y + 1] * g[y + 1, z + 1] + end + logp, config = most_probable_config(mmap) + @test exp(logp) ≈ maximum(values(scores)) + @test scores[Tuple(config)] ≈ maximum(values(scores)) + @test log_probability(mmap, config) ≈ logp + end + end +end + +@testset "UAI feasible reference lower bounds" begin problem_sets = dataset_from_artifact("uai2014")["MMAP"] problems = [ ("Segmentation", 12, TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40)), - # ("Segmentation", 13, TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40)), # fails! - # ("Segmentation", 14, TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40)) # fails! + ("Segmentation", 13, TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40)), + ("Segmentation", 14, TreeSA(ntrials = 1, niters = 2, βs = 1:0.1:40)) ] for (problem_set_name, id, optimizer) in problems @testset "$(problem_set_name) problem set, id = $id" begin problem = problem_sets[problem_set_name][id] @info "Testing: $(problem_set_name)_$id" model = MMAPModel(read_model(problem); optimizer, evidence=read_evidence(problem), queryvars=read_queryvars(problem)) - _, solution = most_probable_config(model) - @test solution == read_solution(problem) + logp, solution = most_probable_config(model) + reference_logp = log_probability(model, read_solution(problem)) + + # These external assignments are feasible lower bounds, not certified + # optima. A different assignment is valid when its objective is at + # least as good; the small tests above independently establish that + # the solver finds exact MMAP optima on exhaustively enumerable models. + @test log_probability(model, solution) ≈ logp + @test logp >= reference_logp || isapprox(logp, reference_logp) end end end From 584b2f4a97a57b9ad87437651740832d58fbb944 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Wed, 9 Sep 2026 03:16:22 +0800 Subject: [PATCH 2/4] Make small MMAP oracle output order independent --- test/mmap.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/mmap.jl b/test/mmap.jl index a3a9040..6b478de 100644 --- a/test/mmap.jl +++ b/test/mmap.jl @@ -42,11 +42,12 @@ end for queryvars in ([1], [1, 3]), evidence in (Dict{Int,Int}(), Dict(3 => 1)) mmap = MMAPModel(model; queryvars, evidence) scores = Dict{Tuple,Float64}() - outputvars = get_vars(mmap) + expected_outputvars = sort!(union(queryvars, collect(keys(evidence)))) + @test get_vars(mmap) == expected_outputvars for x in 0:1, y in 0:1, z in 0:1 assignment = [x, y, z] all(assignment[k] == value for (k, value) in evidence) || continue - key = Tuple(assignment[k] for k in outputvars) + key = Tuple(assignment[k] for k in expected_outputvars) scores[key] = get(scores, key, 0.0) + f[x + 1, y + 1] * g[y + 1, z + 1] end logp, config = most_probable_config(mmap) From c1d3ec4b088f6eff72712a6587825332c769c3a9 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Wed, 9 Sep 2026 03:42:49 +0800 Subject: [PATCH 3/4] Isolate MMAP tests from global RNG --- test/mmap.jl | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/test/mmap.jl b/test/mmap.jl index 6b478de..3ab6c0f 100644 --- a/test/mmap.jl +++ b/test/mmap.jl @@ -69,16 +69,21 @@ end @testset "$(problem_set_name) problem set, id = $id" begin problem = problem_sets[problem_set_name][id] @info "Testing: $(problem_set_name)_$id" - model = MMAPModel(read_model(problem); optimizer, evidence=read_evidence(problem), queryvars=read_queryvars(problem)) - logp, solution = most_probable_config(model) - reference_logp = log_probability(model, read_solution(problem)) + rng_state = id == 12 ? nothing : copy(Random.default_rng()) + try + model = MMAPModel(read_model(problem); optimizer, evidence=read_evidence(problem), queryvars=read_queryvars(problem)) + logp, solution = most_probable_config(model) + reference_logp = log_probability(model, read_solution(problem)) - # These external assignments are feasible lower bounds, not certified - # optima. A different assignment is valid when its objective is at - # least as good; the small tests above independently establish that - # the solver finds exact MMAP optima on exhaustively enumerable models. - @test log_probability(model, solution) ≈ logp - @test logp >= reference_logp || isapprox(logp, reference_logp) + # These external assignments are feasible lower bounds, not certified + # optima. A different assignment is valid when its objective is at + # least as good; the small tests above independently establish that + # the solver finds exact MMAP optima on exhaustively enumerable models. + @test log_probability(model, solution) ≈ logp + @test logp >= reference_logp || isapprox(logp, reference_logp) + finally + isnothing(rng_state) || copy!(Random.default_rng(), rng_state) + end end end end From 8fcf6f3bd17e220824f5c5f05547c2f8c38616e5 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Wed, 9 Sep 2026 03:51:43 +0800 Subject: [PATCH 4/4] Revert "Isolate MMAP tests from global RNG" This reverts commit 3926d45851e54a585fbdf397d6ca5a9a54702a52. --- test/mmap.jl | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/test/mmap.jl b/test/mmap.jl index 3ab6c0f..6b478de 100644 --- a/test/mmap.jl +++ b/test/mmap.jl @@ -69,21 +69,16 @@ end @testset "$(problem_set_name) problem set, id = $id" begin problem = problem_sets[problem_set_name][id] @info "Testing: $(problem_set_name)_$id" - rng_state = id == 12 ? nothing : copy(Random.default_rng()) - try - model = MMAPModel(read_model(problem); optimizer, evidence=read_evidence(problem), queryvars=read_queryvars(problem)) - logp, solution = most_probable_config(model) - reference_logp = log_probability(model, read_solution(problem)) + model = MMAPModel(read_model(problem); optimizer, evidence=read_evidence(problem), queryvars=read_queryvars(problem)) + logp, solution = most_probable_config(model) + reference_logp = log_probability(model, read_solution(problem)) - # These external assignments are feasible lower bounds, not certified - # optima. A different assignment is valid when its objective is at - # least as good; the small tests above independently establish that - # the solver finds exact MMAP optima on exhaustively enumerable models. - @test log_probability(model, solution) ≈ logp - @test logp >= reference_logp || isapprox(logp, reference_logp) - finally - isnothing(rng_state) || copy!(Random.default_rng(), rng_state) - end + # These external assignments are feasible lower bounds, not certified + # optima. A different assignment is valid when its objective is at + # least as good; the small tests above independently establish that + # the solver finds exact MMAP optima on exhaustively enumerable models. + @test log_probability(model, solution) ≈ logp + @test logp >= reference_logp || isapprox(logp, reference_logp) end end end