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 76 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 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
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
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ 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"
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
23 changes: 17 additions & 6 deletions src/JunctionTrees.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,52 @@ module JunctionTrees


import AMD
import Catlab.BasicGraphs
import CuthillMcKee
import LinkedLists
import Metis
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


# 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/child_indices.jl")
include("junction_trees/postorder_trees.jl")
include("junction_trees/elimination_trees.jl")
include("junction_trees/abstract_ordered_graphs.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
31 changes: 31 additions & 0 deletions src/junction_trees/abstract_ordered_graphs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
abstract type AbstractOrderedGraph <: AbstractSimpleGraph{Int} end


############################
# Abstract Graph Interface #
############################


function SimpleGraphs.is_directed(::Type{AbstractOrderedGraph})
true

Check warning on line 10 in src/junction_trees/abstract_ordered_graphs.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/abstract_ordered_graphs.jl#L9-L10

Added lines #L9 - L10 were not covered by tests
end


function SimpleGraphs.edgetype(graph::AbstractOrderedGraph)
SimpleEdge{Int}

Check warning on line 15 in src/junction_trees/abstract_ordered_graphs.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/abstract_ordered_graphs.jl#L14-L15

Added lines #L14 - L15 were not covered by tests
end


function SimpleGraphs.has_edge(graph::AbstractOrderedGraph, edge::SimpleEdge{Int})
i = src(edge)
j = dst(edge)
i < j && insorted(j, outneighbors(graph, i))

Check warning on line 22 in src/junction_trees/abstract_ordered_graphs.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/abstract_ordered_graphs.jl#L19-L22

Added lines #L19 - L22 were not covered by tests
end


# Multiline printing.
function Base.show(io::IO, ::MIME"text/plain", graph::AbstractOrderedGraph)
print(io, "ordered graph:\n")
SparseArrays._show_with_braille_patterns(io, adjacencymatrix(graph))

Check warning on line 29 in src/junction_trees/abstract_ordered_graphs.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/abstract_ordered_graphs.jl#L27-L29

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

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
100 changes: 57 additions & 43 deletions src/junction_trees/elimination_algorithms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,45 +52,51 @@


"""
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 65 in src/junction_trees/elimination_algorithms.jl

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/elimination_algorithms.jl#L65

Added line #L65 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


# 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

Expand All @@ -102,45 +108,54 @@


# 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)
m = BasicGraphs.ne(graph)
n = BasicGraphs.nv(graph)
colptr = Vector{Int}(undef, n + 1)
rowval = Vector{Int}(undef, m)
count = 1

for i in 1:n
colptr[i] = count
neighbor = collect(BasicGraphs.all_neighbors(graph, i))
sort!(neighbor)

for j in neighbor
rowval[count] = j
count += 1
end
end

nzval = ones(Int, length(rowval))
colptr[n + 1] = m + 1
nzval = ones(Bool, m)
SparseMatrixCSC(n, n, colptr, rowval, nzval)
end


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

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

View check run for this annotation

Codecov / codecov/patch

src/junction_trees/elimination_algorithms.jl#L142-L143

Added lines #L142 - L143 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)
function mcs(graph::AbstractSparseMatrixCSC)
n = size(graph, 1)
α = Order(undef, n)
len = Vector{Int}(undef, n)
set = Vector{LinkedLists.LinkedList{Int}}(undef, n)
pointer = Vector{LinkedLists.ListNode{Int}}(undef, n)

for i in 1:n
size[i] = 1
len[i] = 1
set[i] = LinkedLists.LinkedList{Int}()
pointer[i] = push!(set[1], i)
end
Expand All @@ -151,15 +166,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 +185,7 @@
end
end

β, α
α
end


Expand Down
Loading
Loading