static void set_copy_match(vset_t dst, vset_t src, int p_len, int* proj, int*match) { LACE_ME; // Create bdd of "match" // Assumption: proj is ordered (if not, you get bad performance) sylvan_deref(dst->bdd); sylvan_gc_disable(); BDD match_bdd = sylvan_true; for (int i=p_len;i-->0;) { uint32_t b = match[i]; for (int j=fddbits;j-->0;) { BDD val = sylvan_ithvar(src->dom->vec_to_bddvar[proj[i]*fddbits+j]); if (!(b&1)) val = sylvan_not(val); match_bdd = sylvan_and(val, match_bdd); b >>= 1; } } sylvan_ref(match_bdd); sylvan_gc_enable(); dst->bdd = sylvan_ref(sylvan_and(match_bdd, src->bdd)); sylvan_deref(match_bdd); }
/** * Enumerate all states that match partial state <match> * <match> is p_len long * <proj> is a list of integers, containing indices of each match integer */ static void set_enum_match(vset_t set, int p_len, int* proj, int* match, vset_element_cb cb, void* context) { LACE_ME; // Create bdd of "match" // Assumption: proj is ordered (if not, you get bad performance) sylvan_gc_disable(); BDD match_bdd = sylvan_true; for (int i=p_len;i-->0;) { uint32_t b = match[i]; for (int j=fddbits;j-->0;) { BDD val = sylvan_ithvar(set->dom->vec_to_bddvar[proj[i]*fddbits+j]); if (!(b&1)) val = sylvan_not(val); match_bdd = sylvan_and(val, match_bdd); b >>= 1; } } sylvan_ref(match_bdd); sylvan_gc_enable(); BDD old = match_bdd; match_bdd = sylvan_ref(sylvan_and(match_bdd, set->bdd)); sylvan_deref(old); int vec[set->vector_size]; memset(vec, 0, sizeof(int)*set->vector_size); set_enum_do(match_bdd, set->variables, vec, 0, cb, context); sylvan_deref(match_bdd); }
static void rel_load(FILE* f, vrel_t rel) { if (rel->bdd) sylvan_deref(rel->bdd); if (rel->vec_to_bddvar) RTfree(rel->vec_to_bddvar); if (rel->prime_vec_to_bddvar) RTfree(rel->prime_vec_to_bddvar); if (rel->variables) sylvan_deref(rel->variables); if (rel->prime_variables) sylvan_deref(rel->prime_variables); if (rel->all_variables) sylvan_deref(rel->all_variables); sylvan_serialize_fromfile(f); size_t bdd; fread(&bdd, sizeof(size_t), 1, f); rel->bdd = sylvan_ref(sylvan_serialize_get_reversed(bdd)); fread(&rel->vector_size, sizeof(size_t), 1, f); rel->vec_to_bddvar = (BDDVAR*)RTmalloc(sizeof(BDDVAR) * fddbits * rel->vector_size); rel->prime_vec_to_bddvar = (BDDVAR*)RTmalloc(sizeof(BDDVAR) * fddbits * rel->vector_size); fread(rel->vec_to_bddvar, sizeof(BDDVAR), rel->vector_size*fddbits, f); fread(rel->prime_vec_to_bddvar, sizeof(BDDVAR), rel->vector_size*fddbits, f); sylvan_gc_disable(); LACE_ME; rel->variables = sylvan_ref(sylvan_set_fromarray(rel->vec_to_bddvar, fddbits * rel->vector_size)); rel->prime_variables = sylvan_ref(sylvan_set_fromarray(rel->prime_vec_to_bddvar, fddbits * rel->vector_size)); rel->all_variables = sylvan_ref(sylvan_set_addall(rel->prime_variables, rel->variables)); sylvan_gc_enable(); }
TASK_3(BDD, union_par, BDD*, arr, int, first, int, last) { if (first == last) return arr[first]; BDD left, right; int mid = (first+last)/2; // check: last == first + 1 if (first == mid) { // we have 2 return CALL(sylvan_ite, arr[first], sylvan_true, arr[last], 0); // or } if (mid+1 == last) { // we have 3 left = sylvan_ref(CALL(sylvan_ite, arr[first], sylvan_true, arr[mid], 0)); // or BDD result = CALL(sylvan_ite, left, sylvan_true, arr[last], 0); sylvan_deref(left); return result; } SPAWN(union_par, arr, first, mid); right = sylvan_ref(CALL(union_par, arr, mid+1, last)); left = sylvan_ref(SYNC(union_par)); BDD result = CALL(sylvan_ite, left, sylvan_true, right, 0); sylvan_deref(left); sylvan_deref(right); return result; }
/** * Destroy a set. * The set must be created first with set_create */ static void set_destroy(vset_t set) { sylvan_deref(set->bdd); sylvan_deref(set->projection); sylvan_deref(set->variables); RTfree(set->vec_to_bddvar); RTfree(set); }
/** * Destroy a relation. */ static void rel_destroy(vrel_t rel) { sylvan_deref(rel->bdd); sylvan_deref(rel->variables); sylvan_deref(rel->prime_variables); sylvan_deref(rel->all_variables); RTfree(rel->vec_to_bddvar); RTfree(rel->prime_vec_to_bddvar); RTfree(rel); }
/** * Add all elements of src to dst and remove all elements that were in dst already from src * in other words: newDst = dst + src * newSrc = src - dst */ static void set_zip(vset_t dst, vset_t src) { LACE_ME; BDD tmp1 = dst->bdd; BDD tmp2 = src->bdd; dst->bdd = sylvan_ref(sylvan_or(tmp1, tmp2)); src->bdd = sylvan_ref(sylvan_diff(tmp2, tmp1)); sylvan_deref(tmp1); sylvan_deref(tmp2); }
/** * Adds e to set */ static void set_add(vset_t set, const int* e) { LACE_ME; // For some reason, we never get projected e, we get full e. BDD bdd = state_to_bdd(e, set->dom->shared.size, set->dom->vec_to_bddvar, set->projection); BDD prev = set->bdd; set->bdd = sylvan_ref(sylvan_or(prev, bdd)); sylvan_deref(bdd); sylvan_deref(prev); }
/** * Returns the BDD corresponding to state e according to the projection of set. * Order: [0]<[1]<[n] and hi < lo */ static BDD state_to_bdd(const int* e, size_t vec_length, BDDVAR* vec_to_bddvar, BDD projection) { LACE_ME; check_state(e, vec_length); size_t varcount = vec_length * fddbits; char* cube = (char*)alloca(varcount*sizeof(char)); memset(cube, 0, varcount*sizeof(char)); size_t i; int j; for (i=0;i<vec_length;i++) { for (j=0;j<fddbits;j++) { if (e[i] & (1<<(fddbits-j-1))) cube[i*fddbits+j] = 1; } } // check if in right order for (i=0;i<varcount-1;i++) assert(vec_to_bddvar[i]<vec_to_bddvar[i+1]); BDDSET meta = sylvan_set_fromarray(vec_to_bddvar, varcount); BDD bdd = sylvan_ref(sylvan_cube(meta, cube)); BDD proj = sylvan_ref(sylvan_exists(bdd, projection)); sylvan_deref(bdd); return proj; }
/** * Copy a set from src to dst. * Assumption: projections are equal. */ static void set_copy(vset_t dst, vset_t src) { assert(dst->projection == src->projection); sylvan_deref(dst->bdd); dst->bdd = sylvan_ref(src->bdd); }
/** * Add (src, dst) to the relation * Note that src and dst are PROJECTED (small) vectors! */ static void rel_add(vrel_t rel, const int *src, const int *dst) { LACE_ME; BDD bdd_src = state_to_bdd(src, rel->vector_size, rel->vec_to_bddvar, sylvan_false); BDD bdd_dst = state_to_bdd(dst, rel->vector_size, rel->prime_vec_to_bddvar, sylvan_false); BDD part = sylvan_ref(sylvan_and(bdd_src, bdd_dst)); sylvan_deref(bdd_src); sylvan_deref(bdd_dst); BDD old = rel->bdd; rel->bdd = sylvan_ref(sylvan_or(rel->bdd, part)); sylvan_deref(old); sylvan_deref(part); }
/** * Calculate dst = dst /\ src */ static void set_intersect(vset_t dst, vset_t src) { LACE_ME; BDD old = dst->bdd; dst->bdd = sylvan_ref(sylvan_and(dst->bdd, src->bdd)); sylvan_deref(old); }
/** * Calculate dst = next(src, rel) */ static void set_next(vset_t dst, vset_t src, vrel_t rel) { LACE_ME; assert(dst->projection == src->projection); sylvan_deref(dst->bdd); dst->bdd = sylvan_ref(sylvan_relprod_paired(src->bdd, rel->bdd, rel->all_variables)); }
/** * Calculate dst = dst - src */ static void set_minus(vset_t dst, vset_t src) { LACE_ME; BDD old = dst->bdd; dst->bdd = sylvan_ref(sylvan_diff(dst->bdd, src->bdd)); sylvan_deref(old); }
/** * Calculate dst = dst + src */ static void set_union(vset_t dst, vset_t src) { LACE_ME; BDD old = dst->bdd; dst->bdd = sylvan_ref(sylvan_or(dst->bdd, src->bdd)); sylvan_deref(old); }
/** * Calculate projection of src onto dst */ static void set_project(vset_t dst,vset_t src) { LACE_ME; sylvan_deref(dst->bdd); if (dst->projection != 0) dst->bdd = sylvan_exists(src->bdd, dst->projection); else dst->bdd = src->bdd; sylvan_ref(dst->bdd); }
/** * Calculate dst = prev(src, rel) intersected with univ */ static void set_prev(vset_t dst, vset_t src, vrel_t rel, vset_t univ) { LACE_ME; assert(dst->projection == src->projection); sylvan_deref(dst->bdd); dst->bdd = sylvan_ref(sylvan_relprod_paired_prev(src->bdd, rel->bdd, rel->all_variables)); set_intersect(dst, univ); }
/** * Returns 1 if e is a member of set, 0 otherwise */ static int set_member(vset_t set, const int* e) { LACE_ME; // For some reason, we never get projected e, we get full e. BDD bdd = state_to_bdd(e, set->dom->shared.size, set->dom->vec_to_bddvar, set->projection); int res = sylvan_and(set->bdd, bdd) != sylvan_false ? 1 : 0; sylvan_deref(bdd); return res; }
JNIEXPORT void JNICALL Java_jsylvan_JSylvan_deref(JNIEnv *env, jclass cl, jlong bdd) { sylvan_deref(bdd); }
/** * Clear a set. */ static void set_clear(vset_t set) { sylvan_deref(set->bdd); set->bdd = sylvan_false; }