Search in sources :

Example 1 with SimpleIntSet

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
// 
// }
}
Also used : SimpleIntSet(jcog.data.SimpleIntSet) ImmutableByteList(org.eclipse.collections.api.list.primitive.ImmutableByteList) ByteList(org.eclipse.collections.api.list.primitive.ByteList) FasterList(jcog.list.FasterList) Term(nars.term.Term) RoaringBitmap(org.roaringbitmap.RoaringBitmap) ImmutableByteList(org.eclipse.collections.api.list.primitive.ImmutableByteList)

Aggregations

SimpleIntSet (jcog.data.SimpleIntSet)1 FasterList (jcog.list.FasterList)1 Term (nars.term.Term)1 ByteList (org.eclipse.collections.api.list.primitive.ByteList)1 ImmutableByteList (org.eclipse.collections.api.list.primitive.ImmutableByteList)1 RoaringBitmap (org.roaringbitmap.RoaringBitmap)1