#include #include #include #include #include "conf.h" #include "chart.h" #include "dag.h" #include "tdl.h" #include "timer.h" //#define HIDEOUS_HACK #undef HIDEOUS_HACK /* essentially, QC extracts a skeleton type tree from a dag * and performs *tree*-unification on that skeleton before * the full dag-unifier is allowed to run */ int qc_size; struct qc { struct type *entries[1]; }; int __qc_use_heap = 0; #ifdef HIDEOUS_HACK static struct type *olist, *minus, *_0dlist; static struct type *no_punct, *no_punctuation_min; #endif extern int gen_qc; int eqc_timer = -1; qc_extractor_function qc_extractor = NULL; struct type *dg_type(struct dg *d) { extern unsigned int generation; // this is called on the results of dg_hop... safe to assume it is dereferenced. if(d->gen == generation)return d->type; return d->xtype; } struct qc *extract_qc(struct dg *d) { struct qc *q; long i, iter, sp = 0, dst, fn, onf; int *lp; if(gen_qc)return NULL; static int init = 0; if(!init) { init = 1; qc_extractor = dynamically_link_qc_extractor(); #ifdef HIDEOUS_HACK olist = lookup_type("*olist*"); assert(olist); minus = lookup_type("-"); assert(minus); _0dlist = lookup_type("0-dlist"); assert(_0dlist); no_punct = lookup_type("no_punct"); assert(no_punct); no_punctuation_min = lookup_type("no_punctuation_min"); assert(no_punctuation_min); #endif eqc_timer = new_timer("extract QC"); } if(!__qc_use_heap) q = slab_alloc(sizeof(struct type*)*qc_size); else q = malloc(sizeof(struct type*)*qc_size); //static int hop_timer = -1; //if(hop_timer==-1)hop_timer = new_timer("qc hop"); //start_timer(hop_timer); IFCLOCK( start_timer(eqc_timer);) //IFCLOCK( clock_t T = clock();for(iter=0;iter<100;iter++) ) assert(qc_extractor != NULL); qc_extractor(q->entries, d); //IFCLOCK( extract_clock += clock() - T; ) IFCLOCK( stop_timer(eqc_timer, 1); ) //stop_timer(hop_timer, qc_size * iter); return q; } struct qc *extract_qc_arg(struct dg *d, int arg) { struct dg *to; int i = 0; if(arg>=0) { to = dg_hop(d, 0); // 0 is guaranteed to be ARGS while(to && ixtype->name); exit(-1); } } else to = d; return extract_qc(to); } IFCLOCK(unsigned long long glb_clock;) IFCLOCK(unsigned long long glb_count;) int quickcheck(struct qc *a, struct qc *b) { int i, qcs = qc_size; struct type **ae = a->entries, **be = b->entries; //static int glb_timer = -1; //if(glb_timer==-1)glb_timer =new_timer("qc-glb"); //start_timer(glb_timer); //int J; //for(J=0;J<10;J++) for(i=0;ientries[20] == olist && b->entries[9]==minus)return -1; // if(b->entries[20] == olist && a->entries[9]==minus)return -1; for(i=0;ientries[h->dlist]==_0dlist) if(a->entries[h->list] && a->entries[h->last] && !glb(a->entries[h->list], a->entries[h->last])) return -1; if(a->entries[h->dlist]==_0dlist) if(b->entries[h->list] && b->entries[h->last] && !glb(b->entries[h->list], b->entries[h->last])) return -1; } for(i=0;ientries[h->list] == olist && b->entries[h->opt]==minus)return -1; if(b->entries[h->list] == olist && a->entries[h->opt]==minus)return -1; } // if(a->entries[10] == olist && b->entries[11]==minus)return -1; // if(b->entries[10] == olist && a->entries[11]==minus)return -1; /*if(a->entries[punct_slot] == no_punctuation_min && b->entries[lpunct_slot] && !glb(b->entries[lpunct_slot], no_punct))return -1; if(a->entries[punct_slot] == no_punctuation_min && b->entries[rpunct_slot] && !glb(b->entries[rpunct_slot], no_punct))return -1; if(b->entries[punct_slot] == no_punctuation_min && a->entries[lpunct_slot] && !glb(a->entries[lpunct_slot], no_punct))return -1; if(b->entries[punct_slot] == no_punctuation_min && a->entries[rpunct_slot] && !glb(a->entries[rpunct_slot], no_punct))return -1;*/ #endif return 0; } /* int equiv_quickcheck(struct qc *a, struct qc *b, int *Fw, int *Bk) { int i; struct type *ta, *tb, *g; int fw = 1, bw = 1; for(i=0;ientries[i]; tb = b->entries[i]; if(ta && tb && (ta!=tb)) { g = glb(ta, tb); if(g!=tb)fw = 0; if(g!=ta)bw = 0; } if(ta && !tb)fw = 0; if(tb && !ta)bw = 0; if(!fw && !bw) { *Fw = fw; *Bk = bw; return -1; } } *Fw = fw; *Bk = bw; return 0; }*/ int equiv_quickcheck(struct qc *a, struct qc *b, int *Fw, int *Bk, int *Gz) { int i; struct type *ta, *tb, *g; int fw = 1, bw = 1, gz = 1; for(i=0;ientries[i]; tb = b->entries[i]; int eqtypes = (ta==tb) || (ta && tb && ta->tnum==-1 && tb->tnum==-1 && !strcmp(ta->name, tb->name)); if(ta && tb && !eqtypes) { g = glb(ta, tb); if(g!=tb)fw = 0; if(g!=ta)bw = 0; if(g!=ta && g!=tb)gz = 0; } if(ta && !tb)fw = 0; if(tb && !ta)bw = 0; if(!fw && !bw && !gz) break; } *Fw = fw; *Bk = bw; *Gz = gz; return (!fw && !bw && !gz)?1:0; } struct qc *copy_qc(struct qc *in) { if(!in)return 0; struct qc *out = slab_alloc(sizeof(struct type*)*qc_size); return memcpy(out, in, sizeof(struct type*)*qc_size); } struct type *qc_type_n(struct qc *in, int n) { if(n <0 || n >=qc_size)return NULL; return in->entries[n]; } // qc generator static struct qc_path { struct path path; unsigned long long failures; int rank; } *paths; static int npaths; extern int upathgl; extern struct type *uglb; void gqc_count_failure(struct path path) { int i; for(i=0;ipath.count && ipath.count;i++) if(a->path.fnums[i] != b->path.fnums[i]) return a->path.fnums[i] - b->path.fnums[i]; return a->path.count - b->path.count; } qsort(pth, count, sizeof(struct qc_path), (int(*)(const void*,const void*))lexcmp); if(hops) { int i, hc = pth[0].path.count; // just count hops for(i=1;ifailures - a->failures; } qsort(paths, npaths, sizeof(struct qc_path), (int(*)(const void*,const void*))qcpcmp); for(i=0;i0)?(1-filtration[j-1]):1.0); c_unify = k_unify * unify_attempts_pass_rf * ((i>0)?(1-filtration[i-1]):1.0); c_extract = k_hop * ((i>0)?nhops[i-1]:0) * (unify_attempts_success - unify_attempts_bad_orth); cost = c_check + c_unify + c_extract; /*printf("%3d paths: %10f = %10f + %10f + %10f\n", i, cost, c_check, c_unify, c_extract); if(ixtype->name[0]=='"')n++; for(i=0;inarcs;i++) n += qc_count_strings(arcs[i]); return n; } void recursive_write_qccode(struct dg *qc, FILE *f, int count) { qc = p_dereference_dg(qc); if(qc->xtype->name[0]=='"') { int k = atoi(qc->xtype->name+1); if(k >= count) { fprintf(stderr, "quickcheck instance compiler: find path %d but only thought there were %d paths\n", k, count); exit(-1); } fprintf(f, "REC(%d)\n", k); } int i; struct dg **arcs = DARCS(qc); for(i=0;inarcs;i++) { extern char **fnames; fprintf(f, "PUSH(%s) ", fnames[qc->label[i]]); recursive_write_qccode(arcs[i], f, count); fprintf(f, "POP "); } } void write_qccode_from_pet_instance(struct dg *petqc, FILE *f) { struct dg *mainqc = dg_hop(petqc, lookup_fname("ARGS")); assert(mainqc != NULL || !"Quickcheck instance had no ARGS feature"); int n = qc_count_strings(mainqc); fprintf(f, "QC_SIZE(%d)\n", n); recursive_write_qccode(mainqc, f, n); }