Example #1
0
    def tensorDoubleDD(self, dd_graph1, dd_graph2):
        """Compute the type DD structure DD1 * CFAA(Id) * DD2."""
        assert dd_graph1.tensor_side == 2 and dd_graph2.tensor_side == 1
        assert dd_graph1.algebra2.opp() == self.pmc_alg
        assert dd_graph2.algebra1 == self.pmc_alg
        ddstr = SimpleDDStructure(F2, dd_graph1.algebra1, dd_graph2.algebra2)
        # Generators of the type DD structure:
        for ddgen1, node1 in dd_graph1.ddgen_node.items():
            for ddgen2, node2 in dd_graph2.ddgen_node.items():
                if node1.idem2 == node2.idem1.opp().comp():
                    cur_gen = DATensorDDGenerator(ddstr, ddgen1, ddgen2)
                    ddstr.addGenerator(cur_gen)

        # Search the graphs for type DD operations
        for gen_start in ddstr.getGenerators():
            ddgen1, ddgen2 = gen_start
            d1_pos = dd_graph1.ddgen_node[ddgen1]
            d2_pos = dd_graph2.ddgen_node[ddgen2]
            aa_pos = self.homology_node[ddgen1.idem2.opp()]
            pos = [(d1_pos, d2_pos, aa_pos)]
            end_states = self._searchDoubleD(dd_graph1, dd_graph2, pos)[0]
            for d1_end, d2_end, aa_end in end_states:
                gen_end = DATensorDDGenerator(ddstr,
                                              d1_end.ddgen, d2_end.ddgen)
                ddstr.addDelta(gen_start, gen_end, d1_end.sd, d2_end.sd, 1)
        return ddstr
Example #2
0
    def toDDStructure(self):
        """Convert this to a type DD structure over algebra1 and cobar of
        algebra2.

        """
        cobar2 = CobarAlgebra(self.algebra2)
        ddstr = SimpleDDStructure(self.ring, self.algebra1, cobar2)
        dagen_to_ddgen_map = dict()
        for gen in self.generators:
            ddgen = SimpleDDGenerator(ddstr, gen.idem1, gen.idem2, gen.name)
            dagen_to_ddgen_map[gen] = ddgen
            ddstr.addGenerator(ddgen)
        for (gen_from, coeffs_a), target in self.da_action.items():
            for (coeff_d, gen_to), ring_coeff in target.items():
                idem = None
                if len(coeffs_a) == 0:
                    idem = gen_from.idem2
                    assert idem == gen_to.idem2
                cobar_gen = TensorStarGenerator(coeffs_a, cobar2, idem)
                ddstr.addDelta(dagen_to_ddgen_map[gen_from],
                               dagen_to_ddgen_map[gen_to],
                               coeff_d, cobar_gen, ring_coeff)
        return ddstr
Example #3
0
    def tensorDD(self, ddstr):
        """Compute the box tensor product DA * DD of this bimodule with the
        given type DD structure. Returns the resulting type DD structure. Uses
        delta() and deltaPrefix() functions of this type DA structure.

        """
        ddstr_result = SimpleDDStructure(F2, self.algebra1, ddstr.algebra2)
        # Compute list of generators in the box tensor product
        for gen_left in self.getGenerators():
            for gen_right in ddstr.getGenerators():
                if gen_left.idem2 == gen_right.idem1:
                    ddstr_result.addGenerator(DATensorDDGenerator(
                        ddstr_result, gen_left, gen_right))

        def search(start_gen, cur_ddgen, cur_algd, cur_coeffs_a):
            """Searching for an arrow in the box tensor product.
            - start_gen: starting generator in the box tensor product. The
              resulting arrow will start from here.
            - cur_ddgen: current location in the type DD structure.
            - cur_algd: current product algebra outputs on the right side of the
              DD structure.
            - cur_coeffs_a: current list of A-side inputs to the type DA
              structure (or alternatively, list of algebra outputs on the left
              side of the DD structure).

            """
            start_dagen, start_dgen = start_gen
            cur_delta = self.delta(start_dagen, cur_coeffs_a)
            for (coeff_d, gen_to), ring_coeff in cur_delta.items():
                ddstr_result.addDelta(start_gen, DATensorDDGenerator(
                    ddstr_result, gen_to, cur_ddgen), coeff_d, cur_algd, 1)
            if self.deltaPrefix(start_dagen, cur_coeffs_a):
                for (coeff_out1, coeff_out2, dgen_to), ring_coeff in \
                    ddstr.delta(cur_ddgen).items():
                    new_algd = cur_algd * coeff_out2
                    if new_algd != E0:
                        search(start_gen, dgen_to, new_algd.getElt(),
                               cur_coeffs_a + (coeff_out1,))

        for x in ddstr_result.getGenerators():
            dagen, ddgen = x
            search(x, ddgen, ddgen.idem2.toAlgElt(ddstr.algebra2), ())
            # Add arrows coming from idempotent output on the left DD-side
            for (coeff_out1, coeff_out2, dgen_to), ring_coeff in \
                ddstr.delta(ddgen).items():
                if coeff_out1.isIdempotent():
                    ddstr_result.addDelta(
                        x, DATensorDDGenerator(ddstr_result, dagen, dgen_to),
                        dagen.idem1.toAlgElt(self.algebra1), coeff_out2, 1)

        # Grading is omitted.
        return ddstr_result
Example #4
0
    def getAdmissibleDDStructure(self):
        """Returns the type DD structure corresponding to the Heegaard diagram
        created by a finger move of the beta circle to the right.

        """
        alg1 = self.start_pmc.getAlgebra(mult_one = True)
        alg2 = alg1
        ddstr = SimpleDDStructure(F2, alg1, alg2)

        # Add generators for the non-admissible case - that is, those generators
        # that do not contain the two intersections created by the finger move.
        original_idems = self._getIdems()
        for i in range(len(original_idems)):
            left_idem, right_idem = original_idems[i]
            ddstr.addGenerator(
                SimpleDDGenerator(ddstr, left_idem, right_idem, "0_%d" % i))

        # Now add the new generators. These just correspond to the complementary
        # idempotents with c_pair on the left, repeated twice.
        left_idems = [idem for idem in self.start_pmc.getIdempotents()
                      if self.c_pair in idem]
        for i in range(len(left_idems)):
            left_idem = left_idems[i]
            right_idem = left_idem.opp().comp()
            ddstr.addGenerator(
                SimpleDDGenerator(ddstr, left_idem, right_idem, "1_%d" % i))
            ddstr.addGenerator(
                SimpleDDGenerator(ddstr, left_idem, right_idem, "2_%d" % i))

        gen_set = []
        for i in range(3):
            gen_set.append([gen for gen in ddstr.getGenerators()
                            if gen.name[:1] == "%d" % i])

        # Enumerate the non-special chords (those that do not dependent on the
        # idempotent. See the functions themselves for the format of all_chords.
        if self.is_degenerate:
            all_chords = self._getAdmissibleNonSpecialChordsDegenerate()
        else:
            all_chords = self._getAdmissibleNonSpecialChords()
        for i, j in itertools.product(range(3), range(3)):
            all_chords[i][j] = [self._StrandsFromChords(chord1, chord2)
                                for chord1, chord2 in all_chords[i][j]]

        # Now we emulate the logic in ddstructure.DDStrFromChords, except we
        # distinguish between ''classes'' of generators, by the first character
        # of the name of the generator.
        for i, j in itertools.product(range(3), range(3)):
            for x, y in itertools.product(gen_set[i], gen_set[j]):
                for l_chord, r_chord in all_chords[i][j]:
                    if l_chord.idemCompatible(x.idem1, y.idem1) and \
                       r_chord.idemCompatible(x.idem2, y.idem2):
                        ddstr.addDelta(x, y,
                                       StrandDiagram(alg1, x.idem1, l_chord),
                                       StrandDiagram(alg2, x.idem2, r_chord), 1)

        # Special handling for these. From class 2 to class 1, add only if the
        # c-pair is occupied on the left side (and not on the right).
        # Non-degenerate cases only.
        sp_chords = []
        if not self.is_degenerate:
            for x in range(0, self.c1):
                for y in range(self.c2+1, self.n):
                    sp_chords.append(([(x, y)], [(x, self.u), (self.u, y)]))
                    sp_chords.append(([(x, y)], [(x, self.d), (self.d, y)]))
                    sp_chords.append(([(x, self.d), (self.u, y)],
                                      [(x, self.d), (self.u, y)]))

        sp_chords = [self._StrandsFromChords(chord1, chord2)
                     for chord1, chord2 in sp_chords]
        for x, y in itertools.product(gen_set[2], gen_set[1]):
            for l_chord, r_chord in sp_chords:
                if self.c_pair in x.idem1 and \
                   l_chord.idemCompatible(x.idem1, y.idem1) and \
                   r_chord.idemCompatible(x.idem2, y.idem2):
                    assert self.c_pair not in x.idem2.opp() and \
                        self.c_pair in y.idem1 and \
                        self.c_pair not in y.idem2.opp()
                    ddstr.addDelta(x, y,
                                   StrandDiagram(alg1, x.idem1, l_chord),
                                   StrandDiagram(alg2, x.idem2, r_chord), 1)

        assert ddstr.testDelta()
        return ddstr
Example #5
0
    def testDDStructureDelta(self):
        # Construct type DD structures, and test whether d^2 = 0 holds.

        # PMC on both sides are genus 1 split PMC.
        pmc = splitPMC(1)
        # Strand algebra corresponding to pmc.
        alg = pmc.getAlgebra()
        # Initialize type DD structure over field F_2, with (left-left) action
        # by the genus 1 strand algebra. Intend to make this type DD bimodule
        # for identity.
        ddstr1 = SimpleDDStructure(F2, alg, alg)
        # Initialize the list of generators to add to ddstr1.
        # The generators have "complementary" idempotents. However, since the
        # PMCs are in opposite direction on both sides, the vector specifying
        # idempotents are the same.
        idems = {"x" : ([0], [0]),
                 "y" : ([1], [1])}
        gens = {}
        for name, (idem1, idem2) in idems.items():
            gens[name] = SimpleDDGenerator(
                ddstr1, Idempotent(pmc, idem1), Idempotent(pmc, idem2), name)
            ddstr1.addGenerator(gens[name])
        # Now add delta
        ddstr1.addDelta(gens["x"], gens["y"],
                        pmc.sd([(0, 1)]), pmc.sd([(2, 3)]), 1)
        ddstr1.addDelta(gens["y"], gens["x"],
                        pmc.sd([(1, 2)]), pmc.sd([(1, 2)]), 1)
        ddstr1.addDelta(gens["x"], gens["y"],
                        pmc.sd([(2, 3)]), pmc.sd([(0, 1)]), 1)
        # This already satisfies d^2 = 0
        self.assertTrue(ddstr1.testDelta())
        # However, one more arrow to finish the bimodule
        ddstr1.addDelta(gens["x"], gens["y"],
                        pmc.sd([(0, 3)]), pmc.sd([(0, 3)]), 1)
        # This is now the identity bimodule, of course satisfying d^2 = 0.
        self.assertTrue(ddstr1.testDelta())

        # Second example, showing failure of testDelta()
        ddstr2 = SimpleDDStructure(F2, alg, alg)
        # Add the same generators as before
        gens = {}
        for name, (idem1, idem2) in idems.items():
            gens[name] = SimpleDDGenerator(
                ddstr2, Idempotent(pmc, idem1), Idempotent(pmc, idem2), name)
            ddstr2.addGenerator(gens[name])
        # Now add delta
        ddstr2.addDelta(gens["x"], gens["y"],
                        pmc.sd([(0, 1)]), pmc.sd([(0, 1)]), 1)
        ddstr2.addDelta(gens["y"], gens["x"],
                        pmc.sd([(1, 2)]), pmc.sd([(1, 2)]), 1)
        # Prints the type DD structure. Note the code already checks that
        # idempotent matches in all added arrows (throws an error if they don't
        # match).
        print ddstr2
        # However, testDelta() fails. Prints a term in d^2(x).
        self.assertFalse(ddstr2.testDelta())
Example #6
0
    def testHochchild(self):
        pmc = splitPMC(1)
        alg = MinusStrandAlgebra(F2, pmc)
        ddstr = SimpleDDStructure(F2, alg, alg)
        # Initialize the list of generators to add to ddstr1.
        idems = {"x" : ([0], [0]),
                 "y" : ([1], [1])}
        gens = {}
        for name, (idem1, idem2) in idems.items():
            gens[name] = SimpleDDGenerator(
                ddstr, Idempotent(pmc, idem1), Idempotent(pmc, idem2), name)
            ddstr.addGenerator(gens[name])
        # Now add delta
        ddstr.addDelta(gens["x"], gens["y"],
                       minusSD(pmc, [(0, 1)]), minusSD(pmc, [(2, 3)]), 1)
        ddstr.addDelta(gens["y"], gens["x"],
                       minusSD(pmc, [(1, 2)]), minusSD(pmc, [(1, 2)]), 1)
        ddstr.addDelta(gens["x"], gens["y"],
                       minusSD(pmc, [(2, 3)]), minusSD(pmc, [(0, 1)]), 1)
        ddstr.addDelta(gens["y"], gens["x"],
                       minusSD(pmc, [(3, 0)]), minusSD(pmc, [(3, 0)]), 1)
        print ddstr
        self.assertTrue(ddstr.testDelta())

        dstr = ddstr.toDStructure()
        print dstr
        self.assertTrue(dstr.testDelta())
        hochchild = dstr.morToD(dstr)
        print hochchild
        hochchild.simplify(find_homology_basis = True)
        print len(hochchild)
        meaning_len = [len(gen.prev_meaning)
                       for gen in hochchild.getGenerators()]
        for gen in hochchild.getGenerators():
            print gen.prev_meaning