def __init__(cls, *args, **kws): setattr(C, cls.__name__, cls) # --- assumptions --- # initialize default_assumptions dictionary default_assumptions = {} for k,v in cls.__dict__.iteritems(): if not k.startswith('is_'): continue # this is not an assumption (e.g. is_Integer) if k[3:] not in AssumeMeths._assume_defined: continue k = k[3:] if isinstance(v,(bool,int,long,type(None))): if v is not None: v = bool(v) default_assumptions[k] = v # XXX maybe we should try to keep ._default_premises out of class ? # XXX __slots__ in class ? cls._default_premises = default_assumptions for base in cls.__bases__: try: base_premises = base._default_premises except AttributeError: continue # no ._default_premises is ok for k,v in base_premises.iteritems(): # if an assumption is already present in child, we should ignore base # e.g. Integer.is_integer=T, but Rational.is_integer=F (for speed) if k in default_assumptions: continue default_assumptions[k] = v # deduce all consequences from default assumptions -- make it complete xass = AssumeMeths._assume_rules.deduce_all_facts(default_assumptions) # and store completed set into cls -- this way we'll avoid rededucing # extensions of class default assumptions each time on instance # creation -- we keep it prededuced already. cls.default_assumptions = xass # let's store new derived assumptions back into class. # this will result in faster access to this attributes. # # Timings # ------- # # a = Integer(5) # %timeit a.is_zero -> 20 us (without this optimization) # %timeit a.is_zero -> 2 us (with this optimization) # # # BTW: it is very important to study the lessons learned here -- # we could drop Basic.__getattr__ completely (!) # # %timeit x.is_Add -> 2090 ns (Basic.__getattr__ present) # %timeit x.is_Add -> 825 ns (Basic.__getattr__ absent) # # so we may want to override all assumptions is_<xxx> methods and # remove Basic.__getattr__ # first we need to collect derived premises derived_premises = {} for k,v in xass.iteritems(): if k not in default_assumptions: derived_premises[k] = v cls._derived_premises = derived_premises for k,v in xass.iteritems(): assert v == cls.__dict__.get('is_'+k, v), (cls,k,v) # NOTE: this way Integer.is_even = False (inherited from Rational) # NOTE: the next code blocks add 'protection-properties' to overcome this setattr(cls, 'is_'+k, v) # protection e.g. for Initeger.is_even=F <- (Rational.is_integer=F) for base in cls.__bases__: try: base_derived_premises = base._derived_premises except AttributeError: continue # no ._derived_premises is ok for k,v in base_derived_premises.iteritems(): if ('is_'+k) not in cls.__dict__: is_k = make__get_assumption(cls.__name__, k) setattr(cls, 'is_'+k, property(is_k))
def __init__(cls, *args, **kws): setattr(C, cls.__name__, cls) # --- assumptions --- # initialize default_assumptions dictionary default_assumptions = {} for k, v in cls.__dict__.iteritems(): if not k.startswith('is_'): continue # this is not an assumption (e.g. is_Integer) if k[3:] not in AssumeMeths._assume_defined: continue k = k[3:] if isinstance(v, (bool, int, long, type(None))): if v is not None: v = bool(v) default_assumptions[k] = v # XXX maybe we should try to keep ._default_premises out of class ? # XXX __slots__ in class ? cls._default_premises = default_assumptions for base in cls.__bases__: try: base_premises = base._default_premises except AttributeError: continue # no ._default_premises is ok for k, v in base_premises.iteritems(): # if an assumption is already present in child, we should ignore base # e.g. Integer.is_integer=T, but Rational.is_integer=F (for speed) if k in default_assumptions: continue default_assumptions[k] = v # deduce all consequences from default assumptions -- make it complete xass = AssumeMeths._assume_rules.deduce_all_facts(default_assumptions) # and store completed set into cls -- this way we'll avoid rededucing # extensions of class default assumptions each time on instance # creation -- we keep it prededuced already. cls.default_assumptions = xass # let's store new derived assumptions back into class. # this will result in faster access to this attributes. # # Timings # ------- # # a = Integer(5) # %timeit a.is_zero -> 20 us (without this optimization) # %timeit a.is_zero -> 2 us (with this optimization) # # # BTW: it is very important to study the lessons learned here -- # we could drop Basic.__getattr__ completely (!) # # %timeit x.is_Add -> 2090 ns (Basic.__getattr__ present) # %timeit x.is_Add -> 825 ns (Basic.__getattr__ absent) # # so we may want to override all assumptions is_<xxx> methods and # remove Basic.__getattr__ # first we need to collect derived premises derived_premises = {} for k, v in xass.iteritems(): if k not in default_assumptions: derived_premises[k] = v cls._derived_premises = derived_premises for k, v in xass.iteritems(): assert v == cls.__dict__.get('is_' + k, v), (cls, k, v) # NOTE: this way Integer.is_even = False (inherited from Rational) # NOTE: the next code blocks add 'protection-properties' to overcome this setattr(cls, 'is_' + k, v) # protection e.g. for Initeger.is_even=F <- (Rational.is_integer=F) for base in cls.__bases__: try: base_derived_premises = base._derived_premises except AttributeError: continue # no ._derived_premises is ok for k, v in base_derived_premises.iteritems(): if ('is_' + k) not in cls.__dict__: is_k = make__get_assumption(cls.__name__, k) setattr(cls, 'is_' + k, property(is_k))