https://github.com/mirefek/geo_logic
Raw File
Tip revision: def2dac4c2a0cf80d50a8346d8e54caa3de81921 authored by mirefek on 23 January 2020, 09:39:53 UTC
lies_on visualisation
Tip revision: def2dac
primitive_tools.py
import geo_object
from geo_object import *
from tools import *
import primitive_constr
import primitive_pred
from itertools import product

def angle_num_comp(obj_sum, frac_const):
    return (float(frac_const%1) + obj_sum)%1
def angle_num_check(obj_sum, frac_const):
    return eps_identical((float(frac_const%1) + obj_sum+0.5)%1, 0.5)
def angle_postulate(model, *args): model.add_angle_equation(*args)
def angle_check(model, *args): return model.check_angle_equation(*args)

def ratio_num_comp(obj_sum, frac_const):
    return np.array((np.log(float(frac_const)), 0),
                    dtype = float) + obj_sum
def ratio_num_check(obj_sum, frac_const):
    return eps_zero(np.array((np.log(float(frac_const)), 0),
                             dtype = float) + obj_sum)
def ratio_postulate(model, *args): model.add_ratio_equation(*args)
def ratio_check(model, *args): return model.check_ratio_equation(*args)

def intypes_iter(f):
    in_varnames = f.__code__.co_varnames[:f.__code__.co_argcount]
    in_types = [f.__annotations__.get(name, None) for name in in_varnames]
    in_types_tups = [
        (Line, Circle) if t == PointSet else (t,)
        for t in in_types
    ]
    for in_types in product(*in_types_tups):
        if None not in in_types: yield in_types
        else:
            for joker_t in (Point, Line, Circle, Angle, Ratio):
                yield tuple(joker_t if t is None else t for t in in_types)

def make_primitive_tool_dict():
    d = dict()

    # load predicates
    for name, f in primitive_pred.__dict__.items():
        if not callable(f) or name.startswith('_') or name in geo_object.__dict__:
            continue
        for in_types in intypes_iter(f):
            if name == "lies_on": willingness = 0
            else: willingness = 1
            d[name, in_types] = PrimitivePred(f, in_types, name = name, willingness = willingness)

    # load constructions and movable tools
    for fname, f in primitive_constr.__dict__.items():
        if not callable(f) or fname.startswith('_') or fname in geo_object.__dict__:
            continue
        out_type = f.__annotations__['return']
        for in_types in intypes_iter(f):
            if fname in ("intersection_remoter", "intersection0") and in_types[:2] == (Line, Line):
                continue
            out_types = (out_type,)
            if in_types[:2] == (float, float):
                name = fname
                tool = MovableTool(f, in_types[2:], out_types, name = name)
                if fname == "point_on":
                    tool.add_effect(d["lies_on", out_types+in_types[2:]])
                    pass
            else:
                name = "prim__"+fname
                tool = PrimitiveConstr(f, in_types, out_types, name = name)

            d[name, in_types] = tool

    # dimension tools
    DimCompute(Angle, angle_num_comp, angle_postulate, "angle_compute", d)
    DimCompute(Ratio, ratio_num_comp, ratio_postulate, "ratio_compute", d)
    DimPred(Angle, angle_num_check, angle_postulate, angle_check, "angle_pred", d)
    DimPred(Ratio, ratio_num_check, ratio_postulate, ratio_check, "ratio_pred", d)

    # equality tool
    eq_tool = EqualObjects()
    for t in (Point, Line, Circle, Angle, Ratio):
        d[eq_tool.name, (t,t)] = eq_tool

    return d

if __name__ == "__main__":
    d = make_primitive_tool_dict()
    for key, value in d.items():
        if isinstance(key, tuple):
            name, in_types = key
            in_types = ' '.join(x.__name__ for x in in_types)
        else:
            name, in_types = key, "???"
        out_types = ' '.join(x.__name__ for x in value.out_types)
        if out_types == '': out_types = '()'
        print("{} : {} -> {}".format(name, in_types, out_types))
back to top