Search in sources :

Example 66 with Triple

use of catdata.Triple in project fql by CategoricalData.

the class Algebra method createAndLoad.

/**
 * MUST close this connection
 */
public Connection createAndLoad(Map<En, List<String>> indices, Pair<Map<X, Integer>, Map<Integer, X>> I, int vlen) {
    try {
        Map<En, Triple<List<Chc<Fk, Att>>, List<String>, List<String>>> xxx = schema().toSQL("", "integer", "id", -1, Object::toString, vlen);
        Connection conn = DriverManager.getConnection("jdbc:h2:mem:db_temp_" + session_id++ + ";DB_CLOSE_DELAY=-1");
        try (Statement stmt = conn.createStatement()) {
            for (En en1 : schema().ens) {
                Triple<List<Chc<Fk, Att>>, List<String>, List<String>> qqq = xxx.get(en1);
                for (String s : qqq.second) {
                    stmt.execute(s);
                }
                for (String s : qqq.third) {
                    // don't need fks for AQL's internal use
                    if (!s.startsWith("alter table")) {
                        stmt.execute(s);
                    }
                }
                for (String s : indices.get(en1)) {
                    stmt.execute(s);
                }
                for (X x : en(en1)) {
                    storeMyRecord(I, conn, x, qqq.first, en1.toString(), "", -1);
                }
            }
            stmt.close();
            // this.conn = conn;
            return conn;
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
        throw new RuntimeException(ex);
    }
}
Also used : SQLException(java.sql.SQLException) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) Connection(java.sql.Connection) SQLException(java.sql.SQLException) Triple(catdata.Triple) List(java.util.List) LinkedList(java.util.LinkedList) Chc(catdata.Chc)

Example 67 with Triple

use of catdata.Triple in project fql by CategoricalData.

the class RawTerm method infer2.

public static Triple<Ctx<Var, Chc<Ty, En>>, Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Term<Ty, En, Sym, Fk, Att, Gen, Sk>> infer2(List<Pair<String, String>> l, RawTerm a, RawTerm b, Collage<Ty, En, Sym, Fk, Att, Gen, Sk> col, AqlJs<Ty, Sym> js) {
    Map<String, Chc<Ty, En>> ctx = new HashMap<>();
    for (Pair<String, String> p : l) {
        if (ctx.containsKey(p.first)) {
            throw new RuntimeException("Duplicate variable " + p.first + " in context " + Ctx.toString(l));
        }
        if (p.second != null) {
            if (col.tys.contains(p.second) && col.ens.contains(p.second)) {
                throw new RuntimeException("Ambiguous: " + p.second + " is an entity and a type");
            } else if (col.tys.contains(p.second)) {
                Ty tt = new Ty(p.second);
                // TODO aql remove for
                ctx.put(p.first, Chc.inLeft(tt));
            // loops for other ones
            } else if (col.ens.contains(p.second)) {
                En tt = new En(p.second);
                ctx.put(p.first, Chc.inRight(tt));
            } else {
                throw new RuntimeException(p.second + " is neither a type nor entity");
            }
        } else {
            ctx.put(p.first, null);
        }
    }
    Triple<Ctx<Var, Chc<Ty, En>>, Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Term<Ty, En, Sym, Fk, Att, Gen, Sk>> eq0 = infer1x(ctx, a, b, null, col, "", js).first3();
    LinkedHashMap<Var, Chc<Ty, En>> map = new LinkedHashMap<>();
    for (String k : ctx.keySet()) {
        Chc<Ty, En> v = eq0.first.get(new Var(k));
        map.put(new Var(k), v);
    }
    Ctx<Var, Chc<Ty, En>> ctx2 = new Ctx<>(map);
    Triple<Ctx<Var, Chc<Ty, En>>, Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Term<Ty, En, Sym, Fk, Att, Gen, Sk>> tr = new Triple<>(ctx2, eq0.second, eq0.third);
    return tr;
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Ty(catdata.aql.exp.TyExpRaw.Ty) Ctx(catdata.Ctx) En(catdata.aql.exp.SchExpRaw.En) LinkedHashMap(java.util.LinkedHashMap) Triple(catdata.Triple) Chc(catdata.Chc)

Example 68 with Triple

use of catdata.Triple in project fql by CategoricalData.

the class RawTerm method infer_good.

private static Set<Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>>> infer_good(RawTerm e, Chc<Ty, En> expected, Collage<Ty, En, Sym, Fk, Att, Gen, Sk> col, String pre, AqlJs<Ty, Sym> js, Map<Var, Chc<Ty, En>> vars) {
    if (e.annotation != null && !col.tys.contains(new Ty(e.annotation))) {
        throw new RuntimeException(pre + "Annotation " + e.annotation + " is not a type (" + col.tys + ").");
    }
    Set<Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>>> ret = new HashSet<>();
    if (vars.keySet().contains(new Var((String) e.head)) && e.annotation == null) {
        Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Var(new Var((String) e.head));
        if (expected != null) {
            Ctx<Var, Chc<Ty, En>> ret2 = new Ctx<>();
            ret2.put(new Var((String) e.head), expected);
            if (ret2.agreeOnOverlap(Ctx.fromNullable(vars))) {
                ret.add(new Triple<>(ret1, ret2, expected));
            }
        } else {
            for (En en : col.ens) {
                Ctx<Var, Chc<Ty, En>> ret2 = new Ctx<>();
                ret2.put(new Var((String) e.head), Chc.inRight(en));
                if (ret2.agreeOnOverlap(Ctx.fromNullable(vars))) {
                    ret.add(new Triple<>(ret1, ret2, Chc.inRight(en)));
                }
            }
            for (Ty ty : col.tys) {
                Ctx<Var, Chc<Ty, En>> ret2 = new Ctx<>();
                if (ret2.agreeOnOverlap(Ctx.fromNullable(vars))) {
                    ret2.put(new Var((String) e.head), Chc.inLeft(ty));
                }
                ret.add(new Triple<>(ret1, ret2, Chc.inLeft(ty)));
            }
        }
    }
    if (col.syms.containsKey(new Sym(e.head)) && e.annotation == null) {
        // //System.out.println("a " + e);
        List<List<Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>>>> l = new LinkedList<>();
        l.add(new LinkedList<>());
        for (int i = 0; i < e.args.size(); i++) {
            RawTerm arg = e.args.get(i);
            // //System.out.println("arg " + arg);
            Ty ty = col.syms.get(new Sym(e.head)).first.get(i);
            Set<Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>>> z = infer_good(arg, Chc.inLeft(ty), col, pre, js, vars);
            List<List<Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>>>> l2 = new LinkedList<>();
            for (List<Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>>> old : l) {
                // //System.out.println("old " + old);
                for (Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>> y : z) {
                    if (y.third.equals(Chc.inLeft(ty))) {
                        // //System.out.println("z z");
                        l2.add(Util.append(old, Util.singList(y)));
                    }
                }
            }
            l = l2;
        }
        outer: for (List<Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>>> outcome : l) {
            // //System.out.println("outcome " + outcome);
            List<Term<Ty, En, Sym, Fk, Att, Gen, Sk>> w = outcome.stream().map(x -> x.first).collect(Collectors.toList());
            Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Sym(new Sym(e.head), w);
            Ctx<Var, Chc<Ty, En>> ret2 = new Ctx<>();
            for (Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>> ctx0 : outcome) {
                if (!ctx0.second.agreeOnOverlap(ret2) || !ctx0.second.agreeOnOverlap(Ctx.fromNullable(vars))) {
                    // //System.out.println("xxx ");
                    continue outer;
                }
                // //System.out.println("yyy");
                ret2.map.putAll(ctx0.second.map);
            }
            for (int i = 0; i < e.args.size(); i++) {
                RawTerm arg = e.args.get(i);
                // //System.out.println("2arx " + arg);
                Chc<Ty, En> ty = Chc.inLeft(col.syms.get(new Sym(e.head)).first.get(i));
                Var v = new Var((String) arg.head);
                if (vars.keySet().contains(v)) {
                    // //System.out.println("a " + v);
                    if (ret2.containsKey(v) && !ret2.get(v).equals(ty)) {
                        // //System.out.println("b " + v);
                        continue;
                    } else if (!ret2.containsKey(v)) {
                        // //System.out.println("c " + v);
                        ret2.put(new Var(e.args.get(i).head), ty);
                    }
                }
            }
            Chc<Ty, En> ret3 = Chc.inLeft(col.syms.get(new Sym(e.head)).second);
            if (expected != null && !expected.equals(ret3)) {
            // //System.out.println("d " );
            } else {
                // //System.out.println("e " );
                if (ret2.agreeOnOverlap(Ctx.fromNullable(vars))) {
                    ret.add(new Triple<>(ret1, ret2, ret3));
                }
            }
        }
    }
    for (En en : col.ens) {
        if (col.fks.containsKey(new Fk(en, e.head)) && e.args.size() == 1 && e.annotation == null) {
            for (Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>> outcome : infer_good(e.args.get(0), Chc.inRight(col.fks.get(new Fk(en, e.head)).first), col, pre, js, vars)) {
                Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Fk(new Fk(en, e.head), outcome.first);
                // System.out.println("trying " + en + " and " + e.head);
                Ctx<Var, Chc<Ty, En>> ret2 = new Ctx<>(outcome.second.map);
                Var v = new Var(e.args.get(0).head);
                Chc<Ty, En> ty = Chc.inRight(col.fks.get(new Fk(en, e.head)).first);
                if (vars.keySet().contains(v)) {
                    if (ret2.containsKey(v) && !ret2.get(v).equals(ty)) {
                        // System.out.println("no1");
                        continue;
                    } else if (!ret2.containsKey(v)) {
                        ret2.put(new Var(e.args.get(0).head), ty);
                    }
                }
                Chc<Ty, En> ret3 = Chc.inRight(col.fks.get(new Fk(en, e.head)).second);
                Chc<Ty, En> argt = Chc.inRight(col.fks.get(new Fk(en, e.head)).first);
                if (expected != null && !expected.equals(ret3)) {
                } else {
                    if (argt.equals(outcome.third)) {
                        if (ret2.agreeOnOverlap(Ctx.fromNullable(vars))) {
                            ret.add(new Triple<>(ret1, ret2, ret3));
                        } else {
                        // System.out.println("b3");
                        }
                    } else {
                    // System.out.println("c3");
                    }
                }
            }
        }
        if (col.atts.containsKey(new Att(en, e.head)) && e.args.size() == 1 && e.annotation == null) {
            // System.out.println("x " + e);
            for (Triple<Term<Ty, En, Sym, Fk, Att, Gen, Sk>, Ctx<Var, Chc<Ty, En>>, Chc<Ty, En>> outcome : infer_good(e.args.get(0), Chc.inRight(col.atts.get(new Att(en, e.head)).first), col, pre, js, vars)) {
                // System.out.println("y " + outcome);
                Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Att(new Att(en, e.head), outcome.first);
                Ctx<Var, Chc<Ty, En>> ret2 = new Ctx<>(outcome.second.map);
                Var v = new Var(e.args.get(0).head);
                Chc<Ty, En> ty = Chc.inRight(col.atts.get(new Att(en, e.head)).first);
                if (vars.keySet().contains(v)) {
                    if (ret2.containsKey(v) && !ret2.get(v).equals(ty)) {
                        continue;
                    } else if (!ret2.containsKey(v)) {
                        // System.out.println("b " + v);
                        ret2.put(v, ty);
                    }
                }
                Chc<Ty, En> ret3 = Chc.inLeft(col.atts.get(new Att(en, e.head)).second);
                Chc<Ty, En> argt = Chc.inRight(col.atts.get(new Att(en, e.head)).first);
                if (expected != null && !expected.equals(ret3)) {
                // System.out.println("d " + v);
                } else {
                    // System.out.println("e " + v);
                    if (argt.equals(outcome.third)) {
                        // System.out.println("f " + v);
                        if (ret2.agreeOnOverlap(Ctx.fromNullable(vars))) {
                            ret.add(new Triple<>(ret1, ret2, ret3));
                        }
                    }
                }
            }
        }
    }
    if (col.gens.containsKey(new Gen(e.head)) && e.args.isEmpty() && e.annotation == null) {
        Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Gen(new Gen(e.head));
        Chc<Ty, En> ret3 = Chc.inRight(col.gens.get(new Gen(e.head)));
        if (expected != null && !expected.equals(ret3)) {
        } else {
            ret.add(new Triple<>(ret1, new Ctx<>(), ret3));
        }
    }
    if (col.sks.containsKey(new Sk(e.head)) && e.args.isEmpty() && e.annotation == null) {
        Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Sk(new Sk(e.head));
        Chc<Ty, En> ret3 = Chc.inLeft(col.sks.get(new Sk(e.head)));
        if (expected != null && !expected.equals(ret3)) {
        } else {
            ret.add(new Triple<>(ret1, new Ctx<>(), ret3));
        }
    }
    if (e.args.isEmpty() && e.annotation != null) {
        Ty ty = new Ty(e.annotation);
        Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Obj(js.parse(ty, e.head), ty);
        Chc<Ty, En> ret3 = Chc.inLeft(ty);
        if (expected != null && !expected.equals(ret3)) {
        } else {
            ret.add(new Triple<>(ret1, new Ctx<>(), ret3));
        }
    }
    // as primitive - only if not a variable/generator/etc in scope i.e. none above fired
    if (e.args.isEmpty() && e.annotation == null && ret.isEmpty()) {
        for (Ty ty : col.tys) {
            if (expected != null && !expected.equals(Chc.inLeft(ty))) {
                continue;
            }
            try {
                Term<Ty, En, Sym, Fk, Att, Gen, Sk> ret1 = Term.Obj(js.parse(ty, e.head), ty);
                Chc<Ty, En> ret3 = Chc.inLeft(ty);
                if (expected != null && !expected.equals(ret3)) {
                // System.out.println("zzz");
                } else {
                    ret.add(new Triple<>(ret1, new Ctx<>(), ret3));
                // System.out.println("added " + ret + " and " + ret3);
                }
            } catch (Exception ex) {
                if (expected != null) {
                    ex.printStackTrace();
                // throw ex;
                }
            // //ex.printStackTrace();
            }
        }
    }
    return ret;
}
Also used : Att(catdata.aql.exp.SchExpRaw.Att) Ctx(catdata.Ctx) En(catdata.aql.exp.SchExpRaw.En) List(java.util.List) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet) Ty(catdata.aql.exp.TyExpRaw.Ty) Fk(catdata.aql.exp.SchExpRaw.Fk) Sym(catdata.aql.exp.TyExpRaw.Sym) LinkedList(java.util.LinkedList) Triple(catdata.Triple) Gen(catdata.aql.exp.InstExpRaw.Gen) Sk(catdata.aql.exp.InstExpRaw.Sk) Chc(catdata.Chc)

Example 69 with Triple

use of catdata.Triple in project fql by CategoricalData.

the class OplParser method program.

public static Program<OplExp> program(String s) {
    List<Triple<String, Integer, OplExp>> ret = new LinkedList<>();
    List decls = (List) program.parse(s);
    sugarForNat = false;
    for (Object d : decls) {
        org.jparsec.functors.Pair pr = (org.jparsec.functors.Pair) d;
        Tuple3 decl = (Tuple3) pr.b;
        toProgHelper(pr.a.toString(), s, ret, decl);
    }
    sugarForNat = false;
    return new Program<>(ret, null);
}
Also used : Triple(catdata.Triple) Program(catdata.Program) Tuple3(org.jparsec.functors.Tuple3) List(java.util.List) LinkedList(java.util.LinkedList) LinkedList(java.util.LinkedList) Pair(catdata.Pair)

Example 70 with Triple

use of catdata.Triple in project fql by CategoricalData.

the class OplParser method toSCHEMA.

private static OplExp toSCHEMA(Object ox) {
    Tuple4 oy = (Tuple4) ox;
    String ts = (String) oy.d;
    org.jparsec.functors.Pair newobj = (org.jparsec.functors.Pair) oy.b;
    List<String> imports = newobj.a == null ? new LinkedList<>() : (List<String>) ((org.jparsec.functors.Pair) newobj.a).b;
    Tuple5 t = (Tuple5) newobj.b;
    Tuple3 a = (Tuple3) t.a;
    Tuple3 b = (Tuple3) t.b;
    Tuple3 c = (Tuple3) t.c;
    Tuple3 d = (Tuple3) t.d;
    Tuple3 e = (Tuple3) t.e;
    Set<String> sorts = a == null ? new HashSet<>() : new HashSet<>((Collection<String>) a.b);
    List<Tuple3> symbolsE0 = b == null ? new LinkedList<>() : (List<Tuple3>) b.b;
    List<Tuple3> symbolsA0 = c == null ? new LinkedList<>() : (List<Tuple3>) c.b;
    List<org.jparsec.functors.Pair> equationsE0 = c == null ? new LinkedList<>() : (List<org.jparsec.functors.Pair>) d.b;
    List<org.jparsec.functors.Pair> equationsA0 = c == null ? new LinkedList<>() : (List<org.jparsec.functors.Pair>) e.b;
    Map<String, Pair<List<String>, String>> symbolsE = new HashMap<>();
    Map<String, Pair<List<String>, String>> symbolsA = new HashMap<>();
    Map<String, Pair<List<String>, String>> symbolsEA = new HashMap<>();
    Map<String, Integer> prec = new HashMap<>();
    for (Tuple3 x : symbolsE0) {
        String dom;
        List<String> args;
        if (x.c instanceof Tuple3) {
            Tuple3 zzz = (Tuple3) x.c;
            args = (List<String>) zzz.a;
            dom = (String) zzz.c;
        } else {
            dom = (String) x.c;
            args = new LinkedList<>();
        }
        List<org.jparsec.functors.Pair> name0s = (List<org.jparsec.functors.Pair>) x.a;
        for (org.jparsec.functors.Pair name0 : name0s) {
            String name = (String) name0.a;
            if (name0.b != null) {
                org.jparsec.functors.Pair zzz = (org.jparsec.functors.Pair) name0.b;
                Integer i = (Integer) zzz.b;
                prec.put(name, i);
            }
            if (symbolsE.containsKey(name)) {
                throw new DoNotIgnore("Duplicate symbol " + name);
            }
            symbolsE.put(name, new Pair<>(args, dom));
            symbolsEA.put(name, new Pair<>(args, dom));
        }
    }
    for (Tuple3 x : symbolsA0) {
        String dom;
        List<String> args;
        if (x.c instanceof Tuple3) {
            Tuple3 zzz = (Tuple3) x.c;
            args = (List<String>) zzz.a;
            dom = (String) zzz.c;
        } else {
            dom = (String) x.c;
            args = new LinkedList<>();
        }
        List<org.jparsec.functors.Pair> name0s = (List<org.jparsec.functors.Pair>) x.a;
        for (org.jparsec.functors.Pair name0 : name0s) {
            String name = (String) name0.a;
            if (name0.b != null) {
                org.jparsec.functors.Pair zzz = (org.jparsec.functors.Pair) name0.b;
                Integer i = (Integer) zzz.b;
                prec.put(name, i);
            }
            if (symbolsA.containsKey(name)) {
                throw new DoNotIgnore("Duplicate symbol " + name);
            }
            symbolsA.put(name, new Pair<>(args, dom));
            symbolsEA.put(name, new Pair<>(args, dom));
        }
    }
    // /////////////
    List<Triple<OplCtx<String, String>, OplTerm<String, String>, OplTerm<String, String>>> equationsE = new LinkedList<>();
    List<Triple<OplCtx<String, String>, OplTerm<String, String>, OplTerm<String, String>>> equationsA = new LinkedList<>();
    for (org.jparsec.functors.Pair<Tuple3, Tuple3> x : equationsE0) {
        List<Tuple3> fa = x.a == null ? new LinkedList<>() : (List<Tuple3>) x.a.b;
        OplCtx<String, String> ctx = toCtx(fa);
        Tuple3 eq = x.b;
        OplTerm lhs = toTerm(ctx.names(), consts(symbolsEA), eq.a, false);
        OplTerm rhs = toTerm(ctx.names(), consts(symbolsEA), eq.c, false);
        equationsE.add(new Triple<>(ctx, lhs, rhs));
    }
    for (org.jparsec.functors.Pair<Tuple3, Tuple3> x : equationsA0) {
        List<Tuple3> fa = x.a == null ? new LinkedList<>() : (List<Tuple3>) x.a.b;
        OplCtx<String, String> ctx = toCtx(fa);
        Tuple3 eq = x.b;
        OplTerm lhs = toTerm(ctx.names(), consts(symbolsEA), eq.a, false);
        OplTerm rhs = toTerm(ctx.names(), consts(symbolsEA), eq.c, false);
        equationsA.add(new Triple<>(ctx, lhs, rhs));
    }
    OplSCHEMA0 ret = new OplSCHEMA0(prec, sorts, symbolsE, symbolsA, equationsE, equationsA, ts);
    ret.imports = new HashSet<>(imports);
    return ret;
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) List(java.util.List) LinkedList(java.util.LinkedList) Pair(catdata.Pair) LinkedList(java.util.LinkedList) OplSCHEMA0(catdata.opl.OplExp.OplSCHEMA0) Tuple4(org.jparsec.functors.Tuple4) Triple(catdata.Triple) Tuple5(org.jparsec.functors.Tuple5) Tuple3(org.jparsec.functors.Tuple3) Collection(java.util.Collection)

Aggregations

Triple (catdata.Triple)116 Pair (catdata.Pair)93 LinkedList (java.util.LinkedList)84 List (java.util.List)75 HashMap (java.util.HashMap)65 Map (java.util.Map)49 HashSet (java.util.HashSet)47 LinkedHashMap (java.util.LinkedHashMap)36 Set (java.util.Set)28 Chc (catdata.Chc)22 Util (catdata.Util)18 En (catdata.aql.exp.SchExpRaw.En)18 Ty (catdata.aql.exp.TyExpRaw.Ty)18 Ctx (catdata.Ctx)17 Sym (catdata.aql.exp.TyExpRaw.Sym)17 Collectors (java.util.stream.Collectors)17 Att (catdata.aql.exp.SchExpRaw.Att)16 Fk (catdata.aql.exp.SchExpRaw.Fk)16 Tuple3 (org.jparsec.functors.Tuple3)16 Quad (catdata.Quad)13