Esempio n. 1
0
def delta_ell(module: Module, x: ETangleStrands) -> Module.TensorElement:
    out = module.zero()
    unoccupied = set(x.etangle.left_points()) - set(x.left_strands.keys())

    for a1 in unoccupied:
        for a2 in unoccupied:
            if a1 < a2:
                out += delta_ell_case_1(module, x, a1, a2)

    for a1 in x.left_strands.keys():
        for a2 in x.left_strands.keys():
            if a1 < a2 and x.left_strands[a1] > x.left_strands[a2]:
                out += delta_ell_case_2(module, x, a1, a2)

    for a1 in unoccupied:
        for a2 in x.left_strands.keys():
            if a1 < a2:
                out += delta_ell_case_3(module, x, a1, a2)

    for a1 in x.left_strands.keys():
        for a2 in unoccupied:
            if a1 < a2:
                out += delta_ell_case_4(module, x, a1, a2)

    return out
Esempio n. 2
0
def introduce_left_crossing(module: Module, x: ETangleStrands, b1: int,
                            b2: int) -> Module.TensorElement:
    a1 = x.left_y_pos(b1)
    a2 = x.left_y_pos(b2)

    crossing_range_1 = range(a1, b2 + 1) if a1 < b2 else range(b2, a1 + 1)
    crossing_range_2 = range(a2, b1 + 1) if a2 < b1 else range(b1, a2 + 1)
    possible_crossings = list(set(crossing_range_1) & set(crossing_range_2))
    sd = introduce_left_crossing(x, b1, b2, possible_crossings[0])
    for crossing in possible_crossings[1:]:
        new_sd = introduce_left_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_7_relations()
    if powers is None:
        return module.zero()
    for orange, power in powers.items():
        c *= x.etangle.strand_index_to_variable(orange)**power

    new_left_strands = swap_values(x.left_strands, a1, a2)
    x_out = ETangleStrands(x.etangle, new_left_strands, x.right_strands)
    return c * x_out.to_generator(module)
Esempio n. 3
0
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
Esempio n. 4
0
    def __pow__(self, other: TypeDA) -> TypeDA:
        assert self.right_algebra == other.left_algebra

        left_right_iso = Z2PolynomialRing.Map.identity(other.left_algebra.ring,
                                                       self.right_algebra.ring)
        in_m, in_n = self.right_scalar_action.compose(
            left_right_iso).pushout_inclusions(other.left_scalar_action)

        out = TypeDA(in_m.target, self.left_algebra, other.right_algebra,
                     in_m.compose(self.left_scalar_action),
                     in_n.compose(other.right_scalar_action))

        for x_m, x_m_data in self.graph.nodes(data=True):
            for x_n, x_n_data in other.graph.nodes(data=True):
                x_m_grading = x_m_data['grading']
                x_n_grading = x_n_data['grading']
                if x_m.right_idempotent == x_n.left_idempotent:
                    out.add_generator(
                        Module.TensorGenerator(out, (x_m.key, x_n.key),
                                               x_m.left_idempotent,
                                               x_n.right_idempotent),
                        (x_m_grading[0] + x_n_grading[0],
                         x_m_grading[1] + x_n_grading[1]))

        for x_m in self.graph.nodes:
            for x_n in other.graph.nodes:
                if x_m.right_idempotent != x_n.left_idempotent:
                    continue
                x = Module.TensorGenerator(out, (x_m.key, x_n.key),
                                           x_m.left_idempotent,
                                           x_n.right_idempotent)
                for _, y_m, (left_m,
                             right_m), d_m in self.graph.out_edges(x_m,
                                                                   keys=True,
                                                                   data=True):
                    for right_n, y_n, c_n in other.delta_n(right_m, x_n):
                        if y_m.right_idempotent != y_n.left_idempotent:
                            continue
                        c_m = d_m['c']
                        y = Module.TensorGenerator(out, (y_m.key, y_n.key),
                                                   y_m.left_idempotent,
                                                   y_n.right_idempotent)
                        out.add_structure_map(
                            x**right_n,
                            left_m**(in_m.apply(c_m) * in_n.apply(c_n) * y))

        return out
Esempio n. 5
0
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
Esempio n. 6
0
def d_minus(module: Module, x: ETangleStrands) -> Module.TensorElement:
    out = module.zero()
    for black1, black2 in itertools.combinations(x.left_strands.values(), 2):
        b1 = min(black1, black2)
        b2 = max(black1, black2)
        # if the black strands don't cross
        if x.left_y_pos(b1) < x.left_y_pos(b2):
            # introduce a crossing and add it to the output
            out += introduce_left_crossing(module, x, b1, b2)
    return out
Esempio n. 7
0
def d_mixed_case_1(module: Module, x: ETangleStrands, b1: int,
                   b2: int) -> Module.TensorElement:
    c = x.etangle.ring.one()
    powers = x.to_strand_diagram().figure_8_case_1b(b1, b2)
    if powers is None:
        return module.zero()
    for orange, power in powers.items():
        c *= x.etangle.strand_index_to_variable(orange)**power
    x_out = ETangleStrands(x.etangle, x.left_strands,
                           swap_values(x.right_strands, b1, b2))
    return c * x_out.to_generator(module)
Esempio n. 8
0
def m2(module: Module, x: ETangleStrands,
       a: AMinus.Generator) -> Module.TensorElement:
    # if the sign sequences do not match, return 0
    if x.etangle.right_sign_sequence() != a.algebra.ss:
        return module.zero()

    # if the strands cannot be merged, return 0
    if set(x.right_strands.values()) != set(a.strands.keys()):
        return module.zero()

    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():
        black_strands[black] = (black, x.right_strands[black],
                                a.strands[x.right_strands[black]])

    c = x.etangle.ring.one()
    sd = StrandDiagram(orange_strands, orange_signs, black_strands)
    powers = sd.figure_6_relations()
    if powers is None:
        return module.zero()
    for orange, power in powers.items():
        for _ in range(power):
            c *= x.etangle.strand_index_to_variable(orange)

    new_right_strands = {
        sd.black_left_pos(black): sd.black_right_pos(black)
        for black in x.right_strands.keys()
    }
    x_out = ETangleStrands(x.etangle, x.left_strands, new_right_strands)
    return c * x_out.to_generator(module)
Esempio n. 9
0
def delta_ell_case_2(module: Module, x: ETangleStrands, a1: int,
                     a2: int) -> Module.TensorElement:
    c1 = module.left_algebra.ring.one()
    c2 = x.etangle.ring.one()
    powers = x.idempotent_and_left_strands().figure_8_case_2a(a1, a2)
    if powers is None:
        return module.zero()
    for orange, power in powers.items():
        if x.etangle.strand_index_to_left_sign(orange) == 1:
            c1 *= x.etangle.left_algebra_strand_index_to_variable(
                orange)**power
        else:
            c2 *= x.etangle.strand_index_to_variable(orange)**power
    elt = x.left_idempotent()
    y = ETangleStrands(x.etangle, swap_values(x.left_strands, a1, a2),
                       x.right_strands)
    return (c1 * elt)**(c2 * y.to_generator(module))
Esempio n. 10
0
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)
Esempio n. 11
0
def delta_ell_case_4(module: Module, x: ETangleStrands, a1: int,
                     a2: int) -> Module.TensorElement:
    c1 = module.left_algebra.ring.one()
    c2 = x.etangle.ring.one()
    powers = x.idempotent_and_left_strands().figure_8_case_4a(a1, a2)
    if powers is None:
        return module.zero()
    for orange, power in powers.items():
        if x.etangle.strand_index_to_left_sign(orange) == 1:
            c1 *= x.etangle.left_algebra_strand_index_to_variable(
                orange)**power
        else:
            c2 *= x.etangle.strand_index_to_variable(orange)**power
    b1 = x.left_strands[a1]
    b2 = a2
    elt_strands = x.left_idempotent_strands()
    elt_strands[b2] = a1
    new_left_strands = dict(x.left_strands)
    del new_left_strands[a1]
    new_left_strands[a2] = b1
    elt = x.etangle.left_algebra.generator(elt_strands)
    y = ETangleStrands(x.etangle, new_left_strands, x.right_strands)
    return (c1 * elt)**(c2 * y.to_generator(module))
 def __init__(self):
     Module.__init__(self)
Esempio n. 13
0
 def __init__(self):
     Module.__init__(self)
Esempio n. 14
0
 def to_generator(self, module):
     from Modules.Module import Module
     return Module.TensorGenerator(module, str(self),
                                   self.left_idempotent(),
                                   self.right_idempotent())