Skip to content

Instantly share code, notes, and snippets.

@arbenson
Created May 7, 2017 21:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arbenson/58b3fb84f05f60ba1519cd75b846004d to your computer and use it in GitHub Desktop.
Save arbenson/58b3fb84f05f60ba1519cd75b846004d to your computer and use it in GitHub Desktop.
Julia implementation of the motif-based clustering algorithm
# Find a motif-based cluster for any directed triangle motif.
function MotifSpectralClust(A::SparseMatrixCSC{Int64,Int64}, motif::AbstractString)
# Form motif adjacency matrix
B = min.(A, A') # bidirectional links
U = A - B # unidirectional links
if motif == "M1"
C = (U * U) .* U'
W = C + C'
elseif motif == "M2"
C = (B * U) .* U' + (U * B) .* U' + (U * U) .* B
W = C + C'
elseif motif == "M3"
C = (B * B) .* U + (B * U) .* B + (U * B) .* B
W = C + C'
elseif motif == "M4"
W = (B * B) .* B
elseif motif == "M5"
C = (U * U) .* U + (U * U') .* U + (U' * U) .* U
W = C + C'
elseif motif == "M6"
W = (U * B) .* U + (B * U') .* U' + (U' * U) .* B
elseif motif == "M7"
W = (U' * B) .* U' + (B * U) .* U + (U * U') .* B
else
error("Motif must be one of M1, M2, M3, M4, M5, M6, or M7.")
end
# Get Fiedler eigenvector
dinvsqrt = spdiagm(1.0 ./ sqrt.(vec(sum(W, 1))))
LM = I - dinvsqrt * W * dinvsqrt
lambdas, evecs = eigs(LM, nev=2, which=:SM)
z = dinvsqrt * real(evecs[:, 2])
# Sweep cut
sigma = sortperm(z)
C = W[sigma, sigma]
Csums = sum(C, 1)'
motifvolS = cumsum(Csums)
motifvolSbar = sum(W) * ones(length(sigma)) - motifvolS
conductances = cumsum(Csums - 2 * sum(triu(C), 1)') ./ min.(motifvolS, motifvolSbar)
split = indmin(conductances)
if split <= length(size(A, 1) / 2)
return sigma[1:split]
else
return sigma[(split + 1):end]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment