use of jcog.list.FasterList in project narchy by automenta.
the class NarseseParser method popTerms.
FasterList<Term> popTerms(Op[] op) /* hint */
{
FasterList tt = new FasterList(8);
ArrayValueStack<Object> stack = (ArrayValueStack) getContext().getValueStack();
while (!stack.isEmpty()) {
Object p = pop();
if (p instanceof Object[]) {
// it's an array so unpack by pushing everything back onto the stack except the last item which will be used as normal below
Object[] pp = (Object[]) p;
if (pp.length > 1) {
for (int i = pp.length - 1; i >= 1; i--) {
stack.push(pp[i]);
}
}
p = pp[0];
}
if (p == functionalForm) {
op[0] = ATOM;
break;
}
// beginning of stack frame for this term
if (p == Compound.class)
break;
if (p instanceof String) {
// throw new RuntimeException("string not expected here");
// Term t = $.the((String) p);
tt.add(Atomic.the((String) p));
} else if (p instanceof Term) {
if (p == Null) {
stack.clear();
return new FasterList(1).addingAll(Null);
}
tt.add(p);
} else if (p instanceof Op) {
if (op != null)
op[0] = (Op) p;
}
}
tt.reverse();
return tt;
}
use of jcog.list.FasterList in project narchy by automenta.
the class Builtin method registerFunctors.
public static void registerFunctors(NAR nar) {
for (Concept t : Builtin.statik) {
nar.on(t);
}
nar.on(Functor.f1("varIntro", (x) -> {
Pair<Term, Map<Term, Term>> result = DepIndepVarIntroduction.the.apply(x, nar.random());
return result != null ? result.getOne() : Null;
}));
nar.on(Functor.f1((Atom) $.the("termlinkRandom"), (Term t) -> {
@Nullable Concept c = nar.conceptualize(t);
if (c == null)
return Null;
@Nullable PriReference<Term> tl = c.termlinks().sample(nar.random());
if (tl == null)
return Null;
return tl.get();
}));
// nar.on(Functor.f("service", (TermContainer c) ->
// $.sete(
// nar.services().map(
// (e) ->
// $.p(e, $.the(e.getValue().state())))
// .toArray(Term[]::new)
// )
// ));
/**
* subterm, but specifically inside an ellipsis. otherwise pass through
*/
nar.on(Functor.f("esubterm", (Subterms c) -> {
Term x = c.sub(0, null);
if (x == null)
return Null;
Term index = c.sub(1, Null);
if (index == Null)
return Null;
int which;
if (index != null) {
if (index instanceof Variable)
return Null;
which = $.intValue(index, -1);
if (which < 0) {
return Null;
}
} else {
// random
which = nar.random().nextInt(x.subs());
}
return x.sub(which);
}));
nar.on(Functor.f2((Atom) $.the("without"), (Term container, Term content) -> Op.without(container, x -> x.equals(content), nar.random())));
nar.on(Functor.f2((Atom) $.the("withoutPosOrNeg"), (Term container, Term content) -> Op.without(container, x -> x.unneg().equals(content), nar.random())));
/**
* TODO rename this to 'dropAnyCommutive'
* remove an element from a commutive conjunction (or set), at random, and try re-creating
* the compound. wont necessarily work in all situations.
* TODO move the type restriction to another functor to wrap this
*
* this also filter a single variable (depvar) from being a result
*/
nar.on(Functor.f1((Atom) $.the("dropAnySet"), (Term t) -> {
Op oo = t.op();
if (oo == INT) {
if (t instanceof Int.IntRange) {
// select random location in the int and split either up or down
Int.IntRange i = (Int.IntRange) t;
Random rng = nar.random();
if (i.min + 1 == i.max) {
// arity=2
return Int.the(rng.nextBoolean() ? i.min : i.max);
} else if (i.min + 2 == i.max) {
// arity=3
switch(rng.nextInt(4)) {
case 0:
return Int.the(i.min);
case 1:
return Int.range(i.min, i.min + 1);
case 2:
return Int.range(i.min + 1, i.min + 2);
case 3:
return Int.the(i.max);
default:
throw new UnsupportedOperationException();
}
} else {
int split = // midpoint, deterministic
(i.max + i.min) / 2;
// rng.nextInt(i.max-i.min-2);
return (rng.nextBoolean()) ? Int.range(i.min, split + 1) : Int.range(split + 1, i.max);
}
}
// cant drop int by itself
return Null;
}
if (!oo.in(SETi.bit | SETe.bit | SECTi.bit | SECTe.bit))
// returning the original value may cause feedback loop in callees expcting a change in value
return Null;
int size = t.subs();
switch(size) {
case 0:
assert (false) : "empty set impossible here";
return Null;
case 1:
return Null;
/* can't shrink below one element */
case 2:
int n = nar.random().nextInt(2);
return oo.the(t.sub(n));
default:
Term[] y = Terms.dropRandom(nar.random(), t.subterms());
return oo.the(y);
}
}));
/**
* depvar cleaning from commutive conj
*/
nar.on(Functor.f1((Atom) $.the("ifConjCommNoDepVars"), (Term t) -> {
if (!t.hasAny(VAR_DEP))
return t;
Op oo = t.op();
if (oo != CONJ)
return t;
SortedSet<Term> s = t.subterms().toSetSorted();
if (!s.removeIf(x -> x.unneg().op() == VAR_DEP))
return t;
return CONJ.the(t.dt(), s);
}));
/**
* drops a random contained event, whether at first layer or below
*/
nar.on(Functor.f1((Atom) $.the("dropAnyEvent"), (Term t) -> {
Op oo = t.op();
if (oo != CONJ)
// returning the original value may cause feedback loop in callees expcting a change in value
return Null;
FasterList<LongObjectPair<Term>> ee = Conj.eventList(t);
ee.remove(nar.random().nextInt(ee.size()));
return Conj.conj(ee);
// }
// if (r instanceof Variable /*&& r.op()!=VAR_DEP*/)
// return Null; //HACK dont allow returning a variable as an event during decomposition HACK TODO make more careful and return the only result if one subterm is a non-returnable variable
// return r;
}));
nar.on(Functor.f2((Atom) $.the("conjEvent"), (Term c, Term when) -> {
if (c.op() != CONJ || !(when instanceof Atom))
return Null;
// extract earliest or latest &| timeslice of events
throw new TODO();
// if (c.dt() == DTERNAL || c.dt() == 0) {
// return c.sub(nar.random().nextInt(c.subs())); //choose a subterm at random
// }
// assert (c.subs() == 2);
// int target;
// switch (when.toString()) {
// case "early":
// target = 0;
// break;
// case "late":
// target = 1;
// break;
// default:
// throw new UnsupportedOperationException();
// }
// if (c.dt() < 0)
// target = 1 - target;
// return c.sub(target);
}));
/**
* similar to without() but special handling for CONJ sub-events
*/
nar.on(Functor.f2((Atom) $.the("conjWithout"), (Term conj, Term event) -> {
if (conj.op() != CONJ || conj.impossibleSubTerm(event))
return Null;
FasterList<LongObjectPair<Term>> events = Conj.eventList(conj);
IntArrayList found = new IntArrayList(2);
int es = events.size();
assert (es > 1);
for (int i = 0; i < es; i++) {
if (event.equalsRoot(events.get(i).getTwo())) {
found.add(i);
}
}
int fs = found.size(), r;
switch(fs) {
case 0:
return Null;
case 1:
r = found.get(0);
break;
default:
r = found.get(nar.random().nextInt(fs));
break;
}
events.remove(r);
return Conj.conj(events);
// } else {
// return nullToNull(Op.without(conj, event::equalsRoot, nar.random()));
// }
}));
/**
* extracts only the events preceding the specified events
*/
nar.on(Functor.f2((Atom) $.the("conjDropIfLatest"), (Term conj, Term event) -> Conj.conjDrop(conj, event, false)));
nar.on(Functor.f2((Atom) $.the("conjDropIfEarliest"), (Term conj, Term event) -> Conj.conjDrop(conj, event, true)));
nar.on(Functor.f1Concept("belief", nar, (c, n) -> $.quote(n.belief(c, n.time()))));
nar.on(Functor.f1Concept("goal", nar, (c, n) -> $.quote(n.goal(c, n.time()))));
nar.on(f0("self", nar::self));
nar.on(Functor.f1("the", what -> {
if (what instanceof Atom) {
switch(what.toString()) {
case "sys":
return $.p($.quote(nar.emotion.summary()), $.quote(nar.concepts.summary()), $.quote(nar.emotion.summary()), $.quote(nar.exe.toString()));
}
}
Object x = nar.concept(what);
if (x == null)
x = what;
return $.quote($.p($.quote(x.getClass().toString()), $.quote(x.toString())));
}));
// /** slice(<compound>,<selector>)
// selector :-
// a specific integer value index, from 0 to compound size
// (a,b) pair of integers, a range of indices */
nar.on(Functor.f("slice", (args) -> {
if (args.subs() == 2) {
Term x = args.sub(0);
if (x.subs() > 0) {
int len = x.subs();
Term index = args.sub(1);
Op o = index.op();
if (o == INT) {
// specific index
int i = ((Int) index).id;
if (i >= 0 && i < len)
return x.sub(i);
else
return False;
} else if (o == PROD && index.subs() == 2) {
Term start = (index).sub(0);
if (start.op() == INT) {
Term end = (index).sub(1);
if (end.op() == INT) {
int si = ((Int) start).id;
if (si >= 0 && si < len) {
int ei = ((Int) end).id;
if (ei >= 0 && ei <= len) {
if (si == ei)
return Op.EmptyProduct;
if (si < ei) {
return $.p(Arrays.copyOfRange(x.subterms().arrayClone(), si, ei));
}
}
}
// TODO maybe reverse order will return reversed subproduct
return False;
}
}
}
}
}
return null;
}));
}
use of jcog.list.FasterList in project narchy by automenta.
the class Optimize method run.
public Result<X> run(int maxIterations, int repeats, FloatFunction<Supplier<X>> eval) {
assert (repeats >= 1);
final int dim = tweaks.size();
double[] mid = new double[dim];
// double[] sigma = new double[n];
double[] min = new double[dim];
double[] max = new double[dim];
double[] inc = new double[dim];
// double[] range = new double[dim];
X example = subject.get();
int i = 0;
for (Tweak w : tweaks) {
TweakFloat s = (TweakFloat) w;
// initial guess: get from sample, otherwise midpoint of min/max range
Object guess = s.get(example);
mid[i] = guess != null ? ((float) guess) : ((s.getMax() + s.getMin()) / 2f);
min[i] = (s.getMin());
max[i] = (s.getMax());
inc[i] = s.getInc();
// range[i] = max[i] - min[i];
// sigma[i] = Math.abs(max[i] - min[i]) * 0.75f; //(s.getInc());
i++;
}
FasterList<DoubleObjectPair<double[]>> experiments = new FasterList<>(maxIterations);
final double[] maxScore = { Double.NEGATIVE_INFINITY };
ObjectiveFunction func = new ObjectiveFunction(point -> {
double score;
try {
double sum = 0;
for (int r = 0; r < repeats; r++) {
Supplier<X> x = () -> subject(point);
sum += eval.floatValueOf(x);
}
score = sum / repeats;
} catch (Exception e) {
logger.error("{} {} {}", this, point, e);
score = Float.NEGATIVE_INFINITY;
}
if (trace)
csv.out(ArrayUtils.add(point, (int) 0, score));
maxScore[0] = Math.max(maxScore[0], score);
// System.out.println(
// n4(score) + " / " + n4(maxScore[0]) + "\t" + n4(point)
// );
experiments.add(pair(score, point));
experimentIteration(point, score);
return score;
});
if (trace)
csv = new CSVOutput(System.out, Stream.concat(Stream.of("score"), tweaks.stream().map(t -> t.id)).toArray(String[]::new));
experimentStart();
try {
solve(dim, func, mid, min, max, inc, maxIterations);
} catch (Throwable t) {
logger.info("solve {} {}", func, t);
}
return new Result<>(experiments, tweaks);
}
use of jcog.list.FasterList in project narchy by automenta.
the class Tweaks method discover.
/**
* auto discovers tweaks by reflecting a sample of the subject
*/
public Tweaks<X> discover(Discovery<X> each) {
// sample instance
X x = (this.subjects.get());
ObjectGraph o = new ObjectGraph() {
@Override
protected boolean access(Object root, FasterList<Pair<Class, Accessor>> path, Object target) {
if (this.nodes.containsKey(target))
// prevent cycle
return false;
Class<?> targetType = target.getClass();
if (!Tweaks.this.includeClass(targetType))
return false;
if (tweakable(targetType)) {
each.discovered((X) root, path.clone(), targetType);
}
return !Primitives.unwrap(target.getClass()).isPrimitive();
}
@Override
public boolean recurse(Object x) {
Class<?> xc = x.getClass();
return Tweaks.this.includeClass(xc) && !tweakable(xc);
}
@Override
public boolean includeValue(Object v) {
return Tweaks.this.includeClass(v.getClass());
}
@Override
public boolean includeClass(Class<?> c) {
return Tweaks.this.includeClass(c);
}
@Override
public boolean includeField(Field f) {
int m = f.getModifiers();
if (!Modifier.isPublic(m) || !Tweaks.this.includeField(f))
return false;
Class<?> t = Primitives.wrap(f.getType());
boolean primitive = Primitives.unwrap(f.getType()).isPrimitive();
if (tweakable(t)) {
return (!primitive || !Modifier.isFinal(m));
} else
// explore further into Object's, final or not
return !primitive;
}
};
o.add(DEFAULT_DEPTH, x);
return this;
}
use of jcog.list.FasterList in project narchy by automenta.
the class MyConcurrentRadixTree method removeHavingAcquiredWriteLock.
public boolean removeHavingAcquiredWriteLock(SearchResult searchResult, boolean recurse) {
SearchResult.Classification classification = searchResult.classification;
switch(classification) {
case EXACT_MATCH:
Node found = searchResult.found;
Node parent = searchResult.parentNode;
Object v = found.getValue();
if (!recurse && ((v == null) || (v == VoidValue.SINGLETON))) {
// No need to remove it...
return false;
}
List<X> reinsertions = new FasterList<>(0);
if (v != null && v != VoidValue.SINGLETON) {
X xv = (X) v;
boolean removed = tryRemove(xv);
if (!recurse) {
if (!removed)
// remove was disabled for this entry
return false;
} else {
if (!removed) {
// continue removing below then reinsert afterward
reinsertions.add(xv);
}
}
}
// Proceed with deleting the node...
FasterList<Node> childEdges = found.getOutgoingEdges();
int numChildren = childEdges.size();
if (numChildren > 0) {
if (!recurse) {
if (numChildren > 1) {
// This node has more than one child, so if we delete the value from this node, we still need
// to leave a similar node in place to act as the split between the child edges.
// Just delete the value associated with this node.
// -> Clone this node without its value, preserving its child nodes...
@SuppressWarnings("NullableProblems") Node cloned = createNode(found.getIncomingEdge(), null, found.getOutgoingEdges(), false);
// Re-add the replacement node to the parent...
parent.updateOutgoingEdge(cloned);
} else if (numChildren == 1) {
// Node has one child edge.
// Create a new node which is the concatenation of the edges from this node and its child,
// and which has the outgoing edges of the child and the value from the child.
Node child = childEdges.get(0);
AbstractBytes concatenatedEdges = concatenate(found.getIncomingEdge(), child.getIncomingEdge());
Node mergedNode = createNode(concatenatedEdges, child.getValue(), child.getOutgoingEdges(), false);
// Re-add the merged node to the parent...
parent.updateOutgoingEdge(mergedNode);
}
} else {
// collect all values from the subtree, call onRemove for them. then proceed below with removal of this node and its value
forEach(found, (k, f) -> {
boolean removed = tryRemove(f);
if (!removed) {
reinsertions.add(f);
}
});
numChildren = 0;
}
}
if (numChildren == 0) {
if (reinsertions.size() == 1) {
// in this case make no further changes
return false;
}
// Node has no children. Delete this node from its parent,
// which involves re-creating the parent rather than simply updating its child edge
// (this is why we need parentNodesParent).
// However if this would leave the parent with only one remaining child edge,
// and the parent itself has no value (is a split node), and the parent is not the root node
// (a special case which we never merge), then we also need to merge the parent with its
// remaining child.
FasterList<Node> currentEdgesFromParent = parent.getOutgoingEdges();
// Create a list of the outgoing edges of the parent which will remain
// if we remove this child...
int cen = currentEdgesFromParent.size();
FasterList<Node> newEdgesOfParent = new FasterList<>(0, new Node[cen]);
boolean differs = false;
for (int i = 0; i < cen; i++) {
Node node = currentEdgesFromParent.get(i);
if (node != found) {
newEdgesOfParent.add(node);
} else {
differs = true;
}
}
if (!differs)
// re-use original
newEdgesOfParent = currentEdgesFromParent;
// Note the parent might actually be the root node (which we should never merge)...
boolean parentIsRoot = (parent == root);
Node newParent;
if (newEdgesOfParent.size() == 1 && parent.getValue() == null && !parentIsRoot) {
// Parent is a non-root split node with only one remaining child, which can now be merged.
Node parentsRemainingChild = newEdgesOfParent.get(0);
// Merge the parent with its only remaining child...
AbstractBytes concatenatedEdges = concatenate(parent.getIncomingEdge(), parentsRemainingChild.getIncomingEdge());
newParent = createNode(concatenatedEdges, parentsRemainingChild.getValue(), parentsRemainingChild.getOutgoingEdges(), parentIsRoot);
} else {
// Parent is a node which either has a value of its own, has more than one remaining
// child, or is actually the root node (we never merge the root node).
// Create new parent node which is the same as is currently just without the edge to the
// node being deleted...
newParent = createNode(parent.getIncomingEdge(), parent.getValue(), newEdgesOfParent, parentIsRoot);
}
// Re-add the parent node to its parent...
if (parentIsRoot) {
// Replace the root node...
this.root = newParent;
} else {
// Re-add the parent node to its parent...
searchResult.parentNodesParent.updateOutgoingEdge(newParent);
}
}
reinsertions.forEach(this::put);
return true;
default:
return false;
}
}
Aggregations