def _some_tuples_sampling(elements, repeat, max_samples, n): """ Internal function for :func:`some_tuples`. TESTS:: sage: from sage.misc.misc import _some_tuples_sampling sage: l = list(_some_tuples_sampling(range(3), 3, 2, 3)) sage: len(l) 2 sage: all(len(tup) == 3 for tup in l) True sage: all(el in range(3) for tup in l for el in tup) True sage: l = list(_some_tuples_sampling(range(20), None, 4, 20)) sage: len(l) 4 sage: all(el in range(20) for el in l) True """ from sage.rings.integer import Integer N = n if repeat is None else n**repeat # We sample on range(N) and create tuples manually since we don't want to create the list of all possible tuples in memory for a in random.sample(range(N), max_samples): if repeat is None: yield elements[a] else: yield tuple(elements[j] for j in Integer(a).digits(n, padto=repeat))
def transmit_unsafe(self, message): r""" Returns ``message`` with as many errors as ``self._number_errors`` in it. If ``self._number_errors`` was passed as a tuple for the number of errors, it will pick a random integer between the bounds of the tuple and use it as the number of errors. This method does not check if ``message`` belongs to the input space of``self``. INPUT: - ``message`` -- a vector OUTPUT: - a vector of the output space EXAMPLES:: sage: F = GF(59)^6 sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(F, n_err) sage: msg = F((4, 8, 15, 16, 23, 42)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) (4, 8, 4, 16, 23, 53) """ w = copy(message) number_errors = randint(*self.number_errors()) V = self.input_space() for i in sample(xrange(V.dimension()), number_errors): w[i] = V.base_ring().random_element() return w
def transmit_unsafe(self, message): r""" Returns ``message`` with as many errors as ``self._number_errors`` in it, and as many erasures as ``self._number_erasures`` in it. If ``self._number_errors`` was passed as an tuple for the number of errors, it will pick a random integer between the bounds of the tuple and use it as the number of errors. It does the same with ``self._number_erasures``. All erased positions are set to 0 in the transmitted message. It is guaranteed that the erasures and the errors will never overlap: the received message will always contains exactly as many errors and erasures as expected. This method does not check if ``message`` belongs to the input space of``self``. INPUT: - ``message`` -- a vector OUTPUT: - a couple of vectors, namely: - the transmitted message, which is ``message`` with erroneous and erased positions - the erasure vector, which contains ``1`` at the erased positions of the transmitted message , 0 elsewhere. EXAMPLES:: sage: F = GF(59)^11 sage: n_err, n_era = 2, 2 sage: Chan = channels.ErrorErasureChannel(F, n_err, n_era) sage: msg = F((3, 14, 15, 9, 26, 53, 58, 9, 7, 9, 3)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) ((31, 0, 15, 9, 38, 53, 58, 9, 0, 9, 3), (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0)) """ number_errors = randint(*self.number_errors()) number_erasures = randint(*self.number_erasures()) V = self.input_space() n = V.dimension() zero = V.base_ring().zero() errors = sample(xrange(n), number_errors + number_erasures) error_positions = errors[:number_errors] erasure_positions = errors[number_errors:] error_vector = random_error_vector(n, V.base_ring(), error_positions) erasure_vector = random_error_vector(n , GF(2), erasure_positions) message = message + error_vector for i in erasure_positions: message[i] = zero return message, erasure_vector
def transmit_unsafe(self, message): r""" Returns ``message`` with as many errors as ``self._number_errors`` in it, and as many erasures as ``self._number_erasures`` in it. If ``self._number_errors`` was passed as an tuple for the number of errors, it will pick a random integer between the bounds of the tuple and use it as the number of errors. It does the same with ``self._number_erasures``. All erased positions are set to 0 in the transmitted message. It is guaranteed that the erasures and the errors will never overlap: the received message will always contains exactly as many errors and erasures as expected. This method does not check if ``message`` belongs to the input space of``self``. INPUT: - ``message`` -- a vector OUTPUT: - a couple of vectors, namely: - the transmitted message, which is ``message`` with erroneous and erased positions - the erasure vector, which contains ``1`` at the erased positions of the transmitted message , 0 elsewhere. EXAMPLES:: sage: F = GF(59)^11 sage: n_err, n_era = 2, 2 sage: Chan = channels.ErrorErasureChannel(F, n_err, n_era) sage: msg = F((3, 14, 15, 9, 26, 53, 58, 9, 7, 9, 3)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) ((31, 0, 15, 9, 38, 53, 58, 9, 0, 9, 3), (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0)) """ number_errors = randint(*self.number_errors()) number_erasures = randint(*self.number_erasures()) V = self.input_space() n = V.dimension() zero = V.base_ring().zero() errors = sample(xrange(n), number_errors + number_erasures) error_positions = errors[:number_errors] erasure_positions = errors[number_errors:] error_vector = random_error_vector(n, V.base_ring(), error_positions) erasure_vector = random_error_vector(n, GF(2), erasure_positions) message = message + error_vector for i in erasure_positions: message[i] = zero return message, erasure_vector
def time_information_set_steps(): before = process_time() while True: I = sample(range(n), k) Gi = G.matrix_from_columns(I) try: Gi_inv = Gi.inverse() except ZeroDivisionError: continue return process_time() - before
def random_element(self): """ Returns a random choice of k things from range(n). EXAMPLES:: sage: from sage.combinat.choose_nk import ChooseNK sage: ChooseNK(5,2).random_element() [0, 2] """ r = sorted(rnd.sample(xrange(self._n),self._k)) return r
def random_element(self): r""" Return a random submultiset of given length EXAMPLES:: sage: Subsets(7,3).random_element() {1, 4, 7} sage: Subsets(7,5).random_element() {1, 3, 4, 5, 7} """ return rnd.sample(self._l, self._k)
def random_element(self): """ Returns a random permutation of k things from range(n). EXAMPLES:: sage: from sage.combinat.permutation_nk import PermutationsNK sage: PermutationsNK(3,2).random_element() [0, 1] """ n, k = self._n, self._k rng = range(n) r = rnd.sample(rng, k) return r
def random_element(self): r""" Return a random submultiset of given length EXAMPLES:: sage: s = Subsets(7,3).random_element() sage: s in Subsets(7,3) True sage: s = Subsets(7,5).random_element() sage: s in Subsets(7,5) True """ return rnd.sample(self._l, self._k)
def random_element(self): """ Returns a random set partition of range(n) into a set of size k and a set of size n-k. EXAMPLES:: sage: from sage.combinat.split_nk import SplitNK sage: SplitNK(5,2).random_element() [[0, 2], [1, 3, 4]] """ r = rnd.sample(xrange(self._n),self._n) r0 = r[:self._k] r1 = r[self._k:] r0.sort() r1.sort() return [ r0, r1 ]
def transmit_unsafe(self, message): r""" Returns ``message`` with as many errors as ``self._number_errors`` in it. If ``self._number_errors`` was passed as a tuple for the number of errors, it will pick a random integer between the bounds of the tuple and use it as the number of errors. This method does not check if ``message`` belongs to the input space of``self``. INPUT: - ``message`` -- a vector OUTPUT: - a vector of the output space EXAMPLES:: sage: F = GF(59)^6 sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(F, n_err) sage: msg = F((4, 8, 15, 16, 23, 42)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) (4, 8, 4, 16, 23, 53) This checks that :trac:`19863` is fixed:: sage: V = VectorSpace(GF(2), 1000) sage: Chan = channels.StaticErrorRateChannel(V, 367) sage: c = V.random_element() sage: (c - Chan(c)).hamming_weight() 367 """ w = copy(message) number_errors = randint(*self.number_errors()) V = self.input_space() R = V.base_ring() for i in sample(range(V.dimension()), number_errors): err = R.random_element() while (w[i] == err): err = R.random_element() w[i] = err return w
def random_partial_injection(n): r""" Return a uniformly chosen random partial injection on 0, 1, ..., n-1. INPUT: - ``n`` -- integer OUTPUT: list EXAMPLES:: sage: from slabbe import random_partial_injection sage: random_partial_injection(10) [3, 5, 2, None, 1, None, 0, 8, 7, 6] sage: random_partial_injection(10) [1, 7, 4, 8, 3, 5, 9, None, 6, None] sage: random_partial_injection(10) [5, 6, 8, None, 7, 4, 0, 9, None, None] TODO:: Adapt the code once this is merged: https://trac.sagemath.org/ticket/24416 AUTHORS: - Sébastien Labbé and Vincent Delecroix, Nov 30, 2017, Sage Thursdays at LaBRI """ L = number_of_partial_injection(n) s = sum(L).n() L = [a/s for a in L] # because of the bug #24416 X = GeneralDiscreteDistribution(L) k = X.get_random_element() codomain = sample(range(n), k) missing = [None]*(n-k) codomain.extend(missing) shuffle(codomain) return codomain
def random_element(self): """ Returns a random element of the class of subsets of s of size k (in other words, a random subset of s of size k). EXAMPLES:: sage: Subsets(3, 2).random_element() {1, 2} sage: Subsets(3,4).random_element() Traceback (most recent call last): ... EmptySetError """ lset = self._ls if self._k > len(lset): raise EmptySetError else: return self.element_class(rnd.sample(lset, self._k))
def random_element(self): r""" Return a random subword of given length with uniform law. EXAMPLES:: sage: S1 = Subwords([1,2,3,2,1],3) sage: S2 = Subwords([4,4,5,5,4,5,4,4],3) sage: for i in range(100): ....: w = S1.random_element() ....: if w in S2: ....: assert(w == []) sage: for i in range(100): ....: w = S2.random_element() ....: if w in S1: ....: assert(w == []) """ sample = prandom.sample(self._w, self._k) if self._build is list: return sample return self._build(sample)
def random_element(self): r""" Return a random subword of given length with uniform law. EXAMPLES:: sage: S1 = Subwords([1,2,3,2,1],3) sage: S2 = Subwords([4,4,5,5,4,5,4,4],3) sage: for i in xrange(100): ....: w = S1.random_element() ....: if w in S2: ....: assert(w == []) sage: for i in xrange(100): ....: w = S2.random_element() ....: if w in S1: ....: assert(w == []) """ sample = prandom.sample(self._w, self._k) if self._build is list: return sample return self._build(sample)
def __init__(self, index=20, index_max=50, odd_probability=0.5): r""" Create an arithmetic subgroup testing object. INPUT: - ``index`` - the index of random subgroup to test - ``index_max`` - the maximum index for congruence subgroup to test EXAMPLES:: sage: from sage.modular.arithgroup.tests import Test sage: Test() Arithmetic subgroup testing class """ self.congroups = [] i = 1 self.odd_probability = odd_probability if index%2: self.odd_probability=0 while Gamma(i).index() < index_max: self.congroups.append(Gamma(i)) i += 1 i = 1 while Gamma0(i).index() < index_max: self.congroups.append(Gamma0(i)) i += 1 i = 2 while Gamma1(i).index() < index_max: self.congroups.append(Gamma1(i)) M = Zmod(i) U = [x for x in M if x.is_unit()] for j in xrange(1,len(U)-1): self.congroups.append(GammaH(i,prandom.sample(U,j))) i += 1 self.index = index
def __init__(self, index=20, index_max=50, odd_probability=0.5): r""" Create an arithmetic subgroup testing object. INPUT: - ``index`` - the index of random subgroup to test - ``index_max`` - the maximum index for congruence subgroup to test EXAMPLES:: sage: from sage.modular.arithgroup.tests import Test sage: Test() Arithmetic subgroup testing class """ self.congroups = [] i = 1 self.odd_probability = odd_probability if index % 4: self.odd_probability = 0 while Gamma(i).index() < index_max: self.congroups.append(Gamma(i)) i += 1 i = 1 while Gamma0(i).index() < index_max: self.congroups.append(Gamma0(i)) i += 1 i = 2 while Gamma1(i).index() < index_max: self.congroups.append(Gamma1(i)) M = Zmod(i) U = [x for x in M if x.is_unit()] for j in range(1, len(U) - 1): self.congroups.append(GammaH(i, prandom.sample(U, j))) i += 1 self.index = index
def UniformRandomUniform(self, n, k, m): r""" Return a uniformly sampled `k`-uniform hypergraph on `n` points with `m` hyperedges. - ``n`` -- number of nodes of the graph - ``k`` -- uniformity - ``m`` -- number of edges EXAMPLES:: sage: H = hypergraphs.UniformRandomUniform(52, 3, 17) sage: H Incidence structure with 52 points and 17 blocks sage: H.is_connected() False TESTS:: sage: hypergraphs.UniformRandomUniform(-52, 3, 17) Traceback (most recent call last): ... ValueError: number of vertices should be non-negative sage: hypergraphs.UniformRandomUniform(52.9, 3, 17) Traceback (most recent call last): ... ValueError: number of vertices should be an integer sage: hypergraphs.UniformRandomUniform(52, -3, 17) Traceback (most recent call last): ... ValueError: the uniformity should be non-negative sage: hypergraphs.UniformRandomUniform(52, I, 17) Traceback (most recent call last): ... ValueError: the uniformity should be an integer """ from sage.rings.integer import Integer from sage.combinat.subset import Subsets from sage.misc.prandom import sample # Construct the vertex set if n < 0: raise ValueError("number of vertices should be non-negative") try: nverts = Integer(n) except TypeError: raise ValueError("number of vertices should be an integer") vertices = range(nverts) # Construct the edge set if k < 0: raise ValueError("the uniformity should be non-negative") try: uniformity = Integer(k) except TypeError: raise ValueError("the uniformity should be an integer") all_edges = Subsets(vertices, uniformity) try: edges = sample(all_edges, m) except OverflowError: raise OverflowError("binomial({}, {}) too large to be treated".format(n, k)) except ValueError: raise ValueError("number of edges m must be between 0 and binomial({}, {})".format(n, k)) from sage.combinat.designs.incidence_structures import IncidenceStructure return IncidenceStructure(points=vertices, blocks=edges)
def UniformRandomUniform(self, n, k, m): r""" Return a uniformly sampled `k`-uniform hypergraph on `n` points with `m` hyperedges. - ``n`` -- number of nodes of the graph - ``k`` -- uniformity - ``m`` -- number of edges EXAMPLES:: sage: H = hypergraphs.UniformRandomUniform(52, 3, 17) sage: H Incidence structure with 52 points and 17 blocks sage: H.is_connected() False TESTS:: sage: hypergraphs.UniformRandomUniform(-52, 3, 17) Traceback (most recent call last): ... ValueError: number of vertices should be non-negative sage: hypergraphs.UniformRandomUniform(52.9, 3, 17) Traceback (most recent call last): ... ValueError: number of vertices should be an integer sage: hypergraphs.UniformRandomUniform(52, -3, 17) Traceback (most recent call last): ... ValueError: the uniformity should be non-negative sage: hypergraphs.UniformRandomUniform(52, I, 17) Traceback (most recent call last): ... ValueError: the uniformity should be an integer """ from sage.rings.integer import Integer from sage.combinat.subset import Subsets from sage.misc.prandom import sample # Construct the vertex set if n < 0: raise ValueError("number of vertices should be non-negative") try: nverts = Integer(n) except TypeError: raise ValueError("number of vertices should be an integer") vertices = range(nverts) # Construct the edge set if k < 0: raise ValueError("the uniformity should be non-negative") try: uniformity = Integer(k) except TypeError: raise ValueError("the uniformity should be an integer") all_edges = Subsets(vertices, uniformity) try: edges = sample(all_edges, m) except OverflowError: raise OverflowError( "binomial({}, {}) too large to be treated".format(n, k)) except ValueError: raise ValueError( "number of edges m must be between 0 and binomial({}, {})". format(n, k)) from sage.combinat.designs.incidence_structures import IncidenceStructure return IncidenceStructure(points=vertices, blocks=edges)
def decode(self, r): r""" The Lee-Brickell algorithm as described in the class doc. Note that either parameters must be given at construction time or :meth:`sage.coding.information_set_decoder.InformationSetAlgorithm.calibrate()` should be called before calling this method. INPUT: - `r` -- a received word, i.e. a vector in the ambient space of :meth:`decoder.Decoder.code`. OUTPUT: A codeword whose distance to `r` satisfies ``self.decoding_interval()``. EXAMPLES:: sage: M = matrix(GF(2), [[1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0],\ [0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1],\ [0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0],\ [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1],\ [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1]]) sage: C = codes.LinearCode(M) sage: from sage.coding.information_set_decoder import LeeBrickellISDAlgorithm sage: A = LeeBrickellISDAlgorithm(C, (2,2)) sage: c = C.random_element() sage: Chan = channels.StaticErrorRateChannel(C.ambient_space(), 2) sage: r = Chan(c) sage: c_out = A.decode(r) sage: (r - c).hamming_weight() == 2 True """ import itertools from sage.misc.prandom import sample C = self.code() n, k = C.length(), C.dimension() tau = self.decoding_interval() p = self.parameters()['search_size'] F = C.base_ring() G = C.generator_matrix() Fstar = F.list()[1:] while True: # step 1. I = sample(range(n), k) Gi = G.matrix_from_columns(I) try: Gi_inv = Gi.inverse() except ZeroDivisionError: # I was not an information set continue Gt = Gi_inv * G #step 2. y = r - vector([r[i] for i in I]) * Gt g = Gt.rows() #step 3. for pi in range(p + 1): for A in itertools.combinations(range(k), pi): for m in itertools.product(Fstar, repeat=pi): e = y - sum(m[i] * g[A[i]] for i in range(pi)) errs = e.hamming_weight() if errs >= tau[0] and errs <= tau[1]: return r - e