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

Adding FGES #78

Closed
wants to merge 7 commits into from
Closed

Adding FGES #78

wants to merge 7 commits into from

Conversation

RobertGregg
Copy link
Contributor

So it looks like I've got FGES working with the DiGraphs from Graphs.jl. I've also simplified some parts of the package I wrote:

  • Got rid of the message() function as that was specific to running the package on a cluster
  • Using good old X \ y to perform linear regression
  • Changed the debug keyword with verbose to match the other algorithms

I added a test for fges (copying the test from pc2.jl) and it passed. Let me know if you want me to add other tests.

I also added two dependencies Memoization and LRUCache. FGES performs A LOT of linear regressions and often performs the same one more than once. These two packages basically keep a dictionary of inputs and outputs that it checks before running the score function.

Let me know what you think!


"""
fges(data; penalty = 1.0, verbose=false)
Compute a causal graph for the given observed data.
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
Compute a causal graph for the given observed data.
Compute a causal graph for the given observed data.

Comment on lines +7 to +8
d = Normal()
p = 0.01
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
d = Normal()
p = 0.01

unused?

neighborList = Int64[]

#loop through all vertices except for x
for vᵢ in Iterators.filter(!isequal(x),vertices(g))
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
for vᵢ in Iterators.filter(!isequal(x),vertices(g))
for vᵢ in Iterators.filter(!isequal(x), vertices(g))

Copy link
Owner

Choose a reason for hiding this comment

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

below too

allpairs(v) = Iterators.filter(i -> isless(i...), Iterators.product(v,v))

#Get every undirected edge in the entire graph g
allundirected(g) = [Edge(nodePair) for nodePair in allpairs(vertices(g)) if isundirected(g,nodePair)]
Copy link
Owner

Choose a reason for hiding this comment

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

Make it a generator?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean something like this?

Suggested change
allundirected(g) = [Edge(nodePair) for nodePair in allpairs(vertices(g)) if isundirected(g,nodePair)]
allundirected(g) = (Edge(nodePair) for nodePair in allpairs(vertices(g)) if isundirected(g,nodePair))

Copy link
Owner

Choose a reason for hiding this comment

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

Yes.

# Neighborhood functions
####################################################################

#Should these be non-allocating iterators?
Copy link
Owner

Choose a reason for hiding this comment

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

Aren't they?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think they weren't originally, but I changed it and forgot to remove the comment.

####################################################################

"""
orientedge!(g, x, y)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
orientedge!(g, x, y)
orientedge!(g, x, y)


#Do the nodesRemoved block all semi-directed paths between src and dest?
"""
isblocked(g, src, dest, nodesRemoved)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
isblocked(g, src, dest, nodesRemoved)
isblocked(g, src, dest, nodesRemoved)

@mschauer
Copy link
Owner

mschauer commented Feb 1, 2023

Very nice, no problem with the additional dependencies. One could think of getting rid of camel case in function names findNextEquivClass! => find_next_equiv_class! but that's a bit busy-work. I left some comments!

end

#Simple structure to hold the current edge, a subset of neighbors, and a score change
Base.@kwdef mutable struct Step{A,B}
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
Base.@kwdef mutable struct Step{A,B}
Base.@kwdef mutable struct FESStep{A,B}

This should have a more specific name


#Simple structure to hold the current edge, a subset of neighbors, and a score change
Base.@kwdef mutable struct Step{A,B}
edge::Edge = Edge(1,2)
Copy link
Owner

Choose a reason for hiding this comment

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

Could be that this should be SimpleEdge as Edge is an abstract type. Is this struct performance critical / used in a tight loop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Very good point. We should change this to a concrete type

####################################################################

"""
fges(data; penalty = 1.0, verbose=false)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
fges(data; penalty = 1.0, verbose=false)
fges(data; penalty = 1.0, verbose=false)

I am adding these spaces after the function signature in the doc string

@mschauer mschauer mentioned this pull request Feb 1, 2023
@mschauer
Copy link
Owner

mschauer commented Feb 1, 2023

You committed the manifest and a settings file by accident, I think this might cause the test failure.

@mschauer
Copy link
Owner

What are your thoughts on this?

@RobertGregg
Copy link
Contributor Author

Ah apologies, I completely dropped the ball on this. I'll look at your comments this weekend in more detail, but overall they seem like good/minor additions. I'll make sure the manifest file doesn't get committed and check out the Edge() struct. That might have been leftover from when I was converting to using Graphs.jl

Not needed for FGES
Copy link
Contributor Author

@RobertGregg RobertGregg left a comment

Choose a reason for hiding this comment

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

All the suggestions seem good. I've only done a pull request once before so sorry if anything looks weird. I'll try and commit the suggestions and remove the manifest file to see if things check out.


#Simple structure to hold the current edge, a subset of neighbors, and a score change
Base.@kwdef mutable struct Step{A,B}
edge::Edge = Edge(1,2)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Very good point. We should change this to a concrete type

allpairs(v) = Iterators.filter(i -> isless(i...), Iterators.product(v,v))

#Get every undirected edge in the entire graph g
allundirected(g) = [Edge(nodePair) for nodePair in allpairs(vertices(g)) if isundirected(g,nodePair)]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean something like this?

Suggested change
allundirected(g) = [Edge(nodePair) for nodePair in allpairs(vertices(g)) if isundirected(g,nodePair)]
allundirected(g) = (Edge(nodePair) for nodePair in allpairs(vertices(g)) if isundirected(g,nodePair))

@mschauer
Copy link
Owner

I think you forgot to add the new test to the runtest file.

@mschauer
Copy link
Owner

Ps: If it is easier, just make a new PR.

@mschauer mschauer mentioned this pull request Jul 22, 2023
@mschauer
Copy link
Owner

Continued in #92

@mschauer mschauer closed this Jul 22, 2023
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.

None yet

2 participants