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

added in forest fire graph generator and needed helper functions #71

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

charlescolley
Copy link
Contributor

No description provided.

@codecov
Copy link

codecov bot commented Feb 14, 2023

Codecov Report

Merging #71 (417f88c) into master (7203a2a) will increase coverage by 0.30%.
The diff coverage is 99.03%.

@@            Coverage Diff             @@
##           master      #71      +/-   ##
==========================================
+ Coverage   92.38%   92.68%   +0.30%     
==========================================
  Files          21       22       +1     
  Lines        2126     2228     +102     
==========================================
+ Hits         1964     2065     +101     
- Misses        162      163       +1     
Impacted Files Coverage Δ
src/generators.jl 95.36% <98.71%> (+0.86%) ⬆️
src/network_formatting.jl 100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

Copy link
Contributor

@dgleich dgleich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you look at the comments?

seed::Union{Nothing,UInt}=nothing,
random_node=x->rand(1:x)) where S

if !(seed === nothing)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you replace this with specifying the RNG where Random.GlobalRNG is the default? Then they can give StableRNG(seed) if they want reliable seeds...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GIven that we let the user pass in the random_node function as well, how should I adapt it to work with an rng variable?

Seems like random_node=(x,rng)->rand(rng,1:x)) would force the user to think about a seed if they want to adjust the parent's probability of being selected.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention is for rand functions in Julia to take in an optional random number generator to avoid using the global one. Users should have to think about how to make their random results reproducible if they want them :), but it should be easy enough ... The random node stuff is just a placeholder right now, let's not worry about it.


end

A = list_of_list_to_sparse_matrix(neighbors)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use the parametric types to handle this?

e.g. _convert_to_output(input, sparse) which will convert sparse to input type?

end


function _burn!(neighbors::Vector{Vector{S}},new_v::Int,v0::Int,burn_p::Float64,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IF this is easy --- can we make this a top level function? e.g. there are other instances where you want to do forest fire sampling... Since the process is the same, it'd be nice to be able to reuse the function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the best interface for this to be a top function? burn(A,v0::Int,p::Float64) for just a single step and return final neighbor list of the random walk? Or something like burn(A,steps::Int, rand_v::Int->Int) which runs the process for a number of steps and selects random nodes by calling rand_v().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

burn(A,v0,p) and burn!(A,v0,p,temparrays...) are the best top level interface

matrix_to_list_of_list(A::MatrixNetwork) = matrix_to_list_of_list(eltype(A.ci),A)


function matrix_to_list_of_list(::Type{S}, A::MatrixNetwork) where S
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you write these in terms of getting the rowptr/colval/etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These is the matrix_to_list_of_lists

@@ -0,0 +1,43 @@
matrix_to_list_of_list(A::SparseMatrixCSC) = matrix_to_list_of_list(eltype(A.rowval),A)

function matrix_to_list_of_list(::Type{S}, A::SparseMatrixCSC) where S
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a subtle bug here, this is correct for undirected graphs, but not for directed graphs since that will transpose in-edges to out-edges.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what the best solution for this is. When I wrote them it was intended for undirected graphs because the
forest_fire_graph is expecting an undirected input, and generates new edges with the intention of symmetrizing them.

I can either

  1. Rename list_of_list_to_matrixto reference they’re for undirected neighbor lists
  2. Write a _get_inedges for MatrixNetworks to be more careful, but we’d also need to rename the list_of_list_to_matrix function to better express what the output is, because it won’t be an undirected neighbor list.
  3. Convert MatrixNetwork to a SparseCSCMatrix before calling the code, but this seems like a bad solution as the package is about the MatrixNetwork.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard solution in MatrixNetworks is just to take a transpose... if they want to avoid that, then they use a MatrixNetwork type instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I was thinking about the wrong function! Ok that works

Copy link
Contributor

@dgleich dgleich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still a few small changes on burn...

end


function _burn!(neighbors::Vector{Vector{S}},new_v::Int,v0::Int,burn_p::Float64,
toburn,burnt,burning,alive) where S
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if there was any misunderstanding, burn should not add the edges to the graph. It should simply return the the set of burned vertices. e.g. if you wanted to run a forest fire sample of an existing graph, you want to run "burn" from multiple vertices. This is a sampled graph that should have similar properties to the original. But you definitely don't want to add anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taken care of! Any suggestions on tests that can be added to this routine? Currently just ensuring seeded calls return the same for MatrixNetwork and SparseMatrixCSC inputs.

(i >= 1 && i <= size(A,1)) || throw(ArgumentError("i must be in {1,...,size(A,1)}"))
return A.ci[A.rp[i]:A.rp[i+1]-1],A.vals[A.rp[i]:A.rp[i+1]-1]
@boundscheck (i >= 1 && i <= size(A,1)) || throw(ArgumentError("i must be in {1,...,$(size(A,1))}"))
return A.ci[A.rp[i]:A.rp[i+1]-1],A.vals[A.rp[i]:A.rp[i+1]-1]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to return an array? can you return a generator or a view?

Copy link
Contributor Author

@charlescolley charlescolley Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're now returning views, and matrix_to_list_of_list uses collect to allocate the arrays needed.

src/generators.jl Outdated Show resolved Hide resolved
src/generators.jl Outdated Show resolved Hide resolved
src/generators.jl Outdated Show resolved Hide resolved
…erators now, and small documentation changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants