# Ticket #14234: trac_14232_latexDrawing.patch

File trac_14232_latexDrawing.patch, 36.1 KB (added by ghseeli, 8 years ago)
• ## sage/combinat/diagram_algebras.py

# HG changeset patch
# User George H. Seelinger <ghseeli@gmail.com>
# Date 1369881292 14400
# Node ID 67701ca9d7127018110cd655267011f15e977ec1
# Parent  50e0a52c20ecd4e5125a11d46d32d1f53ae9f896
diff --git a/sage/combinat/diagram_algebras.py b/sage/combinat/diagram_algebras.py
 a Diagram/Partition Algebras """ #***************************************************************************** #  Copyright (C) 2007 Mike Hansen , #  Copyright (C) 2007 Mike Hansen , #                2012 Stephen Doty , #                     Aaron Lauve , #                     George H. Seelinger #***************************************************************************** from sage.categories.all import FiniteDimensionalAlgebrasWithBasis from sage.combinat.family import Family from sage.combinat.free_module import (CombinatorialFreeModule, from sage.combinat.free_module import (CombinatorialFreeModule, CombinatorialFreeModuleElement) from sage.combinat.set_partition import SetPartitions from sage.sets.set import Set from sage.graphs.graph import Graph from sage.misc.cachefunc import cached_method from sage.misc.latex import latex import collections import functools, math ##these four imports are for drawing diagrams; these may be removed in the final version. #import networkx #import pylab #import matplotlib.pyplot as plt #import itertools ## def partition_diagrams(k): r""" Set partitions of [1, 2, -1, -2] with sizes in [[2, 2]] sage: brauer_diagrams(2.5) #random order [{{1, 2}, {3, -3}, {-1, -2}}, {{2, -2}, {3, -3}, {1, -1}}, {{2, -1}, {3, -3}, {1, -2}}] """ if int(k) == k: return SetPartitions( range(1,k+1) + [-j for j in range(1,k+1)], [2 for j in range(1,k+1)] ) TODO: SHOULD BE MADE A METHOD OF THE SetPartitions CLASS ? """ return s in partition_diagrams(k) class PartitionAlgebra(CombinatorialFreeModule): class DiagramAlgebra(CombinatorialFreeModule): r""" Abstract class designed not to be used directly. If used directly, the class could create an algebra that is not actually an algebra. TESTS:: sage: D = DiagramAlgebra(x, QQ[x], 'P', partition_diagrams(2)) sage: D.basis() Lazy family (Term map from Set partitions of [1, 2, -1, -2] to Free module generated by Set partitions of [1, 2, -1, -2] over Univariate Polynomial Ring in x over Rational Field(i))_{i in Set partitions of [1, 2, -1, -2]} """ def __init__(self, q, base_ring, prefix, diagrams): r""" See :class:DiagramAlgebra for full documentation. TESTS:: sage: D = DiagramAlgebra(x, QQ[x], 'P', partition_diagrams(2)) """ self._prefix = prefix self._q = base_ring(q) category = FiniteDimensionalAlgebrasWithBasis(base_ring) CombinatorialFreeModule.__init__(self, base_ring, diagrams, category = category, prefix=prefix) def _element_constructor_(self, set_partition): r""" If D is a particular diagram algebra (previously defined) then D( sp ) returns the element of the algebra D corresponding to a given set partition sp. TESTS:: sage: D = DiagramAlgebra(x, QQ[x], 'P', partition_diagrams(2)) sage: sp = to_set_partition( [[1,2], [-1,-2]] )  # create a set partition sage: sp {{1, 2}, {-1, -2}} sage: D(sp)  # construct a basis element from it P[{{1, 2}, {-1, -2}}] sage: D(sp) in D True sage: D([[1,2],[-1,-2]]) P[{{1, 2}, {-1, -2}}] sage: D([{1,2},{-1,-2}]) P[{{1, 2}, {-1, -2}}] """ if (set_partition in self.basis().keys()) and isinstance(set_partition, collections.Hashable): return self.monomial(set_partition) elif isinstance(set_partition, list): sp = to_set_partition(set_partition) # attempt coercion assert sp in self.basis().keys() # did it work? return self.monomial(sp) else: raise AssertionError, "%s invalid form" % set_partition def set_partitions(self): r""" This method returns the collection of underlying set partitions indexing the basis elements of a given diagram algebra. TESTS:: sage: D = DiagramAlgebra(x, QQ[x], 'P', partition_diagrams(2)) sage: D.set_partitions() == partition_diagrams(2) True """ return self.basis().keys() def product_on_basis(self, d1, d2): r""" This method defines the product of two basis diagrams. Usually it is not called directly, but indirectly through usualy arithmetic operators. TESTS:: sage: D = DiagramAlgebra(x, QQ[x], 'P', partition_diagrams(2)); sage: D.product_on_basis(D([[1,2],[-1,-2]]), D([[1,2],[-1,-2]])) x*P[{{1, {{1, 2}, {-1, -2}}}}] """ (composite_diagram, loops_removed) = set_partition_composition(d1, d2) return self.term(composite_diagram, self._q**loops_removed) # The following subclass provides a few additional methods for # partition algebra elements.  NOTE: Most element methods we need are # ALREADY implemented! Use the __dir__() builtin python function # to figure out what methods are defined. class Element(CombinatorialFreeModuleElement): r""" This subclass provides a few additional methods for partition algebra elements. Most element methods are already implemented elsewhere. """ def diagram(self): r""" This method returns the underlying diagram of a given basis element (or an error if not a basis element.) """ if len(self) != 1: raise NotImplementedError("this works only for basis elements") PA = self.parent() ans = self.support_of_term() if is_partition_diagram(ans,PA.order()): return ans raise NotImplementedError("element should be keyed by a diagram") def diagrams(self): r""" this method returns the diagrams in the support of any given element. It is just a rename of "support" which already exists. """ return self.support() def _latex_(self): latex.add_to_mathjax_avoid_list('tikzpicture') latex.add_package_to_preamble_if_available('tikz') #these allow the view command to work. Should be moved? diagram = self.diagram() l1 = [] #list of blocks l2 = [] #lsit of nodes for i in list(diagram): l1.append(list(i)) for j in list(i): l2.append(j) output = "\\begin{tikzpicture}[scale = 0.9,thick] \n\\tikzstyle{vertex} = [shape = circle, minimum size = 9pt, inner sep = 1pt] \n" #setup beginning of picture for i in l2: #add nodes output = output + "\\node[vertex] (G-%s) at (%s, %s) [shape = circle, draw] {}; \n" % (i, (abs(i)-1)*1.5, sgn(i)) for i in l1: #add edges if (len(i) > 1): l4 = list(i) posList = [] negList = [] for i in l4: #sort list so rows are grouped together if i > 0: posList.append(i) elif i < 0: negList.append(i) posList.sort() negList.sort() l4 = posList + negList l5 = l4[:] #deep copy for j in range(len(l5)): l5[j-1] = l4[j] #create a permuted list if (len(l4) == 2): l4.pop() l5.pop() #pops to prevent duplicating edges for j in zip(l4, l5): xdiff = abs(j[1])-abs(j[0]) y1 = sgn(j[0]) y2 = sgn(j[1]) if ((y2-y1) == 0 and abs(xdiff) < 5): #if nodes are close to each other on same row diffCo = (0.5+0.1*(abs(xdiff)-1)) #gets bigger as nodes are farther apart; max value of 1; min value of 0.5. outVec = (sgn(xdiff)*diffCo, -1*diffCo*y1) inVec = (-1*diffCo*sgn(xdiff), -1*diffCo*y2) elif ((y2-y1) != 0 and abs(xdiff) == 1): #if nodes are close enough curviness looks bad. outVec = (sgn(xdiff)*0.75, -1*y1) inVec = (-1*sgn(xdiff)*0.75, -1*y2) else: outVec = (sgn(xdiff)*1, -1*y1) inVec = (-1*sgn(xdiff), -1*y2) output = output + "\\draw (G-%s) .. controls +%s and +%s .. (G-%s); \n" % (j[0], outVec, inVec,j[1]) output = output + "\\end{tikzpicture}" #end picture return output class PartitionAlgebra(DiagramAlgebra): r""" INPUT: the product of two set partitions is simply given by their composition. The Iwahori-Hecke algebra of type A (with a single parameter) is naturally a subalgebra of the partition algebra. a subalgebra of the partition algebra. An excellent reference for partition algebras and its various subalgebras (Brauer algebra, Temperley-Lieb algebra, etc) is the paper [HR]_. The following shorthand simultaneously define the univariate polynomial ring over the rationals as well as the variable x:: sage: R. = PolynomialRing(QQ) sage: R Univariate Polynomial Ring in x over Rational Field :: sage: PA.one() #random order from SetPartitions P[{{2, -2}, {1, -1}}] P[{{2, -2}, {1, -1}}] sage: PA.one()*P[7] P[{{1, 2}, {-2, -1}}] sage: P[7]*PA.one() sage: PA = PartitionAlgebra(2, q, RR['q'], prefix='B') sage: PA Partition Algebra of rank 2 with parameter q over Univariate Polynomial Ring in q over Real Field with 53 bits of precision, with prefix B sage: PA.basis().list()[7] sage: PA([[1,2],[-1,-2]]) #random order due to set partitions. 1.00000000000000*B[{{1, 2}, {-2, -1}}] sage: PA = PartitionAlgebra(2, 5, base_ring=ZZ, prefix='B') sage: PA Partition Algebra of rank 2 with parameter 5 over Integer Ring, with prefix B sage: P = PA.basis().list() sage: (P[6] - 2*P[7])^2 sage: (P[6] - 2*P[7])^2 #Is this an okay test? Is the order of basis elements always the same? 16*B[{{1, 2}, {-2, -1}}] + B[{{2, -2}, {1, -1}}] """ sage: PA = PartitionAlgebra(2, q, RR['q']) sage: TestSuite(PA).run() """ self._k = k self._prefix = prefix self._q = base_ring(q) category = FiniteDimensionalAlgebrasWithBasis(base_ring) CombinatorialFreeModule.__init__(self, base_ring, partition_diagrams(k), category = category, prefix=prefix) DiagramAlgebra.__init__(self, q, base_ring, prefix, partition_diagrams(k)) # The following constructs a basis element from a given set partition. # It should never be called directly. def _element_constructor_(self, set_partition): r""" If PA is a particular partition algebra (previously defined) then PA( sp ) returns the element of the algebra PA corresponding to a given set partition sp. EXAMPLES:: sage: q = var('q') sage: PA = PartitionAlgebra(2,q,QQ['q']) sage: PA Partition Algebra of rank 2 with parameter q over Univariate Polynomial Ring in q over Rational Field, with prefix P sage: sp = to_set_partition( [[1,2], [-1,-2]] )  # create a set partition sage: sp {{1, 2}, {-1, -2}} sage: PA(sp)  # construct a basis element from it P[{{1, 2}, {-1, -2}}] sage: PA(sp) in PA True sage: PA([[1,2],[-1,-2]]) P[{{1, 2}, {-1, -2}}] sage: PA([{1,2},{-1,-2}]) P[{{1, 2}, {-1, -2}}] """ if (set_partition in self.basis().keys()) and isinstance(set_partition, collections.Hashable): return self.monomial(set_partition) elif isinstance(set_partition, list): sp = to_set_partition(set_partition) # attempt coercion assert sp in self.basis().keys() # did it work? return self.monomial(sp) else: raise AssertionError, "%s invalid form" % set_partition #       CombinatorialFreeModule.__init__(self, base_ring, partition_diagrams(k), #            category = category, prefix=prefix) @cached_method def one_basis(self): """ return self._k def set_partitions(self): r""" The method PA.set_partitions() returns the collection of underlying set partitions indexing the basis elements of the given partition algebra PA. EXAMPLES:: sage: PA = PartitionAlgebra(2, x) sage: PA.set_partitions() Set partitions of [1, 2, -1, -2] sage: PA.set_partitions().list() #random order [{{1, 2, -1, -2}}, {{2, -1, -2}, {1}}, {{2}, {1, -1, -2}}, {{-1}, {1, 2, -2}}, {{-2}, {1, 2, -1}}, {{2, -1}, {1, -2}}, {{2, -2}, {1, -1}}, {{1, 2}, {-2, -1}}, {{2}, {-1, -2}, {1}}, {{-1}, {2, -2}, {1}}, {{-2}, {2, -1}, {1}}, {{-1}, {2}, {1, -2}}, {{-2}, {2}, {1, -1}}, {{-1}, {-2}, {1, 2}}, {{-1}, {-2}, {2}, {1}}] """ return self.basis().keys() def product_on_basis(self, d1, d2): r""" This method defines the product of two basis diagrams. Usually it is not called directly, but indirectly through usualy arithmetic operators. TESTS:: sage: P = PartitionAlgebra(2, x); sage: P.product_on_basis(P([[1,2],[-1,-2]]), P([[1,2],[-1,-2]])) x*P[{{1, {{1, 2}, {-1, -2}}}}] """ (composite_diagram, loops_removed) = set_partition_composition(d1, d2) return self.term(composite_diagram, self._q**loops_removed) # The following subclass provides a few additional methods for # partition algebra elements.  NOTE: Most element methods we need are # ALREADY implemented! Use the __dir__() builtin python function # to figure out what methods are defined. class Element(CombinatorialFreeModuleElement): r""" This subclass provides a few additional methods for partition algebra elements. Most element methods are already implemented elsewhere. """ def diagram(self): r""" This method returns the underlying diagram of a given basis element (or an error if not a basis element.) """ if len(self) != 1: raise NotImplementedError("this works only for basis elements") PA = self.parent() ans = self.support_of_term() if is_partition_diagram(ans,PA.order()): return ans raise NotImplementedError("element should be keyed by a diagram") def diagrams(self): r""" this method returns the diagrams in the support of any given element. It is just a rename of "support" which already exists. """ return self.support() #        def show(self): #            diagram = self.diagram() #            sp = to_set_partition(diagram) #            sageGraph = to_graph(sp) #            G = sageGraph.networkx_graph() #            flatlist = itertools.chain(*diagram) #            k = max(flatlist) #            pos=dict(zip(range(1,k+1),zip(range(1,k+1),[1]*k))) #            pos.update(dict(zip(reversed(range(-k,0)),zip(range(1,k+1),[0.5]*k)))) #            plt.clf() #            networkx.draw(G,pos) #            pylab.xlim(-1,9) #            pylab.ylim(-1,2) #            plt.savefig("tmp.png", bbox_inches='tight', pad_inches=-1) #            plt.show() class BrauerAlgebra(CombinatorialFreeModule): class BrauerAlgebra(DiagramAlgebra): r""" INPUT: The following shorthand simultaneously define the univariate polynomial ring over the rationals as well as the variable x:: sage: R. = PolynomialRing(QQ) sage: R Univariate Polynomial Ring in x over Rational Field self._prefix = prefix self._q = base_ring(q) category = FiniteDimensionalAlgebrasWithBasis(base_ring) CombinatorialFreeModule.__init__(self, base_ring, brauer_diagrams(k), category = category, prefix=prefix) DiagramAlgebra.__init__(self, q, base_ring, prefix, brauer_diagrams(k)) @cached_method def one_basis(self): r""" """ return identity_set_partition(self._k) def _repr_(self): msg = "Brauer Algebra of rank %s with parameter %s over %s, with prefix %s" return msg % (self._k, self._q, self.base_ring(), self._prefix) def _element_constructor_(self, set_partition): r""" If BA is a particular Brauer algebra (previously defined) then If BA is a particular Brauer algebra (previously defined) then BA( sp ) returns the element of the algebra BA corresponding to a given set partition sp. sage: BA([{1,2},{-1,-2}]) B[{{1, 2}, {-1, -2}}] """ if (set_partition in self.basis().keys()) and isinstance(set_partition, collections.Hashable): return self.monomial(set_partition) elif isinstance(set_partition, list): sp = to_set_partition(set_partition) # attempt coercion assert sp in self.basis().keys() # did it work? return self.monomial(sp) else: raise AssertionError, "%s invalid form" % set_partition set_partition = to_Brauer_partition(set_partition, k = self.order()) return DiagramAlgebra._element_constructor_(self, set_partition) #These methods allow for BrauerAlgebra to be correctly identified as a sub-algebra of PartitionAlgebra #With the DiagramAlgebra superclass, are these really necessary? def ambient(self): r""" ambient returns the partition algebra the Brauer algebra is a sub-algebra of. for i in xrange(len(monomial_coefficients)): result += monomial_coefficients[i]*self.monomial(monomial_indices[i]) return result #These methods depend on the above three methods def product_on_basis(self, left, right): r""" This method is not made to be called directly but by using arithematic operators on elements. EXAMPLES:: sage: BA = BrauerAlgebra(2, x) sage: E = BA([[1,2],[-1,-2]]) sage: E*E x*B[{{1, 2}, {-2, -1}}] sage: E^4 x^3*B[{{1, 2}, {-2, -1}}] """ return self.ambient().product_on_basis(left,right) def order(self): r""" Returns the order of the Brauer Algebra 2 """ return self.ambient().order() class TemperleyLiebAlgebra(CombinatorialFreeModule): class TemperleyLiebAlgebra(DiagramAlgebra): r""" INPUT: The following shorthand simultaneously define the univariate polynomial ring over the rationals as well as the variable x:: sage: R. = PolynomialRing(QQ); R Univariate Polynomial Ring in x over Rational Field sage: x self._prefix = prefix self._q = base_ring(q) category = FiniteDimensionalAlgebrasWithBasis(base_ring) CombinatorialFreeModule.__init__(self, base_ring, temperley_lieb_diagrams(k), category = category, prefix=prefix) DiagramAlgebra.__init__(self, q, base_ring, prefix, temperley_lieb_diagrams(k)) @cached_method def one_basis(self): sage: TL([{1,2},{-1,-2}]) T[{{1, 2}, {-1, -2}}] """ if (set_partition in self.basis().keys()) and isinstance(set_partition, collections.Hashable): return self.monomial(set_partition) elif isinstance(set_partition, list): sp = to_set_partition(set_partition) # attempt coercion assert sp in self.basis().keys() # did it work? return self.monomial(sp) else: raise AssertionError, "%s invalid form" % set_partition set_partition = to_Brauer_partition(set_partition, k = self.order()) return DiagramAlgebra._element_constructor_(self, set_partition) def ambient(self): r""" result += monomial_coefficients[i]*self.monomial(monomial_indices[i]) return result def product_on_basis(self, left, right): r""" This method is not made to be called directly but by using arithematic operators on elements. EXAMPLES:: sage: TL = TemperleyLiebAlgebra(2, x) sage: E = TL([[1,2],[-1,-2]]) sage: E*E x*T[{{1, 2}, {-2, -1}}] sage: E^4 x^3*T[{{1, 2}, {-2, -1}}] """ return self.ambient().product_on_basis(left,right) def order(self): r""" Returns the order of the Temperley-Lieb Algebra """ return self.ambient().order() class PlanarAlgebra(CombinatorialFreeModule): class PlanarAlgebra(DiagramAlgebra): r""" INPUT: The following shorthand simultaneously define the univariate polynomial ring over the rationals as well as the variable x:: sage: R. = PolynomialRing(QQ); R Univariate Polynomial Ring in x over Rational Field sage: x self._prefix = prefix self._q = base_ring(q) category = FiniteDimensionalAlgebrasWithBasis(base_ring) CombinatorialFreeModule.__init__(self, base_ring, planar_diagrams(k), category = category, prefix=prefix) DiagramAlgebra.__init__(self, q, base_ring, prefix, planar_diagrams(k)) @cached_method def one_basis(self): msg = "Planar Algebra of rank %s with parameter %s over %s, with prefix %s" return msg % (self._k, self._q, self.base_ring(), self._prefix) def _element_constructor_(self, set_partition): r""" If PlA is a particular Planar algebra (previously defined) then PlA( sp ) returns the element of the algebra PlA corresponding to a given set partition sp. EXAMPLES:: sage: q = var('q') sage: PlA = PlanarAlgebra(2,q,QQ['q']) sage: PlA Planar Algebra of rank 2 with parameter q over Univariate Polynomial Ring in q over Rational Field, with prefix Pl sage: sp = to_set_partition( [[1,2], [-1,-2]] )  # create a set partition sage: sp {{1, 2}, {-1, -2}} sage: PlA(sp)  # construct a basis element from it Pl[{{1, 2}, {-1, -2}}] sage: PlA(sp) in PlA True sage: PlA([[1,2],[-1,-2]]) Pl[{{1, 2}, {-1, -2}}] sage: PlA([{1,2},{-1,-2}]) Pl[{{1, 2}, {-1, -2}}] """ if (set_partition in self.basis().keys()) and isinstance(set_partition, collections.Hashable): return self.monomial(set_partition) elif isinstance(set_partition, list): sp = to_set_partition(set_partition) # attempt coercion assert sp in self.basis().keys() # did it work? return self.monomial(sp) else: raise AssertionError, "%s invalid form" % set_partition def ambient(self): r""" ambient returns the partition algebra the Planar algebra result += monomial_coefficients[i]*self.monomial(monomial_indices[i]) return result def product_on_basis(self, left, right): r""" This method is not made to be called directly but by using arithematic operators on elements. EXAMPLES:: sage: PlA = PlanarAlgebra(2, x) sage: E = PlA([[1,2],[-1,-2]]) sage: E*E x*Pl[{{1, 2}, {-2, -1}}] sage: E^4 x^3*Pl[{{1, 2}, {-2, -1}}] """ return self.ambient().product_on_basis(left,right) def order(self): r""" Returns the order of the Planar Algebra """ return self.ambient().order() class IdealAlgebra(CombinatorialFreeModule): class IdealAlgebra(DiagramAlgebra): r""" INPUT: The following shorthand simultaneously define the univariate polynomial ring over the rationals as well as the variable x:: sage: R. = PolynomialRing(QQ); R Univariate Polynomial Ring in x over Rational Field sage: x self._prefix = prefix self._q = base_ring(q) category = FiniteDimensionalAlgebrasWithBasis(base_ring) CombinatorialFreeModule.__init__(self, base_ring, ideal_diagrams(k), category = category, prefix=prefix) DiagramAlgebra.__init__(self, q, base_ring, prefix, ideal_diagrams(k)) @cached_method def one_basis(self): instead one should use I.one() if I is a previously defined Ideal algebra instance. Technically speaking, the Ideal algebra is an algebra without a multiplicative identity. This has to be fixed by the creation of a new category, such as FiniteDimensionalAlgebraWithBasisWithoutUnity. TODO: Make this method correct. msg = "Ideal Algebra of rank %s with parameter %s over %s, with prefix %s" return msg % (self._k, self._q, self.base_ring(), self._prefix) def _element_constructor_(self, set_partition): r""" If I is a particular Ideal algebra (previously defined) then I( sp ) returns the element of the algebra I corresponding to a given set partition sp. EXAMPLES:: sage: q = var('q') sage: I = IdealAlgebra(2,q,QQ['q']) sage: I Ideal Algebra of rank 2 with parameter q over Univariate Polynomial Ring in q over Rational Field, with prefix I sage: sp = to_set_partition( [[1,2], [-1,-2]] )  # create a set partition sage: sp {{1, 2}, {-1, -2}} sage: I(sp)  # construct a basis element from it I[{{1, 2}, {-1, -2}}] sage: I(sp) in I True sage: I([[1,2],[-1,-2]]) I[{{1, 2}, {-1, -2}}] sage: I([{1,2},{-1,-2}]) I[{{1, 2}, {-1, -2}}] """ if (set_partition in self.basis().keys()) and isinstance(set_partition, collections.Hashable): return self.monomial(set_partition) elif isinstance(set_partition, list): sp = to_set_partition(set_partition) # attempt coercion assert sp in self.basis().keys() # did it work? return self.monomial(sp) else: raise AssertionError, "%s invalid form" % set_partition def ambient(self): r""" ambient returns the partition algebra the Ideal algebra result += monomial_coefficients[i]*self.monomial(monomial_indices[i]) return result def product_on_basis(self, left, right): r""" This method is not made to be called directly but by using arithematic operators on elements. EXAMPLES:: sage: I = IdealAlgebra(2, x) sage: E = I([[1,2],[-1,-2]]) sage: E*E x*I[{{1, 2}, {-2, -1}}] sage: E^4 x^3*I[{{1, 2}, {-2, -1}}] """ return self.ambient().product_on_basis(left,right) def order(self): r""" Returns the order of the Temperley-Lieb Algebra # with partition diagrams, compositions of partition diagrams, and so on. # --> CHANGED 'identity' to 'identity_set_partition' for enhanced clarity. ######################################################################### def is_planar(sp): r""" Returns True if the diagram corresponding to the set partition is planar; otherwise, it returns False. EXAMPLES:: sage: import sage.combinat.partition_algebra as pa sage: pa.is_planar( pa.to_set_partition([[1,-2],[2,-1]])) False #Singletons don't affect planarity to_consider = filter(lambda x: len(x) > 1, to_consider) n = len(to_consider) for i in range(n): #Get the positive and negative entries of this #part continue else: rng = range(row[s] + 1, row[s+1]) #Go through and make sure any parts that #contain numbers in this range are completely #contained in this range else: sr = Set(map(lambda x: -1*x, rng)) sj = Set(to_consider[j]) intersection = sr.intersection(sj) if intersection: return True def to_graph(sp): r""" Returns a graph representing the set partition sp. EXAMPLES:: sage: import sage.combinat.partition_algebra as pa sage: g = pa.to_graph( pa.to_set_partition([[1,-2],[2,-1]])); g Graph on 4 vertices :: sage: g.vertices() #random [1, 2, -2, -1] sage: g.edges() #random Returns a graph consisting of the graphs of set partitions sp1 and sp2 along with edges joining the bottom row (negative numbers) of sp1 to the top row (positive numbers) of sp2. EXAMPLES:: sage: import sage.combinat.partition_algebra as pa sage: sp1 = pa.to_set_partition([[1,-2],[2,-1]]) sage: sp2 = pa.to_set_partition([[1,-2],[2,-1]]) sage: sp2 = pa.to_set_partition([[1,-2],[2,-1]]) sage: g = pa.pair_to_graph( sp1, sp2 ); g Graph on 8 vertices :: sage: g.vertices() #random [(1, 2), (-1, 1), (-2, 2), (-1, 2), (-2, 1), (2, 1), (2, 2), (1, 1)] sage: g.edges() #random #Add the edge to the second part of the graph if part_list[0] < 0 and len(part_list) > 1: g.add_edge( (part_list[0], 1), (abs(part_list[0]),2)  ) for i in range(1, len(part_list)): g.add_vertex( (part_list[i],1) ) #Add the edge to the second part of the graph if part_list[i] < 0: g.add_edge( (part_list[i], 1), (abs(part_list[i]),2) ) for i in range(1, len(part_list)): g.add_vertex( (part_list[i],2) ) g.add_edge( (part_list[i-1],2), (part_list[i],2) ) return g def propagating_number(sp): Returns the propagating number of the set partition sp. The propagating number is the number of blocks with both a positive and negative number. EXAMPLES:: sage: import sage.combinat.partition_algebra as pa sage: sp1 = pa.to_set_partition([[1,-2],[2,-1]]) sage: sp2 = pa.to_set_partition([[1,2],[-2,-1]]) sage: sp2 = pa.to_set_partition([[1,2],[-2,-1]]) sage: pa.propagating_number(sp1) 2 sage: pa.propagating_number(sp2) Converts a list of a list of numbers to a set partitions. Each list of numbers in the outer list specifies the numbers contained in one of the blocks in the set partition. If k is specified, then the set partition will be a set partition of 1, ..., k, -1, ..., -k. Otherwise, k will default to the minimum number needed to contain all of the specified numbers. EXAMPLES:: sage: import sage.combinat.partition_algebra as pa sage: import sage.combinat.partition_algebra as pa #TODO: change this sage: pa.to_set_partition([[1,-1],[2,-2]]) == pa.identity(2) True """ k = max( map( lambda x: max( map(abs, x) ), l) ) to_be_added = Set( range(1, k+1) + map(lambda x: -1*x, range(1, k+1) ) ) sp = [] for part in l: spart = Set(part) sp.append(Set([singleton])) return Set(sp) def to_Brauer_partition(l,k=None): r""" Works like to_set_partition but assumes ommitted elements are connected straight through. EXAMPLES:: sage: to_Brauer_partition([[1,2],[-1,-2]]) {{1, 2}, {-1, -2}} sage: to_Brauer_partition([[1,3],[-1,-3]]) {{1, 3}, {-3, -1}, {2, -2}} sage: to_Brauer_partition([[1,2],[-1,-2]], k=4) {{1, 2}, {3, -3}, {-1, -2}, {4, -4}} sage: to_Brauer_partition([[1,-4],[-3,-1],[3,4]]) {{-3, -1}, {2, -2}, {1, -4}, {3, 4}} """ L = to_set_partition(l, k) L2 = [] paired = [] not_paired = [] for i in L: L2.append(list(i)) for i in L2: assert len(i) < 3 if (len(i) == 2): paired.append(i) if (len(i) == 1): not_paired.append(i) for i in not_paired: for j in paired: assert i[0] not in j assert -1*i[0] not in j for i in not_paired: if [-1*i[0]] in not_paired: not_paired.remove([-1*i[0]]) paired.append([i[0], -1*i[0]]) return to_set_partition(paired) def identity_set_partition(k): """ Returns the identity set partition 1, -1, ..., k, -k EXAMPLES:: sage: identity_set_partition(2) #random order {{2, -2}, {1, -1}} """ Returns a tuple consisting of the composition of the set partitions sp1 and sp2 and the number of components removed from the middle rows of the graph. EXAMPLES:: sage: import sage.combinat.partition_algebra as pa sage: import sage.combinat.partition_algebra as pa #change to this file? sage: sp1 = pa.to_set_partition([[1,-2],[2,-1]]) sage: sp2 = pa.to_set_partition([[1,-2],[2,-1]]) sage: pa.set_partition_composition(sp1, sp2) == (pa.identity(2), 0) ########################################################################## # END BORROWED CODE ########################################################################## ##########################################################################