diff --git a/src/FiniteStateAutomata.jl b/src/FiniteStateAutomata.jl
index 3e2beca6e1773ae41625908619d785047dabe543..7daa93d61efa3ae10529f2f1460bd2ce6682dcaf 100644
--- a/src/FiniteStateAutomata.jl
+++ b/src/FiniteStateAutomata.jl
@@ -44,7 +44,7 @@ export
 include("abstractfsa.jl")
 include("fsa.jl")
 include("ops.jl")
-include("intersect.jl")
 include("dense_fsa.jl")
+include("intersect.jl")
 
 end
diff --git a/src/autograd.jl b/src/autograd.jl
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/criterion.jl b/src/criterion.jl
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/dense_fsa.jl b/src/dense_fsa.jl
index 339480d1fae075e83bb1cace16057d01381995b3..9e6bf98cd352a87f289f6e8ecad810226826101d 100644
--- a/src/dense_fsa.jl
+++ b/src/dense_fsa.jl
@@ -39,86 +39,3 @@ end
 ρ(G::DenseFSA) = G.ρ
 λ(G::DenseFSA) = repeat(G.Σ, size(G.H, 2) - 1)
 
-# Intersection with DenseFSA
-struct IntersectedDenseFSA{K, L, T<:AbstractFSA{K, L}} <: AbstractAcyclicFSA{K, L}
-    A::DenseFSA{K, L}
-    B::T
-    C::AbstractMatrix{K}  # of shape |Σ| x nstates(A)
-end
-
-_computeC(::Type{K}, Σ::AbstractVector, labels::AbstractVector) where K = begin
-    rows = []
-    cols = []
-    for (i,s) in enumerate(Σ)
-        for (j, l) in enumerate(labels)
-            if s == l
-                push!(rows, i)
-                push!(cols, j)
-            end
-        end
-    end
-    sparse(rows, cols, one(K), length(Σ), length(labels))
-end
-
-IntersectedDenseFSA(A::DenseFSA{K}, B::AbstractFSA{K}) where K = begin
-    C = _computeC(K, A.Σ, λ(B)) # TODO switch cols and rows
-    IntersectedDenseFSA(A, B, C)
-    # Hn = C' * A.H
-    # Hn[:, 1] .*= α(B)
-    # Hn[:, end] .*= ω(B)
-    # DenseFSA(Hn, λ(B), ρ(A) * ρ(B))
-end
-
-Base.intersect(A::DenseFSA, B::AbstractFSA) = IntersectedDenseFSA(A, B) 
-Base.intersect(A::AbstractFSA, B::DenseFSA) = IntersectedDenseFSA(B, A) # we assume ∩ to be commutative w.r.t any K
-
-α(I::IntersectedDenseFSA) = begin
-    h1 = I.A.H[:, 1]
-    Q = nstates(I.B) * (size(I.A.H, 2) - 1)
-    vals = (I.C' * h1) .* α(I.B)
-    sparsevec(findnz(vals)..., Q)
-end
-
-ω(I::IntersectedDenseFSA) = begin
-    h = I.A.H[:, end]
-    Q = nstates(I.B) * (size(I.A.H, 2) - 1)
-    vals = (I.C' * h) .* ω(I.B)
-    I, V = findnz(vals)
-    sparsevec(I .+ (Q - length(vals)), V, Q)
-end
-
-T(I::IntersectedDenseFSA) = begin
-    H = I.A.H
-    Tb = T(I.B)
-    C = I.C
-    K = eltype(H)
-    Σ = length(I.A.Σ)
-    Λ = nstates(I.B)
-    Q = Λ * (size(H, 2) - 1)
-
-    rows = []
-    cols = []
-    vals = K[]
-
-    for n in 2:size(H, 2) - 1
-        tmp = ones(K, Λ) * (C' * H[:, n])' .* Tb
-        r, c, v = findnz(tmp)
-        append!(rows, (n - 2) * Λ .+ r)
-        append!(cols, (n - 1) * Λ .+ c)
-        append!(vals, v)
-    end
-    sparse(rows, cols, vals, Q, Q)
-end
-
-λ(I::IntersectedDenseFSA) = repeat(λ(I.B), size(I.A.H, 2) - 1)
-
-ρ(I::IntersectedDenseFSA) = ρ(I.B) * ρ(I.A)
-
-function Base.sum(I::IntersectedDenseFSA, n = size(I.A.H, 2) - 1)
-    CH = I.C' * I.A.H
-    v = CH[:, 1] .* α(I.B)
-    for n in 2:n
-        v = (T(I.B)' * v) .* CH[:, n]
-    end
-    dot(v, ω(I.B) .* CH[:, end]) + ρ(I)
-end
diff --git a/src/intersect.jl b/src/intersect.jl
index ee1e13bb560fa8c254fe29a6b9e43a86d0ae28cd..b7088a96cfded8b3dcd754deb6ba552ee4b3e2d2 100644
--- a/src/intersect.jl
+++ b/src/intersect.jl
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: CECILL-2.1
+
+# Generic intersection
 struct IntersectedFSA{K, L, T_A<:AbstractFSA{K,L}, T_B<:AbstractFSA{K,L}} <: AbstractFSA{K, L}
     A::T_A
     B::T_B
@@ -33,3 +36,86 @@ T(I::IntersectedFSA) = I.M' * kron(T(I.A), T(I.B)) * I.M
 ω(I::IntersectedFSA) = I.M' * kron(ω(I.A), ω(I.B))
 ρ(I::IntersectedFSA) = ρ(I.A) * ρ(I.B)
 
+# Intersection with DenseFSA
+struct IntersectedDenseFSA{K, L, T<:AbstractFSA{K, L}} <: AbstractAcyclicFSA{K, L}
+    A::DenseFSA{K, L}
+    B::T
+    C::AbstractMatrix{K}  # of shape |Σ| x nstates(A)
+end
+
+_computeC(::Type{K}, Σ::AbstractVector, labels::AbstractVector) where K = begin
+    rows = []
+    cols = []
+    for (i,s) in enumerate(Σ)
+        for (j, l) in enumerate(labels)
+            if s == l
+                push!(rows, i)
+                push!(cols, j)
+            end
+        end
+    end
+    sparse(rows, cols, one(K), length(Σ), length(labels))
+end
+
+IntersectedDenseFSA(A::DenseFSA{K}, B::AbstractFSA{K}) where K = begin
+    C = _computeC(K, A.Σ, λ(B)) # TODO switch cols and rows
+    IntersectedDenseFSA(A, B, C)
+    # Hn = C' * A.H
+    # Hn[:, 1] .*= α(B)
+    # Hn[:, end] .*= ω(B)
+    # DenseFSA(Hn, λ(B), ρ(A) * ρ(B))
+end
+
+Base.intersect(A::DenseFSA, B::AbstractFSA) = IntersectedDenseFSA(A, B) 
+Base.intersect(A::AbstractFSA, B::DenseFSA) = IntersectedDenseFSA(B, A) # we assume ∩ to be commutative w.r.t any K
+
+α(I::IntersectedDenseFSA) = begin
+    h1 = I.A.H[:, 1]
+    Q = nstates(I.B) * (size(I.A.H, 2) - 1)
+    vals = (I.C' * h1) .* α(I.B)
+    sparsevec(findnz(vals)..., Q)
+end
+
+ω(I::IntersectedDenseFSA) = begin
+    h = I.A.H[:, end]
+    Q = nstates(I.B) * (size(I.A.H, 2) - 1)
+    vals = (I.C' * h) .* ω(I.B)
+    I, V = findnz(vals)
+    sparsevec(I .+ (Q - length(vals)), V, Q)
+end
+
+T(I::IntersectedDenseFSA) = begin
+    H = I.A.H
+    Tb = T(I.B)
+    C = I.C
+    K = eltype(H)
+    Σ = length(I.A.Σ)
+    Λ = nstates(I.B)
+    Q = Λ * (size(H, 2) - 1)
+
+    rows = []
+    cols = []
+    vals = K[]
+
+    for n in 2:size(H, 2) - 1
+        tmp = ones(K, Λ) * (C' * H[:, n])' .* Tb
+        r, c, v = findnz(tmp)
+        append!(rows, (n - 2) * Λ .+ r)
+        append!(cols, (n - 1) * Λ .+ c)
+        append!(vals, v)
+    end
+    sparse(rows, cols, vals, Q, Q)
+end
+
+λ(I::IntersectedDenseFSA) = repeat(λ(I.B), size(I.A.H, 2) - 1)
+
+ρ(I::IntersectedDenseFSA) = ρ(I.B) * ρ(I.A)
+
+function Base.sum(I::IntersectedDenseFSA, n = size(I.A.H, 2) - 1)
+    CH = I.C' * I.A.H
+    v = CH[:, 1] .* α(I.B)
+    for n in 2:n
+        v = (T(I.B)' * v) .* CH[:, n]
+    end
+    dot(v, ω(I.B) .* CH[:, end]) + ρ(I)
+end