Esempio n. 1
0
    def toDStructure(self):
        """Convert this type DD structure into a type D structure over the
        tensor product of two algebras.

        """
        bialgebra = TensorDGAlgebra((self.algebra1, self.algebra2))
        dstr = SimpleDStructure(self.ring, bialgebra, ACTION_LEFT)
        gen_map = dict()
        for gen in self.generators:
            new_gen = gen.toDGenerator(dstr)
            gen_map[gen] = new_gen
            dstr.addGenerator(new_gen)
        for gen_from in self.generators:
            for (a1, a2, gen_to), coeff in self.delta_map[gen_from].items():
                dstr.addDelta(gen_map[gen_from], gen_map[gen_to],
                              TensorGenerator((a1, a2), bialgebra), coeff)
        return dstr
Esempio n. 2
0
    def tensorDandDD(self, d_graph, dd_graph):
        """Computes the type D structure D1 * CFAA(Id) * DD2, where D1 is a
        type D structure with graph d_graph, CFAA(Id) is represented by this
        graph, and DD2 is a type DD structure with graph dd_graph.

        """
        assert dd_graph.tensor_side == 1
        assert d_graph.algebra.opp() == self.pmc_alg
        assert dd_graph.algebra1 == self.pmc_alg
        dstr = SimpleDStructure(F2, dd_graph.algebra2)
        # Generators of the type D structure:
        for node1 in d_graph.getNodes():
            for ddgen, node2 in dd_graph.ddgen_node.items():
                if node1.idem == node2.idem1.opp().comp():
                    cur_gen = ATensorDDGenerator(dstr, node1.dgen, ddgen)
                    dstr.addGenerator(cur_gen)

        # Search the graphs for type D operations
        for gen_start in dstr.getGenerators():
            dgen, ddgen = gen_start
            d1_pos = d_graph.graph_node[dgen]
            d2_pos = dd_graph.ddgen_node[ddgen]
            aa_pos = self.homology_node[dgen.idem.opp()]
            pos = [(d1_pos, d2_pos, aa_pos)]
            end_states = self._searchDoubleD(d_graph, dd_graph, pos)[0]
            for d1_end, d2_end, aa_end in end_states:
                gen_end = ATensorDDGenerator(dstr, d1_end.dgen, d2_end.ddgen)
                dstr.addDelta(gen_start, gen_end, d2_end.sd, 1)
        return dstr
Esempio n. 3
0
    def tensorD(self, dstr):
        """Compute the box tensor product DA * D of this bimodule with the given
        type D structure. Returns the resulting type D structure. Uses delta()
        and deltaPrefix() functions of this type DA structure.

        """
        dstr_result = SimpleDStructure(F2, self.algebra1)
        # Compute list of generators in the box tensor product
        for gen_left in self.getGenerators():
            for gen_right in dstr.getGenerators():
                if gen_left.idem2 == gen_right.idem:
                    dstr_result.addGenerator(DATensorDGenerator(
                        dstr_result, gen_left, gen_right))

        def search(start_gen, cur_dgen, 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_dgen: current location in the type D structure.
            - cur_coeffs_a: current list of A-side inputs to the type DA
              structure (or alternatively, list of algebra outputs produced by
              the existing path through the type D 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():
                dstr_result.addDelta(start_gen, DATensorDGenerator(
                    dstr_result, gen_to, cur_dgen), coeff_d, 1)
            if self.deltaPrefix(start_dagen, cur_coeffs_a):
                for (coeff_out, dgen_to), ring_coeff in \
                    dstr.delta(cur_dgen).items():
                    search(start_gen, dgen_to, cur_coeffs_a + (coeff_out,))

        for x in dstr_result.getGenerators():
            dagen, dgen = x
            search(x, dgen, ())
            # Add arrows coming from idempotent output on the D-side
            for (coeff_out, dgen_to), ring_coeff in dstr.delta(dgen).items():
                if coeff_out.isIdempotent():
                    dstr_result.addDelta(
                        x, DATensorDGenerator(dstr_result, dagen, dgen_to),
                        dagen.idem1.toAlgElt(self.algebra1), 1)

        # Find grading set if available on both components
        def tensorGradingSet():
            """Find the grading set of the new type D structure."""
            return GeneralGradingSet([self.gr_set, dstr.gr_set])

        def tensorGrading(gr_set, dagen, dgen):
            """Find the grading of the generator (x, y) in the tensor type D
            structure. The grading set need to be provided as gr_set.

            """
            return GeneralGradingSetElement(
                gr_set, [self.grading[dagen], dstr.grading[dgen]])
            
        if hasattr(self, "gr_set") and hasattr(dstr, "gr_set"):
            dstr_result.gr_set = tensorGradingSet()
            dstr_result.grading = dict()
            for x in dstr_result.getGenerators():
                dagen, dgen = x
                dstr_result.grading[x] = tensorGrading(
                    dstr_result.gr_set, dagen, dgen)

        return dstr_result
Esempio n. 4
0
    def morToD(self, other):
        """Compute the type D structure of morphisms from self to other. Note
        ``other`` must be a type D structure.

        """
        assert self.algebra1 == other.algebra
        alg_gens = self.algebra1.getGenerators()
        xlist = self.getGenerators()
        ylist = other.getGenerators()
        gens = list()
        dstr = SimpleDStructure(F2, self.algebra2.opp())
        genType = MorDDtoDGenerator

        def morGradingSet():
            """Find the grading set of the new type D structure."""
            lr_domains = [(d1, d2.opp())
                          for d1, d2 in self.gr_set.periodic_domains]
            self.lr_set = SimpleDbGradingSet(
                self.gr_set.gr_group1, ACTION_LEFT,
                self.gr_set.gr_group2.opp(), ACTION_RIGHT, lr_domains)
            return GeneralGradingSet([self.lr_set.inverse(), other.gr_set])

        def morGrading(gr_set, x, a, y):
            """Find the grading of the generator x -> ay in the morphism
            type D structure. The grading set need to be provided as gr_set.

            """
            gr_x1, gr_x2 = self.grading[x].data
            gr_x_lr = SimpleDbGradingSetElement(self.lr_set,
                                                (gr_x1, gr_x2.opp()))
            gr = [gr_x_lr.inverse(), other.grading[y] * a.getGrading()]
            return GeneralGradingSetElement(gr_set, gr)

        # Prepare rev_delta for the last step in computing differentials
        rev_delta = self.getReverseDelta()

        # Get the list of generators
        for x in xlist:
            for a in alg_gens:
                for y in ylist:
                    if x.idem1 == a.getLeftIdem() and \
                       y.idem == a.getRightIdem():
                        gens.append(genType(dstr, x, a, y))
        for gen in gens:
            dstr.addGenerator(gen)

        # Get the type D structure maps
        for gen in gens:
            # Differential of y in (x -> ay)
            x, a, y = gen.source, gen.coeff, gen.target
            ady = a * y.delta()
            for (b, q), coeff in ady.items():
                dstr.addDelta(gen, genType(dstr, x, b, q), None, coeff)
            # Differential of a
            for da_gen, coeff in a.diff().items():
                dstr.addDelta(gen, genType(dstr, x, da_gen, y), None, coeff)
            # For each p such that (b1,b2)*x is in dp, add opp(b2)*(p->(b1*a)y)
            for (b1, b2, p), coeff1 in rev_delta[x]:
                for b1a_gen, coeff2 in (b1*a).items():
                    dstr.addDelta(gen, genType(dstr, p, b1a_gen, y),
                                  b2.opp(), coeff1*coeff2)

        # Find grading set and grading of elements
        if hasattr(self, "gr_set") and hasattr(other, "gr_set"):
            dstr.gr_set = morGradingSet()
            dstr.grading = dict()
            for gen in gens:
                dstr.grading[gen] = morGrading(
                    dstr.gr_set, gen.source, gen.coeff, gen.target)
        return dstr
Esempio n. 5
0
 def testTrefoilSurgery(self):
     """Computes HF for +1 and -1 surgery on left-handed trefoil. """
     # Everything is over the PMC of genus 1
     pmc = splitPMC(1)
     algebra = pmc.getAlgebra()
     # Two idempotents
     i0 = pmc.idem([0])
     i1 = pmc.idem([1])
     # Some algebra elements
     rho1 = pmc.sd([(0,1)])
     rho2 = pmc.sd([(1,2)])
     rho3 = pmc.sd([(2,3)])
     rho23 = pmc.sd([(1,3)])
     rho123 = pmc.sd([(0,3)])
     # Now CFD(H_+1)
     d_p1 = SimpleDStructure(F2, algebra)
     a = SimpleDGenerator(d_p1, i1, "a")
     b = SimpleDGenerator(d_p1, i0, "b")
     d_p1.addGenerator(a)
     d_p1.addGenerator(b)
     d_p1.addDelta(a, b, rho2, 1)
     d_p1.addDelta(b, a, rho123, 1)
     print "CFD(H_+1): ", d_p1
     # and CFD(H_-1)
     d_p2 = SimpleDStructure(F2, algebra)
     a = SimpleDGenerator(d_p2, i1, "a")
     b = SimpleDGenerator(d_p2, i0, "b")
     d_p2.addGenerator(a)
     d_p2.addGenerator(b)
     d_p2.addDelta(b, a, rho1, 1)
     d_p2.addDelta(b, a, rho3, 1)
     print "CFD(H_-1): ", d_p2
     # CFD(trefoil)
     d_trefoil = SimpleDStructure(F2, algebra)
     x = SimpleDGenerator(d_trefoil, i0, "x")
     y = SimpleDGenerator(d_trefoil, i0, "y")
     z = SimpleDGenerator(d_trefoil, i0, "z")
     k = SimpleDGenerator(d_trefoil, i1, "k")
     l = SimpleDGenerator(d_trefoil, i1, "l")
     mu1 = SimpleDGenerator(d_trefoil, i1, "mu1")
     mu2 = SimpleDGenerator(d_trefoil, i1, "mu2")
     for gen in [x, y, z, k, l, mu1, mu2]:
         d_trefoil.addGenerator(gen)
     d_trefoil.addDelta(x, k, rho1, 1)
     d_trefoil.addDelta(y, k, rho123, 1)
     d_trefoil.addDelta(mu2, x, rho2, 1)
     d_trefoil.addDelta(mu1, mu2, rho23, 1)
     d_trefoil.addDelta(z, mu1, rho123, 1)
     d_trefoil.addDelta(l, y, rho2, 1)
     d_trefoil.addDelta(z, l, rho3, 1)
     print "CFD(trefoil): ", d_trefoil
     # Compute the Mor complexes
     cx1 = d_p1.morToD(d_trefoil)
     # cx1 = computeATensorD(d_p1, d_trefoil)
     cx1.simplify()
     print "First result: ", cx1
     cx2 = d_p2.morToD(d_trefoil)
     # cx2 = computeATensorD(d_p2, d_trefoil)
     cx2.simplify()
     print "Second result: ", cx2
Esempio n. 6
0
def mappingConeD(f, returnDicts = False):
    "Return the mapping cone of a morphism f (Element class) from one SimpleDStructure to another."
    #Extract some basic info from f
    for f0 in f.keys():
        P = f0.source.parent #Source of f
        Q = f0.target.parent #Target of f
    answer = SimpleDStructure(F2,P.algebra)        
    from_to_new = dict()
    to_to_new = dict()
    new_to_old = dict()
    #Add the generators
    for x in P.getGenerators():
        newx = DGenerator(answer, x.idem)
        from_to_new[x] = newx
        new_to_old[newx] = x
        answer.addGenerator(newx)
    for x in Q.getGenerators():
        newx = DGenerator(answer, x.idem)
        to_to_new[x] = newx
        new_to_old[newx] = x
        answer.addGenerator(newx)
    #Add the differential on P
    for x in P.getGenerators():
        dx = P.delta(x)
        for ay in dx.keys():
            answer.addDelta(from_to_new[x],from_to_new[ay[1]],ay[0],dx[ay])
    for x in Q.getGenerators():
        dx = Q.delta(x)
        for ay in dx.keys():
            answer.addDelta(to_to_new[x],to_to_new[ay[1]],ay[0],dx[ay])
    for f0 in f.keys():
        answer.addDelta(from_to_new[f0.source],to_to_new[f0.target],f0.coeff,f[f0])
    if returnDicts:
        return (answer, from_to_new, to_to_new, new_to_old)
    return answer
Esempio n. 7
0
    def tensorD(self, dstr):
        """Compute the box tensor product DA * D of this bimodule with the given
        type D structure. Returns the resulting type D structure. Uses delta()
        and deltaPrefix() functions of this type DA structure.

        """
        dstr_result = SimpleDStructure(F2, self.algebra1)
        # Compute list of generators in the box tensor product
        for gen_left in self.getGenerators():
            for gen_right in dstr.getGenerators():
                if gen_left.idem2 == gen_right.idem:
                    dstr_result.addGenerator(DATensorDGenerator(
                        dstr_result, gen_left, gen_right))

        def search(start_gen, cur_dgen, algs, last_assign, algs_local,
                   last_prod_d):
            """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_dgen: current location in the type D structure.
            - algs: current list of A-side inputs to the type DA structure (or
              alternatively, list of algebra outputs produced by the existing
              path through the type D structure).
            - algs_local: current list of local restrictions of algs.
            - last_assign: a list of length self.num_singles. For each split
              idempotent, specify the single assignments at the last algebra
              input.
            - prod_d: product of the outer restrictions, except for the last
              algebra input.

            """
            start_dagen, start_dgen = start_gen
            local_MGen = start_dagen.local_gen

            # Preliminary tests
            if len(algs) > 0:
                assert algs[0].left_idem == start_dagen.idem2
            for i in range(len(algs)-1):
                assert algs[i].right_idem == algs[i+1].left_idem
            if any(alg.isIdempotent() for alg in algs):
                return

            # First, adjust local module generator, and check for delta.
            if len(algs_local) > 0:
                local_MGen = self.adjustLocalMGen(local_MGen, algs_local[0])
                if local_MGen is None:
                    return
            local_delta = self.local_da.delta(local_MGen, tuple(algs_local))
            has_delta = (local_delta != E0)

            # Second, check for delta prefix.
            has_delta_prefix = False
            if len(algs) == 0:
                has_delta_prefix = True
            else:
                dbls = [self.single_idems2[i] for i in range(self.num_singles)
                        if last_assign[i] == self.DOUBLE]
                for to_remove in subset(dbls):
                    if len(to_remove) != 0:
                        cur_algs_local = tuple([alg.removeSingleHor(to_remove)
                                                for alg in algs_local])
                    else:
                        cur_algs_local = algs_local
                    if self.testPrefix(local_MGen, cur_algs_local):
                        has_delta_prefix = True
                        break

            if (not has_delta) and (not has_delta_prefix):
                return

            # Now, compute new prod_d.
            if len(algs) > 0:
                prod_d = self.getNewProdD(last_assign, algs[-1], last_prod_d)
            else:
                prod_d = last_prod_d
            if prod_d is None:
                return

            # If has_delta is True, add to delta
            for (local_d, local_y), ring_coeff in local_delta.items():
                alg_d, y = self.joinOutput(local_d, local_y, prod_d)
                if alg_d is not None:
                    dstr_result.addDelta(start_gen, DATensorDGenerator(
                        dstr_result, y, cur_dgen), alg_d, 1)

            if not has_delta_prefix:
                return
            for (new_alg, dgen_to), ring_coeff in dstr.delta(cur_dgen).items():
                new_assign, new_local, last_prod_d = self.extendRestrictions(
                    last_assign, algs_local, prod_d, new_alg)
                if new_assign is not None:
                    search(start_gen, dgen_to, algs + [new_alg],
                           new_assign, new_local, last_prod_d)

        # Perform search for each generator in dstr_result.
        for x in dstr_result.getGenerators():
            dagen, dgen = x
            prod_d = \
                self.splitting2.restrictIdempotentOuter(dagen.idem2).toAlgElt()
            prod_d = prod_d.removeSingleHor()  # always goes to LOCAL
            search(x, dgen, [], [self.DOUBLE] * self.num_singles, [], prod_d)
            # Add arrows coming from idempotent output on the D-side
            for (coeff_out, dgen_to), ring_coeff in dstr.delta(dgen).items():
                if coeff_out.isIdempotent():
                    dstr_result.addDelta(
                        x, DATensorDGenerator(dstr_result, dagen, dgen_to),
                        dagen.idem1.toAlgElt(self.algebra1), 1)

        # Find grading set if available on both components
        def tensorGradingSet():
            """Find the grading set of the new type D structure."""
            return GeneralGradingSet([self.gr_set, dstr.gr_set])

        def tensorGrading(gr_set, dagen, dgen):
            """Find the grading of the generator (x, y) in the tensor type D
            structure. The grading set need to be provided as gr_set.

            """
            return GeneralGradingSetElement(
                gr_set, [self.grading[dagen], dstr.grading[dgen]])

        if hasattr(self, "gr_set") and hasattr(dstr, "gr_set"):
            dstr_result.gr_set = tensorGradingSet()
            dstr_result.grading = dict()
            for x in dstr_result.getGenerators():
                dagen, dgen = x
                dstr_result.grading[x] = tensorGrading(
                    dstr_result.gr_set, dagen, dgen)

        return dstr_result