use of nars.Task in project narchy by automenta.
the class Revision method mergeTemporal.
/**
* assumes:
* the tasks to be sorted in descending strength
* the input minEvi corresponds to the absolute minimum accepted
* evidence integral (evidence * time) for a point-like result (dtRange == 0)
*/
@Nullable
static Task mergeTemporal(float eviMinInteg, NAR nar, int results, TaskRegion... tt) {
assert (tt.length > 1);
Task first = tt[0].task();
// TODO calculate the temporal density at the same time as this first part to avoid naively generating a sparse result afterward
// TODO combine evidensity with the stamp calculation
// TODO allow evidensity to skip a task in the array and proceed to the next without recurse
LongHashSet evidence = new LongHashSet();
int overlap = 0, totalEv = 0;
int tasks = 0;
boolean termSame = true;
EviDensity density = new EviDensity();
for (int i = 0; i < results; i++) {
TaskRegion ri = tt[i];
if (ri == null)
continue;
Task ti = ri.task();
// assert (!t.isEternal());
long[] ts = ti.stamp();
totalEv += ts.length;
int overlapsToAdd;
if (tasks == 0) {
overlapsToAdd = 0;
} else {
overlapsToAdd = Stamp.overlaps(evidence, ts);
if (overlapsToAdd > 0) {
if (totalEv > 0 && Param.overlapFactor(overlap + overlapsToAdd) < Float.MIN_NORMAL) {
/* current amount so far */
// would cause zero evidence, regardless of whatever truth is calculated later
tt[i] = null;
// skip this one
continue;
}
} else {
if (termSame) {
Term termI = ti.term();
if ((i > 0) && !termI.equals(first.term())) {
if (tasks == 1 && termI.op() != CONJ) /* dont do CONJ now because it might produce an occurrence shift which isnt tracked yet */
{
// limit termpolation to max 2 tasks for now
// difference in terms
termSame = false;
// TODO loop dont recurse, just buffer the accumulated evidence changes to the end of the loop
tt = new TaskRegion[] { first, ri };
// cause the for-loop to end after this iteration
i = results;
// continue
} else {
// skip this term, it would conflict with the other 2+ terms which are already known to be the same
tt[i] = null;
// skip this one
continue;
}
}
}
}
}
density.add(ri);
evidence.addAll(ts);
if (tasks > 1)
// because it may be compared against frequently
evidence.compact();
overlap += overlapsToAdd;
tasks++;
}
if (tasks == 1) {
// return the top one, nothing could be merged
return first;
}
// dont settle for anything worse than the first (strongest) task by un-revised
eviMinInteg = Math.max(first.eviInteg(), eviMinInteg);
float overlapFactor = Param.overlapFactor(((float) overlap) / totalEv);
if (overlapFactor < Float.MIN_NORMAL)
return first;
float densityFactor = density.factor();
if (tasks != tt.length)
tt = ArrayUtils.removeNulls(tt, Task[]::new);
long start = density.unionStart;
long end = density.unionEnd;
long range = 1 + (end - start);
Term content;
float differenceFactor = 1f;
if (!termSame) {
Task second = tt[1].task();
float diff = dtDiff(first.term(), second.term());
if (!Float.isFinite(diff))
// impossible
return null;
if (diff > 0)
// proport
differenceFactor = (float) Param.evi(1f, diff, Math.max(1, range));
float e1 = first.eviInteg();
float e2 = second.eviInteg();
float firstProp = e1 / (e1 + e2);
content = intermpolate(first.term(), second.term(), firstProp, nar);
if (!Task.validTaskTerm(content))
return first;
} else {
content = first.term();
}
int dur = nar.dur();
Truth truth = new TruthPolation(start, end, dur, tt).truth(true);
if (truth == null)
return first;
float factor = overlapFactor * differenceFactor * densityFactor;
float eAdjusted = truth.evi() * factor;
if ((eAdjusted * range) < eviMinInteg)
return first;
Task t = Task.tryTask(content, first.punc(), truth, (c, tr) -> {
@Nullable PreciseTruth cTruth = tr.dither(nar, factor);
if (cTruth == null)
return null;
return new NALTask(c, first.punc(), cTruth, nar.time(), start, end, Stamp.sample(Param.STAMP_CAPACITY, evidence, /* TODO account for relative evidence contributions */
nar.random()));
});
if (t == null)
return first;
t.priSet(Priority.fund(Util.max((TaskRegion p) -> p.task().priElseZero(), tt), false, Tasked::task, tt));
((NALTask) t).cause = Cause.sample(Param.causeCapacity.intValue(), tt);
if (Param.DEBUG)
t.log("Temporal Merge");
for (TaskRegion x : tt) {
// forward to the revision
x.task().meta("@", (k) -> t);
}
return t;
}
use of nars.Task in project narchy by automenta.
the class Revision method merge.
@Nullable
@Deprecated
public static Task merge(/*@NotNull*/
Task a, /*@NotNull*/
Task b, long now, float minEvi, NAR nar) {
assert (!a.isEternal() && !b.isEternal()) : "can not merge eternal tasks";
// if (a.op() == CONJ) {
// //avoid intermpolation of 2 conjunctions with opposite polarities
// if (!a.term().equals(b.term())
// && (a.isPositive() ^ b.isPositive()) && (a.term().dtRange() != 0 || b.term().dtRange() != 0))
// return null;
// }
// ObjectFloatPair<long[]> s = Stamp.zip(new FasterList(a, b), Param.STAMP_CAPACITY);
float overlap = Stamp.overlapFraction(a.stamp(), b.stamp());
float overlapFactor = Param.overlapFactor(overlap);
if (overlapFactor < Float.MIN_NORMAL)
return null;
long as, bs;
if ((as = a.start()) > (bs = b.start())) {
// swap so that 'a' is left aligned
Task x = a;
a = b;
b = x;
long xs = as;
as = bs;
bs = xs;
}
assert (bs != ETERNAL);
assert (as != ETERNAL);
// float ae = a.evi();
// float aa = ae * (1 + ai.length());
// float be = b.evi();
// float bb = be * (1 + bi.length());
// float p = aa / (aa + bb);
// relate high frequency difference with low confidence
// float freqDiscount =
// 0.5f + 0.5f * (1f - Math.abs(a.freq() - b.freq()));
// factor *= freqDiscount;
// if (factor < Prioritized.EPSILON) return null;
// float temporalOverlap = timeOverlap==null || timeOverlap.length()==0 ? 0 : timeOverlap.length()/((float)Math.min(ai.length(), bi.length()));
// float confMax = Util.lerp(temporalOverlap, Math.max(w2c(ae),w2c(be)), 1f);
//
//
// float timeDiscount = 1f;
// if (timeOverlap == null) {
// long separation = Math.max(a.timeDistance(b.start()), a.timeDistance(b.end()));
// if (separation > 0) {
// long totalLength = ai.length() + bi.length();
// timeDiscount =
// (totalLength) /
// (separation + totalLength)
// ;
// }
// }
// width will be the average width
// long width = (ai.length() + bi.length()) / 2; //TODO weight
// long mid = (ai.mid() + bi.mid()) / 2; //TODO weight
// Truth expected = table.truth(mid, now, dur);
// if (expected == null)
// return null;
int dur = nar.dur();
// float intermvalDistance = dtDiff(a.term(), b.term()) /
// ((1 + Math.max(a.term().dtRange(), b.term().dtRange())) * dur);
// factor *= (1f / (1f + intermvalDistance));
// if (factor < Prioritized.EPSILON) return null;
EviDensity density = new EviDensity(a, b);
long start = density.unionStart;
long end = density.unionEnd;
Truth an = a.truth(start, end, dur, 0);
if (an == null)
return null;
Truth bn = b.truth(start, end, dur, 0);
if (bn == null)
return null;
Truth rawTruth = revise(an, bn, // joint.factor(Math.abs( an.freq() - bn.freq() ))
density.factor(), Truth.EVI_MIN);
if (rawTruth == null)
return null;
float e2 = rawTruth.evi() * overlapFactor;
if (e2 < minEvi)
return null;
rawTruth = rawTruth.withEvi(e2);
Truth cTruth = rawTruth.dither(nar);
if (cTruth == null)
return null;
Term cc = null;
assert (a.punc() == b.punc());
float aProp = a.isQuestOrQuestion() ? 0.5f : an.evi() / (an.evi() + bn.evi());
Term at = a.term();
Term bt = b.term();
if (!at.equals(bt)) {
for (int i = 0; i < Param.MAX_TERMPOLATE_RETRIES; i++) {
Term t;
if (at.equals(bt)) {
t = at;
// no need to retry
i = Param.MAX_TERMPOLATE_RETRIES;
} else {
long dt = bs - as;
t = intermpolate(at, dt, bt, aProp, nar);
if (t == null || !t.unneg().op().conceptualizable)
continue;
}
ObjectBooleanPair<Term> ccp = Task.tryContent(t, a.punc(), Param.DEBUG_EXTRA);
/*if (ccp != null) */
{
cc = ccp.getOne();
if (ccp.getTwo())
cTruth = cTruth.neg();
break;
}
}
if (cc == null)
return null;
// if (cc.op() == CONJ) {
// long mid = Util.lerp(aProp, b.mid(), a.mid());
// long range = cc.op() == CONJ ?
// cc.dtRange() :
// (Util.lerp(aProp, b.range(), a.range()));
// start = mid - range / 2;
// end = start + range;
// } else {
// if (u > s) {
// start = end = Util.lerp(aProp, b.mid(), a.mid());
// } else {
// }
// }
} else {
cc = at;
}
if (equalOrWeaker(a, cTruth, start, end, cc, nar))
return a;
if (equalOrWeaker(b, cTruth, start, end, cc, nar))
return b;
NALTask t = new NALTask(cc, a.punc(), cTruth, now, start, end, // get a stamp collecting all evidence from the table, since it all contributes to the result
Stamp.zip(a.stamp(), b.stamp(), aProp));
// if (overlap > 0 || a.isCyclic() || b.isCyclic())
// t.setCyclic(true);
t.priSet(Util.lerp(aProp, b.priElseZero(), a.priElseZero()));
// t.setPri(a.priElseZero() + b.priElseZero());
t.cause = Cause.sample(Param.causeCapacity.intValue(), a, b);
if (Param.DEBUG)
t.log("Revection Merge");
// forward to the revision
a.meta("@", (k) -> t);
// forward to the revision
b.meta("@", (k) -> t);
return t;
}
use of nars.Task in project narchy by automenta.
the class EternalTable method setCapacity.
public void setCapacity(int c) {
int wasCapacity = this.capacity();
if (wasCapacity != c) {
List<Task> trash = null;
synchronized (this) {
// just to be sure
wasCapacity = capacity();
int s = size;
if (s > c) {
// TODO can be accelerated by batch/range remove operation
trash = new FasterList(s - c);
while (c < s--) {
trash.add(removeLast());
}
}
if (wasCapacity != c)
resize(c);
}
// do this outside of the synch
if (trash != null) {
// Task s = strongest();
// if (s!=null) {
// TaskLink.GeneralTaskLink sl = new TaskLink.GeneralTaskLink(s, 0);
// trash.forEach(t -> ((NALTask)t).delete(sl));
// } else {
trash.forEach(Task::delete);
// }
}
}
}
use of nars.Task in project narchy by automenta.
the class BeliefTable method answer.
/**
* projects a match
*/
@Nullable
default Task answer(long start, long end, int dur, @Nullable Task question, Term template, NAR nar, Consumer<Task> withNovel) {
if (isEmpty())
return null;
Task answer = match(start, end, template, nar);
if (answer == null || answer.isDeleted())
return null;
// (answer instanceof AnswerTask); //includes: answers, revision, or dynamic
boolean novel = false;
// project if different occurrence
boolean relevantTime = start == ETERNAL || answer.intersects(start, end);
if (/*!answer.isEternal() && */
!relevantTime) {
long t = answer.nearestPointExternal(start, end);
Truth aProj = answer.truth(t, dur, nar);
if (aProj != null) {
final Task aa = answer;
Task a = Task.tryTask(answer.term(), answer.punc(), aProj, (content, truth) -> new NALTask(content, aa.punc(), truth, nar.time(), t, t, aa.stamp()));
// Stamp.zip(aa.stamp(), question.stamp(), 0.5f) : aa.stamp()));
if (a == null)
return null;
float confFrac = Util.unitize(aProj.evi() / answer.evi());
a.priSet(answer.priElseZero() * confFrac);
if (question != null)
((NALTask) a).cause = Cause.sample(Param.causeCapacity.intValue(), question, answer);
// if (Param.DEBUG)
// a.log("Answer Projected");
// because it was projected
novel = true;
// relevantTime = true;
answer = a;
}
}
if (novel && question != null && question.isQuestOrQuestion()) {
withNovel.accept(answer);
}
return answer;
}
use of nars.Task in project narchy by automenta.
the class RTreeBeliefTable method add.
@Override
public boolean add(Task x, TaskConcept c, NAR n) {
if (capacity() == 0)
return false;
float incoming = x.priElseZero();
List<Tasked> added = new FasterList<>(2);
write(treeRW -> {
if (treeRW.add(x)) {
if (!x.isDeleted()) {
added.add(x);
ensureCapacity(treeRW, x, added::add, n);
}
}
});
for (int i = 0, addedSize = added.size(); i < addedSize; i++) {
Task y = added.get(i).task();
if (y != null) {
// completely activate a temporal task being stored in this table
float pri = y.pri();
if (pri == pri) {
Tasklinks.linkTask(y, pri, c, n);
}
} else {
// eternal task input already done by calling the .task() method. it willl have returned null
}
}
if (x.isDeleted()) {
Task xisting = x.meta("merge");
if (xisting != null) {
// use incoming priority but the existing task instance
Tasklinks.linkTask(xisting, incoming, c, n);
}
return false;
} else {
return true;
}
}
Aggregations