︠f68ec36b-97d8-49dd-bfd6-a90c9dbbcf9a︠
class Triangles:
    """
    Base class to study equilateral triangles over finite fields
    
    Attributes:
        self.q = number of elements in base field
        self.p = characteristic of base fields
        self.K = base field
        self.KK = list of elements in base field
        self.triangles = list of triangles (rather, indexes relative to self.KK)
        self.Gamma = adjacency graph of triangles
        self.GammaZero = connected component of self.Gamma containing (0,1,-j²)
    """
    def __init__(self,q,all=0):
        self.q = q
        if not is_prime_power(q):
            print "The parameter q is not a prime power!"
            return
        if (self.q-1)%3 != 0:
            print "Field without cubic roots of 1!"
            return
        self.p = list(factor(q))[0][0]
        if self.p == self.q:
            self.K = FiniteField(q)
        else:
            self.K = FiniteField(q,'a')
        self.KK = self.K.list()
        self.R = PolynomialRing(self.K,1,'X')
        self.X = self.R.gens()[0]
        self.j = -(factor(self.X^2+self.X+1)[0][0].coefficient({self.X:0}))
        self.GammaZero = self.gamma() # principal connected component of Gamma_q
        if all==1:
            self.triangles = self.all_triangles()
            self.Gamma = self.graph_all_triangles() # graph Gamma_q

    def voisins(self,triplet):
        """
        Returns the three adjacent equilateral triangles.
        """
        b, c, d = triplet
        return [tuple(sorted([b, c, b + c - d])),
                tuple(sorted([c, d, c + d - b])),
                tuple(sorted([d, b, d + b - c]))]

    def voisinsbis(self,triplet):
        """
        Returns the three adjacent equilateral triangles.
        """
        b, c, d = triplet
        B, C, D = self.KK[b], self.KK[c], self.KK[d]
        return [tuple(sorted([b, c, self.KK.index(B+C-D)])),
                tuple(sorted([c, d, self.KK.index(C+D-B)])),
                tuple(sorted([d, b, self.KK.index(D+B-C)]))]

    def gamma(self):
        """
        Returns the connected component of (0,1,-j²) in the adjacency graph of equilateral triangles.
        This procedure was kindly written for us by Frédéric Chapoton.
        """
        graine = tuple(sorted([self.KK.index(self.K(0)),self.KK.index(self.K(1)),self.KK.index(-self.j^2)]))
        #graine = tuple(sorted([0,1,-self.j^2]))
        it = RecursivelyEnumeratedSet([graine], self.voisinsbis)
        L = list(it)
        G = Graph(loops=False, multiedges=False)
        for v in L:
            for w in self.voisinsbis(v):
                G.add_edge((v, w))
        return G

    def all_triangles(self):
        """
        Returns the list of //all// equilateral triangles.
        """
        TT = []
        for b in range(self.q-1):
            for c in range(b+1,self.q):
                for w in [-self.j^2, -self.j]:
                    d = self.KK[b] + (self.KK[c]-self.KK[b])*w
                    t = tuple(sorted([b,c,self.KK.index(d)]))
                    if not(t in TT):
                        TT.append(t)
        return TT

    def graph_all_triangles(self):
        """
        Returns the adjacency graph of all triangles
        """
        G = Graph(loops=False, multiedges=False)
        for v in self.triangles:
            for w in self.voisinsbis(v):
                G.add_edge((v, w))
        return G
︡b2204381-00c5-452f-8415-98537e94110b︡{"done":true}︡
︠3182ed41-981e-420c-9574-06b6ab49ab1bs︠
T = Triangles(7,1)
print 'Total number of triangles: %s' % len(T.triangles)
print 'Number of triangles in a connected component: %s' % len(T.GammaZero.vertices())
print 'List of triangles: %s' % T.triangles
︡a5ade3dc-7dee-4951-af31-30f85348ba43︡{"stdout":"Total number of triangles: 14\n"}︡{"stdout":"Number of triangles in a connected component: 14\n"}︡{"stdout":"List of triangles: [(0, 1, 5), (0, 1, 3), (0, 2, 3), (0, 2, 6), (0, 4, 6), (0, 4, 5), (1, 2, 6), (1, 2, 4), (1, 3, 4), (1, 5, 6), (2, 3, 5), (2, 4, 5), (3, 4, 6), (3, 5, 6)]\n"}︡{"done":true}︡
︠58131773-ee37-4909-9688-c822a7908997s︠
T.GammaZero.automorphism_group().is_isomorphic(PGL(2,7))
︡6ad3165c-5315-4cec-a1fc-3fe73e1f5ad7︡{"stdout":"True"}︡{"stdout":"\n"}︡{"done":true}︡
︠e8eed0be-a595-4691-9754-276467b5b782s︠
U = Triangles(25,1)
print 'Total number of triangles: %s' % len(U.triangles)
print 'Number of triangles in a connected component: %s' % len(U.GammaZero.vertices())
U.GammaZero.show()
︡3e4e0c98-8ae0-46a6-93ad-8799ed2b7b8f︡{"stdout":"Total number of triangles: 200\n"}︡{"stdout":"Number of triangles in a connected component: 50\n"}︡{"file":{"filename":"/projects/aa0accd2-e77c-44c5-bfc9-1f4c0dab2c3f/.sage/temp/compute3-us/2104/tmp_PE5b3W.svg","show":true,"text":null,"uuid":"6048e635-c4d9-4fab-9c6a-c3eca2930b8e"},"once":false}︡{"html":"<div align='center'></div>"}︡{"done":true}︡
︠1de01784-a36c-416a-97c3-35f5e0d69f41s︠
V = Triangles(16,1)
print 'Total number of triangles: %s' % len(V.triangles)
print 'Number of triangles in a connected component: %s' % len(V.GammaZero.vertices())
V.GammaZero.show()
︡7cc8b99b-8881-49aa-a4fb-154d97eb4515︡{"stdout":"Total number of triangles: 80\n"}︡{"stdout":"Number of triangles in a connected component: 4\n"}︡{"file":{"filename":"/projects/aa0accd2-e77c-44c5-bfc9-1f4c0dab2c3f/.sage/temp/compute3-us/2104/tmp_GHzF0M.svg","show":true,"text":null,"uuid":"cac7525d-30c2-4883-97d9-3ed00bd1d60d"},"once":false}︡{"html":"<div align='center'></div>"}︡{"done":true}︡
︠f577671d-ca22-47c8-bd57-bdc8f870d39b︠









