Exemple #1
0
def parse_core(primitive_parse):
    all_intersections = _get_all_intersections(primitive_parse,
                                               params.INTERSECTION_EPS)
    clustered_intersections = _cluster_intersections(
        all_intersections, params.KMEANS_RADIUS_THRESHOLD)
    intersections = dict(enumerate(clustered_intersections))
    assignment = {}
    point_variables = {}
    for idx in intersections.keys():
        id_ = "point_%d" % idx
        vs = VariableSignature(id_, 'point')
        point_variables[idx] = FormulaNode(vs, [])
        assignment[id_] = intersections[idx]

    radius_variables = {}
    circles = _get_circles(primitive_parse, intersections)
    for point_idx, d in circles.iteritems():
        radius_variables[point_idx] = {}
        for radius_idx in d.keys():
            id_ = "radius_%d_%d" % (point_idx, radius_idx)
            vs = VariableSignature(id_, 'number')
            radius_variables[point_idx][radius_idx] = FormulaNode(vs, [])
            assignment[id_] = circles[point_idx][radius_idx].radius
    core_parse = CoreParse(primitive_parse, intersections, point_variables,
                           circles, radius_variables, assignment)
    return core_parse
Exemple #2
0
    def tester(node):
        if node.signature.valence == 2 and node.is_singular():
            child_node = node.children[0]
            if child_node.signature in graph.nodes() and len(
                    graph.edges(child_node.signature)) == 1:
                nbr = graph[child_node.signature].keys()[0]
                if is_valid_relation(node.signature, nbr, 1):
                    nbr_node = FormulaNode(nbr, [])
                    return FormulaNode(node.signature,
                                       [node.children[0], nbr_node])

            # insert dummy variable
            nbr = VariableSignature("dummy",
                                    node.signature.arg_types[1],
                                    name=node.signature.arg_types[1])
            nbr_node = FormulaNode(nbr, [])
            return FormulaNode(node.signature, [node.children[0], nbr_node])

        if node.signature not in firsts:
            return None
        if node.parent is None:
            raise Exception
        if isinstance(node.parent,
                      FormulaNode) and (node.parent.signature.valence == 1
                                        or node.parent.is_plural()):
            args = [
                FormulaNode(nbr, []) for nbr in graph[node.signature]
                if is_valid_relation(node.parent.signature, nbr, node.index)
            ]
            if len(args) == 0:
                return None
            return SetNode([node] + args)
        return None
def parse_confident_formulas(graph_parse):
    eps = 0.5  # to be updated by the scale of the diagram
    core_parse = graph_parse.core_parse
    line_graph = graph_parse.line_graph
    circle_dict = graph_parse.circle_dict
    confident_formulas = []

    for from_key, to_key, data in line_graph.edges(data=True):
        line_variable = FormulaNode(signatures['Line'], [
            core_parse.point_variables[from_key],
            core_parse.point_variables[to_key]
        ])
        points = data['points']
        for point_key, point in points.iteritems():
            point_variable = core_parse.point_variables[point_key]
            variable_node = FormulaNode(signatures['PointLiesOnLine'],
                                        [point_variable, line_variable])
            confident_formulas.append(variable_node)

    for center_key, d in circle_dict.iteritems():
        for radius_key, dd in d.iteritems():
            circle_variable = FormulaNode(signatures['Circle'], [
                core_parse.point_variables[center_key],
                core_parse.radius_variables[center_key][radius_key]
            ])
            points = dd['points']
            for point_key, point in points.iteritems():
                point_variable = core_parse.point_variables[point_key]
                variable_node = FormulaNode(signatures['PointLiesOnCircle'],
                                            [point_variable, circle_variable])
                confident_formulas.append(variable_node)
    """
    for key, angle in get_all_instances(graph_parse, 'angle', True).iteritems():
        r = FormulaNode(signatures['Pi'], [])/2.0
        formula = FormulaNode(signatures['Ge'], [r, FormulaNode(signatures['MeasureOf'], [angle])])
        tv = graph_parse.core_parse.evaluate(formula)
        if tv.norm == 0:
            confident_formulas.append(formula)
    """

    # Just enforce non collapsing between known labels?
    """
    for from_point, to_point in itertools.combinations(graph_parse.core_parse.point_variables.values(), 2):
        line = FormulaNode(signatures['Line'], [from_point, to_point])
        length = FormulaNode(signatures['SquaredLengthOf'], [line])
        threshold = FormulaNode(FunctionSignature(str(eps**2), 'number', []), [])
        formula = FormulaNode(signatures['Ge'], [length, threshold])
        confident_formulas.append(formula)
    """

    return confident_formulas
Exemple #4
0
def _update(formulas, variable):
    assert isinstance(formulas, set)
    assert isinstance(variable, FormulaNode)
    assert isinstance(variable.signature, VariableSignature)
    for from_, to, id_ in high_order_type_inheritances:
        if from_ == variable.return_type:
            new_variable = FormulaNode(
                VariableSignature(variable.signature.id,
                                  to,
                                  name=variable.signature.name), [])
            formula = FormulaNode(signatures[id_], [new_variable])
            formulas.add(formula)
            return new_variable
    return variable
def _ground_formula(match_parse, formula, threshold=0.5):
    if formula.is_leaf():
        if formula.is_grounded(
                match_parse.graph_parse.core_parse.variable_assignment.keys()):
            out = formula
        else:
            out = _ground_variable(match_parse, formula)
    else:
        children = [
            _ground_formula(match_parse, child) for child in formula.children
        ]
        if isinstance(formula, SetNode):
            if False:  #formula.children[0].signature.return_type == 'truth':
                new_children = []
                for child in children:
                    if child.has_constant():
                        new_children.append(child)
                    else:
                        tv = match_parse.graph_parse.core_parse.evaluate(child)
                        if tv.conf > threshold:
                            new_children.append(child)
                out = SetNode(new_children)
            else:
                out = SetNode(children)
        else:
            out = FormulaNode(formula.signature, children)
    final = _apply_distribution(out)
    return final
    def add(self, formula_node, assignment=None):
        if assignment is None:
            assignment = {}
        if not isinstance(formula_node, Node):
            return formula_node

        if formula_node.is_leaf():
            assert isinstance(formula_node, FormulaNode)
            sig = formula_node.signature
            if isinstance(sig, FunctionSignature):
                return formula_node
            elif formula_node.signature.id in self.named_entities:
                return self.named_entities[sig.id]
            elif formula_node.return_type == "point":
                init = None
                if sig.id in assignment:
                    init = assignment[sig.id]
                return self.point(sig.id, init)
            elif formula_node.return_type == "number":
                init = None
                if sig.id in assignment:
                    init = assignment[sig.id]
                return self.number(sig.id, init)
            else:
                raise Exception()
        else:
            children = [self.add(child) for child in formula_node.children]
            if isinstance(formula_node, FormulaNode):
                formula = FormulaNode(formula_node.signature, children)
                if formula_node.signature.id in ['Line', 'Circle']:
                    self.entities.append(formula)
            else:
                formula = SetNode(children)
            return formula
def _get_arc_graph(core_parse, circle, circle_variable, circle_points):
    """
    Directional arc graph.

    :param core_parse:
    :param circle:
    :return:
    """
    eps = CIRCLE_EPS
    arc_graph = nx.DiGraph()
    for key0, key1 in itertools.permutations(circle_points, 2):
        p0, p1 = circle_points[key0], circle_points[key1]
        arc = instantiators['arc'](circle, p0, p1)
        v0, v1 = core_parse.point_variables[key0], core_parse.point_variables[
            key1]
        var = FormulaNode(signatures['Arc'], [circle_variable, v0, v1])
        if instance_exists(core_parse, arc):
            arc_points = {}
            for key in set(circle_points).difference({key0, key1}):
                point = circle_points[key]
                if distance_between_arc_and_point(arc, point) <= eps:
                    arc_points[key] = point
            arc_graph.add_edge(key0,
                               key1,
                               instance=arc,
                               points=arc_points,
                               variable=var)
    return arc_graph
Exemple #8
0
def _get_all_polygons(graph_parse, name, n, is_variable):
    polygons = {}
    frozensets = set()
    line_graph = graph_parse.line_graph
    for keys in itertools.permutations(graph_parse.intersection_points, n):
        if frozenset(keys) in frozensets:
            continue
        if not all(line_graph.has_edge(keys[idx-1], key) for idx, key in enumerate(keys)):
            continue

        angles = []
        for idx, key in enumerate(keys):
            angles.extend(_get_angles(graph_parse, False, keys[idx-2], keys[idx-1], key).values())
        if len(angles) < n:
            continue

        convex = polygon_is_convex(tuple(graph_parse.intersection_points[key] for key in keys))

        if is_variable:
            points = list(graph_parse.core_parse.point_variables[key] for key in keys)
        else:
            points = list(graph_parse.intersection_points[key] for key in keys)
        if not convex:
            points.reverse()
        # polygon = instantiators[name](*points)
        polygon = FormulaNode(signatures[name.capitalize()], points)
        polygon_key = tuple(keys)
        polygons[polygon_key] = polygon
        frozensets.add(frozenset(keys))
    return polygons
def _get_circle_dict(core_parse):
    """
    A dictionary of dictionaries, where key of the top dictionary is center point.
    The bottom dictionary contains radii (if multiple circles exist with the same center).

    :param core_parse:
    :return:
    """
    # FIXME : this needs to be changed
    eps = CIRCLE_EPS
    assert isinstance(core_parse, CoreParse)
    circle_dict = {}

    for point_key, dd in core_parse.circles.iteritems():
        d = {}
        for radius_key, circle in dd.iteritems():
            points = {}
            for key in core_parse.intersection_points:
                point = core_parse.intersection_points[key]
                if distance_between_circle_and_point(circle, point) <= eps:
                    points[key] = point
            center_var = core_parse.point_variables[point_key]
            radius_var = core_parse.radius_variables[point_key][radius_key]
            circle_var = FormulaNode(signatures['Circle'],
                                     [center_var, radius_var])
            d[radius_key] = {
                'instance': circle,
                'points': points,
                'variable': circle_var
            }
        if len(d) > 0:
            circle_dict[point_key] = d
    return circle_dict
def _get_angles(graph_parse,
                is_variable,
                a_key,
                b_key,
                c_key,
                ignore_trivial=True):
    assert isinstance(graph_parse, GraphParse)
    line_graph = graph_parse.line_graph
    if line_graph.has_edge(a_key, b_key) and line_graph.has_edge(b_key, c_key):
        if ignore_trivial:
            # line_a = line_graph[b_key][a_key]['instance']
            a_points = line_graph[b_key][a_key]['points']
            # line_c = line_graph[b_key][c_key]['instance']
            c_points = line_graph[b_key][c_key]['points']
            if c_key in a_points or a_key in c_points:
                return {}
            if line_graph.has_edge(a_key, c_key):
                """
                Removes flat angle (180 degrees)
                """
                b_points = line_graph[a_key][c_key]['points']
                if b_key in b_points:
                    return {}
        if is_variable:
            points = graph_parse.core_parse.point_variables
            a, b, c = points[a_key], points[b_key], points[c_key]
            angle = FormulaNode(signatures['Angle'], [a, b, c])
        else:
            points = graph_parse.intersection_points
            a, b, c = points[a_key], points[b_key], points[c_key]
            angle = instantiators['angle'](a, b, c)
        angle_key = (a_key, b_key, c_key)
        return {angle_key: angle}
    else:
        return {}
def _get_line_graph(core_parse):
    """
    line graph is a non-directional graph.
    Nodes are indexed by intersection points.
    Note that angles, triangles, and quadrilaterals can be parsed from this graph.
    :param core_parse:
    :param eps:
    :return:
    """
    eps = LINE_EPS
    line_graph = nx.Graph()

    for key0, key1 in itertools.combinations(core_parse.intersection_points,
                                             2):
        p0, p1 = core_parse.intersection_points[
            key0], core_parse.intersection_points[key1]
        line = instantiators['line'](p0, p1)
        v0, v1 = core_parse.point_variables[key0], core_parse.point_variables[
            key1]
        var = FormulaNode(signatures['Line'], [v0, v1])
        if instance_exists(core_parse, line):
            points = {}
            for key in set(core_parse.intersection_points).difference(
                {key0, key1}):
                point = core_parse.intersection_points[key]
                if distance_between_line_and_point(line, point) <= eps:
                    points[key] = point
            line_graph.add_edge(key0,
                                key1,
                                instance=line,
                                points=points,
                                variable=var)
    return line_graph
Exemple #12
0
def _apply_distribution_helper(node):
    if not isinstance(node, FormulaNode) or len(node.children) == 0:
        return node
    node = FormulaNode(
        node.signature,
        [_apply_distribution_helper(child) for child in node.children])
    if len(node.children) == 1:
        child_node = node.children[0]
        if isinstance(child_node,
                      SetNode) and node.signature.arg_types[0][0] != '*':
            children = [
                FormulaNode(node.signature, [child])
                for child in child_node.children
            ]
            return SetNode(children)
    elif len(node.children) == 2:
        a_node, b_node = node.children
        if isinstance(
                a_node, SetNode
        ) and node.signature.arg_types[0][0] != '*' and isinstance(
                b_node, SetNode) and node.signature.arg_types[1][0] != '*':
            assert len(a_node.children) == len(b_node.children)
            children = [
                FormulaNode(node.signature,
                            [a_node.children[index], b_node.children[index]])
                for index in range(len(a_node.children))
            ]
            return SetNode(children)
        elif isinstance(
                a_node, SetNode
        ) and node.signature.arg_types[0][0] != '*' and isinstance(
                b_node, FormulaNode):
            children = [
                FormulaNode(node.signature, [child, b_node])
                for child in a_node.children
            ]
            return SetNode(children)
        elif isinstance(a_node, FormulaNode) and isinstance(
                b_node, SetNode) and node.signature.arg_types[1][0] != '*':
            children = [
                FormulaNode(node.signature, [a_node, child])
                for child in b_node.children
            ]
            return SetNode(children)

    return node
 def number(self, name, init=None):
     assert name not in self.variables
     if init is None:
         init = np.random.rand()
     self.variables[name] = init
     vn = FormulaNode(VariableSignature(name, 'number'), [])
     self.named_entities[name] = vn
     return vn
Exemple #14
0
def prefix_to_formula(prefix):
    """

    :param list prefix:
    :return FormulaNode:
    """
    if isinstance(prefix, str):
        if prefix in abbreviations:
            return FormulaNode(signatures[abbreviations[prefix]], [])
        elif is_number(prefix):
            return FormulaNode(FunctionSignature(prefix, 'number', []), [])
        else:
            return FormulaNode(VariableSignature(prefix, 'number'), [])
    else:
        sig = signatures[abbreviations[prefix[0]]]
        children = [prefix_to_formula(child) for child in prefix[1:]]
        for idx, child in enumerate(children):
            child.signature.return_type = sig.arg_types[idx]
            child.return_type = sig.arg_types[idx]
        out = FormulaNode(sig, children)
        return out
Exemple #15
0
def parse_match_formulas(match_parse):
    assert isinstance(match_parse, MatchParse)
    match_atoms = []
    for label, terms in match_parse.match_dict.iteritems():
        for term in terms:
            assert isinstance(term, FormulaNode)
            if issubtype(term.return_type, 'entity'):
                if term.signature.id == "Angle":
                    res = FormulaNode(signatures['Ge'], [
                        FormulaNode(signatures['Pi'], []),
                        FormulaNode(signatures['MeasureOf'], [term])
                    ])
                    match_atoms.append(res)
                continue

            # FIXME : to be obtained by tag model

            left_term = prefix_to_formula(
                expression_parser.parse_prefix(label))
            """
            if is_number(label):
                left_term = FormulaNode(FunctionSignature(label, "number", []), [])
            else:
                vs = VariableSignature(label, 'number')
                left_term = FormulaNode(vs, [])
            """

            atom = FormulaNode(signatures['Equals'], [left_term, term])
            match_atoms.append(atom)

            if term.signature.id == "Div":
                # TODO : this should be only constrained if the observed angle is < 180
                # TODO : In fact, the labeling should be reorganized. (x --> x*\degree)
                res = FormulaNode(signatures['Ge'], [180, left_term])
                match_atoms.append(res)

    return match_atoms
Exemple #16
0
def _get_polygons(graph_parse, name, is_variable, *args):
    # TODO : include ignore_trivial parameter. This ignores area-0 polygons.
    assert isinstance(graph_parse, GraphParse)
    line_graph = graph_parse.line_graph
    if all(line_graph.has_edge(args[idx-1], arg) for idx, arg in enumerate(args)):
        convex = polygon_is_convex(tuple(graph_parse.intersection_points[key] for key in args))

        if is_variable:
            points = list(graph_parse.core_parse.point_variables[key] for key in args)
        else:
            points = list(graph_parse.intersection_points[key] for key in args)
        if not convex:
            points.reverse()
        polygon = FormulaNode(signatures[name.capitalize()], points)
        polygon_key = tuple(args)
        return {polygon_key: polygon}
    else:
        return {}
Exemple #17
0
def _apply_is(is_formulas, core_formulas):
    """
    Given a list of formulas, resolve transitivity by Is relation

    :param formula_nodes:
    :return:
    """
    graph = nx.Graph()
    explicit_sigs = set()
    equal_formulas = []
    for formula_node in is_formulas:
        assert isinstance(formula_node, FormulaNode)
        a_node, b_node = formula_node.children
        a_sig, b_sig = a_node.signature, b_node.signature

        if a_sig.return_type == 'number' or b_sig.return_type == 'number':
            equal_formula = FormulaNode(signatures['Equals'], [a_node, b_node])
            equal_formulas.append(equal_formula)

        if not isinstance(a_sig, VariableSignature) or not isinstance(
                b_sig, VariableSignature):
            continue

        graph.add_edge(a_sig, b_sig)
        p = re.compile("^([A-Z]+|[a-z])$")
        if p.match(a_sig.name):
            explicit_sigs.add(a_sig)
        if p.match(b_sig.name):
            explicit_sigs.add(b_sig)

    tester = lambda sig: sig in graph and any(
        nx.has_path(graph, sig, explicit_sig)
        for explicit_sig in explicit_sigs)
    getter = lambda sig: [
        explicit_sig for explicit_sig in explicit_sigs
        if nx.has_path(graph, sig, explicit_sig)
    ][0]
    new_formula_nodes = [
        formula_node.replace_signature(tester, getter)
        for formula_node in core_formulas
    ]
    new_formula_nodes = new_formula_nodes + equal_formulas
    return new_formula_nodes
def _ground_variable(match_parse, variable, references={}):
    assert isinstance(variable, FormulaNode)
    assert isinstance(match_parse, MatchParse)
    return_type = variable.return_type
    graph_parse = match_parse.graph_parse
    core_parse = graph_parse.core_parse
    variable_signature = variable.signature

    if variable_signature.id in signatures:
        # pass What, Which, etc.
        return variable
    elif variable_signature.id in match_parse.graph_parse.core_parse.variable_assignment.keys(
    ):
        # pass point_0, point_1, etc.
        return variable
    elif isinstance(variable_signature,
                    VariableSignature) and variable_signature.is_ref():
        # @v_1, etc.
        return references[variable_signature.name]
    elif return_type == 'number':
        if is_number(variable_signature.name):
            return variable
        elif len(variable_signature.name) == 1:
            # x, y, z, etc. Need to redefine id (id shouldn't be tuple).
            return FormulaNode(
                VariableSignature(variable_signature.name, return_type), [])
        elif len(variable_signature.name
                 ) == 2 and variable_signature.name.isupper():
            new_leaf = FormulaNode(
                VariableSignature(variable.signature.id,
                                  "line",
                                  name=variable.signature.name), [])
            return FormulaNode(signatures['LengthOf'],
                               [_ground_variable(match_parse, new_leaf)])
    elif return_type == 'point':
        if len(variable_signature.name) == 1:
            return match_parse.match_dict[variable_signature.name][0]
        else:
            points = get_all_instances(graph_parse, 'point', True)
            return SetNode(points.values())
    elif return_type == 'line':
        if len(variable_signature.name
               ) == 1 and variable_signature.name in match_parse.match_dict:
            line = match_parse.match_dict[variable_signature.name][0]
            return line
        elif len(variable_signature.name
                 ) == 2 and variable_signature.name.isupper():
            label_a, label_b = variable_signature.name
            point_a = match_parse.match_dict[label_a][0]
            point_b = match_parse.match_dict[label_b][0]
            return FormulaNode(signatures['Line'], [point_a, point_b])
            """
        elif variable_signature.name == 'hypotenuse':
            def func(x):
                l, t = x
                formula = FormulaNode(signatures['IsHypotenuseOf'], (l,t))
                tv = core_parse.evaluate(formula)
                return tv.norm
            lines = get_all_instances(graph_parse, 'line', True).values()
            triangles = get_all_instances(graph_parse, 'triangle', True).values()
            line, triangle = min(itertools.product(lines, triangles), key=func)
            return line
            """

        else:
            lines = get_all_instances(graph_parse, 'line', True)
            return SetNode(lines.values())
    elif return_type == 'circle':
        if len(variable_signature.name) == 1:
            center_label = variable_signature.name
            center = match_parse.match_dict[center_label][0]
            center_idx = int(center.signature.name.split("_")[1])
            return graph_parse.circle_dict[center_idx][0]['variable']
            # radius = match_parse.graph_parse.core_parse.radius_variables[center_idx][0]
        elif variable_signature.name == 'circle':
            circles = get_all_instances(graph_parse, 'circle', True)
            return SetNode(circles.values())
        else:
            raise Exception()
    elif return_type == 'angle':
        # TODO :
        if len(variable_signature.name
               ) == 3 and variable_signature.name.isupper():
            label_a, label_b, label_c = variable_signature.name
            point_a = match_parse.match_dict[label_a][0]
            point_b = match_parse.match_dict[label_b][0]
            point_c = match_parse.match_dict[label_c][0]
            out = FormulaNode(signatures['Angle'], [point_a, point_b, point_c])
            measure = evaluate(FormulaNode(signatures['MeasureOf'], [out]),
                               core_parse.variable_assignment)
            if measure > np.pi:
                out = FormulaNode(signatures['Angle'],
                                  [point_c, point_b, point_a])
            return out
        elif len(variable_signature.name
                 ) == 1 and variable_signature.name.isupper():
            angles = get_all_instances(graph_parse, 'angle', True)
            p = match_parse.match_dict[variable_signature.name][0]
            for formula in angles.values():
                if formula.children[1].signature == p.signature:
                    measure = evaluate(
                        FormulaNode(signatures['MeasureOf'], [formula]),
                        core_parse.variable_assignment)
                    if measure > np.pi:
                        continue
                    return formula

        elif len(variable_signature.name
                 ) == 1 and variable_signature.name.islower():
            return match_parse.match_dict[variable_signature.name][0]
    elif return_type == 'arc':
        if len(variable_signature.name
               ) == 2 and variable_signature.name.isupper():
            point_keys = [
                match_parse.point_key_dict[label]
                for label in variable_signature.name
            ]
            test_arc = get_instances(graph_parse, 'arc', False,
                                     *point_keys).values()[0]
            if MeasureOf(test_arc) > np.pi:
                point_keys = [point_keys[1], point_keys[0]]
            arc = get_instances(graph_parse, 'arc', True,
                                *point_keys).values()[0]
            return arc
        else:
            arcs = get_all_instances(graph_parse, 'arc', True)
            return SetNode(arcs.values())

    elif return_type == 'triangle':
        if variable_signature.name.isupper() and len(
                variable_signature.name) == 3:
            point_keys = [
                match_parse.point_key_dict[label]
                for label in variable_signature.name
            ]
            triangles = get_instances(graph_parse, 'triangle', True,
                                      *point_keys)
            return triangles.values()[0]
        else:
            triangles = get_all_instances(graph_parse, 'triangle', True)
            return SetNode(triangles.values())
    elif return_type == 'quad':
        if variable_signature.name.isupper() and len(
                variable_signature.name) == 4:
            point_keys = [
                match_parse.point_key_dict[label]
                for label in variable_signature.name
            ]
            quads = get_instances(graph_parse, 'quad', True, *point_keys)
            return quads.values()[0]
        else:
            quads = get_all_instances(graph_parse, 'quad', True)
            return SetNode(quads.values())
    elif return_type == 'hexagon':
        if variable_signature.name.isupper() and len(
                variable_signature.name) == 6:
            point_keys = [
                match_parse.point_key_dict[label]
                for label in variable_signature.name
            ]
            hexagons = get_instances(graph_parse, 'hexagon', True, *point_keys)
            return hexagons.values()[0]
        else:
            quads = get_all_instances(graph_parse, 'hexagon', True)
            return SetNode(quads.values())
    elif return_type == 'polygon':
        if variable_signature.name.isupper():
            point_keys = [
                match_parse.point_key_dict[label]
                for label in variable_signature.name
            ]
            polygons = get_instances(graph_parse, 'polygon', True, *point_keys)
            return polygons.values()[0]
        else:
            polygons = get_all_instances(graph_parse, 'polygon', True)
            return SetNode(polygons.values())
    elif return_type == 'twod':
        circles = get_all_instances(graph_parse, 'circle', True)
        polygons = get_all_instances(graph_parse, 'polygon', True)
        return SetNode(polygons.values() + circles.values())
    elif return_type == 'oned':
        lines = get_all_instances(graph_parse, 'line', True)
        arcs = get_all_instances(graph_parse, 'arc', True)
        return SetNode(lines.values() + arcs.values())

    #logging.warning("failed to ground variable: %r" % variable)
    raise Exception()
 def apply(self, name, *args):
     vn = FormulaNode(signatures[name], args)
     if name in ['Point', 'Line', 'Circle']:
         self.entities.append(vn)
     return vn
Exemple #20
0
def v(name, return_type):
    vs = VariableSignature(name, return_type)
    return FormulaNode(vs, [])
Exemple #21
0
def f(name, *args):
    return FormulaNode(signatures[name], args)
def parse_match_from_known_labels(graph_parse, known_labels):
    assert isinstance(graph_parse, GraphParse)
    match_dict = {}
    point_key_dict = {}
    offset = graph_parse.image_segment_parse.diagram_image_segment.offset
    for idx, d in enumerate(known_labels):
        label = d['label']
        x = d['x'] - offset[0]
        y = d['y'] - offset[1]
        label_point = instantiators['point'](x, y)
        type_ = d['type']
        arr = type_.split(' ')
        if len(arr) > 1:
            type_ = arr[-1]

        # Find closest type_ instance's key in graph_parse
        instances = get_all_instances(graph_parse, type_)
        if len(instances) == 0:
            logging.error("no instance found of type %s" % type_)
            continue

        if len(arr) > 1 and type_ == 'line' and arr[0] == 'length':
            distances = [(key,
                          label_distance_to_line(label_point, instance, True))
                         for key, instance in instances.iteritems()]
        elif type_ == 'line':
            distances = [(key,
                          label_distance_to_line(label_point, instance, False))
                         for key, instance in instances.iteritems()]
        elif type_ == 'point':
            distances = [(key, label_distance_to_point(label_point, instance))
                         for key, instance in instances.iteritems()]
        elif type_ == 'arc':
            distances = [(key, label_distance_to_arc(label_point, instance))
                         for key, instance in instances.iteritems()]
        elif type_ == 'angle':
            # filter subangles
            # instances = {key: value for key, value in instances.iteritems() if all(x == value or not is_subangle(x, value) for x in instances.values())}
            distances = [(key, label_distance_to_angle(label_point, instance))
                         for key, instance in instances.iteritems()]

        # Then use the key to get corresponding variable in general graph
        # Wrap the general instance in function nod3. If there are extra prefixes, add these as well the formula
        argmin_key = min(distances, key=lambda pair: pair[1])[0]
        if type_ == 'line':
            a_key, b_key = argmin_key
            a_point = graph_parse.point_variables[a_key]
            b_point = graph_parse.point_variables[b_key]
            formula = FormulaNode(signatures['Line'], [a_point, b_point])
            if len(arr) > 1 and arr[0] == 'length':
                formula = FormulaNode(signatures['LengthOf'], [formula])
        elif type_ == 'point':
            formula = graph_parse.point_variables[argmin_key]
            point_key_dict[label] = argmin_key
        elif type_ == 'angle':
            a_key, b_key, c_key = argmin_key
            a_point = graph_parse.point_variables[a_key]
            b_point = graph_parse.point_variables[b_key]
            c_point = graph_parse.point_variables[c_key]
            formula = FormulaNode(signatures['Angle'],
                                  [a_point, b_point, c_point])
            if len(arr) > 1 and arr[0] == 'angle':
                formula = FormulaNode(signatures['MeasureOf'], [formula])
                formula = FormulaNode(
                    signatures['Div'],
                    [formula, FormulaNode(signatures['Degree'], [])])
        elif type_ == 'arc':
            (center_key, radius_key), a_key, b_key = argmin_key
            center_point = graph_parse.point_variables[center_key]
            radius = graph_parse.radius_variables[center_key][radius_key]
            circle = FormulaNode(signatures['Circle'], [center_point, radius])
            a_point = graph_parse.point_variables[a_key]
            b_point = graph_parse.point_variables[b_key]
            formula = FormulaNode(signatures['Arc'],
                                  [circle, a_point, b_point])
        if label not in match_dict:
            match_dict[label] = []
        elif issubtype(formula.return_type, 'entity'):
            raise Exception()
        match_dict[label].append(formula)

    match_parse = MatchParse(graph_parse, match_dict, point_key_dict)
    return match_parse
Exemple #23
0
 def to_formula(self):
     args = [child.to_formula() for child in self.children]
     return FormulaNode(self.content.signature, args)
Exemple #24
0
def solve(given_formulas, choice_formulas=None, assignment=None):
    """

    :param list true_formulas:
    :param dict choice_formulas:
    :return:
    """
    start_time = time.time()
    out = {}
    #1. Find query formula in true formulas
    true_formulas = []
    query_formula = None
    for formula in given_formulas:
        assert isinstance(formula, FormulaNode)
        if formula.has_signature("What") or formula.has_signature(
                "Which") or formula.has_signature("Find"):
            if query_formula is not None:
                logging.warning("More than one query formula.")
            query_formula = formula
        else:
            true_formulas.append(formula)
    if query_formula is None:
        raise Exception("No query formula.")

    elif query_formula.has_signature("What"):
        if choice_formulas is None:
            ns = NumericSolver(given_formulas, assignment=assignment)
            ns.solve()
            out = ns.assignment['What']
        else:
            ns = NumericSolver(given_formulas, assignment=assignment)
            ns.solve()
            for key, choice_formula in choice_formulas.iteritems():
                equal_formula = FormulaNode(
                    signatures['Equals'],
                    [ns.assignment['What'], choice_formula])
                out[key] = ns.evaluate(equal_formula)
            """
            ns = NumericSolver(true_formulas)
            ns.solve()
            for key, choice_formula in choice_formulas.iteritems():
                # print query_formula.children[1], ns.evaluate(query_formula.children[1])
                # print choice_formula, ns.evaluate(choice_formula)
                tester = lambda node: isinstance(node, FormulaNode) and node.signature.id == "What"
                getter = lambda node: choice_formula
                replaced_formula = query_formula.replace_node(tester, getter)
                # print replaced_formula
                out[key] = ns.evaluate(replaced_formula)
            """
        # display_entities(ns)

    elif query_formula.has_signature("Find"):
        ns = NumericSolver(true_formulas, assignment=assignment)
        ns.solve()
        # display_entities(ns)
        if choice_formulas is None:
            # No choice given; need to find the answer!
            out = ns.evaluate(query_formula.children[0])
        else:
            for key, choice_formula in choice_formulas.iteritems():
                replaced_formula = FormulaNode(
                    signatures['Equals'],
                    [query_formula.children[0], choice_formula])
                out[key] = ns.evaluate(replaced_formula)
        # display_entities(ns)

    elif query_formula.has_signature("Which"):
        ns = NumericSolver(true_formulas, assignment=assignment)
        ns.solve()
        for key, choice_formula in choice_formulas.iteritems():
            # print query_formula.children[1], ns.evaluate(query_formula.children[1])
            # print choice_formula, ns.evaluate(choice_formula)
            tester = lambda node: node.signature.id == "Which"
            getter = lambda node: choice_formula
            replaced_formula = query_formula.replace_node(tester, getter)
            out[key] = ns.evaluate(replaced_formula)

    # this won't be executed!
    elif query_formula.has_signature("Which"):
        tester = lambda node: isinstance(node, FormulaNode
                                         ) and node.signature.id == "Which"
        for choice, choice_formula in choice_formulas.iteritems():
            getter = lambda node: choice_formula
            replaced_formula = query_formula.replace_node(tester, getter)
            all_formulas = true_formulas + [replaced_formula]
            ns = NumericSolver(all_formulas)
            out[choice] = ns.evaluate(replaced_formula)
            print out[choice]

            #display_entities(ns)
    else:
        raise Exception()

    end_time = time.time()
    delta_time = end_time - start_time
    print "%.2f seconds" % delta_time
    return out