def d_mixed(module: Module, x: ETangleStrands) -> Module.TensorElement: out = module.zero() for b1 in x.right_strands.keys(): for b2 in x.right_strands.keys(): # if two black strands don't cross on the right if b1 < b2 and x.right_y_pos(b1) < x.right_y_pos(b2): out += d_mixed_case_1(module, x, b1, b2) for b1 in x.left_strands.values(): for b2 in x.left_strands.values(): # if two black strands cross on the left if b1 < b2 and x.left_y_pos(b1) > x.left_y_pos(b2): out += d_mixed_case_2(module, x, b1, b2) for b1 in x.right_strands.keys(): for b2 in x.left_strands.values(): if b1 < b2: out += d_mixed_case_3(module, x, b1, b2) for b1 in x.left_strands.values(): for b2 in x.right_strands.keys(): if b1 < b2: out += d_mixed_case_4(module, x, b1, b2) return out
def d_plus(module: Module, x: ETangleStrands) -> Module.TensorElement: out = module.zero() for black1, black2 in itertools.combinations(x.right_strands.keys(), 2): b1 = min(black1, black2) b2 = max(black1, black2) if x.right_y_pos(b1) > x.right_y_pos(b2): # smooth the crossing and add it to the output out += smooth_right_crossing(module, x, b1, b2) return out
def smooth_right_crossing(module: Module, x: ETangleStrands, b1: int, b2: int) -> Module.TensorElement: a1 = x.right_y_pos(b1) a2 = x.right_y_pos(b2) crossing_range_1 = range(a1, b1 + 1) if a1 < b1 else range(b1, a1 + 1) crossing_range_2 = range(a2, b2 + 1) if a2 < b2 else range(b2, a2 + 1) possible_crossings = list(set(crossing_range_1) & set(crossing_range_2)) sd = smooth_right_crossing(x, b1, b2, possible_crossings[0]) for crossing in possible_crossings[1:]: new_sd = smooth_right_crossing(x, b1, b2, crossing) if new_sd.num_orange_black_crossings() < sd.num_orange_black_crossings( ): sd = new_sd c = x.etangle.ring.one() powers = sd.figure_6_relations() if powers is None: return module.zero() for orange, power in powers.items(): c *= x.etangle.strand_index_to_variable(orange)**power new_right_strands = swap_values(x.right_strands, b1, b2) x_out = ETangleStrands(x.etangle, x.left_strands, new_right_strands) return c * x_out.to_generator(module)
def smooth_right_crossing(x: ETangleStrands, b1: int, b2: int, crossing: int) -> StrandDiagram: a1 = x.right_y_pos(b1) a2 = x.right_y_pos(b2) orange_strands = {} orange_signs = {} for orange in range(1, len(x.etangle.signs)): if x.etangle.right_y_pos(orange): orange_strands[orange] = (x.etangle.middle_y_pos(orange), x.etangle.right_y_pos(orange), x.etangle.right_y_pos(orange)) orange_signs[orange] = x.etangle.signs[orange] black_strands = {} for black in x.right_strands.keys(): if black == b1: black_strands[b1] = (b1, crossing + .1, a2) elif black == b2: black_strands[b2] = (b2, crossing + .2, a1) else: black_strands[black] = (black, x.right_y_pos(black), x.right_y_pos(black)) return StrandDiagram(orange_strands, orange_signs, black_strands)
def d_mixed_case_4(module: Module, x: ETangleStrands, b1: int, b2: int) -> Module.TensorElement: c = x.etangle.ring.one() powers = x.to_strand_diagram().figure_8_case_4b(b1, b2) if powers is None: return module.zero() for orange, power in powers.items(): c *= x.etangle.strand_index_to_variable(orange)**power a1 = x.left_y_pos(b1) a2 = x.right_y_pos(b2) new_left_strands = dict(x.left_strands) new_left_strands[a1] = b2 new_right_strands = dict(x.right_strands) del new_right_strands[b2] new_right_strands[b1] = a2 x_out = ETangleStrands(x.etangle, new_left_strands, new_right_strands) return c * x_out.to_generator(module)