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
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
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
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
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
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
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
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 {}
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
def v(name, return_type): vs = VariableSignature(name, return_type) return FormulaNode(vs, [])
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
def to_formula(self): args = [child.to_formula() for child in self.children] return FormulaNode(self.content.signature, args)
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