|
From: <tho...@us...> - 2014-03-15 14:00:41
|
Revision: 7982
http://sourceforge.net/p/bigdata/code/7982
Author: thompsonbry
Date: 2014-03-15 14:00:37 +0000 (Sat, 15 Mar 2014)
Log Message:
-----------
Replaced the concept of directedTraversal:boolean with the more general concept of TraversalDirection. The TraversalDirection is a type safe enum with three possible values Forward, Reverse, and Undirected. This generalizes the concept of directed versus undirected traversal and adds support for reverse traversal.
Added a unit test for this.
Updated the wiki page to reflect the changed API.
Modified Paths:
--------------
branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/IGASContext.java
branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/impl/GASContext.java
branches/RDR/bigdata-gas/src/test/com/bigdata/rdf/graph/analytics/TestBFS.java
branches/RDR/bigdata-rdf/src/java/com/bigdata/rdf/graph/impl/bd/GASService.java
Added Paths:
-----------
branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/TraversalDirectionEnum.java
Modified: branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/IGASContext.java
===================================================================
--- branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/IGASContext.java 2014-03-15 13:31:34 UTC (rev 7981)
+++ branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/IGASContext.java 2014-03-15 14:00:37 UTC (rev 7982)
@@ -67,20 +67,22 @@
IGraphAccessor getGraphAccessor();
/**
- * Specify whether the visited edges of the graph are to be interpreted as
- * directed or undirected (default <code>directed</code>).
+ * Specify the traversal direction for the {@link IGASProgram}.
* <p>
* The value specified here is used to determine how the {@link EdgesEnum}
- * will be interpreted for the GATHER and SCATTER phases. See
- * {@link EdgesEnum#asUndirectedTraversal()}.
+ * will be interpreted for the GATHER and SCATTER phases. The default is
+ * {@link TraversalDirectionEnum#Forward}.
+ *
+ * @see TraversalDirectionEnum#asTraversed(EdgesEnum)
+ * @see EdgesEnum#asUndirectedTraversal()
*/
- void setDirectedTraversal(boolean newVal);
+ void setTraversalDirection(TraversalDirectionEnum newVal);
/**
- * Return <code>true</code> if the graph should be interpreted as a directed
- * graph.
+ * Return a type safe value indicating the traversal direction for the
+ * {@link IGASProgram}.
*/
- boolean isDirectedTraversal();
+ TraversalDirectionEnum getTraversalDirection();
/**
* Specify the maximum number of iterations for the algorithm. A value of
Added: branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/TraversalDirectionEnum.java
===================================================================
--- branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/TraversalDirectionEnum.java (rev 0)
+++ branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/TraversalDirectionEnum.java 2014-03-15 14:00:37 UTC (rev 7982)
@@ -0,0 +1,76 @@
+/**
+ Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+package com.bigdata.rdf.graph;
+
+/**
+ * Typesafe enumeration of manner in which an RDF graph will be traversed by an
+ * {@link IGASProgram} based on its {@link EdgesEnum}.
+ *
+ * @author <a href="mailto:tho...@us...">Bryan Thompson</a>
+ */
+public enum TraversalDirectionEnum {
+
+ /**
+ * Directed traversal along the natural direction of the RDF statements
+ * (from Subject to Object).
+ */
+ Forward,
+ /**
+ * Directed traversal along the reverse direction of the RDF statements
+ * (from Object to Subject).
+ */
+ Reverse,
+ /**
+ * Undirected traversal - edges are explored in both the {@link #Forward}
+ * and the {@link #Reverse} direction.
+ */
+ Undirected;
+
+ /**
+ * Interpret the given {@link EdgesEnum}, returning the effective value
+ * required to impose the semantics of this {@link TraversalDirectionEnum}.
+ *
+ * @param edges
+ * The {@link EdgesEnum}.
+ *
+ * @return The effective {@link EdgesEnum} value that will impose the
+ * traversal semantics of this {@link TraversalDirectionEnum}.
+ *
+ * @see EdgesEnum#asUndirectedTraversal()
+ */
+ public EdgesEnum asTraversed(final EdgesEnum edges) {
+
+ switch (this) {
+ case Forward:
+ return edges;
+ case Reverse:
+ switch (edges) {
+ case InEdges:
+ return EdgesEnum.OutEdges;
+ case OutEdges:
+ return EdgesEnum.InEdges;
+ default:
+ return edges;
+ }
+ case Undirected:
+ return edges.asUndirectedTraversal();
+ default:
+ throw new AssertionError();
+ }
+
+ }
+
+}
Modified: branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/impl/GASContext.java
===================================================================
--- branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/impl/GASContext.java 2014-03-15 13:31:34 UTC (rev 7981)
+++ branches/RDR/bigdata-gas/src/java/com/bigdata/rdf/graph/impl/GASContext.java 2014-03-15 14:00:37 UTC (rev 7982)
@@ -19,7 +19,6 @@
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -37,6 +36,7 @@
import com.bigdata.rdf.graph.IGraphAccessor;
import com.bigdata.rdf.graph.IReducer;
import com.bigdata.rdf.graph.IStaticFrontier;
+import com.bigdata.rdf.graph.TraversalDirectionEnum;
import com.bigdata.rdf.graph.util.GASUtil;
import cutthecrap.utils.striterators.Filter;
@@ -65,9 +65,10 @@
/**
* Whether or not the edges of the graph will be traversed with directed
- * graph semantics (default is TRUE).
+ * graph semantics (default is {@link TraversalDirectionEnum#Forward}).
*/
- private final AtomicBoolean directedGraph = new AtomicBoolean(true);
+ private final AtomicReference<TraversalDirectionEnum> traversalDirection = new AtomicReference<TraversalDirectionEnum>(
+ TraversalDirectionEnum.Forward);
/**
* The maximum number of iterations (defaults to {@link Integer#MAX_VALUE}).
@@ -258,12 +259,10 @@
* APPLY is done before the SCATTER - this would not work if we pushed
* down the APPLY into the SCATTER).
*/
- final EdgesEnum gatherEdges = isDirectedTraversal() ? program
- .getGatherEdges() : program.getGatherEdges()
- .asUndirectedTraversal();
- final EdgesEnum scatterEdges = isDirectedTraversal() ? program
- .getScatterEdges() : program.getScatterEdges()
- .asUndirectedTraversal();
+ final EdgesEnum gatherEdges = getTraversalDirection().asTraversed(
+ program.getGatherEdges());
+ final EdgesEnum scatterEdges = getTraversalDirection().asTraversed(
+ program.getScatterEdges());
final boolean pushDownApplyInGather;
final boolean pushDownApplyInScatter;
final boolean runApplyStage;
@@ -816,17 +815,20 @@
}
@Override
- public boolean isDirectedTraversal() {
-
- return directedGraph.get();
-
+ public TraversalDirectionEnum getTraversalDirection() {
+
+ return traversalDirection.get();
+
}
-
+
@Override
- public void setDirectedTraversal(final boolean newVal) {
+ public void setTraversalDirection(final TraversalDirectionEnum newVal) {
- directedGraph.set(newVal);
-
+ if (newVal == null)
+ throw new IllegalArgumentException();
+
+ traversalDirection.set(newVal);
+
}
@Override
Modified: branches/RDR/bigdata-gas/src/test/com/bigdata/rdf/graph/analytics/TestBFS.java
===================================================================
--- branches/RDR/bigdata-gas/src/test/com/bigdata/rdf/graph/analytics/TestBFS.java 2014-03-15 13:31:34 UTC (rev 7981)
+++ branches/RDR/bigdata-gas/src/test/com/bigdata/rdf/graph/analytics/TestBFS.java 2014-03-15 14:00:37 UTC (rev 7982)
@@ -21,6 +21,7 @@
import com.bigdata.rdf.graph.IGASEngine;
import com.bigdata.rdf.graph.IGASState;
import com.bigdata.rdf.graph.IGraphAccessor;
+import com.bigdata.rdf.graph.TraversalDirectionEnum;
import com.bigdata.rdf.graph.impl.sail.AbstractSailGraphTestCase;
/**
@@ -104,11 +105,11 @@
/**
* Variant test in which we choose a vertex (<code>foaf:person</code>) in
- * the middle of the graph and insist on directed edges. Since the edges
- * point from the person to the <code>foaf:person</code> vertex, this BSF
- * traversal does not discover any connected vertices.
+ * the middle of the graph and insist on forward directed edges. Since the
+ * edges point from the person to the <code>foaf:person</code> vertex, this
+ * BSF traversal does not discover any connected vertices.
*/
- public void testBFS_directed() throws Exception {
+ public void testBFS_directed_forward() throws Exception {
final SmallGraphProblem p = setupSmallGraphProblem();
@@ -135,7 +136,8 @@
gasState.setFrontier(gasContext, p.getFoafPerson());
// directed traversal.
- gasContext.setDirectedTraversal(true);
+ gasContext
+ .setTraversalDirection(TraversalDirectionEnum.Forward);
// Converge.
gasContext.call();
@@ -177,6 +179,83 @@
/**
* Variant test in which we choose a vertex (<code>foaf:person</code>) in
+ * the middle of the graph and insist on reverse directed edges. Since the
+ * edges point from the person to the <code>foaf:person</code> vertex,
+ * forward BSF traversal does not discover any connected vertices. However,
+ * since the traversal direction is reversed, the vertices are all one hop
+ * away.
+ */
+ public void testBFS_directed_reverse() throws Exception {
+
+ final SmallGraphProblem p = setupSmallGraphProblem();
+
+ final IGASEngine gasEngine = getGraphFixture()
+ .newGASEngine(1/* nthreads */);
+
+ try {
+
+ final SailConnection cxn = getGraphFixture().getSail()
+ .getConnection();
+
+ try {
+
+ final IGraphAccessor graphAccessor = getGraphFixture()
+ .newGraphAccessor(cxn);
+
+ final IGASContext<BFS.VS, BFS.ES, Void> gasContext = gasEngine
+ .newGASContext(graphAccessor, new BFS());
+
+ final IGASState<BFS.VS, BFS.ES, Void> gasState = gasContext
+ .getGASState();
+
+ // Initialize the froniter.
+ gasState.setFrontier(gasContext, p.getFoafPerson());
+
+ // directed traversal.
+ gasContext
+ .setTraversalDirection(TraversalDirectionEnum.Reverse);
+
+ // Converge.
+ gasContext.call();
+
+ // starting vertex at (0,null).
+ assertEquals(0, gasState.getState(p.getFoafPerson()).depth());
+ assertEquals(null, gasState.getState(p.getFoafPerson())
+ .predecessor());
+
+ // All other vertices are 1-hop.
+ assertEquals(1, gasState.getState(p.getMike()).depth());
+ assertEquals(p.getFoafPerson(), gasState.getState(p.getMike())
+ .predecessor());
+
+ assertEquals(1, gasState.getState(p.getBryan()).depth());
+ assertEquals(p.getFoafPerson(), gasState.getState(p.getBryan())
+ .predecessor());
+
+ assertEquals(1, gasState.getState(p.getMartyn()).depth());
+ assertEquals(p.getFoafPerson(), gasState
+ .getState(p.getMartyn()).predecessor());
+
+ } finally {
+
+ try {
+ cxn.rollback();
+ } finally {
+ cxn.close();
+ }
+
+ }
+
+ } finally {
+
+ gasEngine.shutdownNow();
+
+ }
+
+ }
+
+ /**
+ * Variant test in which we choose a vertex (<code>foaf:person</code>) in
* the middle of the graph and insist on directed edges. Since the edges
* point from the person to the <code>foaf:person</code> vertex, this BSF
* traversal does not discover any connected vertices.
@@ -208,8 +287,9 @@
gasState.setFrontier(gasContext, p.getFoafPerson());
// undirected traversal.
- gasContext.setDirectedTraversal(false);
-
+ gasContext
+ .setTraversalDirection(TraversalDirectionEnum.Undirected);
+
// Converge.
gasContext.call();
Modified: branches/RDR/bigdata-rdf/src/java/com/bigdata/rdf/graph/impl/bd/GASService.java
===================================================================
--- branches/RDR/bigdata-rdf/src/java/com/bigdata/rdf/graph/impl/bd/GASService.java 2014-03-15 13:31:34 UTC (rev 7981)
+++ branches/RDR/bigdata-rdf/src/java/com/bigdata/rdf/graph/impl/bd/GASService.java 2014-03-15 14:00:37 UTC (rev 7982)
@@ -55,6 +55,7 @@
import com.bigdata.rdf.graph.IGraphAccessor;
import com.bigdata.rdf.graph.IPredecessor;
import com.bigdata.rdf.graph.IReducer;
+import com.bigdata.rdf.graph.TraversalDirectionEnum;
import com.bigdata.rdf.graph.analytics.CC;
import com.bigdata.rdf.graph.analytics.PR;
import com.bigdata.rdf.graph.impl.GASEngine;
@@ -167,14 +168,19 @@
int DEFAULT_NTHREADS = 4;
/**
- * This option determines whether the traversal of the graph will
- * interpret the edges as directed or undirected.
+ * This option determines the traversal direction semantics for the
+ * {@link IGASProgram} against the graph, including whether the the
+ * edges of the graph will be interpreted as directed (
+ * {@link TraversalDirectionEnum#Forward} (which is the default),
+ * {@link TraversalDirectionEnum#Reverse}), or
+ * {@link TraversalDirectionEnum#Undirected}.
*
- * @see IGASContext#setDirectedTraversal(boolean)
+ * @see TraversalDirectionEnum
+ * @see IGASContext#setTraversalDirection(TraversalDirectionEnum)
*/
- URI DIRECTED_TRAVERSAL = new URIImpl(NAMESPACE + "directedTraversal");
+ URI TRAVERSAL_DIRECTION = new URIImpl(NAMESPACE + "traversalDirection");
- boolean DEFAULT_DIRECTED_TRAVERSAL = true;
+ TraversalDirectionEnum DEFAULT_DIRECTED_TRAVERSAL = TraversalDirectionEnum.Forward;
/**
* The maximum #of iterations for the GAS program (optional, default
@@ -398,7 +404,7 @@
// options extracted from the SERVICE's graph pattern.
private final int nthreads;
- private final boolean directedTraversal;
+ private final TraversalDirectionEnum traversalDirection;
private final int maxIterations;
private final int maxVisited;
private final URI linkType, linkAttrType;
@@ -433,10 +439,13 @@
store.getValueFactory().createLiteral(
Options.DEFAULT_NTHREADS))).intValue();
- this.directedTraversal = ((Literal) getOnlyArg(Options.PROGRAM,
- Options.DIRECTED_TRAVERSAL, store.getValueFactory()
- .createLiteral(Options.DEFAULT_DIRECTED_TRAVERSAL)))
- .booleanValue();
+ this.traversalDirection = TraversalDirectionEnum
+ .valueOf(((Literal) getOnlyArg(
+ Options.PROGRAM,
+ Options.TRAVERSAL_DIRECTION,
+ store.getValueFactory().createLiteral(
+ Options.DEFAULT_DIRECTED_TRAVERSAL.name())))
+ .stringValue());
this.maxIterations = ((Literal) getOnlyArg(Options.PROGRAM,
Options.MAX_ITERATIONS, store.getValueFactory()
@@ -761,7 +770,7 @@
final IGASContext<VS, ES, ST> gasContext = gasEngine.newGASContext(
graphAccessor, gasProgram);
- gasContext.setDirectedTraversal(directedTraversal);
+ gasContext.setTraversalDirection(traversalDirection);
gasContext.setMaxIterations(maxIterations);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|