Skip to content

Conversation

@renzocom
Copy link
Contributor

In actual causation, when computing causal links, it often occurs that purviews have the same alpha. Currently, the find_causal_link() method returns one arbitrary purview from the ones with maximum alpha.
The find_causal_link() method now adds a hidden attribute _extended_purview to the returned CausalLink with all the purviews with equivalent maximum alpha which are not supersets of each other. For example, if purviews (A,B), (B,C), (A,B,D) have the same maximum alpha, the extended purview is ((A,B),(B,C)).

I've also added pretty formatting methods to print the CausalLinks when they have extended purviews so they look like:
α = 0.415 [[S1, A], [A, D]] ◀━━ [M1]

@wmayner wmayner self-assigned this Dec 13, 2018
@coveralls
Copy link

coveralls commented Dec 13, 2018

Coverage Status

Coverage increased (+0.003%) to 93.835% when pulling 40a0c63 on renzocom:develop into d965289 on wmayner:develop.

@wmayner
Copy link
Owner

wmayner commented Dec 13, 2018

Thanks for the PR @renzocom! The next thing to do is update the tests so that they check the new behavior (and pass); see here for how to run the tests on your local machine.

pyphi/actual.py Outdated
def is_not_superset(purview):
return np.all([(not set(purview).issuperset(set(purview2))) or
(set(purview) == set(purview2)) for purview2 in purviews])

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will, is this kind of inner function declaration, ok?

Copy link
Owner

Choose a reason for hiding this comment

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

Yes, that's a typical pattern when using filter. However, sometimes it makes sense to refactor the function into a general-purpose function that's available elsewhere. In this case, we can just leave it in here.

You don't need to use np.all here, since the argument is not already a NumPy array. You can just use the built-in all, which will be more efficient, since the argument doesn't need to be converted into a NumPy array first.

Finally, the logic here is overcomplicated. Your function is equivalent to the following:

def is_minimal(purview):
    return all(set(purview).issubset(other_purview) for other_purview in purviews)

Note that I'm not constructing a list here, but rather a generator expression (there are no square brackets around the comprehension inside all()). This is because we only need to look at each element in the sequence once, and in this type of situation it's generally more efficient to use generators.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, except from the logic part becauseis_minimal is not equivalent to is_not_superset, e.g. purview = (1,2), purviews = [(1,2,3), (1,2), (0)], is_not_superset(purview) returns True, while is_minimal(purview) returns False.

pyphi/actual.py Outdated
def is_not_superset(purview):
return np.all([(not set(purview).issuperset(set(purview2))) or
(set(purview) == set(purview2)) for purview2 in purviews])

Copy link
Owner

Choose a reason for hiding this comment

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

Yes, that's a typical pattern when using filter. However, sometimes it makes sense to refactor the function into a general-purpose function that's available elsewhere. In this case, we can just leave it in here.

You don't need to use np.all here, since the argument is not already a NumPy array. You can just use the built-in all, which will be more efficient, since the argument doesn't need to be converted into a NumPy array first.

Finally, the logic here is overcomplicated. Your function is equivalent to the following:

def is_minimal(purview):
    return all(set(purview).issubset(other_purview) for other_purview in purviews)

Note that I'm not constructing a list here, but rather a generator expression (there are no square brackets around the comprehension inside all()). This is because we only need to look at each element in the sequence once, and in this type of situation it's generally more efficient to use generators.

def __init__(self, ria):
def __init__(self, ria, extended_purview=None):
self._ria = ria
self._extended_purview = extended_purview
Copy link
Owner

Choose a reason for hiding this comment

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

I would cast this to a tuple:

self._extended_purview = tuple(extended_purview)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if extended_purview is None wouldn't this cast lead to an type error?
Maybe something like self._extended_purview = tuple(extended_purview) if extended_purview is not None else None?

@wmayner
Copy link
Owner

wmayner commented Aug 20, 2019

@renzocom sup

@renzocom
Copy link
Contributor Author

@renzocom sup

SUP WILL

@wmayner wmayner merged commit 2380aeb into wmayner:develop Jan 16, 2020
@wmayner
Copy link
Owner

wmayner commented Jan 16, 2020

Nice work Renzo🥇

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.

3 participants