def RandomDirectedGNP(self, n, p): r""" Returns a random digraph on `n` nodes. Each edge is inserted independently with probability `p`. 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: D = digraphs.RandomDirectedGNP(10, .2) sage: D.num_verts() 10 sage: D.edges(labels=False) [(0, 1), (0, 3), (0, 6), (0, 8), (1, 4), (3, 7), (4, 1), (4, 8), (5, 2), (5, 6), (5, 8), (6, 4), (7, 6), (8, 4), (8, 5), (8, 7), (8, 9), (9, 3), (9, 4), (9, 6)] """ from sage.misc.prandom import random D = DiGraph(n) for i in xrange(n): for j in xrange(i): if random() < p: D.add_edge(i,j) for j in xrange(i+1,n): if random() < p: D.add_edge(i,j) return D
def _generic(self, fan): r""" Returns a vector `v` which is generic with respect to the given fan . TESTS:: sage: A = MW(toric_varieties.P2().fan()) sage: A._generic(A._fan()) # random output [0.2573820339704006, 0.24526498452629364] """ d = fan.dim() v = [random() for r in range(d)] #candidate for generic needToCheck = True while needToCheck: coneFlag = False #change to true if v in a cone of codim 1, that makes v NOT generic for c in fan.cones(d - 1): if v in c: coneFlag = True if coneFlag: #try new generic vector v = [random() for r in range(d)] else: #v is generic needToCheck = False return v
def lyapunov_sample(algo, n_orbits, n_iterations=1000, verbose=False): r""" Return lists of values for theta1, theta2 and 1-theta2/theta1 computed on many orbits. This is computed in parallel. INPUT: - ``n_orbits`` -- integer, number of orbits - ``n_iterations`` -- integer, length of each orbit - ``verbose`` -- bool (default: ``False``) OUTPUT: tuple of three lists EXAMPLES:: sage: from slabbe.lyapunov import lyapunov_sample sage: from slabbe.mult_cont_frac import Brun sage: lyapunov_sample(Brun(), 5, 1000000) # abs tol 0.01 [(0.3027620661266397, 0.3033468535021702, 0.3044950176856005, 0.3030531162480779, 0.30601169862996064), (-0.11116236859835525, -0.11165563059874498, -0.1122595926203868, -0.11190323336181864, -0.11255687513610782), (1.367160820443926, 1.3680790794750939, 1.3686746452327765, 1.3692528714016428, 1.3678188632657973)] """ S = [(random(), random(), random()) for _ in range(n_orbits)] @parallel def compute_exponents(i): try: return algo.lyapunov_exponents(start=S[i], n_iterations=n_iterations) except Exception as err: return "{}: {}".format(err.__class__.__name__, err) L = [v for _, v in compute_exponents(range(n_orbits))] L_filtered = [v for v in L if isinstance(v, tuple)] if verbose: L_error_msg = [v for v in L if not isinstance(v, tuple)] print(L_error_msg) return zip(*L_filtered)
def RandomInterval(n): """ Returns a random interval graph. An interval graph is built from a list `(a_i,b_i)_{1\leq i \leq n}` of intervals : to each interval of the list is associated one vertex, two vertices being adjacent if the two corresponding intervals intersect. A random interval graph of order `n` is generated by picking random values for the `(a_i,b_j)`, each of the two coordinates being generated from the uniform distribution on the interval `[0,1]`. This definitions follows [boucheron2001]_. .. NOTE:: The vertices are named 0, 1, 2, and so on. The intervals used to create the graph are saved with the graph and can be recovered using ``get_vertex()`` or ``get_vertices()``. INPUT: - ``n`` (integer) -- the number of vertices in the random graph. EXAMPLE: As for any interval graph, the chromatic number is equal to the clique number :: sage: g = graphs.RandomInterval(8) sage: g.clique_number() == g.chromatic_number() True REFERENCE: .. [boucheron2001] Boucheron, S. and FERNANDEZ de la VEGA, W., On the Independence Number of Random Interval Graphs, Combinatorics, Probability and Computing v10, issue 05, Pages 385--396, Cambridge Univ Press, 2001 """ from sage.misc.prandom import random intervals = [tuple(sorted((random(), random()))) for i in range(n)] from sage.graphs.generators.families import IntervalGraph return IntervalGraph(intervals)
def lyapunov_sample(algo, n_orbits, n_iterations=1000, verbose=False): r""" Return lists of values for theta1, theta2 and 1-theta2/theta1 computed on many orbits. This is computed in parallel. INPUT: - ``n_orbits`` -- integer, number of orbits - ``n_iterations`` -- integer, length of each orbit - ``verbose`` -- bool (default: ``False``) OUTPUT: tuple of three lists EXAMPLES:: sage: from slabbe.lyapunov import lyapunov_sample sage: from slabbe.mult_cont_frac import Brun sage: lyapunov_sample(Brun(), 5, 1000000) # abs tol 0.01 [(0.3027620661266397, 0.3033468535021702, 0.3044950176856005, 0.3030531162480779, 0.30601169862996064), (-0.11116236859835525, -0.11165563059874498, -0.1122595926203868, -0.11190323336181864, -0.11255687513610782), (1.367160820443926, 1.3680790794750939, 1.3686746452327765, 1.3692528714016428, 1.3678188632657973)] """ S = [(random(), random(), random()) for _ in range(n_orbits)] @parallel def compute_exponents(i): try: return algo.lyapunov_exponents(start=S[i], n_iterations=n_iterations) except Exception as err: return "{}: {}".format(err.__class__.__name__, err) L = [v for _,v in compute_exponents(range(n_orbits))] L_filtered = [v for v in L if isinstance(v, tuple)] if verbose: L_error_msg = [v for v in L if not isinstance(v, tuple)] print(L_error_msg) return zip(*L_filtered)
def transmit_unsafe(self, message): r""" Returns ``message`` where each of the symbols has been changed to another from the alphabet with probability :meth:`error_probability`. This method does not check if ``message`` belongs to the input space of``self``. INPUT: - ``message`` -- a vector EXAMPLES:: sage: F = GF(59)^11 sage: epsilon = 0.3 sage: Chan = channels.QarySymmetricChannel(F, epsilon) sage: msg = F((3, 14, 15, 9, 26, 53, 58, 9, 7, 9, 3)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) (3, 14, 15, 53, 12, 53, 58, 9, 55, 9, 3) """ epsilon = self.error_probability() V = self.input_space() F = V.base_ring() msg = copy(message.list()) for i in range(len(msg)): if random() <= epsilon: a = F.random_element() while a == msg[i]: a = F.random_element() msg[i] = a return V(msg)
def choose_from_prob_list(lst): r""" INPUT: - ``lst`` - A list of tuples, where the first element of each tuple is a nonnegative float (a probability), and the probabilities sum to one. OUTPUT: A tuple randomly selected from the list according to the given probabilities. EXAMPLES:: sage: from sage.symbolic.random_tests import * sage: v = [(0.1, False), (0.9, True)] sage: choose_from_prob_list(v) (0.900000000000000, True) sage: true_count = 0 sage: for _ in range(10000): ... if choose_from_prob_list(v)[1]: ... true_count += 1 sage: true_count 9033 sage: true_count - (10000 * 9/10) 33 """ r = random() for i in range(len(lst)-1): if r < lst[i][0]: return lst[i] r -= lst[i][0] return lst[-1]
def _rand_der(self): """ Produces a random derangement of `[1, 2, \ldots, n]` This is an implementention of the algorithm described by Martinez et. al. in [Martinez08]_. EXAMPLES:: sage: D = Derangements(4) sage: D._rand_der() [2, 3, 4, 1] """ n = len(self._set) A = range(1, n + 1) mark = [x < 0 for x in A] i, u = n, n while u >= 2: if not (mark[i - 1]): while True: j = randint(1, i - 1) if not (mark[j - 1]): A[i - 1], A[j - 1] = A[j - 1], A[i - 1] break p = random() if p < (u - 1) * self._count_der(u - 2) // self._count_der(u): mark[j - 1] = True u -= 1 u -= 1 i -= 1 return A
def _rand_der(self): """ Produces a random derangement of `[1, 2, \ldots, n]`. This is an implementation of the algorithm described by Martinez et. al. in [Martinez08]_. EXAMPLES:: sage: D = Derangements(4) sage: D._rand_der() [2, 3, 4, 1] """ n = len(self._set) A = list(range(1, n + 1)) mark = [x<0 for x in A] i,u = n,n while u >= 2: if not(mark[i-1]): while True: j = randint(1,i-1) if not(mark[j-1]): A[i-1], A[j-1] = A[j-1], A[i-1] break p = random() if p < (u-1) * self._count_der(u-2) // self._count_der(u): mark[j-1] = True u -= 1 u -= 1 i -= 1 return A
def random_sublist(X, s): """ Return a pseudo-random sublist of the list X where the probability of including a particular element is s. INPUT: - ``X`` - list - ``s`` - floating point number between 0 and 1 OUTPUT: list EXAMPLES:: sage: from sage.misc.misc import is_sublist sage: S = [1,7,3,4,18] sage: sublist = random_sublist(S, 0.5); sublist # random [1, 3, 4] sage: is_sublist(sublist, S) True sage: sublist = random_sublist(S, 0.5); sublist # random [1, 3] sage: is_sublist(sublist, S) True """ return [a for a in X if random.random() <= s]
def RandomComplex(self, n, d, p=0.5): """ A random ``d``-dimensional simplicial complex on ``n`` vertices. INPUT: - ``n`` - number of vertices - ``d`` - dimension of the complex - ``p`` - floating point number between 0 and 1 (optional, default 0.5) A random `d`-dimensional simplicial complex on `n` vertices, as defined for example by Meshulam and Wallach, is constructed as follows: take `n` vertices and include all of the simplices of dimension strictly less than `d`, and then for each possible simplex of dimension `d`, include it with probability `p`. EXAMPLES:: sage: simplicial_complexes.RandomComplex(6, 2) Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6) and 15 facets If `d` is too large (if `d > n+1`, so that there are no `d`-dimensional simplices), then return the simplicial complex with a single `(n+1)`-dimensional simplex:: sage: simplicial_complexes.RandomComplex(6,12) Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6, 7) and facets {(0, 1, 2, 3, 4, 5, 6, 7)} REFERENCES: - Meshulam and Wallach, "Homological connectivity of random `k`-dimensional complexes", preprint, math.CO/0609773. """ if d > n + 1: return simplicial_complexes.Simplex(n + 1) else: vertices = range(n + 1) facets = Subsets(vertices, d).list() maybe = Subsets(vertices, d + 1) facets.extend([f for f in maybe if random.random() <= p]) return SimplicialComplex(n, facets)
def RandomComplex(self, n, d, p=0.5): """ A random ``d``-dimensional simplicial complex on ``n`` vertices. INPUT: - ``n`` - number of vertices - ``d`` - dimension of the complex - ``p`` - floating point number between 0 and 1 (optional, default 0.5) A random `d`-dimensional simplicial complex on `n` vertices, as defined for example by Meshulam and Wallach, is constructed as follows: take `n` vertices and include all of the simplices of dimension strictly less than `d`, and then for each possible simplex of dimension `d`, include it with probability `p`. EXAMPLES:: sage: simplicial_complexes.RandomComplex(6, 2) Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6) and 15 facets If `d` is too large (if `d > n+1`, so that there are no `d`-dimensional simplices), then return the simplicial complex with a single `(n+1)`-dimensional simplex:: sage: simplicial_complexes.RandomComplex(6,12) Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6, 7) and facets {(0, 1, 2, 3, 4, 5, 6, 7)} REFERENCES: - Meshulam and Wallach, "Homological connectivity of random `k`-dimensional complexes", preprint, math.CO/0609773. """ if d > n+1: return simplicial_complexes.Simplex(n+1) else: vertices = range(n+1) facets = Subsets(vertices, d).list() maybe = Subsets(vertices, d+1) facets.extend([f for f in maybe if random.random() <= p]) return SimplicialComplex(n, facets)
def RandomTournament(self, n): r""" Returns a random tournament on `n` vertices. For every pair of vertices, the tournament has an edge from `i` to `j` with probability `1/2`, otherwise it has an edge from `j` to `i`. See :wikipedia:`Tournament_(graph_theory)` INPUT: - ``n`` (integer) -- number of vertices. EXAMPLES:: sage: T = digraphs.RandomTournament(10); T Random Tournament: Digraph on 10 vertices sage: T.size() == binomial(10, 2) True sage: digraphs.RandomTournament(-1) Traceback (most recent call last): ... ValueError: The number of vertices cannot be strictly negative! """ from sage.misc.prandom import random g = DiGraph(n) g.name("Random Tournament") for i in range(n - 1): for j in range(i + 1, n): if random() <= 0.5: g.add_edge(i, j) else: g.add_edge(j, i) if n: from sage.graphs.graph_plot import _circle_embedding _circle_embedding(g, range(n)) return g
def RandomTournament(self, n): r""" Returns a random tournament on `n` vertices. For every pair of vertices, the tournament has an edge from `i` to `j` with probability `1/2`, otherwise it has an edge from `j` to `i`. See :wikipedia:`Tournament_(graph_theory)` INPUT: - ``n`` (integer) -- number of vertices. EXAMPLES:: sage: T = digraphs.RandomTournament(10); T Random Tournament: Digraph on 10 vertices sage: T.size() == binomial(10, 2) True sage: digraphs.RandomTournament(-1) Traceback (most recent call last): ... ValueError: The number of vertices cannot be strictly negative! """ from sage.misc.prandom import random g = DiGraph(n) g.name("Random Tournament") for i in range(n - 1): for j in range(i + 1, n): if random() <= .5: g.add_edge(i, j) else: g.add_edge(j, i) if n: from sage.graphs.graph_plot import _circle_embedding _circle_embedding(g, range(n)) return g
def choose_from_prob_list(lst): r""" INPUT: - ``lst`` - A list of tuples, where the first element of each tuple is a nonnegative float (a probability), and the probabilities sum to one. OUTPUT: A tuple randomly selected from the list according to the given probabilities. EXAMPLES:: sage: from sage.symbolic.random_tests import * sage: v = [(0.1, False), (0.9, True)] sage: choose_from_prob_list(v) # random (0.900000000000000, True) sage: true_count = 0 sage: total_count = 0 sage: def more_samples(): ....: global true_count, total_count ....: for _ in range(10000): ....: total_count += 1.0 ....: if choose_from_prob_list(v)[1]: ....: true_count += 1.0 sage: more_samples() sage: while abs(true_count/total_count - 0.9) > 0.01: ....: more_samples() """ r = random() for i in range(len(lst) - 1): if r < lst[i][0]: return lst[i] r -= lst[i][0] return lst[-1]
def random_sublist(X, s): """ Return a pseudo-random sublist of the list X where the probability of including a particular element is s. INPUT: - ``X`` - list - ``s`` - floating point number between 0 and 1 OUTPUT: list EXAMPLES:: sage: S = [1,7,3,4,18] sage: random_sublist(S, 0.5) [1, 3, 4] sage: random_sublist(S, 0.5) [1, 3] """ return [a for a in X if random.random() <= s]
def RandomPoset(n,p): r""" Generate a random poset on ``n`` vertices according to a probability ``p``. INPUT: - ``n`` - number of vertices, a non-negative integer - ``p`` - a probability, a real number between 0 and 1 (inclusive) OUTPUT: A poset on ``n`` vertices. The construction decides to make an ordered pair of vertices comparable in the poset with probability ``p``, however a pair is not made comparable if it would violate the defining properties of a poset, such as transitivity. So in practice, once the probability exceeds a small number the generated posets may be very similar to a chain. So to create interesting examples, keep the probability small, perhaps on the order of `1/n`. EXAMPLES:: sage: Posets.RandomPoset(17,.15) Finite poset containing 17 elements TESTS:: sage: Posets.RandomPoset('junk', 0.5) Traceback (most recent call last): ... TypeError: number of elements must be an integer, not junk sage: Posets.RandomPoset(-6, 0.5) Traceback (most recent call last): ... ValueError: number of elements must be non-negative, not -6 sage: Posets.RandomPoset(6, 'garbage') Traceback (most recent call last): ... TypeError: probability must be a real number, not garbage sage: Posets.RandomPoset(6, -0.5) Traceback (most recent call last): ... ValueError: probability must be between 0 and 1, not -0.5 """ from sage.misc.prandom import random try: n = Integer(n) except TypeError: raise TypeError("number of elements must be an integer, not {0}".format(n)) if n < 0: raise ValueError("number of elements must be non-negative, not {0}".format(n)) try: p = float(p) except Exception: raise TypeError("probability must be a real number, not {0}".format(p)) if p < 0 or p> 1: raise ValueError("probability must be between 0 and 1, not {0}".format(p)) D = DiGraph(loops=False,multiedges=False) D.add_vertices(range(n)) for i in range(n): for j in range(n): if random() < p: D.add_edge(i,j) if not D.is_directed_acyclic(): D.delete_edge(i,j) return Poset(D,cover_relations=False)
def random_dist(p,k,M): """Returns a random distribution with prime p, weight k, and M moments""" moments=vector([ZZ(floor(random()*(p**M))) for i in range(1,M+1)]) return dist(p,k,moments)
def random_dist_char(p,k,chi,M): """Returns a random distribution with prime p, weight k, character chi, and M moments""" moments=[ZZ(floor(random()*(p**M))) for i in [1..M]] return dist_char(p,k,chi,moments)
def Random(self, n=None, A=None, density_edges=None, density_finals=None, verb=False): """ Generate a random DeterministicAutomaton. INPUT: - ``n`` - int (default: ``None``) -- the number of states - ``A`` (default: ``None``) -- alphabet of the result - ``density_edges`` (default: ``None``) -- the density of the transitions among all possible transitions - ``density_finals`` (default: ``None``) -- the density of final states among all states - ``verb`` - bool (default: ``False``) -- print informations for debugging OUTPUT: A :class:`DeterministicAutomaton` EXAMPLES:: sage: dag.Random() # random DeterministicAutomaton with 401 states and an alphabet of 836 letters sage: dag.Random(3, ['a','b']) DeterministicAutomaton with 3 states and an alphabet of 2 letters """ if density_edges is None: density_edges = random() if density_finals is None: density_finals = random() if n is None: n = randint(2, 1000) if A is None: if random() < .5: A = list('abcdefghijklmnopqrstuvwxyz')[:randint(0, 25)] else: A = range(1, randint(1, 1000)) if verb: print( "Random automaton with %s states, density of leaving edges %s, density of final states %s and alphabet %s" % (n, density_edges, density_finals, A)) L = [] for i in range(n): for j in range(len(A)): if random() < density_edges: L.append((i, randint(0, n - 1), A[j])) if verb: print(L) F = [] for i in range(n): if random() < density_finals: F.append(i) if verb: print("final states %s" % F) return DeterministicAutomaton(L, A=A, S=range(n), i=randint(0, n - 1), final_states=F)
def RandomPoset(n, p): r""" Generate a random poset on ``n`` elements according to a probability ``p``. INPUT: - ``n`` - number of elements, a non-negative integer - ``p`` - a probability, a real number between 0 and 1 (inclusive) OUTPUT: A poset on `n` elements. The probability `p` roughly measures width/height of the output: `p=0` always generates an antichain, `p=1` will return a chain. To create interesting examples, keep the probability small, perhaps on the order of `1/n`. EXAMPLES:: sage: set_random_seed(0) # Results are reproducible sage: P = Posets.RandomPoset(5, 0.3) sage: P.cover_relations() [[5, 4], [4, 2], [1, 2]] TESTS:: sage: Posets.RandomPoset('junk', 0.5) Traceback (most recent call last): ... TypeError: number of elements must be an integer, not junk sage: Posets.RandomPoset(-6, 0.5) Traceback (most recent call last): ... ValueError: number of elements must be non-negative, not -6 sage: Posets.RandomPoset(6, 'garbage') Traceback (most recent call last): ... TypeError: probability must be a real number, not garbage sage: Posets.RandomPoset(6, -0.5) Traceback (most recent call last): ... ValueError: probability must be between 0 and 1, not -0.5 sage: Posets.RandomPoset(0, 0.5) Finite poset containing 0 elements """ from sage.misc.prandom import random try: n = Integer(n) except TypeError: raise TypeError( "number of elements must be an integer, not {0}".format(n)) if n < 0: raise ValueError( "number of elements must be non-negative, not {0}".format(n)) try: p = float(p) except Exception: raise TypeError( "probability must be a real number, not {0}".format(p)) if p < 0 or p > 1: raise ValueError( "probability must be between 0 and 1, not {0}".format(p)) D = DiGraph(loops=False, multiedges=False) D.add_vertices(range(n)) for i in range(n): for j in range(i + 1, n): if random() < p: D.add_edge(i, j) D.relabel(list(Permutations(n).random_element())) return Poset(D, cover_relations=False)
def RandomPoset(n, p): r""" Generate a random poset on ``n`` elements according to a probability ``p``. INPUT: - ``n`` - number of elements, a non-negative integer - ``p`` - a probability, a real number between 0 and 1 (inclusive) OUTPUT: A poset on `n` elements. The probability `p` roughly measures width/height of the output: `p=0` always generates an antichain, `p=1` will return a chain. To create interesting examples, keep the probability small, perhaps on the order of `1/n`. EXAMPLES:: sage: set_random_seed(0) # Results are reproducible sage: P = Posets.RandomPoset(5, 0.3) sage: P.cover_relations() [[5, 4], [4, 2], [1, 2]] TESTS:: sage: Posets.RandomPoset('junk', 0.5) Traceback (most recent call last): ... TypeError: number of elements must be an integer, not junk sage: Posets.RandomPoset(-6, 0.5) Traceback (most recent call last): ... ValueError: number of elements must be non-negative, not -6 sage: Posets.RandomPoset(6, 'garbage') Traceback (most recent call last): ... TypeError: probability must be a real number, not garbage sage: Posets.RandomPoset(6, -0.5) Traceback (most recent call last): ... ValueError: probability must be between 0 and 1, not -0.5 sage: Posets.RandomPoset(0, 0.5) Finite poset containing 0 elements """ from sage.misc.prandom import random try: n = Integer(n) except TypeError: raise TypeError("number of elements must be an integer, not {0}".format(n)) if n < 0: raise ValueError("number of elements must be non-negative, not {0}".format(n)) try: p = float(p) except Exception: raise TypeError("probability must be a real number, not {0}".format(p)) if p < 0 or p> 1: raise ValueError("probability must be between 0 and 1, not {0}".format(p)) D = DiGraph(loops=False, multiedges=False) D.add_vertices(range(n)) for i in range(n): for j in range(i+1, n): if random() < p: D.add_edge(i, j) D.relabel(list(Permutations(n).random_element())) return Poset(D, cover_relations=False)