def _puncture(v, points): r""" Returns v punctured as the positions listed in ``points``. INPUT: - ``v`` -- a vector or a list of vectors - ``points`` -- a set of integers, or an integer EXAMPLES:: sage: v = vector(GF(7), (2,3,0,2,1,5,1,5,6,5,3)) sage: from sage.coding.punctured_code import _puncture sage: _puncture(v, {4, 3}) (2, 3, 0, 5, 1, 5, 6, 5, 3) """ if not isinstance(points, (Integer, int, set)): raise TypeError( "points must be either a Sage Integer, a Python int, or a set") if isinstance(v, list): size = len(v[0]) S = VectorSpace(v[0].base_ring(), size - len(points)) l = [] for i in v: new_v = [i[j] for j in range(size) if j not in points] l.append(S(new_v)) return l S = VectorSpace(v.base_ring(), len(v) - len(points)) new_v = [v[i] for i in range(len(v)) if i not in points] return S(new_v)
def _repr_vector_space(self, dim): """ Return a string representation of the vector space of given dimension INPUT: - ``dim`` -- integer. OUTPUT: String representation of the vector space of dimension ``dim``. EXAMPLES:: sage: F = FilteredVectorSpace(3, base_ring=RDF) sage: F._repr_vector_space(1234) 'RDF^1234' sage: F3 = FilteredVectorSpace(3, base_ring=GF(3)) sage: F3._repr_vector_space(1234) 'GF(3)^1234' sage: F3 = FilteredVectorSpace(3, base_ring=AA) sage: F3._repr_vector_space(1234) 'Vector space of dimension 1234 over Algebraic Real Field' """ if dim == 0: return '0' try: return self._repr_field_name() + '^' + str(dim) except NotImplementedError: return repr(VectorSpace(self.base_ring(), dim))
def ambient_vector_space(self): """ Return the ambient vector space. .. SEEALSO:: :meth:`ambient_module` OUTPUT: The vector space (over the fraction field of the base ring) where the linear expressions live. EXAMPLES:: sage: from sage.geometry.linear_expression import LinearExpressionModule sage: L = LinearExpressionModule(QQ, ('x', 'y', 'z')) sage: L.ambient_vector_space() Vector space of dimension 3 over Rational Field sage: M = LinearExpressionModule(ZZ, ('r', 's')) sage: M.ambient_module() Ambient free module of rank 2 over the principal ideal domain Integer Ring sage: M.ambient_vector_space() Vector space of dimension 2 over Rational Field """ from sage.modules.free_module import VectorSpace field = self.base_ring().fraction_field() return VectorSpace(field, self.ngens())
def __init__(self, space, number_errors, number_erasures): r""" TESTS: If the sum of number of errors and number of erasures exceeds (or may exceed, in the case of tuples) the dimension of the input space, it will return an error:: sage: n_err, n_era = 21, 21 sage: Chan = channels.ErrorErasureChannel(GF(59)^40, n_err, n_era) Traceback (most recent call last): ... ValueError: The total number of errors and erasures can not exceed the dimension of the input space """ if isinstance(number_errors, (Integer, int)): number_errors = (number_errors, number_errors) if not isinstance(number_errors, (tuple, list)): raise ValueError("number_errors must be a tuple, a list, an Integer or a Python int") if isinstance(number_erasures, (Integer, int)): number_erasures = (number_erasures, number_erasures) if not isinstance(number_erasures, (tuple, list)): raise ValueError("number_erasures must be a tuple, a list, an Integer or a Python int") output_space = cartesian_product([space, VectorSpace(GF(2), space.dimension())]) super(ErrorErasureChannel, self).__init__(space, output_space) if number_errors[1] + number_erasures[1] > space.dimension(): raise ValueError("The total number of errors and erasures can not exceed the dimension of the input space") self._number_errors = number_errors self._number_erasures = number_erasures
def nonisomorphic_cubes_Z2(n, avoid_complete=False): """ Returns a generator for all n-dimensional Cube-like graphs (Cayley graphs over Z_2^n) with their generators. With avoid_complete=True avoids the complete graph. Iterates over tuples (generatorSet, G). """ vs = VectorSpace(GF(2), n) basegens = vs.gens() optgens = [v for v in vs if sum(map(int, v)) >= 2] total = 2**len(optgens) seen_graphs = set() c = 0 for g in powerset(optgens): c += 1 gens = tuple(list(basegens) + g) if c % (total / 100 + 1) == 0: log.debug("Generating (%d of %d)" % (c, total)) if avoid_complete: if len(g) >= len(optgens): continue G = CayleyGraph(vs, gens) canon = tuple(Graph(G).canonical_label().edges()) if canon in seen_graphs: continue log.debug("Unique graph (%d of %d) gens=%s" % (c, total, gens)) seen_graphs.add(canon) yield (gens, G)
def ProjectiveGeometryDesign(n, d, F, algorithm=None): """ Returns a projective geometry design. A projective geometry design of parameters `n,d,F` has for points the lines of `F^{n+1}`, and for blocks the `d+1`-dimensional subspaces of `F^{n+1}`, each of which contains `\\frac {|F|^{d+1}-1} {|F|-1}` lines. INPUT: - ``n`` is the projective dimension - ``d`` is the dimension of the subspaces of `P = PPn(F)` which make up the blocks. - ``F`` is a finite field. - ``algorithm`` -- set to ``None`` by default, which results in using Sage's own implementation. In order to use GAP's implementation instead (i.e. its ``PGPointFlatBlockDesign`` function) set ``algorithm="gap"``. Note that GAP's "design" package must be available in this case, and that it can be installed with the ``gap_packages`` spkg. EXAMPLES: The points of the following design are the `\\frac {2^{2+1}-1} {2-1}=7` lines of `\mathbb{Z}_2^{2+1}`. It has `7` blocks, corresponding to each 2-dimensional subspace of `\mathbb{Z}_2^{2+1}`:: sage: designs.ProjectiveGeometryDesign(2, 1, GF(2)) Incidence structure with 7 points and 7 blocks sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_block_design() # optional - gap_packages (design package) (True, [2, 7, 3, 1]) """ q = F.order() from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set if algorithm is None: V = VectorSpace(F, n + 1) points = list(V.subspaces(1)) flats = list(V.subspaces(d + 1)) blcks = [] for p in points: b = [] for i in range(len(flats)): if p.is_subspace(flats[i]): b.append(i) blcks.append(b) v = (q**(n + 1) - 1) / (q - 1) return BlockDesign(v, blcks, name="ProjectiveGeometryDesign") if algorithm == "gap": # Requires GAP's Design gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )" % (n, q, d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign")
def __init__(self, surface, label, point, ring=None, limit=None): self._s = surface if ring is None: self._ring = surface.base_ring() else: self._ring = ring p = surface.polygon(label) point = VectorSpace(self._ring, 2)(point) point.set_immutable() pos = p.get_point_position(point) assert pos.is_inside(), \ "Point must be positioned within the polygon with the given label." # This is the correct thing if point lies in the interior of the polygon with the given label. self._coordinate_dict = {label: {point}} if pos.is_in_edge_interior(): label2, e2 = surface.opposite_edge(label, pos.get_edge()) point2 = surface.edge_transformation(label, pos.get_edge())(point) point2.set_immutable() if label2 in self._coordinate_dict: self._coordinate_dict[label2].add(point2) else: self._coordinate_dict[label2] = {point2} if pos.is_vertex(): self._coordinate_dict = {} sing = surface.singularity(label, pos.get_vertex(), limit=limit) for l, v in sing.vertex_set(): new_point = surface.polygon(l).vertex(v) new_point.set_immutable() if l in self._coordinate_dict: self._coordinate_dict[l].add(new_point) else: self._coordinate_dict[l] = {new_point} # Freeze the sets. for label, point_set in iteritems(self._coordinate_dict): self._coordinate_dict[label] = frozenset(point_set)
def __init__(self, center, radius_squared, base_ring=None): r""" Construct a circle from a Vector representing the center, and the radius squared. """ if base_ring is None: self._base_ring = radius_squared.parent() else: self._base_ring = base_ring # for calculations: self._V2 = VectorSpace(self._base_ring,2) self._V3 = VectorSpace(self._base_ring,3) self._center = self._V2(center) self._radius_squared = self._base_ring(radius_squared)
def Vrepresentation_space(self): r""" Return the ambient vector space. This is the vector space or module containing the Vrepresentation vectors. OUTPUT: A free module over the base ring of dimension :meth:`ambient_dim`. EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra sage: Polyhedra(QQ, 4).Vrepresentation_space() Vector space of dimension 4 over Rational Field sage: Polyhedra(QQ, 4).ambient_space() Vector space of dimension 4 over Rational Field """ if self.base_ring() in Fields(): from sage.modules.free_module import VectorSpace return VectorSpace(self.base_ring(), self.ambient_dim()) else: from sage.modules.free_module import FreeModule return FreeModule(self.base_ring(), self.ambient_dim())
def __init__(self, similarity_surface, ring=None): self._s = similarity_surface if ring is None: self._base_ring = self._s.base_ring() else: self._base_ring = ring from sage.modules.free_module import VectorSpace self._V = VectorSpace(self._base_ring, 2)
def test(): "Run unit tests for the module." log.getLogger().setLevel(log.DEBUG) from sage.graphs.graph_generators import graphs K2 = graphs.CompleteGraph(2) K4 = graphs.CompleteGraph(4) Z2_3 = VectorSpace(GF(2), 3) Z2_2 = VectorSpace(GF(2), 2) # nonisomorphic_cubes_Z2 assert len(list(nonisomorphic_cubes_Z2(1))) == 1 assert len(list(nonisomorphic_cubes_Z2(2))) == 2 assert len(list(nonisomorphic_cubes_Z2(3))) == 6 # CayleyGraph K4b = CayleyGraph(Z2_2, [(1, 0), (0, 1), (1, 1)]) assert K4.is_isomorphic(K4b) # squash_cube Ge = CayleyGraph(Z2_2, [(1, 0), (0, 1)]) Smap = squash_cube(Ge, (1, 1)) K2e = Ge.subgraph(Smap.values()) assert K2.is_isomorphic(K2e) assert is_hom(Ge, K2e, Smap) # hom_is_by_subspace Gg = CayleyGraph(Z2_3, [(1, 0, 0), (0, 1, 0)]) Hg = CayleyGraph(Z2_2, [(1, 0), (0, 1), (1, 1)]) homg = { (0, 0, 0): (0, 0), (1, 0, 0): (1, 0), (0, 1, 0): (0, 1), (1, 1, 0): (1, 1), (0, 0, 1): (0, 0), (1, 0, 1): (1, 0), (0, 1, 1): (1, 1), (1, 1, 1): (0, 1) } assert is_hom(Gg, Hg, homg) assert hom_is_by_subspace(Gg, Z2_3, homg, require_isomorphic=False) assert not hom_is_by_subspace(Gg, Z2_3, homg, require_isomorphic=True) for h in extend_hom(Gg, K2, limit=10): assert hom_is_by_subspace(Gg, Z2_3, h, require_isomorphic=True) log.info("All tests passed.")
def squash_cube(G, c): """ Assuming G is a cube-like _undirected_ graph (Cayley over Z_2^n), given a vector c from Z_2^n, finds a homomorphism unifying vectors differing by c. One of the vertives (v, v+c) still must be chosen as the target for the homomorphism in each such pair. Returns a hom map to a subgraph or None if none such exists. """ n = len(c) vs = VectorSpace(GF(2), n) c = vs(c) pairs = {} # vertex -> pair for v in G.vertices(): w = tuple(vs(v) + c) if G.has_edge(v, w): return False # contracting an edge! if w in pairs or v in pairs: continue pairs[v] = (v, w) pairs[w] = (v, w) chosen = {} # pair -> 0 or 1 (first or second in the pair) undecided = set(pairs.values()) # undecided pairs def extend(pair, sel): """Extend `chosen[]` by setting pair to sel (0 or 1). Recursively chooses for pairs forced by this coloring. Returns False on inconsistency, True if all the forcing succeeded.""" if pair in chosen: if chosen[pair] != sel: return False return True chosen[pair] = sel if pair in undecided: undecided.remove(pair) v = pair[sel] w = pair[1 - sel] for n in G.neighbors(v): np = pairs[n] ni = np.index(n) if G.has_edge(n, w): continue if not extend(np, ni): return False return True while undecided: p = undecided.pop() if not extend(p, 0): return None # create the hom-map hom = {} for p, sel in chosen.items(): hom[p[0]] = p[sel] hom[p[1]] = p[sel] return hom
def cycle_space(self, degree): r""" Returns the space of cycles of degree i Zi = ker(der: C_i -> C_{i-1}) """ assert (degree > -2 and degree < 3) if degree == -1: return VectorSpace(QQ, 1) return self._objects[degree].cycle_space()
def circle_from_three_points(p,q,r,base_ring=None): r""" Construct a circle from three points on the circle. """ if base_ring is None: base_ring=p.base_ring() V2 = VectorSpace(base_ring.fraction_field(), 2) V3 = VectorSpace(base_ring.fraction_field(), 3) v1=V3((p[0]+q[0],p[1]+q[1],2)) v2=V3((p[1]-q[1],q[0]-p[0],0)) line1=v1.cross_product(v2) v1=V3((p[0]+r[0],p[1]+r[1],2)) v2=V3((p[1]-r[1],r[0]-p[0],0)) line2=v1.cross_product(v2) center_3 = line1.cross_product(line2) if center_3[2].is_zero(): raise ValueError("The three points lie on a line.") center = V2( (center_3[0]/center_3[2], center_3[1]/center_3[2]) ) return Circle(center, (p[0]-center[0])**2+(p[1]-center[1])**2 )
def ambient_space(self): r""" Returns the ambient vector space of ``self``. EXAMPLES:: sage: C = codes.HammingCode(GF(2), 3) sage: C.ambient_space() Vector space of dimension 7 over Finite Field of size 2 """ return VectorSpace(self.base_ring(),self.length())
def message_space(self): r""" Return the message space of ``self``. EXAMPLES:: sage: C = codes.ParityCheckCode(GF(5),7) sage: E = codes.encoders.ParityCheckCodeStraightforwardEncoder(C) sage: E.message_space() Vector space of dimension 7 over Finite Field of size 5 """ return VectorSpace(self.code().base_field(), self.code().dimension())
def chain_space(self, degree): r""" Chain space. INPUT: - ``degree`` -- either """ assert (degree > -2 and degree < 3) if degree == -1: return VectorSpace(QQ, 1) return self._objects[degree].chain_space()
def tiny_integrals_on_basis(self, P, Q): r""" Evaluate the integrals `\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}` by formally integrating a power series in a local parameter `t`. `P` and `Q` MUST be in the same residue disc for this result to make sense. INPUT: - P a point on self - Q a point on self (in the same residue disc as P) OUTPUT: The integrals `\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}` EXAMPLES:: sage: K = pAdicField(17, 5) sage: E = EllipticCurve(K, [-31/3, -2501/108]) # 11a sage: P = E(K(14/3), K(11/2)) sage: TP = E.teichmuller(P); sage: E.tiny_integrals_on_basis(P, TP) (17 + 14*17^2 + 17^3 + 8*17^4 + O(17^5), 16*17 + 5*17^2 + 8*17^3 + 14*17^4 + O(17^5)) :: sage: K = pAdicField(11, 5) sage: x = polygen(K) sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16) sage: P = C.lift_x(11^(-2)) sage: Q = C.lift_x(3*11^(-2)) sage: C.tiny_integrals_on_basis(P,Q) (3*11^3 + 7*11^4 + 4*11^5 + 7*11^6 + 5*11^7 + O(11^8), 3*11 + 10*11^2 + 8*11^3 + 9*11^4 + 7*11^5 + O(11^6), 4*11^-1 + 2 + 6*11 + 6*11^2 + 7*11^3 + O(11^4), 11^-3 + 6*11^-2 + 2*11^-1 + 2 + O(11^2)) Note that this fails if the points are not in the same residue disc:: sage: S = C(0,1/4) sage: C.tiny_integrals_on_basis(P,S) Traceback (most recent call last): ... ValueError: (11^-2 + O(11^3) : 11^-5 + 8*11^-2 + O(11^0) : 1 + O(11^5)) and (0 : 3 + 8*11 + 2*11^2 + 8*11^3 + 2*11^4 + O(11^5) : 1 + O(11^5)) are not in the same residue disc """ if P == Q: V = VectorSpace(self.base_ring(), 2 * self.genus()) return V(0) R = PolynomialRing(self.base_ring(), ['x', 'y']) x, y = R.gens() return self.tiny_integrals([x**i for i in range(2 * self.genus())], P, Q)
def chain_space(self): r""" Return the space of chain on this finite set of vertices. EXAMPLES:: sage: from surface_dynamics.all import * sage: o = Origami('(1,2,3,4)', '(1,5)') sage: V = o._vertices() sage: V.chain_space() Vector space of dimension 3 over Rational Field """ return VectorSpace(QQ, self.cardinality())
def make_random_instance(n, m): solution = VectorSpace(ZZ2, n).random_element() results = [] quad_forms = [] for _ in range(m): e = [] for _ in range(n * (n + 1) / 2): e.append(ZZ2.random_element()) quad_form = QuadraticForm(ZZ2, n, e) quad_forms.append(quad_form) results.append(quad_form(solution)) instance = Instance(n, quad_forms, results) prover = Prover(instance, solution) return (instance, prover)
def HomologyGroup(n, base_ring, invfac=None): """ Abelian group on `n` generators which represents a homology group in a fixed degree. INPUT: - ``n`` -- integer; the number of generators - ``base_ring`` -- ring; the base ring over which the homology is computed - ``inv_fac`` -- list of integers; the invariant factors -- ignored if the base ring is a field OUTPUT: A class that can represent the homology group in a fixed homological degree. EXAMPLES:: sage: from sage.homology.homology_group import HomologyGroup sage: G = AbelianGroup(5, [5,5,7,8,9]); G Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9 sage: H = HomologyGroup(5, ZZ, [5,5,7,8,9]); H C5 x C5 x C7 x C8 x C9 sage: AbelianGroup(4) Multiplicative Abelian group isomorphic to Z x Z x Z x Z sage: HomologyGroup(4, ZZ) Z x Z x Z x Z sage: HomologyGroup(100, ZZ) Z^100 """ if base_ring.is_field(): return VectorSpace(base_ring, n) # copied from AbelianGroup: if invfac is None: if isinstance(n, (list, tuple)): invfac = n n = len(n) else: invfac = [] if len(invfac) < n: invfac = [0] * (n - len(invfac)) + invfac elif len(invfac) > n: raise ValueError("invfac (={}) must have length n (={})".format( invfac, n)) M = HomologyGroup_class(n, invfac) return M
def ProjectiveGeometryDesign(n, d, F, algorithm=None): """ INPUT: - ``n`` is the projective dimension - ``v`` is the number of points `PPn(GF(q))` - ``d`` is the dimension of the subspaces of `P = PPn(GF(q))` which make up the blocks - ``b`` is the number of `d`-dimensional subspaces of `P` Wraps GAP Design's PGPointFlatBlockDesign. Does *not* require GAP's Design. EXAMPLES:: sage: designs.ProjectiveGeometryDesign(2, 1, GF(2)) Incidence structure with 7 points and 7 blocks sage: BD = designs.ProjectiveGeometryDesign(2, 1, GF(2), algorithm="gap") # optional - gap_packages (design package) sage: BD.is_block_design() # optional - gap_packages (design package) (True, [2, 7, 3, 1]) """ q = F.order() from sage.interfaces.gap import gap, GapElement from sage.sets.set import Set if algorithm == None: V = VectorSpace(F, n + 1) points = list(V.subspaces(1)) flats = list(V.subspaces(d + 1)) blcks = [] for p in points: b = [] for i in range(len(flats)): if p.is_subspace(flats[i]): b.append(i) blcks.append(b) v = (q**(n + 1) - 1) / (q - 1) return BlockDesign(v, blcks, name="ProjectiveGeometryDesign") if algorithm == "gap": # Requires GAP's Design gap.load_package("design") gap.eval("D := PGPointFlatBlockDesign( %s, %s, %d )" % (n, q, d)) v = eval(gap.eval("D.v")) gblcks = eval(gap.eval("D.blocks")) gB = [] for b in gblcks: gB.append([x - 1 for x in b]) return BlockDesign(v, gB, name="ProjectiveGeometryDesign")
def ambient_vector_space(self): """ Return the ambient (unfiltered) vector space. OUTPUT: A vector space. EXAMPLES:: sage: V = FilteredVectorSpace(1, 0) sage: V.ambient_vector_space() Vector space of dimension 1 over Rational Field """ return VectorSpace(self.base_ring(), self.dimension())
def _smallscale_present_linearlayer(nsboxes=16): """ .. TODO:: switch to sage.crypto.linearlayer (:trac:`25735`) as soon as it is included in sage EXAMPLES:: sage: from sage.crypto.block_cipher.present import _smallscale_present_linearlayer sage: _smallscale_present_linearlayer(4) [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] """ from sage.modules.free_module import VectorSpace from sage.modules.free_module_element import vector from sage.matrix.constructor import Matrix from sage.rings.finite_rings.finite_field_constructor import GF def present_llayer(n, x): dim = 4 * n y = [0] * dim for i in range(dim - 1): y[i] = x[(n * i) % (dim - 1)] y[dim - 1] = x[dim - 1] return vector(GF(2), y) m = Matrix(GF(2), [ present_llayer(nsboxes, ei) for ei in VectorSpace(GF(2), 4 * nsboxes).basis() ]) return m
def ambient_vector_space(self): """ Return the ambient (unfiltered) vector space. OUTPUT: A vector space. EXAMPLES:: sage: V = FilteredVectorSpace(2, 0) sage: W = FilteredVectorSpace(2, 2) sage: F = MultiFilteredVectorSpace({'a':V, 'b':W}) sage: F.ambient_vector_space() Vector space of dimension 2 over Rational Field """ return VectorSpace(self.base_ring(), self.dimension())
def reduced_charges(M): """ Given a snappy manifold M, we find all reduced charges so that: (1) no loop in the triangulation passes an odd number of pi's. (2) no tetrahedron has three pi's and """ out = sol_and_kernel(M) x, A = out nt = M.num_tetrahedra() dim = 3 * nt V = VectorSpace(ZZ2, dim) AA = V.subspace(A) # the reduced kernel xx = V(x) # the reduced solution charges = [xx + sum(B) for B in powerset(AA.basis())] charges = [c for c in charges if not has_pi_triple(c) ] # reject if there are three pi's in any tet. return charges
def Hrepresentation_space(self): r""" Return the linear space containing the H-representation vectors. OUTPUT: A free module over the base ring of dimension :meth:`ambient_dim` + 1. EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra sage: Polyhedra(ZZ, 2).Hrepresentation_space() Ambient free module of rank 3 over the principal ideal domain Integer Ring """ if self.base_ring() in Fields(): from sage.modules.free_module import VectorSpace return VectorSpace(self.base_ring(), self.ambient_dim() + 1) else: from sage.modules.free_module import FreeModule return FreeModule(self.base_ring(), self.ambient_dim() + 1)
def __init__(self, base_field, length, default_encoder_name, default_decoder_name, metric='Hamming'): """ Initializes mandatory parameters that any linear code shares. This method only exists for inheritance purposes as it initializes parameters that need to be known by every linear code. The class :class:`sage.coding.linear_code_no_metric.AbstractLinearCodeNoMetric` should never be directly instantiated. INPUT: - ``base_field`` -- the base field of ``self`` - ``length`` -- the length of ``self`` (a Python int or a Sage Integer, must be > 0) - ``default_encoder_name`` -- the name of the default encoder of ``self`` - ``default_decoder_name`` -- the name of the default decoder of ``self`` - ``metric`` -- (default: ``Hamming``) the metric of ``self`` """ self._registered_encoders['Systematic'] = LinearCodeSystematicEncoder if not base_field.is_field(): raise ValueError("'base_field' must be a field (and {} is not one)".format(base_field)) if not default_encoder_name in self._registered_encoders: raise ValueError("You must set a valid encoder as default encoder for this code, by filling in the dictionary of registered encoders") if not default_decoder_name in self._registered_decoders: raise ValueError("You must set a valid decoder as default decoder for this code, by filling in the dictionary of registered decoders") #if not self.dimension() <= length: # raise ValueError("The dimension of the code can be at most its length, {}".format(length)) super(AbstractLinearCodeNoMetric, self).__init__(length, default_encoder_name, default_decoder_name, metric) cat = Modules(base_field).FiniteDimensional().WithBasis().Finite() facade_for = VectorSpace(base_field, self._length) self.Element = type(facade_for.an_element()) #for when we made this a non-facade parent Parent.__init__(self, base=base_field, facade=facade_for, category=cat)
def construct_from_generators_indices(generators, filtration, base_ring, check): """ Construct a filtered vector space. INPUT: - ``generators`` -- a list/tuple/iterable of vectors, or something convertible to them. The generators spanning various subspaces. - ``filtration`` -- a list or iterable of filtration steps. Each filtration step is a pair ``(degree, ray_indices)``. The ``ray_indices`` are a list or iterable of ray indices, which span a subspace of the vector space. The integer ``degree`` stipulates that all filtration steps of degree higher or equal than ``degree`` (up to the next filtration step) are said subspace. EXAMPLES:: sage: from sage.modules.filtered_vector_space import construct_from_generators_indices sage: gens = [(1,0), (0,1), (-1,-1)] sage: V = construct_from_generators_indices(gens, {1:[0,1], 3:[1]}, QQ, True); V QQ^2 >= QQ^1 >= QQ^1 >= 0 TESTS:: sage: gens = [(int(1),int(0)), (0,1), (-1,-1)] sage: construct_from_generators_indices(iter(gens), {int(0):[0, int(1)], 2:[2]}, QQ, True) QQ^2 >= QQ^1 >= QQ^1 >= 0 """ # normalize generators generators = [list(g) for g in generators] # deduce dimension if len(generators) == 0: dim = ZZ(0) else: dim = ZZ(len(generators[0])) ambient = VectorSpace(base_ring, dim) # complete generators to a generating set if matrix(base_ring, generators).rank() < dim: complement = ambient.span(generators).complement() generators = generators + list(complement.gens()) # normalize generators II generators = tuple(ambient(v) for v in generators) for v in generators: v.set_immutable() # normalize filtration data normalized = dict() for deg, gens in filtration.items(): deg = normalize_degree(deg) gens = [ZZ(i) for i in gens] if any(i < 0 or i >= len(generators) for i in gens): raise ValueError('generator index out of bounds') normalized[deg] = tuple(sorted(gens)) try: del normalized[minus_infinity] except KeyError: pass filtration = normalized return FilteredVectorSpace_class(base_ring, dim, generators, filtration, check=check)
def HughesPlane(q2, check=True): r""" Return the Hughes projective plane of order ``q2``. Let `q` be an odd prime, the Hughes plane of order `q^2` is a finite projective plane of order `q^2` introduced by D. Hughes in [Hu57]_. Its construction is as follows. Let `K = GF(q^2)` be a finite field with `q^2` elements and `F = GF(q) \subset K` be its unique subfield with `q` elements. We define a twisted multiplication on `K` as .. MATH:: x \circ y = \begin{cases} x\ y & \text{if y is a square in K}\\ x^q\ y & \text{otherwise} \end{cases} The points of the Hughes plane are the triples `(x, y, z)` of points in `K^3 \backslash \{0,0,0\}` up to the equivalence relation `(x,y,z) \sim (x \circ k, y \circ k, z \circ k)` where `k \in K`. For `a = 1` or `a \in (K \backslash F)` we define a block `L(a)` as the set of triples `(x,y,z)` so that `x + a \circ y + z = 0`. The rest of the blocks are obtained by letting act the group `GL(3, F)` by its standard action. For more information, see :wikipedia:`Hughes_plane` and [We07]. .. SEEALSO:: :func:`DesarguesianProjectivePlaneDesign` to build the Desarguesian projective planes INPUT: - ``q2`` -- an even power of an odd prime number - ``check`` -- (boolean) Whether to check that output is correct before returning it. As this is expected to be useless (but we are cautious guys), you may want to disable it whenever you want speed. Set to ``True`` by default. EXAMPLES:: sage: H = designs.HughesPlane(9) sage: H (91,10,1)-Balanced Incomplete Block Design We prove in the following computations that the Desarguesian plane ``H`` is not Desarguesian. Let us consider the two triangles `(0,1,10)` and `(57, 70, 59)`. We show that the intersection points `D_{0,1} \cap D_{57,70}`, `D_{1,10} \cap D_{70,59}` and `D_{10,0} \cap D_{59,57}` are on the same line while `D_{0,70}`, `D_{1,59}` and `D_{10,57}` are not concurrent:: sage: blocks = H.blocks() sage: line = lambda p,q: next(b for b in blocks if p in b and q in b) sage: b_0_1 = line(0, 1) sage: b_1_10 = line(1, 10) sage: b_10_0 = line(10, 0) sage: b_57_70 = line(57, 70) sage: b_70_59 = line(70, 59) sage: b_59_57 = line(59, 57) sage: set(b_0_1).intersection(b_57_70) {2} sage: set(b_1_10).intersection(b_70_59) {73} sage: set(b_10_0).intersection(b_59_57) {60} sage: line(2, 73) == line(73, 60) True sage: b_0_57 = line(0, 57) sage: b_1_70 = line(1, 70) sage: b_10_59 = line(10, 59) sage: p = set(b_0_57).intersection(b_1_70) sage: q = set(b_1_70).intersection(b_10_59) sage: p == q False TESTS: Some wrong input:: sage: designs.HughesPlane(5) Traceback (most recent call last): ... EmptySetError: No Hughes plane of non-square order exists. sage: designs.HughesPlane(16) Traceback (most recent call last): ... EmptySetError: No Hughes plane of even order exists. Check that it works for non-prime `q`:: sage: designs.HughesPlane(3**4) # not tested - 10 secs (6643,82,1)-Balanced Incomplete Block Design """ if not q2.is_square(): raise EmptySetError("No Hughes plane of non-square order exists.") if q2 % 2 == 0: raise EmptySetError("No Hughes plane of even order exists.") q = q2.sqrt() K = FiniteField(q2, prefix='x') F = FiniteField(q, prefix='y') A = q3_minus_one_matrix(F) A = A.change_ring(K) m = K.list() V = VectorSpace(K, 3) zero = K.zero() one = K.one() points = [(x, y, one) for x in m for y in m] + \ [(x, one, zero) for x in m] + \ [(one, zero, zero)] relabel = {tuple(p): i for i, p in enumerate(points)} blcks = [] for a in m: if a not in F or a == 1: # build L(a) aa = ~a l = [] l.append(V((-a, one, zero))) for x in m: y = -aa * (x + one) if not y.is_square(): y *= aa**(q - 1) l.append(V((x, y, one))) # compute the orbit of L(a) blcks.append( [relabel[normalize_hughes_plane_point(p, q)] for p in l]) for i in range(q2 + q): l = [A * j for j in l] blcks.append( [relabel[normalize_hughes_plane_point(p, q)] for p in l]) from .bibd import BalancedIncompleteBlockDesign return BalancedIncompleteBlockDesign(q2**2 + q2 + 1, blcks, check=check)