def index(self, indexer: Indexer): ret = [] triangles = indexer.index_by_type(Triangle) exist_relations = set() two_sums = indexer.index_by_type(TwoSum) for two_sum in two_sums: exist_relations.add(two_sum.relationship.id) for tri in triangles: known_angles = [] for angle in tri.angles: angle_A_cond = indexer.index_value_condition(angle, 'angle') if angle_A_cond.attr_value is not None: known_angles.append(angle_A_cond) if len(known_angles) >= 2: pairs = itertools.product(known_angles, known_angles) for angle_B_cond, angle_C_cond in pairs: id_ = f'{angle_B_cond.obj.id}.angle_{angle_C_cond.obj.id}.angle' if id_ in exist_relations: continue two_sum_relation = TwoSum( id_, angle_B_cond.obj, 'angle', angle_C_cond.obj, 'angle', angle_B_cond.attr_value + angle_C_cond.attr_value) r = RelationshipBased(two_sum_relation) ret.append([[angle_B_cond, angle_C_cond], r]) return ret
def index(self, indexer: Indexer): ret = [] two_sums = indexer.index_by_type(TwoSum) equal_conds = indexer.index_by_type(ValueEquivalence) if not equal_conds: return [] for two_sum in two_sums: r = two_sum.relationship for cond in equal_conds: eq_r = cond.relationship if r.entity1 in eq_r.obj_list and r.entity2 in eq_r.obj_list: idx1 = eq_r.obj_list.index(r.entity1) idx2 = eq_r.obj_list.index(r.entity2) if r.attr1 == eq_r.attr_list[ idx1] and r.attr2 == eq_r.attr_list[idx2]: cond1 = indexer.index_value_condition( r.entity1, r.attr1, False) cond2 = indexer.index_value_condition( r.entity2, r.attr2, False) if cond1 is None: cond1 = indexer.index_value_condition( r.entity1, r.attr1) ret.append([[two_sum, cond], cond1]) if cond2 is None: cond2 = indexer.index_value_condition( r.entity2, r.attr2) ret.append([[two_sum, cond], cond2]) return ret
def index(self, indexer: Indexer): ret = [] nls_conds = indexer.index_by_type(NLineSector) for cond in nls_conds: r = cond.relationship # Existence of ratio condition is guaranteed. ratio_cond = indexer.index_value_condition(r, 'ratio') ratio = ratio_cond.attr_value near_point, split_point, far_point = r.three_points line_near = indexer.index_line_by_points(near_point, split_point) line_far = indexer.index_line_by_points(far_point, split_point) line_full = indexer.index_line_by_points(near_point, far_point) near_cond = indexer.index_value_condition(line_near, 'length') far_cond = indexer.index_value_condition(line_far, 'length') full_cond = indexer.index_value_condition(line_full, 'length') if full_cond.attr_value is None: if near_cond.attr_value is not None: ret.append([[near_cond, ratio_cond, 1/ratio], full_cond]) elif far_cond.attr_value is not None: ret.append([[far_cond, ratio_cond, 1/(1-ratio)], full_cond]) if near_cond.attr_value is None: if full_cond.attr_value is not None: ret.append([[full_cond, ratio_cond, ratio], near_cond]) elif far_cond.attr_value is not None: ret.append([[far_cond, ratio_cond, ratio/(1-ratio)], near_cond]) if far_cond.attr_value is None: if full_cond.attr_value is not None: ret.append([[full_cond, ratio_cond, 1-ratio], far_cond]) elif near_cond.attr_value is not None: ret.append([[near_cond, ratio_cond, (1-ratio)/ratio], far_cond]) return ret
def index(self, indexer: Indexer): conditions = [] cvas = indexer.index_by_type(CommonVertexAngle) for cva_cond in cvas: cond = self._find_common_vertex_angle(cva_cond, indexer) if cond is not None: conditions.append(cond) return conditions
def index(self, indexer: Indexer): ret = [] r_conds = indexer.index_by_type(IsRightTriangle) triangles = indexer.index_by_type(Triangle) right_triangles = [cond.relationship.triangle for cond in r_conds] for th in triangles: if th in right_triangles: continue for angle in [th.angle1, th.angle2, th.angle3]: a_cond = indexer.index_value_condition(angle, 'angle') if a_cond.attr_value is not None and a_cond.attr_value == 90: rt = IsRightTriangle(th.id, th, angle) rt_cond = RelationshipBased(rt) ret.append([[a_cond], rt_cond]) break return ret
def index(self, indexer: Indexer): conditions = [] cols = indexer.index_by_type(Collineation) for col_cond in cols: cond = self._find_lines_by_collineation(col_cond, indexer) if cond is not None: conditions.append(cond) return conditions
def index(self, indexer: Indexer): ret = [] triangles = indexer.index_by_type(Triangle) exist_relations = {} two_sums = indexer.index_by_type(TwoSum) for two_sum in two_sums: exist_relations[two_sum.relationship.id] = two_sum for tri in triangles: for angle in tri.angles: angle_A_cond = indexer.index_value_condition(angle, 'angle') if angle_A_cond.attr_value is None: angle_B, angle_C = [a for a in tri.angles if a != angle] id_ = f'{angle_B.id}.angle_{angle_C.id}.angle' if id_ in exist_relations: two_angle_sum = exist_relations[id_] ret.append([[two_angle_sum], angle_A_cond]) return ret
def index(self, indexer: Indexer): ret = [] conds = indexer.index_by_type(SupplementaryAngle) exist_relations = set() two_sums = indexer.index_by_type(TwoSum) for two_sum in two_sums: exist_relations.add(two_sum.relationship.id) for cond in conds: r = cond.relationship angle1_cond = indexer.index_value_condition(r.angle1, 'angle') angle2_cond = indexer.index_value_condition(r.angle2, 'angle') id_ = f'{angle1_cond.obj.id}.angle_{angle2_cond.obj.id}.angle' if id_ in exist_relations: continue two_sum_relation = TwoSum(id_, angle1_cond.obj, 'angle', angle2_cond.obj, 'angle', 180) r = RelationshipBased(two_sum_relation) ret.append([[cond], r]) return ret
def index(self, indexer: Indexer): ret = [] rt_conds = indexer.index_by_type(IsRightTriangle) for cond in rt_conds: r = cond.relationship angle = r.right_angle angle_cond = indexer.index_value_condition(angle, 'angle') if angle_cond.attr_value is None: ret.append([[cond], angle_cond]) return ret
def index(self, indexer: Indexer): ret = [] triangles = indexer.index_by_type(Triangle) pattern = TrianglePattern(angle_A=AttributeState.KNOWN, angle_B=AttributeState.KNOWN, angle_C=AttributeState.KNOWN) st_conds = indexer.index_by_type(SimilarTriangle) all_st = [cond.relationship for cond in st_conds] def get_corresp(): th1_conds = [indexer.index_value_condition(th1_angle, 'angle') \ for th1_angle in th1.angles] th2_conds = [indexer.index_value_condition(th2_angle, 'angle') \ for th2_angle in th2.angles] cor_angle = [] for cond1 in th1_conds: for cond2 in th2_conds: if cond1.attr_value == cond2.attr_value: cor_angle.append((cond1.obj, cond2.obj)) break return cor_angle, th1_conds, th2_conds replaced, entities = indexer.index_by_pattern(pattern, True) size = len(entities) for i in range(size): for j in range(i + 1, size): i_angles = set([replaced[i].angle_A, replaced[i].angle_B, replaced[i].angle_C]) j_angles = set([replaced[j].angle_A, replaced[j].angle_B, replaced[j].angle_C]) if i_angles == j_angles: th1 = entities[i] th2 = entities[j] cor_angle, conds1, conds2 = get_corresp() st = SimilarTriangle('_'.join([th1.id, th2.id]), th1, th2, cor_angle) if st not in all_st: ret.append([conds1+conds2, RelationshipBased(st)]) return ret
def index(self, indexer: Indexer): """Find interior angles on the same side from parallel relationship.""" ret = [] def find_alternate_angles(link_col, col1, col2, p1, p2): p1_index = link_col.index(p1) p2_index = link_col.index(p2) reverse = lambda x: -1 if x == 0 else 0 compare = p1_index < p2_index p1_direction = -1 if compare else 0 for k in [0, -1]: if link_col[p1_direction] == p1 or col1[k] == p1: continue if link_col[reverse(p1_direction)] == p2 or col2[k] == p2: continue angle1 = indexer.index_angle_by_points(\ link_col[p1_direction], p1, col1[k]) angle2 = indexer.index_angle_by_points(\ link_col[reverse(p1_direction)], p2, col2[k]) a1_cond = indexer.index_value_condition(angle1, 'angle') a2_cond = indexer.index_value_condition(angle2, 'angle') if a1_cond.attr_value is None \ and a2_cond.attr_value is not None: ret.append([[a2_cond], a1_cond]) elif a1_cond.attr_value is not None \ and a2_cond.attr_value is None: ret.append([[a1_cond], a2_cond]) conds = indexer.index_by_type(Parallel) for cond in conds: r = cond.relationship line1, line2 = r.line1, r.line2 # col is a list of point entity. col1 = indexer.index_collineation_by_line(line1) col2 = indexer.index_collineation_by_line(line2) if r.reverse: col2 = list(reversed(col2)) for p1 in col1: for p2 in col2: # Link line is the line links two parallel lines. link_line = indexer.index_line_by_points(p1, p2) # One link line can generate four corresponding angles at most. if link_line is None: continue link_col = indexer.index_collineation_by_line(link_line) find_alternate_angles(link_col, col1, col2, p1, p2) return ret
def index(self, indexer: Indexer): ret = [] e_conds = indexer.index_by_type(IsEquilateralTriangle) for cond in e_conds: r = cond.relationship tg = [] for angle in r.triangle.angles: angle_cond = indexer.index_value_condition(angle, 'angle') if angle_cond.attr_value is None: tg.append(angle_cond) for t in tg: ret.append([[cond], t]) return ret
def index(self, indexer: Indexer): ret = [] triangles = indexer.index_by_type(Triangle) exist_relations = set() two_sums = indexer.index_by_type(TwoSum) for two_sum in two_sums: exist_relations.add(two_sum.relationship.id) for tri in triangles: for angle in tri.angles: angle_A_cond = indexer.index_value_condition(angle, 'angle') if angle_A_cond.attr_value is not None: angle_B, angle_C = [a for a in tri.angles if a != angle] id_ = f'{angle_B.id}.angle_{angle_C.id}.angle' if id_ in exist_relations: continue two_sum_relation = TwoSum(id_, angle_B, 'angle', angle_C, 'angle', 180 - angle_A_cond.attr_value) r = RelationshipBased(two_sum_relation) ret.append([[angle_A_cond], r]) return ret
def index(self, indexer: Indexer): ret = [] rt_conds = indexer.index_by_type(IsRightTriangle) for cond in rt_conds: r = cond.relationship hypotenuse = r.hypotenuse legs = r.legs a = indexer.index_value_condition(legs[0], 'length') b = indexer.index_value_condition(legs[1], 'length') c = indexer.index_value_condition(hypotenuse, 'length') if attr_value_known_num([a, b, c]) == 2: ret.append([[cond, a, b], c]) return ret
def index(self, indexer: Indexer): ret = [] conds = indexer.index_by_type(OppositeVerticalAngle) for cond in conds: r = cond.relationship angle1_cond = indexer.index_value_condition(r.angle1, 'angle') angle2_cond = indexer.index_value_condition(r.angle2, 'angle') if angle1_cond.attr_value is not None and \ angle2_cond.attr_value is None: ret.append([[cond, angle1_cond], angle2_cond]) elif angle1_cond.attr_value is None and \ angle2_cond.attr_value is not None: ret.append([[cond, angle2_cond], angle1_cond]) return ret
def index(self, indexer: Indexer): ret = [] i_conds = indexer.index_by_type(IsIsoscelesTriangle) triangles = indexer.index_by_type(Triangle) isosceles_triangles = [cond.relationship.triangle for cond in i_conds] for th in triangles: if th in isosceles_triangles: continue permutaton = [(th.side1, th.side2, th.vertex3), \ (th.side1, th.side3, th.vertex2), \ (th.side2, th.side3, th.vertex1)] for s1, s2, v in permutaton: s1_cond = indexer.index_value_condition(s1, 'length') s2_cond = indexer.index_value_condition(s2, 'length') if s1_cond.attr_value is None or s2_cond.attr_value is None: continue if s1_cond.attr_value == s2_cond.attr_value: it = IsIsoscelesTriangle(th.id, th, v) it_cond = RelationshipBased(it) ret.append([[s1_cond, s2_cond], it_cond]) break return ret
def index(self, indexer: Indexer): ret = [] i_conds = indexer.index_by_type(IsIsoscelesTriangle) triangles = indexer.index_by_type(Triangle) isosceles_triangles = [cond.relationship.triangle for cond in i_conds] for th in triangles: if th in isosceles_triangles: continue permutaton = [(th.side1, th.side2, th.vertex3), \ (th.side1, th.side3, th.vertex2), \ (th.side2, th.side3, th.vertex1)] for s1, s2, v in permutaton: eq_cond = index_equivalent_value(indexer, obj1=s1, attr1='length', obj2=s2, attr2='length') if eq_cond is not None: it = IsIsoscelesTriangle(th.id, th, v) it_cond = RelationshipBased(it) ret.append([[eq_cond], it_cond]) return ret
def index(self, indexer: Indexer): ret = [] i_conds = indexer.index_by_type(IsIsoscelesTriangle) triangles = indexer.index_by_type(Triangle) isosceles_triangles = [cond.relationship.triangle for cond in i_conds] for th in triangles: if th in isosceles_triangles: continue permutaton = [(th.angle1, th.angle2, th.vertex3), \ (th.angle1, th.angle3, th.vertex2), \ (th.angle2, th.angle3, th.vertex1)] for a1, a2, v in permutaton: a1_cond = indexer.index_value_condition(a1, 'angle') a2_cond = indexer.index_value_condition(a2, 'angle') if a1_cond.attr_value is None or a2_cond.attr_value is None: continue if a1_cond.attr_value == a2_cond.attr_value: it = IsIsoscelesTriangle(th.id, th, v) it_cond = RelationshipBased(it) ret.append([[a1_cond, a2_cond], it_cond]) break return ret
def index(self, indexer: Indexer): ret = [] st_conds = indexer.index_by_type(SimilarTriangle) for cond in st_conds: r = cond.relationship for angle1, angle2 in r.cor_angle: a1_cond = indexer.index_value_condition(angle1, 'angle') a2_cond = indexer.index_value_condition(angle2, 'angle') if a1_cond.attr_value is None \ and a2_cond.attr_value is not None: ret.append([[cond, a2_cond], a1_cond]) elif a1_cond.attr_value is not None \ and a2_cond.attr_value is None: ret.append([[cond, a1_cond], a2_cond]) return ret
def index(self, indexer: Indexer): ret = [] e_conds = indexer.index_by_type(IsEquilateralTriangle) triangles = indexer.index_by_type(Triangle) e_triangles = [cond.relationship.triangle for cond in e_conds] def f(th): for i in range(3): a_cond = indexer.index_value_condition(th.angles[i], 'angle') if a_cond.attr_value is None or a_cond.attr_value != 60: yield False else: yield True for th in triangles: if th in e_triangles: continue if all(f(th)): pre = [indexer.index_value_condition(th.angles[i], 'angle') \ for i in range(3)] r = IsEquilateralTriangle(th.id, th) tg = RelationshipBased(r) ret.append([pre, tg]) return ret
def index(self, indexer: Indexer): ret = [] two_sums = indexer.index_by_type(TwoSum) for two_sum in two_sums: r = two_sum.relationship cond1 = indexer.index_value_condition(r.entity1, r.attr1, False) cond2 = indexer.index_value_condition(r.entity2, r.attr2, False) if cond1 is None and cond2 is not None: cond1 = indexer.index_value_condition(r.entity1, r.attr1) ret.append([[two_sum, cond2], cond1]) elif cond1 is not None and cond2 is None: cond2 = indexer.index_value_condition(r.entity2, r.attr2) ret.append([[two_sum, cond1], cond2]) return ret
def index(self, indexer: Indexer): ret = [] i_conds = indexer.index_by_type(IsIsoscelesTriangle) for cond in i_conds: r = cond.relationship h = r.hypotenuse h0_cond = indexer.index_value_condition(h[0], 'length') h1_cond = indexer.index_value_condition(h[1], 'length') if h0_cond.attr_value is None \ and h1_cond.attr_value is not None: ret.append([[cond, h1_cond], h0_cond]) elif h0_cond.attr_value is not None \ and h1_cond.attr_value is None: ret.append([[cond, h0_cond], h1_cond]) return ret
def index(self, indexer: Indexer): ret = [] triangles = indexer.index_by_type(Triangle) for th in triangles: side1 = indexer.index_value_condition(th.side1, 'length') if side1.attr_value is None: continue side2 = indexer.index_value_condition(th.side2, 'length') if side2.attr_value is None: continue side3 = indexer.index_value_condition(th.side3, 'length') if side3.attr_value is None: continue ret.append([[side1, side2, side3], AttributeValue(th, **{'circumference': None})]) return ret
def index(self, indexer: Indexer): ret = [] st_conds = indexer.index_by_type(SimilarTriangle) for cond in st_conds: r = cond.relationship ratio_cond = indexer.index_value_condition(r, 'ratio') if ratio_cond.attr_value is None: continue for side1, side2 in r.cor_sides: s1_cond = indexer.index_value_condition(side1, 'length') s2_cond = indexer.index_value_condition(side2, 'length') if sum( [s1_cond.attr_value is None, s2_cond.attr_value is None]) == 1: ret.append([[cond, s1_cond, ratio_cond], s2_cond]) return ret
def index(self, indexer: Indexer): ret = [] st_conds = indexer.index_by_type(SimilarTriangle) for cond in st_conds: r = cond.relationship for side1, side2 in r.cor_sides: side1_cond = indexer.index_value_condition(side1, 'length') side2_cond = indexer.index_value_condition(side2, 'length') if side1_cond.attr_value is not None \ and side2_cond.attr_value is not None: ratio = indexer.index_value_condition(r, 'ratio') if ratio.attr_value is None: ret.append([[cond, side1_cond, side2_cond], ratio]) break return ret
def index(self, indexer: Indexer): ret = [] i_conds = indexer.index_by_type(IsIsoscelesTriangle) for cond in i_conds: r = cond.relationship base_angle = r.base_angle a0_cond = indexer.index_value_condition(base_angle[0], 'angle') a1_cond = indexer.index_value_condition(base_angle[1], 'angle') if a0_cond.attr_value is None \ and a1_cond.attr_value is not None: ret.append([[cond, a1_cond], a0_cond]) elif a0_cond.attr_value is not None \ and a1_cond.attr_value is None: ret.append([[cond, a0_cond], a1_cond]) return ret
def index(self, indexer: Indexer): ret = [] triangles = indexer.index_by_type(Triangle) for th in triangles: side1 = indexer.index_value_condition(th.side1, 'length') if side1.attr_value is None: continue side2 = indexer.index_value_condition(th.side2, 'length') if side2.attr_value is None: continue side3 = indexer.index_value_condition(th.side3, 'length') if side3.attr_value is None: continue area = indexer.index_value_condition(th, 'area') if area.attr_value is None: ret.append([[side1, side2, side3], area]) return ret
def index(self, indexer: Indexer): ret = [] e_conds = indexer.index_by_type(IsEquilateralTriangle) for cond in e_conds: r = cond.relationship pre = [] tg = [] for side in r.triangle.sides: side_cond = indexer.index_value_condition(side, 'length') if side_cond.attr_value is None: tg.append(side_cond) else: pre.append(side_cond) if pre: pre = [cond] + pre for t in tg: ret.append([pre, t]) return ret
def index(self, indexer: Indexer): ret = [] rt_conds = indexer.index_by_type(IsRightTriangle) for cond in rt_conds: r = cond.relationship triangle = r.triangle area_cond = indexer.index_value_condition(triangle, 'area') # If area is already known, skip. if area_cond.attr_value is not None: continue leg1_cond = indexer.index_value_condition(r.legs[0], 'length') if leg1_cond.attr_value is None: continue leg2_cond = indexer.index_value_condition(r.legs[1], 'length') if leg2_cond.attr_value is None: continue ret.append([[cond, leg1_cond, leg2_cond], area_cond]) return ret
def index(self, indexer: Indexer): """Find corresponding angles from parallel relationship.""" ret = [] def find_corresponding_angles(link_col, col1, col2, p1, p2): for i in [0, -1]: for j in [0, -1]: if link_col[i] == p1 or col1[j] == p1: continue if link_col[i] == p2 or col2[j] == p2: continue angle1 = indexer.index_angle_by_points(\ link_col[i], p1, col1[j]) angle2 = indexer.index_angle_by_points(\ link_col[i], p2, col2[j]) a1_cond = indexer.index_value_condition(angle1, 'angle') a2_cond = indexer.index_value_condition(angle2, 'angle') if a1_cond.attr_value is None \ and a2_cond.attr_value is not None: ret.append([[a2_cond], a1_cond]) elif a1_cond.attr_value is not None \ and a2_cond.attr_value is None: ret.append([[a1_cond], a2_cond]) conds = indexer.index_by_type(Parallel) for cond in conds: r = cond.relationship line1, line2 = r.line1, r.line2 # col is a list of point entity. col1 = indexer.index_collineation_by_line(line1) col2 = indexer.index_collineation_by_line(line2) if r.reverse: col2 = list(reversed(col2)) for p1 in col1: for p2 in col2: # Link line is the line links two parallel lines. link_line = indexer.index_line_by_points(p1, p2) # One link line can generate four corresponding angles at most. if link_line is None: continue link_col = indexer.index_collineation_by_line(link_line) find_corresponding_angles(link_col, col1, col2, p1, p2) return ret