📄 rules.c
字号:
rule = (RULE*)malloc(sizeof(RULE) +(maxcond-1) *sizeof(COND)); if (!rule) return NULL; /* allocate memory and */ rule->attset = attset; /* initialize fields */ rule->set = NULL; rule->id = -1; rule->supp = rule->conf = 0; rule->condvsz = maxcond; rule->condcnt = 0; rule->head.att = -1; /* invalidate head attribute */ rule->head.op = 0; /* and comparison operator */ return rule; /* return the created rule */} /* r_create() *//*--------------------------------------------------------------------*/void r_delete (RULE *rule){ /* --- delete a rule */ assert(rule); /* check the function argument */ if (rule->set) /* remove rule from containing set */ rs_rulerem(rule->set, rule->id); if (rule->head.op == R_IN) /* delete value vetors */ free(rule->head.val.p); /* from the head and */ r_condrem(rule, -1); /* from all conditions */ free(rule); /* delete rule body */} /* r_delete() *//*--------------------------------------------------------------------*/int r_copy (RULE *dst, RULE *src){ /* --- copy a rule */ int i; /* loop variable */ COND *sc, *dc; /* to traverse the conditions */ assert(src && dst /* check the function arguments */ && (dst->condvsz >= src->condcnt)); if (dst->head.op == R_IN) /* delete value vectors */ free(dst->head.val.p); /* from the head and */ r_condrem(dst, -1); /* from all conditions */ if (_condcopy(&dst->head, &src->head) != 0) return -1; /* copy the rule head */ dst->supp = src->supp; /* copy rule support */ dst->conf = src->conf; /* and confidence */ dst->condcnt = src->condcnt; /* traverse conditions */ sc = src->conds; dc = dst->conds; for (i = src->condcnt; --i >= 0; dc++, sc++) if (_condcopy(dc, sc) != 0) { dst->condcnt -= i+1; return -1; } return 0; /* copy conditions and return 'ok' */} /* r_copy() *//*--------------------------------------------------------------------*/int r_headset (RULE *rule, int att, int op, INST *val){ /* --- set the head of a rule */ void *vec; /* buffer for value vector */ INST dummy; /* dummy for head deletion */ assert(rule /* check the function arguments */ && (att >= 0) && (att < as_attcnt(rule->attset))); if (att < 0) { op = 0; val = &dummy; } vec = (rule->head.op == R_IN) ? rule->head.val.p : NULL; if (_condset(&rule->head, att, op, val) != 0) return -1; /* set new rule head and */ if (vec) free(vec); /* delete value vector (if any) */ return 0; /* and return 'ok' */} /* r_headset() *//*--------------------------------------------------------------------*/int r_condadd (RULE *rule, int att, int op, INST *val){ /* --- add a condition to a rule */ int i; /* loop variable */ int min, max; /* min./max. condition to adapt */ COND new; /* new condition (to add to the rule) */ COND *cond, *dst; /* to traverse conditions */ int cmp; /* result of value comparison */ int *set; /* buffer for value subset */ unsigned int bits; /* buffer for bitflags */ assert(rule /* check the function arguments */ && (att >= 0) && (att < as_attcnt(rule->attset))); if (_condset(&new, att, op, val) != 0) return -1; /* create new condition */ /* --- check compatibility of new condition --- */ min = -1; max = -2; /* initialize condition indices */ cond = rule->conds; /* traverse conditions */ for (i = 0; i < rule->condcnt; i++, cond++) { if (cond->att != att) /* if condition refers to a */ continue; /* different attribute, skip it */ if ((new.op >= R_IN) /* if there is a subset operator */ || (cond->op >= R_IN)) { /* in one of the conditions */ if (_isect(&new, cond) == 0) break; } else { /* if there is no subset operator */ cmp = (new.val.f > cond->val.f) ? R_GT : (new.val.f < cond->val.f) ? R_LT : R_EQ; if (cmp == R_EQ) { /* if values in conditions are equal, */ new.op &= cond->op; /* combine condition operators */ if (new.op <= 0) break; } /* and check the result */ else { /* if values in conditions differ */ if (cond->op & cmp) { /* if new value in same direction */ if (!(new.op & cmp)) /* if new operator has opp. dir., */ continue; } /* condition merging is not possible */ else { /* if new value in opp. direction */ if (new.op & cmp) /* if new operator has opp. dir., */ break; /* the conditions are incompatible */ new.op = cond->op; /* if the new operator has same dir., */ new.val = cond->val; /* the old condition is stronger, */ } /* so replace the new condition */ } /* (the new condition is modified to */ } /* represent the combined conditions) */ cond->op |= MARK; /* mark condition to replace */ if (min < 0) min = i; /* and note condition index for */ max = i; /* later adaption of the conditions */ } if (i < rule->condcnt) { /* if new condition is not compatible */ cond = rule->conds; /* remove all condition markers */ for (i = min; i <= max; i++) (cond++)->op &= ~MARK; if (new.op == R_IN) free(new.val.p); return -2; /* delete a value vector rep. */ } /* and abort the function */ /* --- simplify new condition --- */ if (new.op == R_BF) { /* if bitflag rep. in new condition, */ for (i = 0, bits = new.val.i; bits; i++, bits >>= 1) if (bits & 1) break; /* find the index of the first value */ if (bits && !(bits >> 1)) { /* if there is only one value */ new.op = R_EQ; new.val.i = i; } } /* simplify condition */ if (new.op == R_IN) { /* if vector rep. in new condition, */ set = new.val.p; /* check the value vector */ if (*set == 1) { /* if there is only one value, */ new.op = R_EQ; new.val.i = set[1]; free(set); } /* simplify cond. and delete vector */ else { /* if there is more than one value, */ for (bits = 0, i = *set++; --i >= 0; ) { if (*set > MSBIT) break;/* traverse the value vector */ bits |= 1 << *set++; /* and try to convert it to */ } /* a bitflag representation */ if (i < 0) { /* if the conversion was successful, */ free(new.val.p); /* delete the value vector */ new.op = R_BF; new.val.i = bits; } /* replace the condition by */ } /* a subset test that uses */ } /* a bitflag representation */ /* --- add new condition --- */ if (min < 0) { /* if no adaptable condition found */ if (rule->condcnt >= rule->condvsz) return -3; /* check the number of conditions */ rule->conds[rule->condcnt] = new; return rule->condcnt++; /* insert new condition into the rule */ } /* and return the condition index */ /* --- adapt old condition(s) --- */ cond = rule->conds +min; /* get a pointer to the condition */ cond->op &= ~MARK; /* to adapt and remove the marker */ if (new.op != R_NE) { /* if to adapt condition, */ if (cond->op == R_IN) free(cond->val.p); *cond = new; /* delete an existing value vector */ } /* and replace the condition */ if (max <= min) return min; /* if only one cond. to adapt, abort */ dst = ++cond; /* traverse remaining conditions */ for (i = rule->condcnt -min; --i > 0; cond++) { if (!(cond->op & MARK)) /* group together all */ *dst++ = *cond; /* unmarked conditions */ else if ((cond->op & ~MARK) == R_IN) free(cond->val.p); /* delete an existing value vector */ } /* from the marked conditions */ rule->condcnt = (int)(dst -rule->conds); return min; /* set new number of conditions and */} /* r_condadd() */ /* return index of changed condition *//*--------------------------------------------------------------------*/void r_condrem (RULE *rule, int index){ /* --- remove a cond. from a rule */ int i; /* loop variable */ COND *cond; /* to traverse the conditions */ assert(rule /* check the function arguments */ && (index < rule->condcnt)); if (index < 0) { /* if to remove all conditions, */ cond = rule->conds; /* delete value vectors */ for (i = rule->condcnt; --i >= 0; cond++) if (cond->op == R_IN) free(cond->val.p); rule->condcnt = 0; } /* clear condition counter */ else { /* if to remove one condition */ cond = rule->conds +index; /* get the condition and delete */ if (cond->op == R_IN) free(cond->val.p); /* value vector */ for (i = --rule->condcnt -index; --i >= 0; cond++) *cond = cond[1]; /* shift conditions to fill the gap */ } /* left by the deleted condition */} /* r_condrem() *//*--------------------------------------------------------------------*/void r_condsort (RULE *rule){ /* --- sort rule conditions */ assert(rule); /* check the function argument */ qsort(rule->conds, rule->condcnt, sizeof(COND), _condcmp);} /* r_condsort() */ /* sort the rule conditions *//*--------------------------------------------------------------------*/int r_check (RULE *rule){ /* --- check applicability of a rule */ int i, t; /* loop variable, attribute type */ COND *cond; /* to traverse the conditions */ ATT *att; /* to traverse the attributes */ INST *val; /* to traverse the values */ double f; /* buffer for comparisons */ int *p; /* to traverse an identifier vector */ assert(rule); /* check the function argument */ for (cond = rule->conds, i = rule->condcnt; --i >= 0; cond++) { att = as_att(rule->attset, cond->att); val = att_inst(att); /* traverse the conditions and */ t = att_type(att); /* get the corresponding attribute */ if (t == AT_SYM) { /* if the attribute is symbolic */ if (cond->op == R_EQ) { /* equality to a value */ if (cond->val.i != val->i) return i; } else if (cond->op == R_BF) { /* bit flag represented set */ if ((val->i >= 32) || !(cond->val.i & (1 << val->i))) return i; } /* check whether the bit is set */ else { /* identifier vector represented set */ for (t = *(p = cond->val.p); --t >= 0; ) if (*++p == val->i) break; if (t < 0) return i; /* traverse the identifiers and */ } } /* try to find the value */ else { /* if the attribute is numeric */ if (t == AT_INT) f = (double)val->i; /* get the value from */ else f = (double)val->f; /* the attribute set */ switch (cond->op) { /* evaluate the comparison operator */ case R_EQ: if (f != cond->val.f) return i; break; case R_LT: if (f >= cond->val.f) return i; break; case R_GT: if (f <= cond->val.f) return i; break; case R_LE: if (f > cond->val.f) return i; break; case R_GE: if (f < cond->val.f) return i; break; default : if (f == cond->val.f) return i; break; } /* if the comparison fails, */ } /* return the index of */ } /* the condition that fails */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -