def RandomLinearCodeGuava(n,k,F): r""" The method used is to first construct a `k \times n` matrix of the block form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a `k \times (n-k)` matrix constructed using random elements of `F`. Then the columns are permuted using a randomly selected element of the symmetric group `S_n`. INPUT: Integers `n,k`, with `n>k>1`. OUTPUT: Returns a "random" linear code with length n, dimension k over field F. EXAMPLES:: sage: C = RandomLinearCodeGuava(30,15,GF(2)); C # optional - gap_packages (Guava package) Linear code of length 30, dimension 15 over Finite Field of size 2 sage: C = RandomLinearCodeGuava(10,5,GF(4,'a')); C # optional - gap_packages (Guava package) Linear code of length 10, dimension 5 over Finite Field in a of size 2^2 AUTHOR: David Joyner (11-2005) """ current_randstate().set_seed_gap() q = F.order() gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))") gap.eval("G:=GeneratorMat(C)") k = int(gap.eval("Length(G)")) n = int(gap.eval("Length(G[1])")) G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i,j)),F) for j in range(1,n+1)] for i in range(1,k+1)] MS = MatrixSpace(F,k,n) return LinearCode(MS(G))
def random_element(self): """ Return a random element of this group. EXAMPLES:: sage: G = Sp(4,GF(3)) sage: G.random_element() # random [2 1 1 1] [1 0 2 1] [0 1 1 0] [1 0 0 1] sage: G.random_element() in G True :: sage: F = GF(5); MS = MatrixSpace(F,2,2) sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])] sage: G = MatrixGroup(gens) sage: G.random_element() # random [1 3] [0 3] sage: G.random_element() in G True """ # Note: even with fixed random seed, the Random() element # returned by gap does depend on execution order and # architecture. Presumably due to different memory loctions. current_randstate().set_seed_gap() F = self.field_of_definition() return self.element_class(gap(self).Random()._matrix_(F), self, check=False)
def conjugacy_class_representatives(self): """ Return a set of representatives for each of the conjugacy classes of the group. EXAMPLES:: sage: G = SU(3,GF(2)) sage: len(G.conjugacy_class_representatives()) 16 sage: len(GL(2,GF(3)).conjugacy_class_representatives()) 8 sage: len(GU(2,GF(5)).conjugacy_class_representatives()) 36 """ current_randstate().set_seed_gap() try: return self.__reps except AttributeError: pass G = self._gap_().ConjugacyClasses() reps = list(gap.List(G, 'x -> Representative(x)')) F = self.field_of_definition() self.__reps = Sequence([self(g._matrix_(F)) for g in reps], cr=True, universe=self, check=False) return self.__reps
def RandomShell(constructor, seed=None): """ Returns a random shell graph for the constructor given. INPUT: - ``constructor`` - a list of 3-tuples (n,m,d), each representing a shell - ``n`` - the number of vertices in the shell - ``m`` - the number of edges in the shell - ``d`` - the ratio of inter (next) shell edges to intra shell edges - ``seed`` - for the random number generator EXAMPLE:: sage: G = graphs.RandomShell([(10,20,0.8),(20,40,0.8)]) sage: G.edges(labels=False) [(0, 3), (0, 7), (0, 8), (1, 2), (1, 5), (1, 8), (1, 9), (3, 6), (3, 11), (4, 6), (4, 7), (4, 8), (4, 21), (5, 8), (5, 9), (6, 9), (6, 10), (7, 8), (7, 9), (8, 18), (10, 11), (10, 13), (10, 19), (10, 22), (10, 26), (11, 18), (11, 26), (11, 28), (12, 13), (12, 14), (12, 28), (12, 29), (13, 16), (13, 21), (13, 29), (14, 18), (16, 20), (17, 18), (17, 26), (17, 28), (18, 19), (18, 22), (18, 27), (18, 28), (19, 23), (19, 25), (19, 28), (20, 22), (24, 26), (24, 27), (25, 27), (25, 29)] sage: G.show() # long time """ if seed is None: seed = current_randstate().long_seed() import networkx return Graph(networkx.random_shell_graph(constructor, seed=seed))
def RandomLobster(n, p, q, seed=None): """ Returns a random lobster. A lobster is a tree that reduces to a caterpillar when pruning all leaf vertices. A caterpillar is a tree that reduces to a path when pruning all leaf vertices (q=0). INPUT: - ``n`` - expected number of vertices in the backbone - ``p`` - probability of adding an edge to the backbone - ``q`` - probability of adding an edge (claw) to the arms - ``seed`` - for the random number generator EXAMPLE: We show the edge list of a random graph with 3 backbone nodes and probabilities `p = 0.7` and `q = 0.3`:: sage: graphs.RandomLobster(3, 0.7, 0.3).edges(labels=False) [(0, 1), (1, 2)] :: sage: G = graphs.RandomLobster(9, .6, .3) sage: G.show() # long time """ if seed is None: seed = current_randstate().long_seed() import networkx return graph.Graph(networkx.random_lobster(n, p, q, seed=seed))
def RandomDirectedGN(self, n, kernel=lambda x:x, seed=None): """ Returns a random GN (growing network) digraph with n vertices. The digraph is constructed by adding vertices with a link to one previously added vertex. The vertex to link to is chosen with a preferential attachment model, i.e. probability is proportional to degree. The default attachment kernel is a linear function of degree. The digraph is always a tree, so in particular it is a directed acyclic graph. INPUT: - ``n`` - number of vertices. - ``kernel`` - the attachment kernel - ``seed`` - for the random number generator EXAMPLE:: sage: D = digraphs.RandomDirectedGN(25) sage: D.edges(labels=False) [(1, 0), (2, 0), (3, 1), (4, 0), (5, 0), (6, 1), (7, 0), (8, 3), (9, 0), (10, 8), (11, 3), (12, 9), (13, 8), (14, 0), (15, 11), (16, 11), (17, 5), (18, 11), (19, 6), (20, 5), (21, 14), (22, 5), (23, 18), (24, 11)] sage: D.show() # long time REFERENCE: - [1] Krapivsky, P.L. and Redner, S. Organization of Growing Random Networks, Phys. Rev. E vol. 63 (2001), p. 066123. """ if seed is None: seed = current_randstate().long_seed() import networkx return DiGraph(networkx.gn_graph(n, kernel, seed=seed))
def RandomDirectedGNC(self, n, seed=None): """ Returns a random GNC (growing network with copying) digraph with n vertices. The digraph is constructed by adding vertices with a link to one previously added vertex. The vertex to link to is chosen with a preferential attachment model, i.e. probability is proportional to degree. The new vertex is also linked to all of the previously added vertex's successors. INPUT: - ``n`` - number of vertices. - ``seed`` - for the random number generator EXAMPLE:: sage: D = digraphs.RandomDirectedGNC(25) sage: D.edges(labels=False) [(1, 0), (2, 0), (2, 1), (3, 0), (4, 0), (4, 1), (5, 0), (5, 1), (5, 2), (6, 0), (6, 1), (7, 0), (7, 1), (7, 4), (8, 0), (9, 0), (9, 8), (10, 0), (10, 1), (10, 2), (10, 5), (11, 0), (11, 8), (11, 9), (12, 0), (12, 8), (12, 9), (13, 0), (13, 1), (14, 0), (14, 8), (14, 9), (14, 12), (15, 0), (15, 8), (15, 9), (15, 12), (16, 0), (16, 1), (16, 4), (16, 7), (17, 0), (17, 8), (17, 9), (17, 12), (18, 0), (18, 8), (19, 0), (19, 1), (19, 4), (19, 7), (20, 0), (20, 1), (20, 4), (20, 7), (20, 16), (21, 0), (21, 8), (22, 0), (22, 1), (22, 4), (22, 7), (22, 19), (23, 0), (23, 8), (23, 9), (23, 12), (23, 14), (24, 0), (24, 8), (24, 9), (24, 12), (24, 15)] sage: D.show() # long time REFERENCE: - [1] Krapivsky, P.L. and Redner, S. Network Growth by Copying, Phys. Rev. E vol. 71 (2005), p. 036118. """ if seed is None: seed = current_randstate().long_seed() import networkx return DiGraph(networkx.gnc_graph(n, seed=seed))
def RandomDirectedGNR(self, n, p, seed=None): """ Returns a random GNR (growing network with redirection) digraph with n vertices and redirection probability p. The digraph is constructed by adding vertices with a link to one previously added vertex. The vertex to link to is chosen uniformly. With probability p, the arc is instead redirected to the successor vertex. The digraph is always a tree. INPUT: - ``n`` - number of vertices. - ``p`` - redirection probability - ``seed`` - for the random number generator. EXAMPLE:: sage: D = digraphs.RandomDirectedGNR(25, .2) sage: D.edges(labels=False) [(1, 0), (2, 0), (2, 1), (3, 0), (4, 0), (4, 1), (5, 0), (5, 1), (5, 2), (6, 0), (6, 1), (7, 0), (7, 1), (7, 4), (8, 0), (9, 0), (9, 8), (10, 0), (10, 1), (10, 2), (10, 5), (11, 0), (11, 8), (11, 9), (12, 0), (12, 8), (12, 9), (13, 0), (13, 1), (14, 0), (14, 8), (14, 9), (14, 12), (15, 0), (15, 8), (15, 9), (15, 12), (16, 0), (16, 1), (16, 4), (16, 7), (17, 0), (17, 8), (17, 9), (17, 12), (18, 0), (18, 8), (19, 0), (19, 1), (19, 4), (19, 7), (20, 0), (20, 1), (20, 4), (20, 7), (20, 16), (21, 0), (21, 8), (22, 0), (22, 1), (22, 4), (22, 7), (22, 19), (23, 0), (23, 8), (23, 9), (23, 12), (23, 14), (24, 0), (24, 8), (24, 9), (24, 12), (24, 15)] sage: D.show() # long time REFERENCE: - [1] Krapivsky, P.L. and Redner, S. Organization of Growing Random Networks, Phys. Rev. E vol. 63 (2001), p. 066123. """ if seed is None: seed = current_randstate().long_seed() import networkx return DiGraph(networkx.gnc_graph(n, seed=seed))
def DegreeSequenceExpected(deg_sequence, seed=None): """ Returns a random graph with expected given degree sequence. Raises a NetworkX error if the proposed degree sequence cannot be that of a graph. One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices. INPUT: - ``deg_sequence`` - a list of integers with each entry corresponding to the expected degree of a different vertex. - ``seed`` - for the random number generator. EXAMPLES:: sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3]) sage: G.edges(labels=False) [(0, 2), (0, 3), (1, 1), (1, 4), (2, 3), (2, 4), (3, 4), (4, 4)] sage: G.show() # long time REFERENCE: .. [ChungLu2002] Chung, Fan and Lu, L. Connected components in random graphs with given expected degree sequences. Ann. Combinatorics (6), 2002 pp. 125-145. """ if seed is None: seed = current_randstate().long_seed() import networkx return Graph(networkx.expected_degree_graph([int(i) for i in deg_sequence], seed=seed), loops=True)
def RandomHolmeKim(n, m, p, seed=None): """ Returns a random graph generated by the Holme and Kim algorithm for graphs with power law degree distribution and approximate average clustering. INPUT: - ``n`` - number of vertices. - ``m`` - number of random edges to add for each new node. - ``p`` - probability of adding a triangle after adding a random edge. - ``seed`` - for the random number generator. From the NetworkX documentation: The average clustering has a hard time getting above a certain cutoff that depends on m. This cutoff is often quite low. Note that the transitivity (fraction of triangles to possible triangles) seems to go down with network size. It is essentially the Barabasi-Albert growth model with an extra step that each random edge is followed by a chance of making an edge to one of its neighbors too (and thus a triangle). This algorithm improves on B-A in the sense that it enables a higher average clustering to be attained if desired. It seems possible to have a disconnected graph with this algorithm since the initial m nodes may not be all linked to a new node on the first iteration like the BA model. EXAMPLE: We show the edge list of a random graph on 8 nodes with 2 random edges per node and a probability `p = 0.5` of forming triangles. :: sage: graphs.RandomHolmeKim(8, 2, 0.5).edges(labels=False) [(0, 2), (0, 5), (1, 2), (1, 3), (2, 3), (2, 4), (2, 6), (2, 7), (3, 4), (3, 6), (3, 7), (4, 5)] :: sage: G = graphs.RandomHolmeKim(12, 3, .3) sage: G.show() # long time REFERENCE: - [1] Holme, P. and Kim, B.J. Growing scale-free networks with tunable clustering, Phys. Rev. E (2002). vol 65, no 2, 026107. """ if seed is None: seed = current_randstate().long_seed() import networkx return graph.Graph(networkx.powerlaw_cluster_graph(n, m, p, seed=seed))
def _cftp(self, start_row): """ Implement coupling from the past. ALGORITHM: The set of Gelfand-Tsetlin patterns can partially ordered by elementwise domination. The partial order has unique maximum and minimum elements that are computed by the methods :meth:`_cftp_upper` and :meth:`_cftp_lower`. We then run the Markov chain that randomly toggles each element up or down from the past until the state reached from the upper and lower start points coalesce as described in [Propp1997]_. EXAMPLES:: sage: G = GelfandTsetlinPatterns(3, 5) sage: G._cftp(0) # random [[5, 3, 2], [4, 2], [3]] sage: G._cftp(0) in G True """ from sage.misc.randstate import current_randstate from sage.misc.randstate import seed from sage.misc.randstate import random count = self._n * self._k seedlist = [(current_randstate().long_seed(), count)] upper = [] lower = [] while True: upper = self._cftp_upper() lower = self._cftp_lower() for currseed, count in seedlist: with seed(currseed): for _ in range(count): for row in range(start_row, self._n): for col in range(self._n - row): direction = random() % 2 self._toggle_markov_chain(upper, row, col, direction) self._toggle_markov_chain(lower, row, col, direction) if all(all(x == y for x,y in zip(l1, l2)) for l1, l2 in zip(upper, lower)): break count = seedlist[0][1] * 2 seedlist.insert(0, (current_randstate().long_seed(), count)) return GelfandTsetlinPattern(upper)
def RandomBarabasiAlbert(n, m, seed=None): u""" Return a random graph created using the Barabasi-Albert preferential attachment model. A graph with m vertices and no edges is initialized, and a graph of n vertices is grown by attaching new vertices each with m edges that are attached to existing vertices, preferentially with high degree. INPUT: - ``n`` - number of vertices in the graph - ``m`` - number of edges to attach from each new node - ``seed`` - for random number generator EXAMPLES: We show the edge list of a random graph on 6 nodes with m = 2. :: sage: graphs.RandomBarabasiAlbert(6,2).edges(labels=False) [(0, 2), (0, 3), (0, 4), (1, 2), (2, 3), (2, 4), (2, 5), (3, 5)] We plot a random graph on 12 nodes with m = 3. :: sage: ba = graphs.RandomBarabasiAlbert(12,3) sage: ba.show() # long time We view many random graphs using a graphics array:: sage: g = [] sage: j = [] sage: for i in range(1,10): ... k = graphs.RandomBarabasiAlbert(i+3, 3) ... g.append(k) ... sage: for i in range(3): ... n = [] ... for m in range(3): ... n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False)) ... j.append(n) ... sage: G = sage.plot.graphics.GraphicsArray(j) sage: G.show() # long time """ if seed is None: seed = current_randstate().long_seed() import networkx return graph.Graph(networkx.barabasi_albert_graph(n, m, seed=seed))
def RandomGNM(n, m, dense=False, seed=None): """ Returns a graph randomly picked out of all graphs on n vertices with m edges. INPUT: - ``n`` - number of vertices. - ``m`` - number of edges. - ``dense`` - whether to use NetworkX's dense_gnm_random_graph or gnm_random_graph EXAMPLES: We show the edge list of a random graph on 5 nodes with 10 edges. :: sage: graphs.RandomGNM(5, 10).edges(labels=False) [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] We plot a random graph on 12 nodes with m = 12. :: sage: gnm = graphs.RandomGNM(12, 12) sage: gnm.show() # long time We view many random graphs using a graphics array:: sage: g = [] sage: j = [] sage: for i in range(9): ... k = graphs.RandomGNM(i+3, i^2-i) ... g.append(k) ... sage: for i in range(3): ... n = [] ... for m in range(3): ... n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False)) ... j.append(n) ... sage: G = sage.plot.graphics.GraphicsArray(j) sage: G.show() # long time """ if seed is None: seed = current_randstate().long_seed() import networkx if dense: return graph.Graph(networkx.dense_gnm_random_graph(n, m, seed=seed)) else: return graph.Graph(networkx.gnm_random_graph(n, m, seed=seed))
def irreducible_characters(self): """ Returns the list of irreducible characters of the group. EXAMPLES:: sage: G = GL(2,2) sage: G.irreducible_characters() [Character of General Linear Group of degree 2 over Finite Field of size 2, Character of General Linear Group of degree 2 over Finite Field of size 2, Character of General Linear Group of degree 2 over Finite Field of size 2] """ current_randstate().set_seed_gap() Irr = self._gap_().Irr() L = [] for irr in Irr: L.append(ClassFunction(self,irr)) return L
def RandomRegular(d, n, seed=None): """ Returns a random d-regular graph on n vertices, or returns False on failure. Since every edge is incident to two vertices, n\*d must be even. INPUT: - ``n`` - number of vertices - ``d`` - degree - ``seed`` - for the random number generator EXAMPLE: We show the edge list of a random graph with 8 nodes each of degree 3. :: sage: graphs.RandomRegular(3, 8).edges(labels=False) [(0, 1), (0, 4), (0, 7), (1, 5), (1, 7), (2, 3), (2, 5), (2, 6), (3, 4), (3, 6), (4, 5), (6, 7)] :: sage: G = graphs.RandomRegular(3, 20) sage: if G: ... G.show() # random output, long time REFERENCES: - [1] Kim, Jeong Han and Vu, Van H. Generating random regular graphs. Proc. 35th ACM Symp. on Thy. of Comp. 2003, pp 213-222. ACM Press, San Diego, CA, USA. http://doi.acm.org/10.1145/780542.780576 - [2] Steger, A. and Wormald, N. Generating random regular graphs quickly. Prob. and Comp. 8 (1999), pp 377-396. """ if seed is None: seed = current_randstate().long_seed() import networkx try: N = networkx.random_regular_graph(d, n, seed=seed) if N is False: return False return graph.Graph(N, sparse=True) except StandardError: return False
def RandomLinearCodeGuava(n, k, F): r""" The method used is to first construct a `k \times n` matrix of the block form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a `k \times (n-k)` matrix constructed using random elements of `F`. Then the columns are permuted using a randomly selected element of the symmetric group `S_n`. INPUT: - ``n,k`` -- integers with `n>k>1`. OUTPUT: Returns a "random" linear code with length `n`, dimension `k` over field `F`. EXAMPLES:: sage: C = codes.RandomLinearCodeGuava(30,15,GF(2)); C # optional - gap_packages (Guava package) [30, 15] linear code over GF(2) sage: C = codes.RandomLinearCodeGuava(10,5,GF(4,'a')); C # optional - gap_packages (Guava package) [10, 5] linear code over GF(4) AUTHOR: David Joyner (11-2005) """ current_randstate().set_seed_gap() q = F.order() if not is_package_installed('gap_packages'): raise PackageNotFoundError('gap_packages') gap.load_package("guava") gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))") gap.eval("G:=GeneratorMat(C)") k = int(gap.eval("Length(G)")) n = int(gap.eval("Length(G[1])")) G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F) for j in range(1, n + 1)] for i in range(1, k + 1)] MS = MatrixSpace(F, k, n) return LinearCode(MS(G))
def RandomRegular(d, n, seed=None): """ Returns a random d-regular graph on n vertices, or returns False on failure. Since every edge is incident to two vertices, n\*d must be even. INPUT: - ``n`` - number of vertices - ``d`` - degree - ``seed`` - for the random number generator EXAMPLES: We show the edge list of a random graph with 8 nodes each of degree 3. :: sage: graphs.RandomRegular(3, 8).edges(labels=False) [(0, 1), (0, 4), (0, 7), (1, 5), (1, 7), (2, 3), (2, 5), (2, 6), (3, 4), (3, 6), (4, 5), (6, 7)] :: sage: G = graphs.RandomRegular(3, 20) sage: if G: ....: G.show() # random output, long time REFERENCES: .. [KimVu2003] Kim, Jeong Han and Vu, Van H. Generating random regular graphs. Proc. 35th ACM Symp. on Thy. of Comp. 2003, pp 213-222. ACM Press, San Diego, CA, USA. http://doi.acm.org/10.1145/780542.780576 .. [StegerWormald1999] Steger, A. and Wormald, N. Generating random regular graphs quickly. Prob. and Comp. 8 (1999), pp 377-396. """ if seed is None: seed = current_randstate().long_seed() import networkx try: N = networkx.random_regular_graph(d, n, seed=seed) if N is False: return False return Graph(N, sparse=True) except Exception: return False
def RandomNewmanWattsStrogatz(n, k, p, seed=None): """ Returns a Newman-Watts-Strogatz small world random graph on n vertices. From the NetworkX documentation: First create a ring over n nodes. Then each node in the ring is connected with its k nearest neighbors. Then shortcuts are created by adding new edges as follows: for each edge u-v in the underlying "n-ring with k nearest neighbors"; with probability p add a new edge u-w with randomly-chosen existing node w. In contrast with watts_strogatz_graph(), no edges are removed. INPUT: - ``n`` - number of vertices. - ``k`` - each vertex is connected to its k nearest neighbors - ``p`` - the probability of adding a new edge for each edge - ``seed`` - for the random number generator EXAMPLE: We show the edge list of a random graph on 7 nodes with 2 "nearest neighbors" and probability `p = 0.2`:: sage: graphs.RandomNewmanWattsStrogatz(7, 2, 0.2).edges(labels=False) [(0, 1), (0, 2), (0, 3), (0, 6), (1, 2), (2, 3), (2, 4), (3, 4), (3, 6), (4, 5), (5, 6)] :: sage: G = graphs.RandomNewmanWattsStrogatz(12, 2, .3) sage: G.show() # long time REFERENCE: - [1] Newman, M.E.J., Watts, D.J. and Strogatz, S.H. Random graph models of social networks. Proc. Nat. Acad. Sci. USA 99, 2566-2572. """ if seed is None: seed = current_randstate().long_seed() import networkx return graph.Graph(networkx.newman_watts_strogatz_graph(n, k, p, seed=seed))
def _pyrand(): r""" A tiny private helper function to return an instance of random.Random from the current \sage random number state. Only for use in prandom.py; other modules should use current_randstate().python_random(). EXAMPLES: sage: from sage.misc.prandom import _pyrand sage: _pyrand() <random.Random object at 0x...> sage: _pyrand().getrandbits(10) 114L """ return current_randstate().python_random()
def RandomLinearCodeGuava(n, k, F): r""" The method used is to first construct a `k \times n` matrix of the block form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a `k \times (n-k)` matrix constructed using random elements of `F`. Then the columns are permuted using a randomly selected element of the symmetric group `S_n`. INPUT: Integers `n,k`, with `n>k>1`. OUTPUT: Returns a "random" linear code with length n, dimension k over field F. EXAMPLES:: sage: C = RandomLinearCodeGuava(30,15,GF(2)); C # optional - gap_packages (Guava package) Linear code of length 30, dimension 15 over Finite Field of size 2 sage: C = RandomLinearCodeGuava(10,5,GF(4,'a')); C # optional - gap_packages (Guava package) Linear code of length 10, dimension 5 over Finite Field in a of size 2^2 AUTHOR: David Joyner (11-2005) """ current_randstate().set_seed_gap() q = F.order() gap.eval("C:=RandomLinearCode(" + str(n) + "," + str(k) + ", GF(" + str(q) + "))") gap.eval("G:=GeneratorMat(C)") k = int(gap.eval("Length(G)")) n = int(gap.eval("Length(G[1])")) G = [[ gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F) for j in range(1, n + 1) ] for i in range(1, k + 1)] MS = MatrixSpace(F, k, n) return LinearCode(MS(G))
def DegreeSequenceConfigurationModel(deg_sequence, seed=None): """ Returns a random pseudograph with the given degree sequence. Raises a NetworkX error if the proposed degree sequence cannot be that of a graph with multiple edges and loops. One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices. INPUT: - ``deg_sequence`` - a list of integers with each entry corresponding to the expected degree of a different vertex. - ``seed`` - for the random number generator. EXAMPLES:: sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) sage: G.adjacency_matrix() [0 1] [1 0] Note: as of this writing, plotting of loops and multiple edges is not supported, and the output is allowed to contain both types of edges. :: sage: G = graphs.DegreeSequenceConfigurationModel([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]) sage: sorted(G.edges(labels=False)) [(0, 2), (0, 10), (0, 15), (1, 6), (1, 16), (1, 17), (2, 5), (2, 19), (3, 7), (3, 14), (3, 14), (4, 9), (4, 13), (4, 19), (5, 6), (5, 15), (6, 11), (7, 11), (7, 17), (8, 11), (8, 18), (8, 19), (9, 12), (9, 13), (10, 15), (10, 18), (12, 13), (12, 16), (14, 17), (16, 18)] sage: G.show() # long time REFERENCE: .. [Newman2003] Newman, M.E.J. The Structure and function of complex networks, SIAM Review vol. 45, no. 2 (2003), pp. 167-256. """ if seed is None: seed = current_randstate().long_seed() import networkx return Graph(networkx.configuration_model([int(i) for i in deg_sequence], seed=seed), loops=True, multiedges=True, sparse=True)
def DegreeSequenceConfigurationModel(deg_sequence, seed=None): """ Returns a random pseudograph with the given degree sequence. Raises a NetworkX error if the proposed degree sequence cannot be that of a graph with multiple edges and loops. One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices. INPUT: - ``deg_sequence`` - a list of integers with each entry corresponding to the expected degree of a different vertex. - ``seed`` - a ``random.Random`` seed or a Python ``int`` for the random number generator (default: ``None``). EXAMPLES:: sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) sage: G.adjacency_matrix() [0 1] [1 0] Note: as of this writing, plotting of loops and multiple edges is not supported, and the output is allowed to contain both types of edges. :: sage: G = graphs.DegreeSequenceConfigurationModel([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]) sage: len(G.edges()) 30 sage: G.show() # long time REFERENCE: [New2003]_ """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) import networkx return Graph(networkx.configuration_model([int(i) for i in deg_sequence], seed=seed), loops=True, multiedges=True, sparse=True)
def DegreeSequenceConfigurationModel(deg_sequence, seed=None): """ Returns a random pseudograph with the given degree sequence. Raises a NetworkX error if the proposed degree sequence cannot be that of a graph with multiple edges and loops. One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices. INPUT: - ``deg_sequence`` - a list of integers with each entry corresponding to the expected degree of a different vertex. - ``seed`` - for the random number generator. EXAMPLES:: sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) sage: G.adjacency_matrix() [0 1] [1 0] Note: as of this writing, plotting of loops and multiple edges is not supported, and the output is allowed to contain both types of edges. :: sage: G = graphs.DegreeSequenceConfigurationModel([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]) sage: G.edges(labels=False) [(0, 2), (0, 10), (0, 15), (1, 6), (1, 16), (1, 17), (2, 5), (2, 19), (3, 7), (3, 14), (3, 14), (4, 9), (4, 13), (4, 19), (5, 6), (5, 15), (6, 11), (7, 11), (7, 17), (8, 11), (8, 18), (8, 19), (9, 12), (9, 13), (10, 15), (10, 18), (12, 13), (12, 16), (14, 17), (16, 18)] sage: G.show() # long time REFERENCE: .. [Newman2003] Newman, M.E.J. The Structure and function of complex networks, SIAM Review vol. 45, no. 2 (2003), pp. 167-256. """ if seed is None: seed = current_randstate().long_seed() import networkx return Graph(networkx.configuration_model([int(i) for i in deg_sequence], seed=seed), loops=True, multiedges=True, sparse=True)
def random_sublist_of_size(k, n): """ INPUT: - k -- an integer - n -- an integer OUTPUT: a randomly chosen sublist of range(k) of size n. EXAMPLES:: sage: import sage.matrix.matrix_integer_dense_saturation as s sage: l = s.random_sublist_of_size(10, 3) sage: len(l) 3 sage: l_check = [-1] + l + [10] sage: all(l_check[i] < l_check[i+1] for i in range(4)) True sage: l = s.random_sublist_of_size(10, 7) sage: len(l) 7 sage: l_check = [-1] + l + [10] sage: all(l_check[i] < l_check[i+1] for i in range(8)) True """ if n > k: raise ValueError("n must be <= len(v)") if n == k: return list(range(k)) if n >= k // 2 + 5: # use complement w = random_sublist_of_size(k, k - n) m = set(w) w = [z for z in range(k) if z not in m] assert (len(w) == n) return w randrange = current_randstate().python_random().randrange w = set([]) while len(w) < n: z = randrange(k) if z not in w: w.add(z) return sorted(w)
def RandomDirectedGNP(self, n, p, loops = False, seed = None): r""" Returns a random digraph on `n` nodes. Each edge is inserted independently with probability `p`. INPUTS: - ``n`` -- number of nodes of the digraph - ``p`` -- probability of an edge - ``loops`` -- is a boolean set to True if the random digraph may have loops, and False (default) otherwise. - ``seed`` -- integer seed for random number generator (default=None). REFERENCES: .. [1] P. Erdos and A. Renyi, On Random Graphs, Publ. Math. 6, 290 (1959). .. [2] E. N. Gilbert, Random Graphs, Ann. Math. Stat., 30, 1141 (1959). PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified. EXAMPLE:: sage: set_random_seed(0) sage: D = digraphs.RandomDirectedGNP(10, .2) sage: D.num_verts() 10 sage: D.edges(labels=False) [(1, 0), (1, 2), (3, 6), (3, 7), (4, 5), (4, 7), (4, 8), (5, 2), (6, 0), (7, 2), (8, 1), (8, 9), (9, 4)] """ from sage.graphs.graph_generators_pyx import RandomGNP if n < 0: raise ValueError("The number of nodes must be positive or null.") if 0.0 > p or 1.0 < p: raise ValueError("The probability p must be in [0..1].") if seed is None: seed = current_randstate().long_seed() return RandomGNP(n, p, directed = True, loops = loops)
def RandomDirectedGNP(self, n, p, loops=False, seed=None): r""" Returns a random digraph on `n` nodes. Each edge is inserted independently with probability `p`. INPUTS: - ``n`` -- number of nodes of the digraph - ``p`` -- probability of an edge - ``loops`` -- is a boolean set to True if the random digraph may have loops, and False (default) otherwise. - ``seed`` -- integer seed for random number generator (default=None). REFERENCES: .. [1] P. Erdos and A. Renyi, On Random Graphs, Publ. Math. 6, 290 (1959). .. [2] E. N. Gilbert, Random Graphs, Ann. Math. Stat., 30, 1141 (1959). PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified. EXAMPLE:: sage: set_random_seed(0) sage: D = digraphs.RandomDirectedGNP(10, .2) sage: D.num_verts() 10 sage: D.edges(labels=False) [(1, 0), (1, 2), (3, 6), (3, 7), (4, 5), (4, 7), (4, 8), (5, 2), (6, 0), (7, 2), (8, 1), (8, 9), (9, 4)] """ from sage.graphs.graph_generators_pyx import RandomGNP if n < 0: raise ValueError("The number of nodes must be positive or null.") if 0.0 > p or 1.0 < p: raise ValueError("The probability p must be in [0..1].") if seed is None: seed = current_randstate().long_seed() return RandomGNP(n, p, directed=True, loops=loops)
def DegreeSequenceConfigurationModel(deg_sequence, seed=None): """ Returns a random pseudograph with the given degree sequence. Raises a NetworkX error if the proposed degree sequence cannot be that of a graph with multiple edges and loops. One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices. INPUT: - ``deg_sequence`` - a list of integers with each entry corresponding to the expected degree of a different vertex. - ``seed`` - a ``random.Random`` seed or a Python ``int`` for the random number generator (default: ``None``). EXAMPLES:: sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) sage: G.adjacency_matrix() [0 1] [1 0] Note: as of this writing, plotting of loops and multiple edges is not supported, and the output is allowed to contain both types of edges. :: sage: G = graphs.DegreeSequenceConfigurationModel([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]) sage: len(G.edges()) 30 sage: G.show() # long time REFERENCE: .. [Newman2003] Newman, M.E.J. The Structure and function of complex networks, SIAM Review vol. 45, no. 2 (2003), pp. 167-256. """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) import networkx return Graph(networkx.configuration_model([int(i) for i in deg_sequence], seed=seed), loops=True, multiedges=True, sparse=True)
def DegreeSequenceConfigurationModel(deg_sequence, seed=None): """ Return a random pseudograph with the given degree sequence. This method raises a NetworkX error if the proposed degree sequence cannot be that of a graph with multiple edges and loops. One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices. INPUT: - ``deg_sequence`` -- list of integers with each entry corresponding to the expected degree of a different vertex - ``seed`` -- (optional) a ``random.Random`` seed or a Python ``int`` for the random number generator EXAMPLES:: sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) sage: G.adjacency_matrix() [0 1] [1 0] The output is allowed to contain both loops and multiple edges:: sage: deg_sequence = [3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3] sage: G = graphs.DegreeSequenceConfigurationModel(deg_sequence) sage: G.order(), G.size() (20, 30) sage: G.has_loops() or G.has_multiple_edges() # random True sage: G.show() # long time REFERENCE: [New2003]_ """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) import networkx deg_sequence = [int(i) for i in deg_sequence] return Graph(networkx.configuration_model(deg_sequence, seed=seed), loops=True, multiedges=True, sparse=True)
def RandomTreePowerlaw(n, gamma=3, tries=100, seed=None): """ Returns a tree with a power law degree distribution. Returns False on failure. From the NetworkX documentation: A trial power law degree sequence is chosen and then elements are swapped with new elements from a power law distribution until the sequence makes a tree (size = order - 1). INPUT: - ``n`` - number of vertices - ``gamma`` - exponent of power law - ``tries`` - number of attempts to adjust sequence to make a tree - ``seed`` - for the random number generator EXAMPLE: We show the edge list of a random graph with 10 nodes and a power law exponent of 2. :: sage: graphs.RandomTreePowerlaw(10, 2).edges(labels=False) [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (6, 8), (6, 9)] :: sage: G = graphs.RandomTreePowerlaw(15, 2) sage: if G: ... G.show() # random output, long time """ if seed is None: seed = current_randstate().long_seed() import networkx try: return graph.Graph(networkx.random_powerlaw_tree(n, gamma, seed=seed, tries=tries)) except networkx.NetworkXError: return False
def RandomTreePowerlaw(n, gamma=3, tries=100, seed=None): """ Returns a tree with a power law degree distribution. Returns False on failure. From the NetworkX documentation: A trial power law degree sequence is chosen and then elements are swapped with new elements from a power law distribution until the sequence makes a tree (size = order - 1). INPUT: - ``n`` - number of vertices - ``gamma`` - exponent of power law - ``tries`` - number of attempts to adjust sequence to make a tree - ``seed`` - for the random number generator EXAMPLE: We show the edge list of a random graph with 10 nodes and a power law exponent of 2. :: sage: graphs.RandomTreePowerlaw(10, 2).edges(labels=False) [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (6, 8), (6, 9)] :: sage: G = graphs.RandomTreePowerlaw(15, 2) sage: if G: ... G.show() # random output, long time """ if seed is None: seed = current_randstate().long_seed() import networkx try: return graph.Graph( networkx.random_powerlaw_tree(n, gamma, seed=seed, tries=tries)) except networkx.NetworkXError: return False
def random_sublist_of_size(k, n): """ INPUT: - k -- an integer - n -- an integer OUTPUT: a randomly chosen sublist of range(k) of size n. EXAMPLES:: sage: import sage.matrix.matrix_integer_dense_saturation as s sage: s.random_sublist_of_size(10,3) [0, 1, 5] sage: s.random_sublist_of_size(10,7) [0, 1, 3, 4, 5, 7, 8] """ if n > k: raise ValueError("n must be <= len(v)") if n == k: return range(k) if n >= k // 2 + 5: # use complement w = random_sublist_of_size(k, k - n) m = set(w) w = [z for z in xrange(k) if z not in m] assert (len(w)) == n return w randrange = current_randstate().python_random().randrange w = set([]) while len(w) < n: z = randrange(k) if not z in w: w.add(z) w = sorted(w) return w
def RandomDirectedGN(self, n, kernel=lambda x: x, seed=None): """ Returns a random GN (growing network) digraph with n vertices. The digraph is constructed by adding vertices with a link to one previously added vertex. The vertex to link to is chosen with a preferential attachment model, i.e. probability is proportional to degree. The default attachment kernel is a linear function of degree. The digraph is always a tree, so in particular it is a directed acyclic graph. INPUT: - ``n`` - number of vertices. - ``kernel`` - the attachment kernel - ``seed`` - for the random number generator EXAMPLE:: sage: D = digraphs.RandomDirectedGN(25) sage: D.edges(labels=False) [(1, 0), (2, 0), (3, 1), (4, 0), (5, 0), (6, 1), (7, 0), (8, 3), (9, 0), (10, 8), (11, 3), (12, 9), (13, 8), (14, 0), (15, 11), (16, 11), (17, 5), (18, 11), (19, 6), (20, 5), (21, 14), (22, 5), (23, 18), (24, 11)] sage: D.show() # long time REFERENCE: - [1] Krapivsky, P.L. and Redner, S. Organization of Growing Random Networks, Phys. Rev. E vol. 63 (2001), p. 066123. """ if seed is None: seed = current_randstate().long_seed() import networkx return DiGraph(networkx.gn_graph(n, kernel, seed=seed))
def DegreeSequenceExpected(deg_sequence, seed=None): """ Returns a random graph with expected given degree sequence. Raises a NetworkX error if the proposed degree sequence cannot be that of a graph. One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices. INPUT: - ``deg_sequence`` - a list of integers with each entry corresponding to the expected degree of a different vertex. - ``seed`` - a ``random.Random`` seed or a Python ``int`` for the random number generator (default: ``None``). EXAMPLES:: sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3]) sage: G.edges(labels=False) [(0, 3), (1, 3), (1, 4), (4, 4)] # 32-bit [(0, 3), (1, 4), (2, 2), (2, 3), (2, 4), (4, 4)] # 64-bit sage: G.show() # long time REFERENCE: [CL2002]_ """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) import networkx return Graph(networkx.expected_degree_graph([int(i) for i in deg_sequence], seed=seed), loops=True)
def RandomGNP(n, p, seed=None, fast=True, method='Sage'): r""" Returns a random graph on `n` nodes. Each edge is inserted independently with probability `p`. INPUTS: - ``n`` -- number of nodes of the digraph - ``p`` -- probability of an edge - ``seed`` -- integer seed for random number generator (default=None). - ``fast`` -- boolean set to True (default) to use the algorithm with time complexity in `O(n+m)` proposed in [3]_. It is designed for generating large sparse graphs. It is faster than other methods for *LARGE* instances (try it to know whether it is useful for you). - ``method`` -- By default (```method='Sage'``), this function uses the method implemented in ```sage.graphs.graph_generators_pyx.pyx``. When ``method='networkx'``, this function calls the NetworkX function ``fast_gnp_random_graph``, unless ``fast=False``, then ``gnp_random_graph``. Try them to know which method is the best for you. The ``fast`` parameter is not taken into account by the 'Sage' method so far. REFERENCES: .. [1] P. Erdos and A. Renyi. On Random Graphs, Publ. Math. 6, 290 (1959). .. [2] E. N. Gilbert. Random Graphs, Ann. Math. Stat., 30, 1141 (1959). .. [3] V. Batagelj and U. Brandes. Efficient generation of large random networks. Phys. Rev. E, 71, 036113, 2005. PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified. EXAMPLES: We show the edge list of a random graph on 6 nodes with probability `p = .4`:: sage: set_random_seed(0) sage: graphs.RandomGNP(6, .4).edges(labels=False) [(0, 1), (0, 5), (1, 2), (2, 4), (3, 4), (3, 5), (4, 5)] We plot a random graph on 12 nodes with probability `p = .71`:: sage: gnp = graphs.RandomGNP(12,.71) sage: gnp.show() # long time We view many random graphs using a graphics array:: sage: g = [] sage: j = [] sage: for i in range(9): ... k = graphs.RandomGNP(i+3,.43) ... g.append(k) ... sage: for i in range(3): ... n = [] ... for m in range(3): ... n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False)) ... j.append(n) ... sage: G = sage.plot.graphics.GraphicsArray(j) sage: G.show() # long time sage: graphs.RandomGNP(4,1) Complete graph: Graph on 4 vertices TESTS:: sage: graphs.RandomGNP(50,.2,method=50) Traceback (most recent call last): ... ValueError: 'method' must be equal to 'networkx' or to 'Sage'. sage: set_random_seed(0) sage: graphs.RandomGNP(50,.2, method="Sage").size() 243 sage: graphs.RandomGNP(50,.2, method="networkx").size() 258 """ if n < 0: raise ValueError("The number of nodes must be positive or null.") if 0.0 > p or 1.0 < p: raise ValueError("The probability p must be in [0..1].") if seed is None: seed = current_randstate().long_seed() if p == 1: from sage.graphs.generators.basic import CompleteGraph return CompleteGraph(n) if method == 'networkx': import networkx if fast: G = networkx.fast_gnp_random_graph(n, p, seed=seed) else: G = networkx.gnp_random_graph(n, p, seed=seed) return graph.Graph(G) elif method in ['Sage', 'sage']: # We use the Sage generator from sage.graphs.graph_generators_pyx import RandomGNP as sageGNP return sageGNP(n, p) else: raise ValueError("'method' must be equal to 'networkx' or to 'Sage'.")
def RandomGNP(n, p, seed=None, fast=True, method='Sage'): r""" Returns a random graph on `n` nodes. Each edge is inserted independently with probability `p`. INPUTS: - ``n`` -- number of nodes of the graph - ``p`` -- probability of an edge - ``seed`` -- integer seed for random number generator (default=None). - ``fast`` -- boolean set to True (default) to use the algorithm with time complexity in `O(n+m)` proposed in [BatBra2005]_. It is designed for generating large sparse graphs. It is faster than other methods for *LARGE* instances (try it to know whether it is useful for you). - ``method`` -- By default (```method='Sage'``), this function uses the method implemented in ```sage.graphs.graph_generators_pyx.pyx``. When ``method='networkx'``, this function calls the NetworkX function ``fast_gnp_random_graph``, unless ``fast=False``, then ``gnp_random_graph``. Try them to know which method is the best for you. The ``fast`` parameter is not taken into account by the 'Sage' method so far. REFERENCES: .. [ErdRen1959] P. Erdos and A. Renyi. On Random Graphs, Publ. Math. 6, 290 (1959). .. [Gilbert1959] E. N. Gilbert. Random Graphs, Ann. Math. Stat., 30, 1141 (1959). .. [BatBra2005] V. Batagelj and U. Brandes. Efficient generation of large random networks. Phys. Rev. E, 71, 036113, 2005. PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified. EXAMPLES: We show the edge list of a random graph on 6 nodes with probability `p = .4`:: sage: set_random_seed(0) sage: graphs.RandomGNP(6, .4).edges(labels=False) [(0, 1), (0, 5), (1, 2), (2, 4), (3, 4), (3, 5), (4, 5)] We plot a random graph on 12 nodes with probability `p = .71`:: sage: gnp = graphs.RandomGNP(12,.71) sage: gnp.show() # long time We view many random graphs using a graphics array:: sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.RandomGNP(i+3,.43) ....: g.append(k) sage: for i in range(3): ....: n = [] ....: for m in range(3): ....: n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False)) ....: j.append(n) sage: G = sage.plot.graphics.GraphicsArray(j) sage: G.show() # long time sage: graphs.RandomGNP(4,1) Complete graph: Graph on 4 vertices TESTS:: sage: graphs.RandomGNP(50,.2,method=50) Traceback (most recent call last): ... ValueError: 'method' must be equal to 'networkx' or to 'Sage'. sage: set_random_seed(0) sage: graphs.RandomGNP(50,.2, method="Sage").size() 243 sage: graphs.RandomGNP(50,.2, method="networkx").size() 258 """ if n < 0: raise ValueError("The number of nodes must be positive or null.") if 0.0 > p or 1.0 < p: raise ValueError("The probability p must be in [0..1].") if seed is None: seed = current_randstate().long_seed() if p == 1: from sage.graphs.generators.basic import CompleteGraph return CompleteGraph(n) if method == 'networkx': import networkx if fast: G = networkx.fast_gnp_random_graph(n, p, seed=seed) else: G = networkx.gnp_random_graph(n, p, seed=seed) return Graph(G) elif method in ['Sage', 'sage']: # We use the Sage generator from sage.graphs.graph_generators_pyx import RandomGNP as sageGNP return sageGNP(n, p) else: raise ValueError("'method' must be equal to 'networkx' or to 'Sage'.")
def simon_two_descent(E, verbose=0, lim1=None, lim3=None, limtriv=None, maxprob=20, limbigprime=30, known_points=[]): """ Interface to Simon's gp script for two-descent. .. NOTE:: Users should instead run E.simon_two_descent() EXAMPLES:: sage: import sage.schemes.elliptic_curves.gp_simon sage: E=EllipticCurve('389a1') sage: sage.schemes.elliptic_curves.gp_simon.simon_two_descent(E) (2, 2, [(5/4 : 5/8 : 1), (-3/4 : 7/8 : 1)]) TESTS:: sage: E = EllipticCurve('37a1').change_ring(QuadraticField(-11,'x')) sage: E.simon_two_descent() (1, 1, [(0 : 0 : 1)]) An example with an elliptic curve defined over a relative number field:: sage: F.<a> = QuadraticField(29) sage: x = QQ['x'].gen() sage: K.<b> = F.extension(x^2-1/2*a+1/2) sage: E = EllipticCurve(K,[1, 0, 5/2*a + 27/2, 0, 0]) # long time (about 3 s) sage: E.simon_two_descent(lim1=2, limtriv=3) (1, 1, ...) Check that :trac:`16022` is fixed:: sage: K.<y> = NumberField(x^4 + x^2 - 7) sage: E = EllipticCurve(K, [1, 0, 5*y^2 + 16, 0, 0]) sage: E.simon_two_descent(lim1=2, limtriv=3) # long time (about 3 s) (1, 1, ...) An example that checks that :trac:`9322` is fixed (it should take less than a second to run) sage: K.<w> = NumberField(x^2-x-232) sage: E = EllipticCurve([2-w,18+3*w,209+9*w,2581+175*w,852-55*w]) sage: E.simon_two_descent() (0, 2, []) """ init() current_randstate().set_seed_gp(gp) K = E.base_ring() K_orig = K # The following is to correct the bug at \#5204: the gp script # fails when K is a number field whose generator is called 'x'. # It also deals with relative number fields. E_orig = E if not K is QQ: K = K_orig.absolute_field('a') from_K,to_K = K.structure() E = E_orig.change_ring(to_K) known_points = [P.change_ring(to_K) for P in known_points] # Simon's program requires that this name be y. with localvars(K.polynomial().parent(), 'y'): gp.eval("K = bnfinit(%s);" % K.polynomial()) if verbose >= 2: print("K = bnfinit(%s);" % K.polynomial()) gp.eval("%s = Mod(y,K.pol);" % K.gen()) if verbose >= 2: print("%s = Mod(y,K.pol);" % K.gen()) else: from_K = lambda x: x to_K = lambda x: x # The block below mimicks the defaults in Simon's scripts, and needs to be changed # when these are updated. if K is QQ: cmd = 'ellrank(%s, %s);' % (list(E.ainvs()), [P._pari_() for P in known_points]) if lim1 is None: lim1 = 5 if lim3 is None: lim3 = 50 if limtriv is None: limtriv = 3 else: cmd = 'bnfellrank(K, %s, %s);' % (list(E.ainvs()), [P._pari_() for P in known_points]) if lim1 is None: lim1 = 2 if lim3 is None: lim3 = 4 if limtriv is None: limtriv = 2 gp('DEBUGLEVEL_ell=%s; LIM1=%s; LIM3=%s; LIMTRIV=%s; MAXPROB=%s; LIMBIGPRIME=%s;'%( verbose, lim1, lim3, limtriv, maxprob, limbigprime)) if verbose >= 2: print(cmd) s = gp.eval('ans=%s;'%cmd) if s.find(" *** ") != -1: raise RuntimeError("\n%s\nAn error occurred while running Simon's 2-descent program"%s) if verbose > 0: print(s) v = gp.eval('ans') if v=='ans': # then the call to ellrank() or bnfellrank() failed raise RuntimeError("An error occurred while running Simon's 2-descent program") if verbose >= 2: print("v = %s" % v) # pari represents field elements as Mod(poly, defining-poly) # so this function will return the respective elements of K def _gp_mod(*args): return args[0] ans = sage_eval(v, {'Mod': _gp_mod, 'y': K.gen(0)}) lower = ZZ(ans[0]) upper = ZZ(ans[1]) points = [E_orig([from_K(c) for c in list(P)]) for P in ans[2]] points = [P for P in points if P.has_infinite_order()] return lower, upper, points
def simon_two_descent(E, verbose=0, lim1=5, lim3=50, limtriv=10, maxprob=20, limbigprime=30): """ Interface to Simon's gp script for two-descent. .. NOTE:: Users should instead run E.simon_two_descent() EXAMPLES:: sage: import sage.schemes.elliptic_curves.gp_simon sage: E=EllipticCurve('389a1') sage: sage.schemes.elliptic_curves.gp_simon.simon_two_descent(E) [2, 2, [(1 : 0 : 1), (-11/9 : -55/27 : 1)]] sage: E.simon_two_descent() (2, 2, [(1 : 0 : 1), (-11/9 : -55/27 : 1)]) TESTS:: sage: E = EllipticCurve('37a1').change_ring(QuadraticField(-11,'x')) sage: E.simon_two_descent() (1, 1, [(-1 : 0 : 1)]) """ init() current_randstate().set_seed_gp(gp) K = E.base_ring() K_orig = K # The following is to correct the bug at \#5204: the gp script # fails when K is a number field whose generator is called 'x'. if not K is QQ: K = K.change_names('a') E_orig = E E = EllipticCurve(K,[K(list(a)) for a in E.ainvs()]) F = E.integral_model() if K != QQ: # Simon's program requires that this name be y. with localvars(K.polynomial().parent(), 'y'): gp.eval("K = bnfinit(%s);" % K.polynomial()) if verbose >= 2: print "K = bnfinit(%s);" % K.polynomial() gp.eval("%s = Mod(y,K.pol);" % K.gen()) if verbose >= 2: print "%s = Mod(y,K.pol);" % K.gen() if K == QQ: cmd = 'ellrank([%s,%s,%s,%s,%s]);' % F.ainvs() else: cmd = 'bnfellrank(K, [%s,%s,%s,%s,%s]);' % F.ainvs() gp('DEBUGLEVEL_ell=%s; LIM1=%s; LIM3=%s; LIMTRIV=%s; MAXPROB=%s; LIMBIGPRIME=%s;'%( verbose, lim1, lim3, limtriv, maxprob, limbigprime)) if verbose >= 2: print cmd s = gp.eval('ans=%s;'%cmd) if s.find("***") != -1: raise RuntimeError, "\n%s\nAn error occurred while running Simon's 2-descent program"%s if verbose > 0: print s v = gp.eval('ans') if v=='ans': # then the call to ellrank() or bnfellrank() failed return 'fail' if verbose >= 2: print "v = ", v # pari represents field elements as Mod(poly, defining-poly) # so this function will return the respective elements of K def _gp_mod(*args): return args[0] ans = sage_eval(v, {'Mod': _gp_mod, 'y': K.gen(0)}) inv_transform = F.isomorphism_to(E) ans[2] = [inv_transform(F(P)) for P in ans[2]] ans[2] = [E_orig([K_orig(list(c)) for c in list(P)]) for P in ans[2]] return ans
def simon_two_descent(E, verbose=0, lim1=None, lim3=None, limtriv=None, maxprob=20, limbigprime=30, known_points=[]): """ Interface to Simon's gp script for two-descent. .. NOTE:: Users should instead run E.simon_two_descent() EXAMPLES:: sage: import sage.schemes.elliptic_curves.gp_simon sage: E=EllipticCurve('389a1') sage: sage.schemes.elliptic_curves.gp_simon.simon_two_descent(E) (2, 2, [(5/4 : 5/8 : 1), (-3/4 : 7/8 : 1)]) TESTS:: sage: E = EllipticCurve('37a1').change_ring(QuadraticField(-11,'x')) sage: E.simon_two_descent() (1, 1, [(0 : 0 : 1)]) An example with an elliptic curve defined over a relative number field:: sage: F.<a> = QuadraticField(29) sage: x = QQ['x'].gen() sage: K.<b> = F.extension(x^2-1/2*a+1/2) sage: E = EllipticCurve(K,[1, 0, 5/2*a + 27/2, 0, 0]) # long time (about 3 s) sage: E.simon_two_descent(lim1=2, limtriv=3) (1, 1, ...) Check that :trac:`16022` is fixed:: sage: K.<y> = NumberField(x^4 + x^2 - 7) sage: E = EllipticCurve(K, [1, 0, 5*y^2 + 16, 0, 0]) sage: E.simon_two_descent(lim1=2, limtriv=3) # long time (about 3 s) (1, 1, ...) An example that checks that :trac:`9322` is fixed (it should take less than a second to run):: sage: K.<w> = NumberField(x^2-x-232) sage: E = EllipticCurve([2-w,18+3*w,209+9*w,2581+175*w,852-55*w]) sage: E.simon_two_descent() (0, 2, []) """ init() current_randstate().set_seed_gp(gp) K = E.base_ring() K_orig = K # The following is to correct the bug at \#5204: the gp script # fails when K is a number field whose generator is called 'x'. # It also deals with relative number fields. E_orig = E if not K is QQ: K = K_orig.absolute_field('a') from_K, to_K = K.structure() E = E_orig.change_ring(to_K) known_points = [P.change_ring(to_K) for P in known_points] # Simon's program requires that this name be y. with localvars(K.polynomial().parent(), 'y'): gp.eval("K = bnfinit(%s);" % K.polynomial()) if verbose >= 2: print("K = bnfinit(%s);" % K.polynomial()) gp.eval("%s = Mod(y,K.pol);" % K.gen()) if verbose >= 2: print("%s = Mod(y,K.pol);" % K.gen()) else: from_K = lambda x: x to_K = lambda x: x # The block below mimicks the defaults in Simon's scripts, and needs to be changed # when these are updated. if K is QQ: cmd = 'ellrank(%s, %s);' % (list( E.ainvs()), [P._pari_() for P in known_points]) if lim1 is None: lim1 = 5 if lim3 is None: lim3 = 50 if limtriv is None: limtriv = 3 else: cmd = 'bnfellrank(K, %s, %s);' % (list( E.ainvs()), [P._pari_() for P in known_points]) if lim1 is None: lim1 = 2 if lim3 is None: lim3 = 4 if limtriv is None: limtriv = 2 gp('DEBUGLEVEL_ell=%s; LIM1=%s; LIM3=%s; LIMTRIV=%s; MAXPROB=%s; LIMBIGPRIME=%s;' % (verbose, lim1, lim3, limtriv, maxprob, limbigprime)) if verbose >= 2: print(cmd) s = gp.eval('ans=%s;' % cmd) if s.find(" *** ") != -1: raise RuntimeError( "\n%s\nAn error occurred while running Simon's 2-descent program" % s) if verbose > 0: print(s) v = gp.eval('ans') if v == 'ans': # then the call to ellrank() or bnfellrank() failed raise RuntimeError( "An error occurred while running Simon's 2-descent program") if verbose >= 2: print("v = %s" % v) # pari represents field elements as Mod(poly, defining-poly) # so this function will return the respective elements of K def _gp_mod(*args): return args[0] ans = sage_eval(v, {'Mod': _gp_mod, 'y': K.gen(0)}) lower = ZZ(ans[0]) upper = ZZ(ans[1]) points = [E_orig([from_K(c) for c in list(P)]) for P in ans[2]] points = [P for P in points if P.has_infinite_order()] return lower, upper, points