Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Sparse Matrices #27

Draft
wants to merge 100 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
0c79f0d
temp commit
samuelsonric Nov 21, 2024
549821a
temp commit
samuelsonric Nov 21, 2024
400e7c1
first class support for sparse matrices
samuelsonric Nov 21, 2024
364b70c
more constructors
samuelsonric Nov 21, 2024
1f7055b
using interface functions
samuelsonric Nov 21, 2024
c969d07
api
samuelsonric Nov 21, 2024
22ec20d
added function sparsitygraph
samuelsonric Nov 21, 2024
9c6385a
temp commit
samuelsonric Nov 21, 2024
5054573
temp commit
samuelsonric Nov 21, 2024
7c13ba2
temp commit
samuelsonric Nov 21, 2024
d8221d8
bool matrices
samuelsonric Nov 21, 2024
739f39e
temp commit
samuelsonric Nov 21, 2024
d7981bf
speedup using views
samuelsonric Nov 21, 2024
7214ea0
using views generally
samuelsonric Nov 21, 2024
5702bbe
removed unused function
samuelsonric Nov 21, 2024
b2c5163
graphs interface
samuelsonric Nov 21, 2024
59c1339
minor cleanup
samuelsonric Nov 21, 2024
be68716
moved a constructor
samuelsonric Nov 21, 2024
1f5eeec
printing
samuelsonric Nov 21, 2024
70b6427
fixed docstring
samuelsonric Nov 21, 2024
e23d136
added function `findnode`
samuelsonric Nov 22, 2024
2cad43b
renamed some functions
samuelsonric Nov 22, 2024
57a5df5
docstrings
samuelsonric Nov 22, 2024
1d32be3
docstrings
samuelsonric Nov 22, 2024
ed36838
`length` -> `treesize` and `height` -> `treeheight`.
samuelsonric Nov 22, 2024
4630fd0
`width` -> `treewidth`
samuelsonric Nov 22, 2024
75e885d
renamed functions again...
samuelsonric Nov 22, 2024
0d2964a
moved things around
samuelsonric Nov 22, 2024
9c4660c
removed functions
samuelsonric Nov 22, 2024
e440d81
renamed functions again. small performance improvements
samuelsonric Nov 23, 2024
b31d75c
tests passing
samuelsonric Nov 23, 2024
a166160
speedup
samuelsonric Nov 23, 2024
5691a93
tiny change
samuelsonric Nov 23, 2024
1627070
another speedup
samuelsonric Nov 23, 2024
908fac6
another performance improvement
samuelsonric Nov 23, 2024
556c897
storing full adjacency matrix
samuelsonric Nov 23, 2024
cfd1040
tests passing...
samuelsonric Nov 23, 2024
2a8de42
temp commit
samuelsonric Nov 23, 2024
1bcf85d
temp commit
samuelsonric Nov 23, 2024
fc44def
removed old function
samuelsonric Nov 23, 2024
bf53113
minor change
samuelsonric Nov 23, 2024
d7fcc7a
postorder tree contains a tree
samuelsonric Nov 23, 2024
ac0f690
performance improvement by implementing children iterator
samuelsonric Nov 23, 2024
272577e
temp commit
samuelsonric Nov 23, 2024
cfc29b5
added file
samuelsonric Nov 23, 2024
501fce3
tests passing
samuelsonric Nov 24, 2024
289391e
zeros in parents
samuelsonric Nov 24, 2024
02c6e30
renamed variable
samuelsonric Nov 25, 2024
927470e
tests passing
samuelsonric Nov 25, 2024
68ee1cb
elimination trees gone
samuelsonric Nov 25, 2024
39f9da0
tests passing somehow
samuelsonric Nov 26, 2024
f5115d6
removed type `SupernodeTree`
samuelsonric Nov 26, 2024
763552f
removed graph from jtree
samuelsonric Nov 26, 2024
aa612fe
renamed variables
samuelsonric Nov 26, 2024
6518848
added some docstrings
samuelsonric Nov 27, 2024
9c68ef6
removed degrees
samuelsonric Nov 27, 2024
7790f63
temp commit
samuelsonric Dec 2, 2024
a6fa24e
temp commit
samuelsonric Dec 2, 2024
695a422
temp commit
samuelsonric Dec 5, 2024
61df456
performance improvement
samuelsonric Dec 5, 2024
d96bad7
fiddled with internals
samuelsonric Dec 5, 2024
be4bb49
removed function fdesc
samuelsonric Dec 6, 2024
b5de2d9
fixed ne calculation
samuelsonric Dec 6, 2024
b61b0c2
changed types
samuelsonric Dec 6, 2024
97b7839
printing
samuelsonric Dec 6, 2024
772162b
order setindex
samuelsonric Dec 6, 2024
4808c77
temp commit
samuelsonric Dec 6, 2024
0243076
tests passing
samuelsonric Dec 6, 2024
4dbd44f
tiny performance improvement
samuelsonric Dec 6, 2024
820345b
deleted swp
samuelsonric Dec 6, 2024
8d6e526
fixed math
samuelsonric Dec 6, 2024
0330446
pointless changes
samuelsonric Dec 6, 2024
4739181
performance improvement during symbolic factorization
samuelsonric Dec 9, 2024
cc8e887
removed unused files
samuelsonric Dec 10, 2024
d1a182b
removed commented code
samuelsonric Dec 11, 2024
9d09828
seperate data structures.
samuelsonric Dec 12, 2024
850d752
removed abstract ordered graphs
samuelsonric Dec 15, 2024
f6f7f24
storing adjacency matrix
samuelsonric Dec 15, 2024
4294dad
ordered handled in place
samuelsonric Dec 15, 2024
ccfc436
permuting graphs in place
samuelsonric Dec 15, 2024
d13d0b2
rewrote a function
samuelsonric Dec 15, 2024
b32201b
tiny change
samuelsonric Dec 15, 2024
971ec93
postordertree -> tree
samuelsonric Dec 16, 2024
c169c83
removed a variable
samuelsonric Dec 16, 2024
0bee9b7
postorder trees gone
samuelsonric Dec 16, 2024
f40b329
simplified things a bit
samuelsonric Dec 16, 2024
ba23c91
moved code to seperate function
samuelsonric Dec 16, 2024
0663226
computing sepptr earlier
samuelsonric Dec 16, 2024
a82562e
changed vector type
samuelsonric Dec 16, 2024
3f0bb98
allocating arrays
samuelsonric Dec 16, 2024
038f9db
removed field partition
samuelsonric Dec 16, 2024
0ef1db9
tiny change
samuelsonric Dec 16, 2024
d58b567
tiny change
samuelsonric Dec 16, 2024
2d1aaab
size hints
samuelsonric Dec 16, 2024
33de42b
removed a variable
samuelsonric Dec 16, 2024
6271a32
commented out first_anc
samuelsonric Dec 16, 2024
25b3337
tests passing
samuelsonric Dec 16, 2024
503ed6d
ancestors back
samuelsonric Dec 16, 2024
db66855
imports
samuelsonric Dec 16, 2024
4241127
added symrcm ordering
samuelsonric Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Catlab = "134e5e36-593f-5add-ad60-77f754baafbe"
CuthillMcKee = "17f17636-5e38-52e3-a803-7ae3aaaf3da9"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
LinkedLists = "70f5e60a-1556-5f34-a19e-a48b3e4aaee9"
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b"
PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
SymRCM = "286e6d88-80af-4590-acc9-0001b223b9bd"
TreeWidthSolver = "7d267fc5-9ace-409f-a54c-cd2374872a55"

[compat]
Expand Down
10 changes: 5 additions & 5 deletions src/Decompositions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ end
# jtree junction tree
# ----------------------------------------
function StrDecomp(graph::AbstractSymmetricGraph, jtree::JunctionTree)
n = length(jtree)
n = treesize(jtree)
tree = Graph(n)

for i in 1:n - 1
Expand Down Expand Up @@ -293,7 +293,7 @@ end


function homomorphisms(graph::AbstractSymmetricGraph, jtree::JunctionTree)
n = length(jtree)
n = treesize(jtree)
subgraph = Vector{Any}(undef, 2n - 1)
homomorphism = Vector{Any}(undef, 2n - 2)

Expand All @@ -310,20 +310,20 @@ function homomorphisms(graph::AbstractSymmetricGraph, jtree::JunctionTree)
for i in 1:n - 1
# seperator(i) → clique(parent(i))
j = parentindex(jtree, i)
homomorphism[i] = induced_homomorphism(subgraph[n + i], subgraph[j], seperator_to_parent(jtree, i))
homomorphism[i] = induced_homomorphism(subgraph[n + i], subgraph[j], lift_par(jtree, i))
end

for i in 1:n - 1
# seperator(i) → clique(i)
homomorphism[n + i - 1] = induced_homomorphism(subgraph[n + i], subgraph[i], seperator_to_self(jtree, i))
homomorphism[n + i - 1] = induced_homomorphism(subgraph[n + i], subgraph[i], lift_sep(jtree, i))
end

subgraph, homomorphism
end


function induced_order(order::Order, elements::AbstractVector)
Order(sortperm(inverse(order, elements)))
Order(sortperm(view(inv(order), elements)))
end


Expand Down
28 changes: 19 additions & 9 deletions src/JunctionTrees.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,51 @@ module JunctionTrees


import AMD
import Catlab.BasicGraphs
import CuthillMcKee
import LinkedLists
import LinkedLists: ListNode, LinkedList
import Metis
import SymRCM
import TreeWidthSolver

using AbstractTrees
using Catlab.BasicGraphs
using Base.Order: Ordering
using DataStructures
using Graphs
using Graphs.SimpleGraphs
using LinearAlgebra
using SparseArrays
using SparseArrays: AbstractSparseMatrixCSC


# Orders
export Order, inverse
export Order


# Elimination Algorithms
export AMDJL_AMD, CuthillMcKeeJL_RCM, MetisJL_ND, TreeWidthSolverJL_BT, MCS
export AMDJL_AMD, CuthillMcKeeJL_RCM, SymRCMJL_RCM, MetisJL_ND, TreeWidthSolverJL_BT, MCS


# Ordered Graphs
export OrderedGraph


# Supernode Types
export Node, Maximal, Fundamental


# Junction Trees
export JunctionTree, width, height, seperator, residual, clique, seperator_to_parent, seperator_to_self
export JunctionTree, treewidth, seperator, residual, clique, find_clique, lift_par, lift_sep, lift


include("junction_trees/fixed_stacks.jl")
include("junction_trees/disjoint_sets.jl")
include("junction_trees/orders.jl")
include("junction_trees/elimination_algorithms.jl")
include("junction_trees/ordered_graphs.jl")
include("junction_trees/trees.jl")
include("junction_trees/postorder_trees.jl")
include("junction_trees/elimination_trees.jl")
include("junction_trees/child_indices.jl")
include("junction_trees/ordered_graphs.jl")
include("junction_trees/supernode_types.jl")
include("junction_trees/supernode_trees.jl")
include("junction_trees/junction_trees.jl")


Expand Down
33 changes: 33 additions & 0 deletions src/junction_trees/child_indices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
struct ChildIndices
tree::Tree
index::Int
end


function Base.iterate(iterator::ChildIndices)
iterate(iterator, iterator.tree.child[iterator.index])
end


function Base.iterate(iterator::ChildIndices, i::Integer)
if iszero(i)
nothing
else
i, iterator.tree.brother[i]
end
end


function Base.IteratorSize(::Type{ChildIndices})
Base.SizeUnknown()
end


function Base.eltype(::Type{ChildIndices})
Int

Check warning on line 27 in src/junction_trees/child_indices.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/child_indices.jl#L26-L27

Added lines #L26 - L27 were not covered by tests
end


function AbstractTrees.childindices(tree::Tree, i::Integer)
ChildIndices(tree, i)
end
21 changes: 21 additions & 0 deletions src/junction_trees/disjoint_sets.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
struct DisjointSets
sets::IntDisjointSets{Int}
index::Vector{Int}
root::Vector{Int}

function DisjointSets(n::Integer)
new(IntDisjointSets(n), collect(1:n), collect(1:n))
end
end


function find!(sets::DisjointSets, u::Integer)
sets.index[find_root!(sets.sets, u)]
end


function Base.union!(sets::DisjointSets, u::Integer, v::Integer)
w = max(u, v)
sets.root[w] = root_union!(sets.sets, sets.root[u], sets.root[v])
sets.index[sets.root[w]] = w
end
117 changes: 69 additions & 48 deletions src/junction_trees/elimination_algorithms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

A graph elimination algorithm. The options are
- [`CuthillMcKeeJL_RCM`](@ref)
- [`SymRCMJL_RCM`](@ref)
- [`AMDJL_AMD`](@ref)
- [`MetisJL_ND`](@ref)
- [`TreeWidthSolverJL_BT`](@ref)
Expand All @@ -19,6 +20,14 @@
struct CuthillMcKeeJL_RCM <: EliminationAlgorithm end


"""
SymRCMJL_RCM <: EliminationAlgorithm

The reverse Cuthill-McKee algorithm. Uses SymRCM.jl.
"""
struct SymRCMJL_RCM <: EliminationAlgorithm end


"""
AMDJL_AMD <: EliminationAlgorithm

Expand Down Expand Up @@ -52,96 +61,109 @@


"""
Order(graph::AbstractSymmetricGraph[, ealg::EliminationAlgorithm])
Order(graph[, ealg::EliminationAlgorithm])

Construct an elimination order for a simple graph, optionally specifying an elimination algorithm.
"""
function Order(graph::AbstractSymmetricGraph)
function Order(graph, ealg::EliminationAlgorithm=DEFAULT_ELIMINATION_ALGORITHM)
Order(adjacencymatrix(graph), ealg)
end


# Construct an elimination order.
function Order(graph::AbstractMatrix)

Check warning on line 74 in src/junction_trees/elimination_algorithms.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/elimination_algorithms.jl#L74

Added line #L74 was not covered by tests
Order(graph, DEFAULT_ELIMINATION_ALGORITHM)
end


# Construct an order using the reverse Cuthill-McKee algorithm. Uses CuthillMcKee.jl.
function Order(graph::AbstractSymmetricGraph, ealg::CuthillMcKeeJL_RCM)
order = CuthillMcKee.symrcm(adjacencymatrix(graph))
function Order(graph::AbstractMatrix, ealg::CuthillMcKeeJL_RCM)
order = CuthillMcKee.symrcm(graph)
Order(order)
end


function Order(graph::AbstractMatrix, ealg::SymRCMJL_RCM)
order = SymRCM.symrcm(graph)
Order(order)
end


# Construct an order using the approximate minimum degree algorithm. Uses AMD.jl.
function Order(graph::AbstractSymmetricGraph, ealg::AMDJL_AMD)
order = AMD.symamd(adjacencymatrix(graph))
function Order(graph::AbstractMatrix, ealg::AMDJL_AMD)
order = AMD.symamd(graph)
Order(order)
end


# Construct an order using the nested dissection heuristic. Uses Metis.jl.
function Order(graph::AbstractSymmetricGraph, ealg::MetisJL_ND)
order, index = Metis.permutation(adjacencymatrix(graph))
function Order(graph::AbstractMatrix, ealg::MetisJL_ND)
order, index = Metis.permutation(graph)
Order(order, index)
end


# Construct an order using the Bouchitte-Todinca algorithm. Uses TreeWidthSolver.jl.
function Order(graph::AbstractSymmetricGraph, ealg::TreeWidthSolverJL_BT)
n = nv(graph)
function Order(graph::AbstractSparseMatrixCSC, ealg::TreeWidthSolverJL_BT)
n = size(graph, 1)
T = TreeWidthSolver.LongLongUInt{n ÷ 64 + 1}
fadjlist = Vector{Vector{Int}}(undef, n)
bitfadjlist = Vector{T}(undef, n)

for i in 1:n
fadjlist[i] = sort(collect(outneighbors(graph, i)))
fadjlist[i] = rowvals(graph)[nzrange(graph, i)]
bitfadjlist[i] = TreeWidthSolver.bmask(T, fadjlist[i])
end

bitgraph = TreeWidthSolver.MaskedBitGraph(bitfadjlist, fadjlist, TreeWidthSolver.bmask(T, 1:n))
decomposition = TreeWidthSolver.bt_algorithm(bitgraph, TreeWidthSolver.all_pmc_enmu(bitgraph, false), ones(n), false, true)
order = reverse(vcat(TreeWidthSolver.EliminationOrder(decomposition.tree).order...))
order = reverse(reduce(vcat, TreeWidthSolver.EliminationOrder(decomposition.tree).order))
Order(order)
end


# Construct an order using the maximum cardinality search algorithm.
function Order(graph::AbstractSymmetricGraph, ealg::MCS)
order, index = mcs(graph)
Order(order, index)
function Order(graph::AbstractMatrix, ealg::MCS)
mcs(graph)
end


# Construct the adjacency matrix of a graph.
function adjacencymatrix(graph::AbstractSymmetricGraph)
m = ne(graph)
n = nv(graph)

colptr = ones(Int, n + 1)
rowval = sizehint!(Vector{Int}(), 2m)

for j in 1:n
ns = collect(neighbors(graph, j))
sort!(ns)
colptr[j + 1] = colptr[j] + length(ns)
append!(rowval, ns)
function adjacencymatrix(graph::BasicGraphs.AbstractSymmetricGraph)
rowval = Vector{Int}(undef, BasicGraphs.ne(graph))
colptr = Vector{Int}(undef, BasicGraphs.nv(graph) + 1)
colptr[1] = 1

for i in BasicGraphs.vertices(graph)
column = BasicGraphs.all_neighbors(graph, i)
colptr[i + 1] = colptr[i] + length(column)
rowval[colptr[i]:colptr[i + 1] - 1] = sort!(collect(column))
end

nzval = ones(Int, length(rowval))
SparseMatrixCSC(n, n, colptr, rowval, nzval)
nzval = ones(Bool, BasicGraphs.ne(graph))
SparseMatrixCSC(BasicGraphs.nv(graph), BasicGraphs.nv(graph), colptr, rowval, nzval)
end


# Construct the adjacency matrix of a graph.
function adjacencymatrix(graph::AbstractGraph)
adjacency_matrix(graph; dir=:both)

Check warning on line 150 in src/junction_trees/elimination_algorithms.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/elimination_algorithms.jl#L149-L150

Added lines #L149 - L150 were not covered by tests
end


# Simple Linear-Time Algorithms to Test Chordality of Graphs, Test Acyclicity of Hypergraphs, and Selectively Reduce Acyclic Hypergraphs
# Tarjan and Yannakakis
# Maximum Cardinality Search
function mcs(graph::AbstractSymmetricGraph)
n = nv(graph)
α = Vector{Int}(undef, n)
β = Vector{Int}(undef, n)
size = Vector{Int}(undef, n)
set = Vector{LinkedLists.LinkedList{Int}}(undef, n)
pointer = Vector{LinkedLists.ListNode{Int}}(undef, n)
function mcs(graph::AbstractSparseMatrixCSC)
n = size(graph, 1)
α = Order(undef, n)
len = Vector{Int}(undef, n)
set = Vector{LinkedList{Int}}(undef, n)
pointer = Vector{ListNode{Int}}(undef, n)

for i in 1:n
size[i] = 1
set[i] = LinkedLists.LinkedList{Int}()
len[i] = 1
set[i] = LinkedList{Int}()
pointer[i] = push!(set[1], i)
end

Expand All @@ -151,15 +173,14 @@
while i >= 1
v = first(set[j])
deleteat!(set[j], pointer[v])
α[v] = i
β[i] = v
size[v] = 0

for w in neighbors(graph, v)
if size[w] >= 1
deleteat!(set[size[w]], pointer[w])
size[w] += 1
pointer[w] = push!(set[size[w]], w)
α[i] = v
len[v] = 0

for w in view(rowvals(graph), nzrange(graph, v))
if len[w] >= 1
deleteat!(set[len[w]], pointer[w])
len[w] += 1
pointer[w] = push!(set[len[w]], w)
end
end

Expand All @@ -171,7 +192,7 @@
end
end

β, α
α
end


Expand Down
Loading
Loading