Marko A. Rodriguez created TINKERPOP3-960:
---------------------------------------------

             Summary: Add a Bulk class which is used by Traverser
                 Key: TINKERPOP3-960
                 URL: https://issues.apache.org/jira/browse/TINKERPOP3-960
             Project: TinkerPop 3
          Issue Type: Bug
          Components: process
    Affects Versions: 3.1.0-incubating
            Reporter: Marko A. Rodriguez
            Assignee: Marko A. Rodriguez


Currently, {{Traverser.bulk()}} is a {{long}}. This should be generalized to 
support any type of "bulk" that can be split, merged, and has a magnitude, 
where our current representation would be a {{LongBulk}}.

There are three reasons to support this. 

1. Right now we use {{Traverser.sack()}} to handle "energy flows" (0/0 to 1.0 
energy in a traverser). We have introduced this ugly 
{{TraversalSource.withBulk(false)}} to allow these to semantically make sense 
(i.e. remain unitary).  The "energy" should be the "bulk" as it can be split, 
merged, and has a magnitude. 

2. We can support complex numbers for bulks (and complex number arrays). There 
is currently no strong use case for this beyond quantum simulation and wave 
dynamics, but you never know what might unfold. A solid algorithm here would be 
epic.

3. We need to be able to support {{BigInteger}} as the bulking model on complex 
graphs easily blows {{long}}. There have been numerous times where I wanted to 
{{repeat()}} more times, but can't without incurring long overflow and thus, 
negative bulk. If the computation calls for it, a user should be able to use 
{{BigInteger}}.

--------------------------

{code}
public interface Bulk<T> {
  public boolean canMerge(Bulk<T> otherBulk);
  public void merge(Bulk<T> otherBulk);
  public Bulk<T> split();
  public Number magnitude();
  public T get();
  public static Bulk<T> identity();
}
{code}

Our current model would be:

{code}
public class LongBulk extends Bulk<Long> {
  public boolean canMerge(LongBulk otherBulk) { return true; }
  public void merge(LongBulk otherBulk) { this.count += otherBulk.count; }
  public LongBulk split() { return new LongBulk(this.count); }
  public Number magnitude() { return this.count; }
  public Long get() { return this.count; }
  public static LongBulk identity() { return new LongBulk(1); } 
}
{code}

Another benefit of this is that bulking is now decoupled from the {{Traverser}} 
class and thus, you would be able to use different bulk classes with the same 
{{Traverser}}-species:

{code}
g.withBulk(BigIntegerBulk.class).V().out().out()
{code}

...where the default is assumed {{LongBulk}} and thus, you don't have to 
specify a {{withBulk}}. For backwards compatible sake, {{withBulk(false)}} 
would simply be {{IdentityLongBulk}} would would just return a {{1}} for 
everything.

We will want to then expose {{it.bulk()}} methods so algorithms can alter the 
bulk as they see fit. However, this is where a backwards compatibility issue 
would happen. {{Traverser.bulk() -> Bulk}} and {{Traverser.magnitude() -> 
Number}} (sidenote ---- perhaps "magnitude" is just called "count").

{code}
g.withBulk(UnitaryBulk).V(0).bulk(1.0).outE().bulk(mult).by('weight').inV()
{code}

What is stellar about this is that it frees up ``sack" for more "objects" and 
not for "bulking" when long is sufficient. Thus, we promote that "sack" is for 
objects and "bulk" is for, well, bulk! Now we no longer have this weird tension 
between bulk and sack as they have two different uses. Bulking is for altering 
the "magnitude" of a traverser and sacking if for gathering statistics/data 
about the graph along the way.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to