Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #####
- ### The code below is written by Benjamin Lind under CC: BY-NC-SA 3.0
- ### If you use or develop this code, please provide proper attribution.
- ### You may contact me at lind.benjamin//at//gmail//d0t//com
- ### You may also find me @benjaminlind on Twitter
- #####
- using Graphs
- #####
- ### Convenient helper functions for the Graphs library in the language of Julia
- ### These do not call on any other library and are written entirely in Julia
- ### For more information on the library, see: graphsjl-docs.readthedocs.org/en/
- #####
- ### To load these functions:
- ## download("http://pastebin.com/raw.php?i=hcRJmCPH", "GraphsLibHelperFunctions.jl"); include("GraphsLibHelperFunctions.jl"); rm("GraphsLibHelperFunctions.jl")
- ### el_2_graph converts an edgelist to a GenericGraph type
- ## They vary based upon string or integer inputs.
- ## They can accept the number of vertices or vertex names are supplied.
- ## If the number of vertices or names are not supplied, then the information is inferred from the edgelist
- function el_2_graph(n::Int, el::Array{Int, 2}; directed::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- # _n_ refers to the number of vertices in the graph
- # _el_ is an integer only edgelist
- vertexnames = [el[:,1], el[:,2]]
- vertexnames = unique(vertexnames)
- if (minimum(vertexnames) < 1) | (n < 1)
- error("The number of vertices ('n') and the vertex indices must be greater than or equal to 1.")
- end
- n = ifelse(maximum(vertexnames) > n, maximum(vertexnames), n)
- ne = size(el, 1)
- if vtype == KeyVertex
- vlist = Array(vtype{Int}, n)
- for i = 1:n
- vlist[i] = vtype(i, i)
- end
- elseif vtype == ExVertex
- vlist = Array(vtype, n)
- for i = 1:n
- vlist[i] = vtype(i, string(i))
- end
- else
- error("'vtype' must be either KeyVertex or ExVertex")
- end
- elist = Array(etype{typeof(vlist[1])}, ne)
- for i = 1:ne
- elist[i] = etype(i, vlist[el[i, 1]], vlist[el[i, 2]])
- end
- return graph(vlist, elist, is_directed = directed)
- end
- function el_2_graph(el::Array{Int, 2}; directed::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- # _el_ is an integer only edgelist
- vertexnames = [el[:,1], el[:,2]]
- vertexnames = unique(vertexnames)
- n = maximum(vertexnames)
- return el_2_graph(n, el; directed = directed, vtype = vtype, etype = etype)
- end
- function el_2_graph(v::Array{String, 1}, el::Array{String, 2}; directed::Bool = true, label::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- # _v_ is a list of vertex "names"
- # _el_ is an edgelist of vertex "names"
- v = unique(v) #In case of double entries
- vertexnames = [el[:,1], el[:,2]]
- vertexnames = unique(vertexnames)
- for i = 1:length(vertexnames)
- if in(vertexnames[i], v) == false
- vunnamed = vertexnames[i]
- warn("Vertex $vunnamed appears in the edge list 'el' but not in the vertex list 'v'. Including $vunnamed in 'v'.")
- push!(v, vunnamed)
- end
- end
- n = length(v)
- ne = size(el, 1)
- if label
- if vtype == KeyVertex
- vlist = Array(vtype{typeof(v[1])}, n)
- elseif vtype == ExVertex
- vlist = Array(vtype, n)
- else
- error("'vtype' must be either KeyVertex or ExVertex")
- end
- for i = 1:n
- vlist[i] = vtype(i, v[i])
- end
- else
- if vtype == KeyVertex
- vlist = Array(vtype{Int}, n)
- for i = 1:n
- vlist[i] = vtype(i, i)
- end
- elseif vtype == ExVertex
- vlist = Array(vtype, n)
- for i = 1:n
- vlist[i] = vtype(i, string(i))
- end
- else
- error("'vtype' must be either KeyVertex or ExVertex")
- end
- end
- elist = Array(etype{typeof(vlist[1])}, ne)
- for i = 1:ne
- elist[i] = etype(i, vlist[findin([v], [el[i, 1]])[1]], vlist[findin([v], [el[i, 2]])[1]])
- end
- return graph(vlist, elist, is_directed = directed)
- end
- function el_2_graph(el::Array{String, 2}; directed::Bool = true, label::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- # _el_ is an edgelist of vertex "names"
- v = unique([el[:,1], el[:,2]])
- return el_2_graph(v, el, directed = directed, label = label, vtype = vtype, etype = etype)
- end
- function el_2_graph(v::Array{String, 1}, el::Array{Int, 2}; directed::Bool = true, label::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- # _v_ is a list of vertex "names"
- # _el_ is an integer only edgelist
- if any(el .> length(v))
- error("The number of indexes referenced in 'el' exceeds the number of vertices provided.")
- end
- eldim = size(el)
- newel = Array(String, eldim[1], eldim[2])
- for i = 1:eldim[1]
- newel[i,:] = [v[el[i, 1]], v[el[i, 2]]]
- end
- return el_2_graph(v, newel, directed = directed, label = label, vtype = vtype, etype = etype)
- end
- function el_2_graph(v::Array{UTF8String, 1}, el::Array{UTF8String, 2}; directed::Bool = true, label::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- v = convert(Array{String, 1}, v)
- el = convert(Array{String, 2}, el)
- return el_2_graph(v, el, directed = directed, label = label, vtype = vtype, etype = etype)
- end
- function el_2_graph(el::Array{UTF8String, 2}; directed::Bool = true, label::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- el = convert(Array{String, 2}, el)
- return el_2_graph(el, directed = directed, label = label, vtype = vtype, etype = etype)
- end
- function el_2_graph(v::Array{UTF8String, 1}, el::Array{Int, 2}; directed::Bool = true, label::Bool = true, vtype::DataType = KeyVertex, etype::DataType = Edge)
- v = convert(Array{String, 1}, v)
- return el_2_graph(v, el, directed = directed, label = label, vtype = vtype, etype = etype)
- end
- ### graph_2_el takes a GenericGraph and returns a two-column edgelist.
- function graph_2_el(g::GenericGraph, label::Bool = true)
- if in(:key, names(g.vertices[1]))
- vtype = KeyVertex
- elseif in(:label, names(g.vertices[1]))
- vtype = ExVertex
- else
- vtype = Int
- label = false
- end
- ne = num_edges(g)
- nv = num_vertices(g)
- alledges = edges(g)
- allsamekeytype = true
- if vtype == KeyVertex
- if nv > 1
- firstkey = typeof(g.vertices[1].key)
- vcounter = 2
- while (vcounter <= nv) & allsamekeytype
- if typeof(g.vertices[vcounter].key) != firstkey
- allsamekeytype = false
- end
- vcounter += 1
- end
- end
- end
- if label & (vtype == KeyVertex) & allsamekeytype
- el = Array(typeof(g.vertices[1].key), ne, 2)
- for i = 1:num_edges(g)
- el[i, 1] = source(alledges[i], g).key
- el[i, 2] = target(alledges[i], g).key
- end
- elseif label & (vtype == ExVertex)
- el = Array(typeof(g.vertices[1].label), ne, 2)
- for i = 1:num_edges(g)
- el[i, 1] = source(alledges[i], g).label
- el[i, 2] = target(alledges[i], g).label
- end
- else
- el = Array(Int, ne, 2)
- for i = 1:num_edges(g)
- el[i, 1] = source(alledges[i], g).index
- el[i, 2] = target(alledges[i], g).index
- end
- end
- return el
- end
- ### These next four functions convert the vertex and edge types.
- function keyvertex_2_exvertex(g::GenericGraph)
- if in(:key, names(g.vertices[1])) == false
- error("GenericGraph 'g' must have vertices of type KeyVertex.")
- end
- nv, ne = num_vertices(g), num_edges(g)
- vlist = Array(ExVertex, nv)
- for i = 1:nv
- vlist[i] = ExVertex(g.vertices[i].index, string(g.vertices[i].key))
- end
- etype = ifelse(in(:attributes, names(g.edges[1])), ExEdge, Edge)
- elist = Array(etype{typeof(vlist[1])}, ne)
- for i = 1:ne
- elist[i] = etype(i, vlist[g.edges[i].source.index], vlist[g.edges[i].target.index])
- end
- return graph(vlist, elist, is_directed = g.is_directed)
- end
- function exvertex_2_keyvertex(g::GenericGraph)
- if in(:label, names(g.vertices[1])) == false
- error("GenericGraph 'g' must have vertices of type ExVertex.")
- end
- nv, ne = num_vertices(g), num_edges(g)
- vlist = Array(KeyVertex, nv)
- for i = 1:nv
- vlist[i] = KeyVertex(g.vertices[i].index, g.vertices[i].label)
- end
- etype = ifelse(in(:attributes, names(g.edges[1])), ExEdge, Edge)
- elist = Array(etype{typeof(vlist[1])}, ne)
- for i = 1:ne
- elist[i] = etype(i, vlist[g.edges[i].source.index], vlist[g.edges[i].target.index])
- end
- return graph(vlist, elist, is_directed = g.is_directed)
- end
- function edge_2_exedge(g::GenericGraph)
- vlist = g.vertices
- ne = num_edges(g)
- elist = Array(ExEdge{typeof(vlist[1])}, ne)
- for i = 1:ne
- elist[i] = ExEdge(i, vlist[g.edges[i].source.index], vlist[g.edges[i].target.index])
- end
- return graph(vlist, elist, is_directed = g.is_directed)
- end
- function exedge_2_edge(g::GenericGraph)
- vlist = g.vertices
- ne = num_edges(g)
- elist = Array(Edge{typeof(vlist[1])}, ne)
- for i = 1:ne
- elist[i] = Edge(i, vlist[g.edges[i].source.index], vlist[g.edges[i].target.index])
- end
- return graph(vlist, elist, is_directed = g.is_directed)
- end
- #####
- ### These following two functions create subgraphs.
- ### The first creates subgraphs by vertex index.
- ### The second creates subgraphs by edge index.
- #####
- function subgraph_vertices(g::GenericGraph, vind::Array{Int, 1})
- if num_vertices(g) == 0
- error("The number of vertices in 'g' equals zero. Cannot base new graph off of it.")
- end
- newg = deepcopy(g)
- vlist = deepcopy(vertices(newg)[vind])
- for i = 1:length(vlist)
- newvert = vlist[i]
- setfield!(newvert, :index, i)
- vlist[i] = newvert
- end
- oldedges = deepcopy(edges(newg))
- elist = typeof(oldedges[1])[]
- nedges = num_edges(newg)
- ecount = 1
- if nedges > 0
- for i = 1:nedges
- sourceinsubgraph = in(vertex_index(source(oldedges[i])), vind)
- targetinsubgraph = in(vertex_index(target(oldedges[i])), vind)
- if sourceinsubgraph & targetinsubgraph
- sv = vlist[find(vertex_index(source(oldedges[i])) .== vind)[1]]
- tv = vlist[find(vertex_index(target(oldedges[i])) .== vind)[1]]
- newedge = typeof(oldedges[i])(ecount, sv, tv)
- push!(elist, newedge)
- ecount += 1
- end
- end
- end
- newg = graph(vlist, elist, is_directed = is_directed(g))
- return newg
- end
- function subgraph_edges(g::GenericGraph, eind::Array{Int, 1})
- ne = num_edges(g)
- if ne == 0
- error("The number of edges in 'g' equals zero. Cannot base new graph off of it.")
- end
- newg = deepcopy(g)
- elist = deepcopy(edges(newg)[eind])
- ne = length(elist)
- sources = Array(typeof(vertex_index(source(elist[1]))), ne)
- targets = Array(typeof(vertex_index(target(elist[1]))), ne)
- for i = 1:ne
- sources[i] = vertex_index(source(elist[i]))
- targets[i] = vertex_index(target(elist[i]))
- end
- vind = unique([sources, targets])
- vlist = deepcopy(vertices(newg)[vind])
- for i = 1:length(vlist)
- newvert = vlist[i]
- setfield!(newvert, :index, i)
- vlist[i] = newvert
- end
- for i = 1:ne
- sv = vlist[find(vertex_index(source(elist[i])) .== vind)[1]]
- tv = vlist[find(vertex_index(target(elist[i])) .== vind)[1]]
- newedge = typeof(elist[i])(i, sv, tv)
- elist[i] = newedge
- end
- newg = graph(vlist, elist, is_directed = is_directed(g))
- return newg
- end
- #####
- ### Attribute methods
- ### Vertex and edge attributes
- ### Both sets of attributes have set, get, list, and remove functions
- ### The indexes can be specified, though if left empty they default to all vertices or edges
- ### Problems
- ### Setting attvalue as type Array{Any, 1} in the functions produce methods errors; I've left it out
- ### The set and remove functions could/should be made mutable.
- #####
- ### Vertex attribute functions
- function set_vertex_attribute(g::GenericGraph, attname::String, attvalue, vertexind::Array{Int, 1})
- if in(:label, names(g.vertices[vertexind[1]])) == false
- warn("GenericGraph 'g' has vertices of type ExVertex. Converting them to ExVertex now.")
- g = keyvertex_2_exvertex(g)
- end
- if length(attvalue) != length(vertexind)
- error("Length of 'attvalue' does not equal the length of 'vertexind'.")
- end
- for i = 1:length(vertexind)
- g.vertices[vertexind[i]].attributes[attname] = attvalue[i]
- end
- return g
- end
- function set_vertex_attribute(g::GenericGraph, attname::String, attvalue)
- vertexind = [1:num_vertices(g)]
- return set_vertex_attribute(g, attname, attvalue, vertexind)
- end
- function set_vertex_attribute(g::GenericGraph, attname::String, attvalue, vertexind::Int)
- vertexind = [vertexind]
- attvalue = [attvalue]
- return set_vertex_attribute(g, attname, attvalue, vertexind)
- end
- function set_vertex_attribute(g::GenericGraph, attname::String, attvalue, vertexind::UnitRange{Int})
- vertexind = [vertexind]
- return set_vertex_attribute(g, attname, attvalue, vertexind)
- end
- function get_vertex_attribute(g::GenericGraph, attname::String, vertexind::Array{Int, 1})
- if in(:label, names(g.vertices[vertexind[1]])) == false
- error("Vertices in GenericGraph 'g' are not of type ExVertex.")
- end
- if in(attname, collect(keys(g.vertices[vertexind[1]].attributes))) == false
- error("Attribute '$attname' not found.")
- end
- nind = length(vertexind)
- retvec = Array(typeof(g.vertices[vertexind[1]].attributes[attname]), nind)
- for i = 1:nind
- retvec[i] = g.vertices[vertexind[i]].attributes[attname]
- end
- return retvec
- end
- function get_vertex_attribute(g::GenericGraph, attname::String)
- vertexind = [1:num_vertices(g)]
- return get_vertex_attribute(g, attname, vertexind)
- end
- function get_vertex_attribute(g::GenericGraph, attname::String, vertexind::UnitRange{Int})
- vertexind = [vertexind]
- return get_vertex_attribute(g, attname, vertexind)
- end
- function get_vertex_attribute(g::GenericGraph, attname::String, vertexind::Int)
- vertexind = [vertexind]
- return get_vertex_attribute(g, attname, vertexind)[1]
- end
- function list_vertex_attributes(g::GenericGraph)
- if in(:label, names(g.vertices[1])) == false
- error("Vertices in GenericGraph 'g' are not of type ExVertex.")
- end
- retvec = UTF8String[]
- for i = 1:length(g.vertices)
- attkeys = collect(keys(g.vertices[i].attributes))
- nattkeys = length(attkeys)
- if nattkeys > 0
- for j = 1:nattkeys
- push!(retvec, attkeys[j])
- end
- end
- end
- retvec = sort(unique(retvec))
- return retvec
- end
- function remove_vertex_attributes(g::GenericGraph, attname::String, vertexind::Array{Int, 1})
- if in(:label, names(g.vertices[vertexind[1]])) == false
- error("Vertices in GenericGraph 'g' are not of type ExVertex.")
- end
- for i = vertexind
- attkeys = collect(keys(g.vertices[i].attributes))
- if in(attname, attkeys)
- tempvertex = ExVertex(g.vertices[i].index, g.vertices[i].label)
- for j = 1:length(attkeys)
- if attkeys[j] != attname
- tempvertex.attributes[attkeys[j]] = g.vertices[i].attributes[attkeys[j]]
- end
- end
- g.vertices[i] = tempvertex
- else
- warn("Attribute '$attname' is not an attribute at vertex index $i of graph 'g'.")
- end
- end
- return g
- end
- function remove_vertex_attributes(g::GenericGraph, attname::String)
- vertexind = [1:num_vertices(g)]
- return remove_vertex_attributes(g, attname, vertexind)
- end
- function remove_vertex_attributes(g::GenericGraph, attname::String, vertexind::Int)
- vertexind = [vertexind]
- return remove_vertex_attributes(g, attname, vertexind)
- end
- function remove_vertex_attributes(g::GenericGraph, attname::String, vertexind::UnitRange{Int})
- vertexind = [vertexind]
- return remove_vertex_attributes(g, attname, vertexind)
- end
- ### Edge attribute functions
- function set_edge_attribute(g::GenericGraph, attname::String, attvalue, edgeind::Array{Int, 1})
- if in(:attributes, names(g.edges[edgeind[1]])) == false
- warn("Edges in GenericGraph 'g' are not of type ExEdge. Converting them to ExEdge now.")
- g = edge_2_exedge(g)
- end
- if length(attvalue) != length(edgeind)
- error("Length of 'attvalue' does not equal the length of 'edgeind'.")
- end
- for i = 1:length(edgeind)
- g.edges[edgeind[i]].attributes[attname] = attvalue[i]
- end
- return g
- end
- function set_edge_attribute(g::GenericGraph, attname::String, attvalue)
- edgeind = [1:num_edges(g)]
- return set_edge_attribute(g, attname, attvalue, edgeind)
- end
- function set_edge_attribute(g::GenericGraph, attname::String, attvalue, edgeind::Int)
- attvalue = [attvalue]
- edgeind = [edgeind]
- return set_edge_attribute(g, attname, attvalue, edgeind)
- end
- function set_edge_attribute(g::GenericGraph, attname::String, attvalue, edgeind::UnitRange{Int})
- edgeind = [edgeind]
- return set_edge_attribute(g, attname, attvalue, edgeind)
- end
- function get_edge_attribute(g::GenericGraph, attname::String, edgeind::Array{Int, 1})
- if in(:attributes, names(g.edges[edgeind[1]])) == false
- error("Edges in GenericGraph 'g' are not of type ExEdge.")
- end
- if in(attname, collect(keys(g.edges[edgeind[1]].attributes))) == false
- error("Attribute '$attname' not found.")
- end
- ninds = length(edgeind)
- retvec = Array(typeof(g.edges[edgeind[1]].attributes[attname]), ninds)
- for i = 1:ninds
- retvec[i] = g.edges[edgeind[i]].attributes[attname]
- end
- return retvec
- end
- function get_edge_attribute(g::GenericGraph, attname::String)
- edgeind = [1:num_edges(g)]
- return get_edge_attribute(g, attname, edgeind)
- end
- function get_edge_attribute(g::GenericGraph, attname::String, edgeind::UnitRange{Int})
- edgeind = [edgeind]
- return get_edge_attribute(g, attname, edgeind)
- end
- function get_edge_attribute(g::GenericGraph, attname::String, edgeind::Int)
- edgeind = [edgeind]
- return get_edge_attribute(g, attname, edgeind)[1]
- end
- function list_edge_attributes(g::GenericGraph)
- if in(:attributes, names(g.edges[1])) == false
- error("Edges in GenericGraph 'g' are not of type ExEdge.")
- end
- retvec = UTF8String[]
- for i = 1:length(g.edges)
- attkeys = collect(keys(g.edges[i].attributes))
- nattkeys = length(attkeys)
- if nattkeys > 0
- for j = 1:nattkeys
- push!(retvec, attkeys[j])
- end
- end
- end
- retvec = sort(unique(retvec))
- return retvec
- end
- function remove_edge_attributes(g::GenericGraph, attname::String, edgeind::Array{Int, 1})
- if in(:attributes, names(g.edges[edgeind[1]])) == false
- error("Edges in GenericGraph 'g' are not of type ExEdge.")
- end
- for i = edgeind
- attkeys = collect(keys(g.edges[i].attributes))
- if in(attname, attkeys)
- tempedge = ExEdge(g.edges[i].index, g.vertices[g.edges[i].source.index], g.vertices[g.edges[i].target.index])
- for j = 1:length(attkeys)
- if attkeys[j] != attname
- tempedge.attributes[attkeys[j]] = g.edges[i].attributes[attkeys[j]]
- end
- end
- g.edges[i] = tempedge
- else
- warn("Attribute '$attname' is not an attribute at edge index $i of graph 'g'.")
- end
- end
- return g
- end
- function remove_edge_attributes(g::GenericGraph, attname::String)
- edgeind = [1:num_edges(g)]
- return remove_edge_attributes(g, attname, edgeind)
- end
- function remove_edge_attributes(g::GenericGraph, attname::String, edgeind::Int)
- edgeind = [edgeind]
- return remove_edge_attributes(g, attname, edgeind)
- end
- function remove_edge_attributes(g::GenericGraph, attname::String, edgeind::UnitRange{Int})
- edgeind = [edgeind]
- return remove_edge_attributes(g, attname, edgeind)
- end
- #####
- ### Loop identification functions
- #####
- function is_loop(g::GenericGraph)
- ne = num_edges(g)
- loopbool = Array(Bool, ne)
- for i = 1:ne
- loopbool[i] = g.edges[i].source.index == g.edges[i].target.index
- end
- return loopbool
- end
- function is_loop(g::GenericGraph, eind::Int)
- loopbool = g.edges[eind].source.index == g.edges[eind].target.index
- return loopbool
- end
- function is_loop(g::GenericGraph, eind::Array{Int, 1})
- nindlen = length(eind)
- loopbool = Array(Bool, nindlen)
- for i = 1:nindlen
- loopbool[i] = g.edges[eind[i]].source.index == g.edges[eind[i]].target.index
- end
- return loopbool
- end
- function has_loop(g::GenericGraph)
- return any(is_loop(g))
- end
- #####
- ### Multiple edge identification function
- #####
- function has_multiple(g::GenericGraph)
- ne = num_edges(g)
- el = Array((Int, Int), ne)
- if is_directed(g)
- for i = 1:ne
- testedge = edges(g)[i]
- sv = vertex_index(source(testedge))
- tv = vertex_index(target(testedge))
- el[i] = (sv, tv)
- end
- else
- for i = 1:ne
- testedge = edges(g)[i]
- sv = vertex_index(source(testedge))
- tv = vertex_index(target(testedge))
- if sv < tv # Ensures consistent ordering
- el[i] = (sv, tv)
- else
- el[i] = (tv, sv)
- end
- end
- end
- return length(el) > length(unique(el))
- end
- #####
- ### Dyad census
- #####
- function dyad_census(g::GenericGraph) # About 10x slower than the version imported from igraph on the Coleman data.
- nv = num_vertices(g)
- ne = num_edges(g)
- if g.is_directed == false
- npossible = nv * (nv - 1) / 2
- npossible = convert(Int, npossible)
- warn("You are conducting a dyad census on a directed graph. No asymmetric dyads are possible.")
- return (nv, 0, npossible - nobs)
- else
- el1 = Array((Int, Int), ne)
- el2 = Array((Int, Int), ne)
- for i = 1:ne
- el1[i] = (g.edges[i].source.index, g.edges[i].target.index)
- el2[i] = (g.edges[i].target.index, g.edges[i].source.index)
- end
- dc = ["Mut" => 0, "Asym" => 0, "Null" => 0]
- isrecip = Array(Bool, ne)
- for i = 1:ne
- if in(el1[i], el2)
- dc["Mut"] +=1
- end
- end
- dc["Asym"] = ne - dc["Mut"]
- dc["Mut"] = int(dc["Mut"] / 2)
- dc["Null"] = int((nv * (nv - 1) / 2) - (dc["Mut"] + dc["Asym"]))
- return dc
- end
- end
- function reciprocity(g::GenericGraph; ignoreloops::Bool = true, mode::String = "default")
- if g.is_directed == false
- warn("You know that g is undirected, right? Of course its reciprocity will equal 1.0.")
- return(1.0)
- else
- acceptablemodes = ["default", "ratio", "edgewise", "dyadic", "dyadic, non-null", "dyadic.nonnull", "dyadicnonnull", "edgewise.lrr", "edgewise log ratio reciprocity", "edgewiselrr"]
- if !in(mode, acceptablemodes)
- error("mode must be in $acceptablemodes")
- end
- dc = dyad_census(g)
- nv = num_vertices(g)
- ne = num_edges(g)
- if (ignoreloops == false) & (mode != "dyadic")
- warn("Sorry, but loop handling is implemented only in the 'dyadic' mode. Ignoring loops...")
- end
- if in(mode, ["default", "edgewise"]) # 2 * Mut / (Asym + 2 * Mut)
- grecip = 2 * dc["Mut"] / (dc["Asym"] + (2 * dc["Mut"])) # I don't know how to measure it with loops
- elseif in(mode, ["ratio", "dyadic, non-null", "dyadic.nonnull", "dyadicnonnull"]) # Mut / (Asym + Mut)
- grecip = dc["Mut"] / (dc["Mut"] + dc["Asym"])
- elseif in(mode, ["edgewise.lrr", "edgewise log ratio reciprocity", "edgewiselrr"])
- ewr = 2 * dc["Mut"] / (dc["Asym"] + (2 * dc["Mut"]))
- den = ne / (nv * (nv -1))
- grecip = log(ewr / den)
- else #Dyadic
- if ignoreloops
- grecip = (dc["Mutual"] + dc["Null"]) / (dc["Mutual"] + dc["Asym"] + dc["Null"])
- else #I think I'm doing the loops right here, but not 100%.
- nloops = sum(is_loop(g))
- grecip = (dc["Mutual"] + dc["Null"] + nloops) / (dc["Mutual"] + dc["Asym"] + dc["Null"] + nv)
- end
- end
- return grecip
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement