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

Monoid and Abelian #134

Merged
merged 11 commits into from Feb 8, 2019

Conversation

Projects
None yet
1 participant
@frankmcsherry
Copy link
Member

frankmcsherry commented Feb 5, 2019

This shifts the Diff trait to be an alias of Abelian, corresponding to an Abelian (commutative) group. There is also a Monoid trait corresponding to a commutative monoid. Abelian is Monoid with the addition of the Sub and Neg traits.

In many cases Monoid is sufficient, and Abelian is only required where subtraction is needed. Operators like join do not require subtraction, though antijoin does in its current implementation.

More generally, we should think about shifting some of the uses of negation to other forms. Iteration requires negation to correct for its initial input, but this is only required when we have an initial input and not otherwise.

cc @eoxxs

@frankmcsherry

This comment has been minimized.

Copy link
Member Author

frankmcsherry commented Feb 5, 2019

The commits just above introduces the group_solve method to the GroupArrange trait. This method takes a different logic closure, one which is presented with the current input, what would be the output if left unadjusted, and a buffer updates into which the logic should write any necessary updates.

For the standard group_arrange method this applies its logic to the input, puts the results in the update buffer, and then subtracts the current output, producing the necessary updates to correct to the intended output:

fn group_arranged<L>(&self, logic: L) -> ...
{
    self.group_solve(move |key, input, output, change| {
        logic(key, input, change);
        change.extend(output.drain(..).map(|(x,d)| (x,-d)));
        consolidate(change);
    })
}

However, the group_solve method is more general, in that we can operate on collections whose difference type is only a commutative monoid, and not a commutative group (it may not have subtraction).

For example, in something like shortest path computation this difference type may track the shortest path (min, rather than sum) and the update rule just considers whether we need an updated min as output, rather than attempting to subtract the old min from the new min (won't work).

    // blah blah collections
    .group_solve(|_key, input, output, updates| {
        if output.is_empty() || input[0].1 < output[0].1 {
            updates.push(((), input[0].1));
        }
    })

A new example/monoid-bfs.rs demonstrates this in a SSSP computation with random weights. Importantly, we are only able to add new edges, because the update type is (in this example) the MinSum type which uses min instead of addition, and for which subtraction and negation are not defined. We can't roll back a low-cost edge, as much as we might want, because the types don't let us.

@frankmcsherry

This comment has been minimized.

Copy link
Member Author

frankmcsherry commented Feb 5, 2019

That should be MonoidVariable, not MonotonicVariable, though .. similar in spirit.

@frankmcsherry frankmcsherry merged commit 1b85ca3 into master Feb 8, 2019

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details

@frankmcsherry frankmcsherry deleted the monoid branch Feb 8, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment