is_not_nothing = make_generic_operator(1, "is_not_nothing", lambda x: not is_nothing(x)) is_anything = lambda x: True def _default_merge(content, increment): debug("Merging {content} and {increment}...".format(**vars())) if content == increment: return content else: return Contradiction('{content} != {increment}'.format(**vars())) merge = make_generic_operator(2, "merge", _default_merge) def implies(v1, v2): return v1 == merge(v1, v2) assign_operation("merge", lambda content, increment: content, [is_not_nothing, is_nothing]) assign_operation("merge", lambda content, increment: increment, [is_nothing, is_not_nothing]) assign_operation("merge", lambda contradiction, _: contradiction, [is_contradictory, is_anything]) assign_operation("merge", lambda _, contradiction: contradiction, [is_anything, is_contradictory])
def _ensure_inside(interval, number): if interval.contains(number): return number else: return Contradiction("{number} is not inside {interval}".format(**vars())) def is_number(thing): return isinstance(thing, (int, float, complex)) def is_interval(thing): return isinstance(thing, Interval) assign_operation("merge", _merge_intervals, [is_interval, is_interval]) assign_operation("merge", lambda content, increment: _ensure_inside(increment, content), [is_number, is_interval]) assign_operation("merge", lambda content, increment: _ensure_inside(content, increment), [is_interval, is_number]) assign_operation("sqrt", lambda i: Interval(sqrt(i.low), sqrt(i.high)), [is_interval]) def coercing(coercer, f): return lambda *args: f(*[coercer(a) for a in args]) def to_interval(thing): if isinstance(thing, Interval): return thing
def _default_merge(content, increment): debug("Merging {content} and {increment}...".format(**vars())) if content == increment: return content else: return Contradiction('{content} != {increment}'.format(**vars())) merge = make_generic_operator(2, "merge", _default_merge) def implies(v1, v2): return v1 == merge(v1, v2) assign_operation("merge", lambda content, increment: content, [is_not_nothing, is_nothing] ) assign_operation("merge", lambda content, increment: increment, [is_nothing, is_not_nothing] ) assign_operation("merge", lambda contradiction, _: contradiction, [is_contradictory, is_anything] ) assign_operation("merge", lambda _, contradiction: contradiction, [is_anything, is_contradictory] )
if interval.contains(number): return number else: return Contradiction( '{number} is not inside {interval}'.format(**vars())) def is_number(thing): return isinstance(thing, (int, float, complex)) def is_interval(thing): return isinstance(thing, Interval) assign_operation("merge", _merge_intervals, [is_interval, is_interval]) assign_operation("merge", lambda content, increment: _ensure_inside(increment, content), [is_number, is_interval]) assign_operation("merge", lambda content, increment: _ensure_inside(content, increment), [is_interval, is_number]) assign_operation("sqrt", lambda i: Interval(sqrt(i.low), sqrt(i.high)), [is_interval]) def coercing(coercer, f): return lambda *args: f(*[coercer(a) for a in args])
return content elif merged_value == increment.value: # New information overrides old information return increment else: # Interesting merge, need both provenances return Supported(merged_value, content.support | increment.support) def is_flat(thing): return isinstance(thing, (int, float, complex, Interval)) def is_supported(thing): return isinstance(thing, Supported) assign_operation("is_nothing", lambda t: t.value is None, [is_supported] ) assign_operation("merge", _merge_supporteds, [is_supported, is_supported] ) assign_operation("merge", lambda s, f: _merge_supporteds(s, Supported(f)), [is_supported, is_flat] ) assign_operation("merge", lambda f, s: _merge_supporteds(Supported(f), s), [is_flat, is_supported]
# New information overrides old information return increment else: # Interesting merge, need both provenances return Supported(merged_value, content.support | increment.support) def is_flat(thing): return isinstance(thing, (int, float, complex, Interval)) def is_supported(thing): return isinstance(thing, Supported) assign_operation("is_nothing", lambda t: t.value is None, [is_supported]) assign_operation("merge", _merge_supporteds, [is_supported, is_supported]) assign_operation("merge", lambda s, f: _merge_supporteds(s, Supported(f)), [is_supported, is_flat]) assign_operation("merge", lambda f, s: _merge_supporteds(Supported(f), s), [is_flat, is_supported]) def supported_unpacking(function): def merge_supports(*supporteds): supports = [supported.support for supported in supporteds] merged_sets = reduce(operator.or_, supports, set()) return Support(merged_sets)