use of jcog.data.SimpleIntSet in project narchy by automenta.
the class Int method intersect.
// public static Term[] intersect(Term[] u) {
//
// TreeSet<Intlike> integers = new TreeSet();
// for (Term x : u) {
// if (x.op() == INT) {
// integers.add((Intlike) x);
// }
// }
//
// int ii = integers.size();
// if (ii < 2)
// return u; //one or less integers, do nothing about it
//
//
// TreeSet<Term> v = new TreeSet<>();
// for (Term uu : u)
// v.add(uu);
//
// Intlike a = integers.pollFirst();
// Intlike b = integers.pollFirst();
// Range ar = a.range();
// Range br = b.range();
// if (ar.isConnected(br)) {
// Intlike combined = Int.the(ar.span(br));
// v.remove(a);
// v.remove(b);
// v.add(combined);
// }
//
//
// return v.toArray(new Term[v.size()]);
//
// }
/**
* TODO permute other arrangements
*/
public static Term[] intersect(final Term... _subs) {
RoaringBitmap factoring = new RoaringBitmap();
int equalVolume = -1, equalStructure = -1;
int pureInts = 0;
for (int i = 0, subsLength = _subs.length; i < subsLength; i++) {
Term x = _subs[i];
if (!x.hasAny(Op.INT)) {
continue;
}
if (x.op() == INT)
pureInts++;
if (equalVolume != -1) {
if (x.volume() != equalVolume) {
// a term with non-matching volume
continue;
}
}
if (equalStructure != -1) {
if (x.structure() != equalStructure) {
continue;
}
}
equalVolume = x.volume();
equalStructure = x.structure();
factoring.add(i);
}
int ff = factoring.getCardinality();
if (ff < 2)
return sorted(_subs);
Term[] subs;
if (ff < _subs.length) {
subs = new Term[ff];
int j = 0;
for (int i = 0; i < _subs.length; i++) {
if (factoring.contains(i))
subs[j++] = _subs[i];
}
assert (j == ff);
} else {
subs = _subs;
}
if (subs.length == 3) {
Term[] rr;
// HACK try permutations to combine some but not all
Term[] ab = intersect(subs[0], subs[1]);
if (ab.length == 1) {
rr = intersect(ab[0], subs[2]);
} else {
Term[] bc = intersect(subs[1], subs[2]);
if (bc.length == 1) {
rr = intersect(bc[0], subs[0]);
} else {
Term[] ac = intersect(subs[0], subs[2]);
if (ac.length == 1) {
rr = intersect(ac[0], subs[1]);
} else {
rr = null;
}
}
}
if (rr != null) {
return intersectResult(factoring, ff, new FasterList(rr), _subs);
}
}
FasterList<Term> yAux = new FasterList(0);
if (pureInts == ff) {
// avoid the path stuff, just merge the int terms
SimpleIntSet s = new SimpleIntSet(ff);
for (Term x : subs) {
((Intlike) x).forEachInt(s::add);
}
int ns = s.size();
assert (ns > 1);
if (ns == 2) {
// simple case
Iterator<Integer> si = s.iterator();
int a = si.next();
int b = si.next();
if (Math.abs(a - b) > 1) {
yAux.add(Int.the(a));
yAux.add(Int.the(b));
} else {
if (a > b) {
int c = b;
b = a;
a = c;
}
yAux.add(Int.range(a, b));
}
} else {
features(s.iterator(), -1).forEachRemaining(yAux::add);
}
} else {
// paths * extracted sequence of numbers at given path for each subterm
Map<ByteList, Object> /*SimpleIntSet*/
data = new LinkedHashMap<>(subs.length);
// if a subterm is not an integer, check for equality of atoms (structure already compared abovec)
final boolean[] valid = { true };
subs[0].pathsTo(x -> x, d -> true, (p, x) -> {
// if (p.isEmpty())
// return true; //continue past root, of course the root term will be unique
ImmutableByteList path = null;
SimpleIntSet c = null;
int xVol = x.volume();
int xStruct = x.structure();
for (int others = 1; others < subs.length; others++) {
Term y = subs[others].subPath(p);
if (x.equals(y))
continue;
if (!x.hasAny(INT)) {
// and we expect differences but only in the INT
if (!y.equals(x)) {
valid[0] = false;
return false;
}
} else if (x.op() == INT) {
if (y.op() != INT) {
valid[0] = false;
return false;
}
if (path == null)
path = p.toImmutable();
// store the path to the integer(s)
if (c == null)
c = (SimpleIntSet) data.computeIfAbsent(path, (pp) -> new SimpleIntSet(2));
((Intlike) y).forEachInt(c::add);
} else {
// this is a term containing an INT but is not an INT; the structure must still match
if (xVol != y.volume() || xStruct != y.structure()) {
valid[0] = false;
return false;
}
}
}
if (x.op() == INT) {
if (c == null) {
if (path == null)
path = p.toImmutable();
data.put(path, c = new SimpleIntSet(1));
}
((Intlike) x).forEachInt(c::add);
}
return true;
});
if (!valid[0])
return _subs;
Iterator<Map.Entry<ByteList, Object>> entries = data.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<ByteList, Object> /*SimpleIntSet*/
e = entries.next();
SimpleIntSet s = (SimpleIntSet) e.getValue();
if (s.size() < 2) {
entries.remove();
// same integer value in each
continue;
}
// for each path where the other numerics are uniformly equal (only one unique value)
/*if (new HashSet(nn).size()==1)*/
Iterator<Integer> si = s.iterator();
if (e.getKey().isEmpty()) {
// root level, get as many as possible
features(si, -1).forEachRemaining(yAux::add);
entries.remove();
} else {
Iterator<Intlike> iii = features(si, 1);
if (iii == null || !iii.hasNext())
// discontiguous or otherwise ununifiable
return _subs;
e.setValue(iii.next());
}
}
Term y;
if (!data.isEmpty()) {
y = subs[0];
for (Map.Entry<ByteList, Object> /*Intlike*/
e : data.entrySet()) {
Object v = e.getValue();
y = y.transform(e.getKey(), (Term) v);
}
} else {
y = null;
}
if (subs.length == _subs.length && yAux.isEmpty()) {
if (y == null)
// ??
return _subs;
return new Term[] { y };
} else {
yAux.add(y);
}
}
return intersectResult(factoring, ff, yAux, _subs);
// int ffs = ff.size();
// if (ffs == 0 || ffs >= numInvolved) {
// //nothing would be gained; dont bother
// continue;
// }
//
// for (Intlike f : ff) {
// byte j = 0;
// for (Term x : subs) {
//
// if (!involved.contains(j)) {
// result.add(x);
// //System.out.println("1: " + result);
// } else {
//
//
// //x is contained within range expression p
// Term xpp = x.subs() > 0 ? x.subPath(pp) : x;
//
// boolean connected;
// if (xpp.op() == INT) {
// connected = (f.range().isConnected(((Intlike) xpp).range()));
// } else {
// connected = false;
// }
//
// if (connected) {
// Term y = x instanceof Compound ?
// x.transform(pp, f)
// : f;
// //if (!y.equals(x)) {
//
// if (!x.equals(y)) {
// subsumed.add(x);
// }
// result.add(y);
// //System.out.println(x + " 3: " + result + "\t + " + y);
// //}
// } else {
// result.add(x);
// }
// }
// j++;
// }
//
//
// }
//
// int results = result.size();
// if ((results == 1) /*|| (results > resultLimit * subCount)*/) {
// break; //reduced to one or exploded, go no further
// }
// }
// result.removeAll(subsumed);
//
// if (result.isEmpty()) {
// return subs;
// } else {
//
// Term[] rr = result.toArray(new Term[result.size()]);
// if (Arrays.equals(rr, subs))
// return rr;
// else
// return intersect(rr); //changed, recompress
//
// }
}
Aggregations