From 73e96441e8a334dd61166d6bb467150278a89fce Mon Sep 17 00:00:00 2001 From: Lucas ONDEL YANG <lucas.ondel@cnrs.fr> Date: Wed, 1 Feb 2023 15:38:44 +0100 Subject: [PATCH] re-organized tests --- src/fsa.jl | 11 ++-- test/runtests.jl | 147 ++++++++++++++++++++++++++--------------------- 2 files changed, 85 insertions(+), 73 deletions(-) diff --git a/src/fsa.jl b/src/fsa.jl index eed027f..2b703ee 100644 --- a/src/fsa.jl +++ b/src/fsa.jl @@ -26,28 +26,27 @@ T(fsa::AbstractFSA) = parent(fsa).T λ(fsa::AbstractFSA) = parent(fsa).λ function Base.convert(f::Function, A::AbstractFSA{K,L}) where {K,L} - l = λ(A) - ρ = f(emptystring(A), one(L)) + ρ = f(emptystring(A), nstates(A) + 1) U = typeof(ρ) α = sparsevec( initstates(A)[1], - [f(v, l[i]) for (i, v) in zip(initstates(A)...)], + [f(v, i) for (i, v) in zip(initstates(A)...)], nstates(A) ) T = sparse( edges(A)[1], edges(A)[2], - [f(v, l[j]) for (i, j, v) in zip(edges(A)...)], + [f(v, j) for (i, j, v) in zip(edges(A)...)], nstates(A), nstates(A) ) ω = sparsevec( finalstates(A)[1], - [f(v, one(L)) for (i, v) in zip(finalstates(A)...)], + [f(v, nstates(A) + 1) for (i, v) in zip(finalstates(A)...)], nstates(A) ) - FSA{U,L}(α, T, ω, ρ, l) + FSA{U,L}(α, T, ω, ρ, λ(A)) end struct AcyclicFSA{K,L} <: AbstractAcyclicFSA{K,L} diff --git a/test/runtests.jl b/test/runtests.jl index 66aec9c..df0e9fc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -16,7 +16,8 @@ Ls = [ StringMonoid, ] -f(L, w, l) = begin +f(L, A, w, i) = begin + l = i <= nstates(A) ? λ(A)[i] : one(L) S = UnionConcatSemiring{L} if iszero(w) return ProductSemiring((w, zero(S))) @@ -25,15 +26,15 @@ f(L, w, l) = begin end end -@testset "FSA" begin - for K in Ks, L in Ls +for K in Ks, L in Ls + @testset verbose=true "FSA - $K" begin α1 = sparsevec([1, 2], K[2, 3], 3) T1 = sparse([1, 1, 2], [2, 3, 3], K[1, 2, 3], 3, 3) ω1 = sparsevec([3], K(5), 3) ρ1 = K(0.6) λ1 = [L("a"), L("b"), L("c")] A1 = FSA(α1, T1, ω1, ρ1, λ1) - B1 = convert((w, l) -> f(L, w, l), A1) + B1 = convert((w, l) -> f(L, A1, w, l), A1) α2 = sparsevec([1, 3], K[3, 5], 4) T2 = sparse([1, 1, 2, 3], [2, 3, 4, 4], K[4, 3, 2, 2], 4, 4) @@ -41,81 +42,93 @@ end ρ2 = zero(K) λ2 = [L("a"), L("b"), L("c"), L("d")] A2 = FSA(α2, T2, ω2, ρ2, λ2) - B2 = convert((w, l) -> f(L, w, l), A2) + B2 = convert((w, l) -> f(L, A2, w, l), A2) Aϵ = FSA(spzeros(K, 0), spzeros(K, 0, 0), spzeros(K, 0), one(K), L[]) - Bϵ = convert((w, l) -> f(L, w, l), Aϵ) - - @test all(α(A1) .≈ α1) - @test all(T(A1) .≈ T1) - @test all(ω(A1) .≈ ω1) - @test all(ρ(A1) ≈ ρ1) - @test all(λ(A1) .== λ1) - - @test all(α(A2) .≈ α2) - @test all(T(A2) .≈ T2) - @test all(ω(A2) .≈ ω2) - @test all(ρ(A2) ≈ ρ2) - @test all(λ(A2) .== λ2) + Bϵ = convert((w, l) -> f(L, Aϵ, w, l), Aϵ) + + @testset verbose=true "properties" begin + @test all(α(A1) .≈ α1) + @test all(T(A1) .≈ T1) + @test all(ω(A1) .≈ ω1) + @test all(ρ(A1) ≈ ρ1) + @test all(λ(A1) .== λ1) + + @test all(α(A2) .≈ α2) + @test all(T(A2) .≈ T2) + @test all(ω(A2) .≈ ω2) + @test all(ρ(A2) ≈ ρ2) + @test all(λ(A2) .== λ2) + end # Number of iteration to sum over the FSA. n = max(nstates(A1), nstates(A2)) - # union - B12 = convert((w, l) -> f(L, w, l), union(A1, A2)) - cs_B12 = sum(B12; n) - cs_B1_B2 = sum(B1; n) + sum(B2; n) - @test cs_B12.tval[1] ≈ cs_B1_B2.tval[1] - @test cs_B12.tval[2] == cs_B1_B2.tval[2] - - # concatenation - B12 = convert((w, l) -> f(L, w, l), cat(A1, A2)) - cs_B12 = sum(B12; n = 2n) - cs_B1_B2 = sum(B2; n) * sum(B1; n) - @test cs_B12.tval[2] ⊇ cs_B1_B2.tval[2] + @testset verbose=true "union" begin + A12 = union(A1, A2) + B12 = convert((w, l) -> f(L, A12, w, l), A12) + cs_B12 = sum(B12; n) + cs_B1_B2 = sum(B1; n) + sum(B2; n) + @test cs_B12.tval[1] ≈ cs_B1_B2.tval[1] + @test cs_B12.tval[2] == cs_B1_B2.tval[2] + end + + @testset verbose=true "concatenation" begin + A12 = cat(A1, A2) + B12 = convert((w, l) -> f(L, A12, w, l), A12) + cs_B12 = sum(B12; n = 2n) + cs_B1_B2 = sum(B2; n) * sum(B1; n) + @test cs_B12.tval[2] ⊇ cs_B1_B2.tval[2] + end # The number of iteration for the cumulative sum depends on the # structure of the FSA for the test to pass. # It should be 3 times the maximum path length of B2. n = 6 - # closure - B2p_n3 = B2 ∪ cat(B2, B2) ∪ cat(B2, B2, B2) - B2_n3 = B2 ∪ cat(B2, B2) ∪ cat(B2, B2, B2) ∪ Bϵ - cB2p = closure(B2; plus = true) - cB2 = closure(B2; plus = false) - cs_B2p_n3 = sum(B2p_n3; n) - cs_B2_n3 = sum(B2_n3; n) - cs_cB2p = sum(cB2p; n) - cs_cB2 = sum(cB2; n) - @test cs_cB2p.tval[1] ≈ cs_B2p_n3.tval[1] - @test cs_cB2p.tval[2] == cs_B2p_n3.tval[2] - @test cs_cB2.tval[1] ≈ cs_B2_n3.tval[1] - @test cs_cB2.tval[2] == cs_B2_n3.tval[2] - - # reverse - rB2 = convert((w, l) -> f(L, w, l), A2 |> reverse) - s1 = val(sum(B2; n).tval[2]) - s2 = Set((StringMonoid ∘ reverse ∘ val).((val ∘ sum)(rB2)[2])) - @test s1 == s2 - - # renorm - @test Base.isapprox(val(sum(A1 |> renorm; n = 100)), val(one(K)), atol=1e-6) - @test Base.isapprox(val(sum(A2 |> renorm; n = 100)), val(one(K)), atol=1e-6) - - # (co)accessibility - A = FSA( - sparsevec([1, 2], one(K), 5), - sparse([2, 3], [3, 3], one(K), 5, 5), - sparsevec([3, 4], one(K), 5), - zero(K), - [L("$i") for i in 1:5] - ) - @test all(accessible(A) .== [true, true, true, false, false]) - @test all(coaccessible(A) .== [false, true, true, true, false]) - - # globalrenorm - @test Base.isapprox(val(sum(AcyclicFSA(A2) |> globalrenorm; n = 100)), val(one(K)), atol=1e-6) + @testset verbose=true "closure" begin + B2p_n3 = B2 ∪ cat(B2, B2) ∪ cat(B2, B2, B2) + B2_n3 = B2 ∪ cat(B2, B2) ∪ cat(B2, B2, B2) ∪ Bϵ + cB2p = closure(B2; plus = true) + cB2 = closure(B2; plus = false) + cs_B2p_n3 = sum(B2p_n3; n) + cs_B2_n3 = sum(B2_n3; n) + cs_cB2p = sum(cB2p; n) + cs_cB2 = sum(cB2; n) + @test cs_cB2p.tval[1] ≈ cs_B2p_n3.tval[1] + @test cs_cB2p.tval[2] == cs_B2p_n3.tval[2] + @test cs_cB2.tval[1] ≈ cs_B2_n3.tval[1] + @test cs_cB2.tval[2] == cs_B2_n3.tval[2] + end + + @testset verbose=true "reversal" begin + rA2 = A2 |> reverse + rB2 = convert((w, l) -> f(L, rA2, w, l), rA2) + s1 = val(sum(B2; n).tval[2]) + s2 = Set((StringMonoid ∘ reverse ∘ val).((val ∘ sum)(rB2)[2])) + @test s1 == s2 + end + + @testset verbose=true "renorm" begin + @test Base.isapprox(val(sum(A1 |> renorm; n = 100)), val(one(K)), atol=1e-6) + @test Base.isapprox(val(sum(A2 |> renorm; n = 100)), val(one(K)), atol=1e-6) + end + + @testset verbose=true "(co)accessible" begin + A = FSA( + sparsevec([1, 2], one(K), 5), + sparse([2, 3], [3, 3], one(K), 5, 5), + sparsevec([3, 4], one(K), 5), + zero(K), + [L("$i") for i in 1:5] + ) + @test all(accessible(A) .== [true, true, true, false, false]) + @test all(coaccessible(A) .== [false, true, true, true, false]) + end + + @testset verbose=true "globalrenorm" begin + @test Base.isapprox(val(sum(AcyclicFSA(A2) |> globalrenorm; n = 100)), val(one(K)), atol=1e-6) + end end end -- GitLab