use of jcog.list.FasterList in project narchy by automenta.
the class MyConcurrentRadixTree method compute.
/**
* Atomically adds the given value to the tree, creating a node for the value as necessary. If the value is already
* stored for the same key, either overwrites the existing value, or simply returns the existing value, depending
* on the given value of the <code>overwrite</code> flag.
*
* @param key The key against which the value should be stored
* @param newValue The value to store against the key
* @param overwrite If true, should replace any existing value, if false should not replace any existing value
* @return The existing value for this key, if there was one, otherwise null
*/
<V> X compute(@NotNull AbstractBytes key, V value, QuadFunction<AbstractBytes, SearchResult, X, V, X> computeFunc) {
// if (key.length() == 0) {
// throw new IllegalArgumentException("The key argument was zero-length");
// }
int version;
X newValue, foundX;
SearchResult result;
int matched;
Object foundValue;
Node found;
version = writes.intValue();
acquireReadLockIfNecessary();
try {
// Note we search the tree here after we have acquired the write lock...
result = searchTree(key);
found = result.found;
matched = result.charsMatched;
foundValue = found != null ? found.getValue() : null;
foundX = ((matched == key.length()) && (foundValue != VoidValue.SINGLETON)) ? ((X) foundValue) : null;
} finally {
releaseReadLockIfNecessary();
}
newValue = computeFunc.apply(key, result, foundX, value);
if (newValue != foundX) {
int version2 = acquireWriteLock();
try {
if (version + 1 != version2) {
// search again because the tree has changed since the initial lookup
result = searchTree(key);
found = result.found;
matched = result.charsMatched;
foundValue = found != null ? found.getValue() : null;
foundX = ((matched == key.length()) && (foundValue != VoidValue.SINGLETON)) ? ((X) foundValue) : null;
if (foundX == newValue)
// no change; the requested value has already been supplied since the last access
return newValue;
}
SearchResult.Classification classification = result.classification;
if (foundX == null)
estSize.incrementAndGet();
FasterList<Node> oedges = found.getOutgoingEdges();
switch(classification) {
case EXACT_MATCH:
if (newValue != foundValue) {
// clone and reattach
cloneAndReattach(result, found, foundValue, oedges);
}
break;
case KEY_ENDS_MID_EDGE:
{
// Search ran out of characters from the key while in the middle of an edge in the node.
// -> Split the node in two: Create a new parent node storing the new value,
// and a new child node holding the original value and edges from the existing node...
AbstractBytes keyCharsFromStartOfNodeFound = key.subSequence(matched - result.charsMatchedInNodeFound, key.length());
AbstractBytes commonPrefix = getCommonPrefix(keyCharsFromStartOfNodeFound, found.getIncomingEdge());
AbstractBytes suffixFromExistingEdge = subtractPrefix(found.getIncomingEdge(), commonPrefix);
// Create new nodes...
Node newChild = createNode(suffixFromExistingEdge, foundValue, oedges, false);
Node newParent = createNode(commonPrefix, newValue, new FasterList(new Node[] { newChild }), false);
// Add the new parent to the parent of the node being replaced (replacing the existing node)...
result.parentNode.updateOutgoingEdge(newParent);
break;
}
case INCOMPLETE_MATCH_TO_END_OF_EDGE:
// Search found a difference in characters between the key and the start of all child edges leaving the
// node, the key still has trailing unmatched characters.
// -> Add a new child to the node, containing the trailing characters from the key.
// NOTE: this is the only branch which allows an edge to be added to the root.
// (Root node's own edge is "" empty string, so is considered a prefixing edge of every key)
// Create a new child node containing the trailing characters...
AbstractBytes keySuffix = key.subSequence(matched, key.length());
Node newChild = createNode(keySuffix, newValue, emptyList, false);
// Clone the current node adding the new child...
int numEdges = oedges.size();
Node[] edgesArray;
if (numEdges > 0) {
edgesArray = new Node[numEdges + 1];
arraycopy(oedges.array(), 0, edgesArray, 0, numEdges);
edgesArray[numEdges] = newChild;
} else {
edgesArray = new Node[] { newChild };
}
cloneAndReattach(result, found, foundValue, new FasterList(edgesArray.length, edgesArray));
break;
case INCOMPLETE_MATCH_TO_MIDDLE_OF_EDGE:
// Search found a difference in characters between the key and the characters in the middle of the
// edge in the current node, and the key still has trailing unmatched characters.
// -> Split the node in three:
// Let's call node found: NF
// (1) Create a new node N1 containing the unmatched characters from the rest of the key, and the
// value supplied to this method
// (2) Create a new node N2 containing the unmatched characters from the rest of the edge in NF, and
// copy the original edges and the value from NF unmodified into N2
// (3) Create a new node N3, which will be the split node, containing the matched characters from
// the key and the edge, and add N1 and N2 as child nodes of N3
// (4) Re-add N3 to the parent node of NF, effectively replacing NF in the tree
AbstractBytes suffixFromKey = key.subSequence(matched, key.length());
// Create new nodes...
Node n1 = createNode(suffixFromKey, newValue, emptyList, false);
AbstractBytes keyCharsFromStartOfNodeFound = key.subSequence(matched - result.charsMatchedInNodeFound, key.length());
AbstractBytes commonPrefix = getCommonPrefix(keyCharsFromStartOfNodeFound, found.getIncomingEdge());
AbstractBytes suffixFromExistingEdge = subtractPrefix(found.getIncomingEdge(), commonPrefix);
Node n2 = createNode(suffixFromExistingEdge, foundValue, oedges, false);
@SuppressWarnings("NullableProblems") Node n3 = createNode(commonPrefix, null, new FasterList(2, new Node[] { n1, n2 }), false);
result.parentNode.updateOutgoingEdge(n3);
// Return null for the existing value...
break;
default:
// This is a safeguard against a new enum constant being added in future.
throw new IllegalStateException("Unexpected classification for search result: " + result);
}
} finally {
releaseWriteLock();
}
}
return newValue;
}
use of jcog.list.FasterList in project narchy by automenta.
the class NodeGraphTest method testObjectGraph.
@Test
public void testObjectGraph() {
MapNodeGraph<Object, Object> h = new MapNodeGraph<>();
h.addEdge(h.addNode("y"), "yx", h.addNode("x"));
ObjectGraph o = new ObjectGraph(3, h) {
@Override
protected boolean access(Object root, FasterList<Pair<Class, ObjectGraph.Accessor>> path, Object target) {
System.out.println(root + " -> " + target + "\n\t" + path);
return true;
}
@Override
public boolean includeValue(Object value) {
return true;
}
@Override
public boolean includeClass(Class<?> c) {
return !c.isPrimitive();
}
@Override
public boolean includeField(Field f) {
return true;
}
};
o.print();
}
use of jcog.list.FasterList in project narchy by automenta.
the class NodeGraphTest method testDFS.
@Test
public void testDFS() {
NodeGraph n = g1();
List<String> trace = new FasterList();
n.dfs("a", new Search() {
@Override
protected boolean next(BooleanObjectPair move, NodeGraph.Node next) {
trace.add(path.toString());
return true;
}
});
assertEquals(4, trace.size());
assertEquals("[[true:a => ab => b], [true:a => ab => b, true:b => bc => c], [true:a => ab => b, true:b => bc => c, true:c => cd => d], [true:a => ae => e]]", trace.toString());
}
use of jcog.list.FasterList in project narchy by automenta.
the class NodeGraphTest method testBFS.
@Test
public void testBFS() {
NodeGraph n = g1();
List<String> trace = new FasterList();
n.bfs("a", new Search() {
@Override
protected boolean next(BooleanObjectPair move, NodeGraph.Node next) {
trace.add(path.toString());
return true;
}
});
assertEquals(4, trace.size());
assertEquals("[[true:a => ab => b], [true:a => ae => e], [true:a => ab => b, true:b => bc => c], [true:a => ab => b, true:b => bc => c, true:c => cd => d]]", trace.toString());
}
use of jcog.list.FasterList in project narchy by automenta.
the class SpeechPlan method next.
public boolean next() {
// long start = nar.time();
float dur = nar.dur() * durationsPerWord;
long now = nar.time();
long startOfNow = now - (int) Math.ceil(dur);
long endOfNow = now + (int) Math.floor(dur);
FasterList<Pair<Term, Truth>> pending = new FasterList<>(0);
synchronized (vocalize) {
// vocalize.rowKeySet().tailSet(startOfNow-1).clear();
SortedSet<Long> tt = vocalize.rowKeySet().headSet(endOfNow);
if (!tt.isEmpty()) {
LongArrayList ll = new LongArrayList(tt.size());
// copy to array so we can modify the vocalize rows
tt.forEach(ll::add);
ll.forEach(t -> {
Set<Map.Entry<Term, TruthAccumulator>> entries = vocalize.row(t).entrySet();
if (t >= startOfNow) {
entries.forEach(e -> {
Truth x = e.getValue().commitSum();
if (x.expectation() > expectationThreshold)
pending.add(Tuples.pair(e.getKey(), x));
});
}
entries.clear();
});
}
}
if (pending.isEmpty())
return true;
// TODO decide word..
Term spoken = decide(pending);
if (spoken != null)
speak.accept(spoken);
return true;
}
Aggregations