def _eval_is_even(self): is_integer = self.is_integer if is_integer: return fuzzy_not(self._eval_is_odd()) elif is_integer == False: return False
def _eval_is_real(self): im_count = 0 re_not = False for t in self.args: if t.is_imaginary: im_count += 1 continue t_real = t.is_real if t_real: continue elif fuzzy_not(t_real): re_not = True else: return None if re_not: return False return im_count % 2 == 0
def _eval_is_real(self): im_count = 0 re_not = False for t in self.args: if t.is_imaginary: im_count += 1 continue t_real = t.is_real if t_real: continue elif fuzzy_not(t_real): re_not = True else: return None if re_not: return False return (im_count % 2 == 0)
def deduce_all_facts(self, facts, base=None): """Deduce all facts from known facts ({} or [] of (k,v)) ********************************************* * This is the workhorse, so keep it *fast*. * ********************************************* base -- previously known facts (must be: fully deduced set) attention: base is modified *in place* /optional/ providing `base` could be needed for performance reasons -- we don't want to spend most of the time just re-deducing base from base (e.g. #base=50, #facts=2) """ # keep frequently used attributes locally, so we'll avoid extra # attribute access overhead rels = self.rels beta_rules = self.beta_rules if base is not None: new_facts = base else: new_facts = {} # XXX better name ? def x_new_facts(keys, v): for k in keys: if k in new_facts and new_facts[k] is not None: assert new_facts[k] == v, \ ('inconsistency between facts', new_facts, k, v) continue else: new_facts[k] = v if type(facts) is dict: fseq = facts.iteritems() else: fseq = facts while True: beta_maytrigger = set() # --- alpha chains --- #print '**' for k,v in fseq: #print '--' # first, convert name to be not a not-name if k[:1] == '!': k = name_not(k) v = fuzzy_not(v) #new_fact(k, v) if k in new_facts: assert new_facts[k] is None or new_facts[k] == v, \ ('inconsistency between facts', new_facts, k, v) # performance-wise it is important not to fire implied rules # for already-seen fact -- we already did them all. continue else: new_facts[k] = v # some known fact -- let's follow its implications if v is not None: # lookup routing tables try: tt, tf, tbeta, ft, ff, fbeta = rels[k] except KeyError: pass else: # Now we have routing tables with *all* the needed # implications for this k. This means we do not have to # process each implications recursively! # XXX this ^^^ is true only for alpha chains # k=T if v: x_new_facts(tt, True) # k -> i x_new_facts(tf, False) # k -> !i beta_maytrigger.update(tbeta) # k=F else: x_new_facts(ft, True) # !k -> i x_new_facts(ff, False) # !k -> !i beta_maytrigger.update(fbeta) # --- beta chains --- # if no beta-rules may trigger -- it's an end-of-story if not beta_maytrigger: break #print '(β) MayTrigger: %s' % beta_maytrigger fseq = [] # XXX this is dumb proof-of-concept trigger -- we'll need to optimize it # let's see which beta-rules to trigger for bidx in beta_maytrigger: bcond,bimpl = beta_rules[bidx] # let's see whether bcond is satisfied for bk in bcond.args: try: if bk[:1] == '!': bv = fuzzy_not(new_facts[bk[1:]]) else: bv = new_facts[bk] except KeyError: break # fact not found -- bcond not satisfied # one of bcond's condition does not hold if not bv: break else: # all of bcond's condition hold -- let's fire this beta rule #print '(β) Trigger #%i (%s)' % (bidx, bimpl) if bimpl[:1] == '!': bimpl = bimpl[1:] v = False else: v = True fseq.append( (bimpl,v) ) return new_facts
def deduce_all_facts(self, facts, base=None): """Deduce all facts from known facts ({} or [] of (k,v)) ********************************************* * This is the workhorse, so keep it *fast*. * ********************************************* base -- previously known facts (must be: fully deduced set) attention: base is modified *in place* /optional/ providing `base` could be needed for performance reasons -- we don't want to spend most of the time just re-deducing base from base (e.g. #base=50, #facts=2) """ # keep frequently used attributes locally, so we'll avoid extra # attribute access overhead rels = self.rels beta_rules = self.beta_rules if base is None: new_facts = {} else: new_facts = base def x_new_facts(keys, v): for k in keys: if k in new_facts and new_facts[k] is not None: assert new_facts[k] == v, \ ('inconsistency between facts', new_facts, k, v) continue else: new_facts[k] = v if type(facts) is dict: fseq = facts.iteritems() else: fseq = facts while True: beta_maytrigger = set() # --- alpha chains --- for k, v in fseq: # first, convert name to be not a not-name if k[:1] == '!': k = name_not(k) v = fuzzy_not(v) #new_fact(k, v) if k in new_facts: assert new_facts[k] is None or new_facts[k] == v, \ ('inconsistency between facts', new_facts, k, v) # performance-wise it is important not to fire implied rules # for already-seen fact -- we already did them all. continue else: new_facts[k] = v # some known fact -- let's follow its implications if v is not None: # lookup routing tables try: tt, tf, tbeta, ft, ff, fbeta = rels[k] except KeyError: pass else: # Now we have routing tables with *all* the needed # implications for this k. This means we do not have to # process each implications recursively! # XXX this ^^^ is true only for alpha chains # k=T if v: x_new_facts(tt, True) # k -> i x_new_facts(tf, False) # k -> !i beta_maytrigger.update(tbeta) # k=F else: x_new_facts(ft, True) # !k -> i x_new_facts(ff, False) # !k -> !i beta_maytrigger.update(fbeta) # --- beta chains --- # if no beta-rules may trigger -- it's an end-of-story if not beta_maytrigger: break fseq = [] # let's see which beta-rules to trigger for bidx in beta_maytrigger: bcond, bimpl = beta_rules[bidx] # let's see whether bcond is satisfied for bk in bcond.args: try: if bk[:1] == '!': bv = fuzzy_not(new_facts[bk[1:]]) else: bv = new_facts[bk] except KeyError: break # fact not found -- bcond not satisfied # one of bcond's condition does not hold if not bv: break else: # all of bcond's condition hold -- let's fire this beta rule if bimpl[:1] == '!': bimpl = bimpl[1:] v = False else: v = True fseq.append((bimpl, v)) return new_facts