https://github.com/mirefek/geo_logic
Raw File
Tip revision: c8c9b715cae0acfb07585c25659b1333d075cc5b authored by mirefek on 25 July 2021, 19:43:55 UTC
bugfix
Tip revision: c8c9b71
primitive_tools.py
import geo_object
from geo_object import *
from tools import *
import primitive_constr
import primitive_pred
from itertools import product

"""
The main function here is "make_primitive_tool_dict" which
creates the initial dictionary of tools. The dictionary
is of the format
  (name, tool_name_or_none) -> tool,
and it is then used in parse.py for loading basic.gl
"""

### Functions for specific instances of DimCompute and DimPred

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(logic, *args): logic.add_angle_equation(*args)
def angle_check(logic, *args): return logic.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(logic, *args): logic.add_ratio_equation(*args)
def ratio_check(logic, *args): return logic.check_ratio_equation(*args)

### A few more tools

class CustomRatio(Tool):
    def __init__(self):
        Tool.__init__(self, (float, float), (), (Ratio,), "custom_ratio")
    def run(self, hyper_params, obj_args, logic, strictness):
        return logic.add_obj(Ratio(hyper_params)),
class CustomAngle(Tool):
    def __init__(self):
        Tool.__init__(self, (float,), (), (Angle,), "custom_angle")
    def run(self, hyper_params, obj_args, logic, strictness):
        float_angle, = hyper_params
        return logic.add_obj(Angle(float_angle)),

"""
The following function is used for analyzing functions in
primitive_constr.py and primitive_pred.py. The input types
of such a function are anotated. They are mostly of the five
bacis types -- Point, Line, Circle, Angle, Ratio.
However, PointSet can be also there,
or an input that is not annotated at all in the case of "not_eq".
The function intypes_iter yields all the possible input types as
tuples of the five basic geometrical types.
"""
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 == "intersecting" and in_types[:2] == (Line, Line):
                continue  # exception, skip intersecting : L L ->
            if name == "lies_on": willingness = 0
            else: willingness = 1
            d[name, in_types] = PrimitivePred(f, in_types, name = name, willingness = willingness)

    # load constructions
    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):
            out_types = (out_type,)
            name = "prim__"+fname
            tool = PrimitiveConstr(f, in_types, out_types, name = name)

            d[name, in_types] = tool

    # dimension tools
    dim_tools = [
        DimCompute(Angle, angle_num_comp, angle_postulate, "angle_compute"),
        DimCompute(Ratio, ratio_num_comp, ratio_postulate, "ratio_compute"),
        DimPred(Angle, angle_num_check, angle_postulate, angle_check, "angle_pred"),
        DimPred(Ratio, ratio_num_check, ratio_postulate, ratio_check, "ratio_pred"),
        CustomRatio(),
        CustomAngle(),
    ]
    for tool in dim_tools: tool.add_to_dict(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