1
0
Fork 0

broken, but need to go home

This commit is contained in:
Jan Steemann 2013-01-09 21:06:34 +01:00
parent e61fc070bd
commit 4bd1aefbc6
1 changed files with 144 additions and 65 deletions

View File

@ -55,10 +55,13 @@
throw "invalid edgeCollection"; throw "invalid edgeCollection";
} }
// properties
this._edgeCollection = edgeCollection;
// callbacks
this._visitor = visitor; this._visitor = visitor;
this._filter = filter || IncludeAllFilter; this._filter = filter || IncludeAllFilter;
this._expander = expander || OutboundExpander; this._expander = expander || OutboundExpander;
this._edgeCollection = edgeCollection;
if (typeof this._visitor !== "function") { if (typeof this._visitor !== "function") {
throw "invalid visitor"; throw "invalid visitor";
@ -105,7 +108,8 @@
// check the visitation strategy // check the visitation strategy
if (visitationStrategy !== ArangoTraverser.BREADTH_FIRST && if (visitationStrategy !== ArangoTraverser.BREADTH_FIRST &&
visitationStrategy !== ArangoTraverser.DEPTH_FIRST) { visitationStrategy !== ArangoTraverser.DEPTH_FIRST_PRE &&
visitationStrategy !== ArangoTraverser.DEPTH_FIRST_POST) {
throw "invalid visitationStrategy"; throw "invalid visitationStrategy";
} }
@ -119,8 +123,12 @@
if (visitationStrategy === ArangoTraverser.BREADTH_FIRST) { if (visitationStrategy === ArangoTraverser.BREADTH_FIRST) {
return BreadthFirstSearch(); return BreadthFirstSearch();
} }
else if (visitationStrategy === ArangoTraverser.DEPTH_FIRST_PRE) {
return DepthFirstSearch(); return DepthFirstPreSearch();
}
else {
return DepthFirstPostSearch();
}
}()); }());
// initialise uniqueness check attributes // initialise uniqueness check attributes
@ -142,7 +150,7 @@
return; return;
} }
if (! levelState.next(levelState)) { if (! levelState.next(this, levelState)) {
// we're done // we're done
return; return;
} }
@ -171,19 +179,17 @@
level: 0, level: 0,
maxLevel: 0, maxLevel: 0,
index: 0, index: 0,
positions: [ 0 ],
stack: [ [ { edge: null, vertex: startVertex, parentIndex: 0 } ] ], stack: [ [ { edge: null, vertex: startVertex, parentIndex: 0 } ] ],
path: { edges: [ ], vertices: [ startVertex ] }, path: { edges: [ ], vertices: [ startVertex ] },
visited: { edges: { }, vertices: { } }, visited: { edges: { }, vertices: { } },
next: function () { next: function (traverser) {
return strategy.next(this); return strategy.next(traverser, this);
}, },
currentElement: function () { currentElement: function () {
var currentElement = strategy.currentElement(this); return strategy.currentElement(this);
strategy.assemblePath(this, currentElement);
return currentElement;
}, },
elementAt: function (searchLevel, searchIndex) { elementAt: function (searchLevel, searchIndex) {
@ -194,6 +200,13 @@
return this.stack[this.level].length; return this.stack[this.level].length;
}, },
canDescend: function () {
if (this.level >= this.maxLevel) {
return false;
}
return (this.stack[this.level + 1].length > 0);
},
isUniqueVertex: function (checkMode, vertex) { isUniqueVertex: function (checkMode, vertex) {
return this.isUnique(checkMode, this.visited.vertices, vertex._id); return this.isUnique(checkMode, this.visited.vertices, vertex._id);
}, },
@ -226,7 +239,10 @@
function BreadthFirstSearch () { function BreadthFirstSearch () {
return { return {
// TODO: ADD UNIQUENESS CHECK HERE // TODO: ADD UNIQUENESS CHECK HERE
next: function (levelState) { next: function (traverser, levelState) {
var currentElement = levelState.elementAt(levelState.level, levelState.index);
traverser._visitor(traverser, currentElement.vertex, levelState.path);
if (++levelState.index >= levelState.numElements()) { if (++levelState.index >= levelState.numElements()) {
levelState.index = 0; levelState.index = 0;
if (++levelState.level > levelState.maxLevel) { if (++levelState.level > levelState.maxLevel) {
@ -239,18 +255,18 @@
}, },
currentElement : function (levelState) { currentElement : function (levelState) {
return levelState.elementAt(levelState.level, levelState.index);
},
assemblePath: function (levelState, currentElement) {
var path = levelState.path; var path = levelState.path;
var currentElement = levelState.elementAt(levelState.level, levelState.index);
var element = currentElement;
for (var i = levelState.level; i > 0; --i) { for (var i = levelState.level; i > 0; --i) {
path.edges[i - 1] = currentElement.edge; path.edges[i - 1] = element.edge;
path.vertices[i] = currentElement.vertex; path.vertices[i] = element.vertex;
currentElement = levelState.elementAt(i - 1, currentElement.parentIndex); element = levelState.elementAt(i - 1, element.parentIndex);
} }
return currentElement;
} }
}; };
} }
@ -259,59 +275,107 @@
/// @brief implementation details for depth-first strategy /// @brief implementation details for depth-first strategy
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function DepthFirstSearch () { function DepthFirstPreSearch () {
return { return {
// TODO: ADD UNIQUENESS CHECK HERE next: function (traverser, levelState) {
next: function (levelState) { var position = levelState.positions[levelState.level];
while (levelState.level < levelState.maxLevel) { var currentElement = levelState.elementAt(levelState.level, position);
// try going into children first
var nextStack = levelState.stack[levelState.level + 1];
if (nextStack.length == 0) { traverser._visitor(traverser, currentElement.vertex, levelState.path);
// nothing to recurse into
break;
}
var nextElement = nextStack[nextStack.length - 1];
if (nextElement.edge === null) {
// nothing to recurse into
break;
}
if (levelState.canDescend()) {
++levelState.level; ++levelState.level;
} }
else {
while (++levelState.positions[levelState.level] >= levelState.numElements()) {
while (levelState.numElements() == 0) { levelState.positions[levelState.level] = 0;
if (levelState.level == 0) { delete levelState.stack[levelState.level];
// we're done
return false; levelState.path.vertices.pop();
levelState.path.edges.pop();
if (levelState.level <= 1) {
// we're done
return false;
}
levelState.level--;
// TODO: make this a function
levelState.maxLevel--;
} }
if (levelState.level > 0) {
var edge = levelState.path.edges.pop();
delete levelState.visited.edges[edge._id];
}
var vertex = levelState.path.vertices.pop();
delete levelState.visited.vertices[vertex._id];
--levelState.level;
--levelState.maxLevel;
} }
var currentElement = levelState.stack[levelState.level][levelState.positions[levelState.level]];
levelState.path.edges[levelState.level - 1] = currentElement.edge;
levelState.path.vertices[levelState.level] = currentElement.vertex;
return true; return true;
}, },
currentElement : function (levelState) { currentElement : function (levelState) {
var currentElement = levelState.stack[levelState.level].pop(); var position = levelState.positions[levelState.level];
return currentElement; var currentElement = levelState.elementAt(levelState.level, position);
},
assemblePath: function (levelState, currentElement) { return currentElement;
if (levelState.level > 0) { }
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief implementation details for depth-first strategy
////////////////////////////////////////////////////////////////////////////////
function DepthFirstPostSearch () {
return {
next: function (traverser, levelState) {
var currentElement = levelState.stack[levelState.level][levelState.positions[levelState.level]];
console.log("level " + levelState.level + ", ele: " + currentElement.vertex._id);
while (levelState.canDescend()) {
++levelState.level;
var currentElement = levelState.stack[levelState.level][levelState.positions[levelState.level]];
console.log("desc, up is " + currentElement.vertex._id);
levelState.path.edges[levelState.level - 1] = currentElement.edge; levelState.path.edges[levelState.level - 1] = currentElement.edge;
levelState.path.vertices[levelState.level] = currentElement.vertex;
} }
levelState.path.vertices[levelState.level] = currentElement.vertex;
while (++levelState.positions[levelState.level] >= levelState.numElements()) {
console.log("undesc");
levelState.positions[levelState.level] = 0;
delete levelState.stack[levelState.level];
if (levelState.level == 0) {
// we're done
return false;
}
levelState.level--;
// TODO: make this a function
levelState.maxLevel--;
// break;
}
var currentElement = levelState.stack[levelState.level][levelState.positions[levelState.level]];
levelState.path.edges[levelState.level - 1] = currentElement.edge;
levelState.path.vertices[levelState.level] = currentElement.vertex;
traverser._visitor(traverser, currentElement.vertex, levelState.path);
return true;
},
currentElement : function (levelState) {
var position = levelState.positions[levelState.level];
var currentElement = levelState.elementAt(levelState.level, position);
return currentElement;
} }
}; };
@ -331,24 +395,23 @@
if (filterResult === ArangoTraverser.INCLUDE_AND_CONTINUE || if (filterResult === ArangoTraverser.INCLUDE_AND_CONTINUE ||
filterResult === ArangoTraverser.INCLUDE_AND_PRUNE) { filterResult === ArangoTraverser.INCLUDE_AND_PRUNE) {
// vertex should be included, so visit it
traverser._visitor(traverser, vertex, levelState.path);
// get connected edges for vertex // get connected edges for vertex
traverser._expander(traverser, vertex, levelState.path).forEach(function (connection) { traverser._expander(traverser, vertex, levelState.path).forEach(function (connection) {
var nextLevel = levelState.level + 1; var nextLevel = levelState.level + 1;
if (levelState.stack[nextLevel] == undefined) { if (levelState.stack[nextLevel] == undefined) {
levelState.stack[nextLevel] = [ ]; levelState.stack[nextLevel] = [ ];
levelState.positions[nextLevel] = 0;
} }
if (levelState.stack[nextLevel].length == 0) { if (levelState.stack[nextLevel].length == 0) {
++levelState.maxLevel; ++levelState.maxLevel;
} }
connection.parentIndex = levelState.index; connection.parentIndex = levelState.index;
levelState.stack[nextLevel].push(connection); levelState.stack[nextLevel].push(connection);
}); });
} }
// return true only if we should continue // return true only if we should continue
@ -409,6 +472,18 @@
/// @{ /// @{
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief pre-order visits
////////////////////////////////////////////////////////////////////////////////
ArangoTraverser.VISIT_PREORDER = 0;
////////////////////////////////////////////////////////////////////////////////
/// @brief post-order visits
////////////////////////////////////////////////////////////////////////////////
ArangoTraverser.VISIT_POSTORDER = 1;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief element may be revisited /// @brief element may be revisited
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -443,7 +518,8 @@
/// @brief visitation strategy depth first /// @brief visitation strategy depth first
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoTraverser.DEPTH_FIRST = 1; ArangoTraverser.DEPTH_FIRST_PRE = 1;
ArangoTraverser.DEPTH_FIRST_POST = 2;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief include this node in the result and continue the traversal /// @brief include this node in the result and continue the traversal
@ -492,11 +568,11 @@
var state = { someState : { } }; var state = { someState : { } };
var visitor = function (traverser, vertex, path) { var visitor = function (traverser, vertex, path) {
var result = ""; var result = path.edges.length + " ";
for (var i = 0; i < path.edges.length; ++i) { for (var i = 0; i < path.edges.length; ++i) {
result += " "; result += " ";
} }
result += "- " + vertex._id; result += "- " + vertex._id + " " + stringifyPath(path);
console.log(result); console.log(result);
}; };
@ -506,9 +582,12 @@
db.trelations.load(); db.trelations.load();
var traverser = new ArangoTraverser("trelations", visitor); var traverser = new ArangoTraverser("trelations", visitor);
traverser.traverse("tusers/claudius", ArangoTraverser.DEPTH_FIRST_PRE, uniqueness, context, state);
traverser.traverse("tusers/claudius", ArangoTraverser.DEPTH_FIRST, uniqueness, context, state);
console.log("------------"); console.log("------------");
var traverser = new ArangoTraverser("trelations", visitor);
traverser.traverse("tusers/claudius", ArangoTraverser.DEPTH_FIRST_POST, uniqueness, context, state);
console.log("------------");
var traverser = new ArangoTraverser("trelations", visitor);
traverser.traverse("tusers/claudius", ArangoTraverser.BREADTH_FIRST, uniqueness, context, state); traverser.traverse("tusers/claudius", ArangoTraverser.BREADTH_FIRST, uniqueness, context, state);
}()); }());