Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Covering designs: coverings of `t`-element subsets of a `v`-set by `k`-sets
A `(v,k,t)` covering design `C` is an incidence structure consisting of a set of points `P` of order `v`, and a set of blocks `B`, where each block contains `k` points of `P`. Every `t`-element subset of `P` must be contained in at least one block.
If every `t`-set is contained in exactly one block of `C`, then we have a block design. Following the block design implementation, the standard representation of a covering design uses `P = [0,1,..., v-1]`.
In addition to the parameters and incidence structure for a covering design from this database, we include extra information:
* Best known lower bound on the size of a `(v,k,t)`-covering design * Name of the person(s) who produced the design * Method of construction used * Date when the design was added to the database
REFERENCES:
.. [1] La Jolla Covering Repository, http://www.ccrwest.org/cover.html
.. [2] Coverings, Daniel Gordon and Douglas Stinson, http://www.ccrwest.org/gordon/hcd.pdf from the Handbook of Combinatorial Designs
AUTHORS:
-- Daniel M. Gordon (2008-12-22): initial version
Classes and methods ------------------- """
#***************************************************************************** # Copyright (C) 2008 Daniel M. Gordon <dmgordo@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function
from sage.misc.sage_eval import sage_eval from sage.structure.sage_object import SageObject from sage.rings.rational import Rational from sage.arith.all import binomial from sage.combinat.combination import Combinations from sage.combinat.designs.incidence_structures import IncidenceStructure
###################### covering design functions ##############################
def schonheim(v,k,t): r""" Schonheim lower bound for size of covering design
INPUT:
- ``v`` -- integer, size of point set - ``k`` -- integer, cardinality of each block - ``t`` -- integer, cardinality of sets being covered
OUTPUT:
The Schonheim lower bound for such a covering design's size: `C(v,k,t) \leq \lceil(\frac{v}{k} \lceil \frac{v-1}{k-1} \cdots \lceil \frac{v-t+1}{k-t+1} \rceil \cdots \rceil \rceil`
EXAMPLES::
sage: from sage.combinat.designs.covering_design import schonheim sage: schonheim(10,3,2) 17 sage: schonheim(32,16,8) 930 """
def trivial_covering_design(v,k,t): r""" Construct a trivial covering design.
INPUT:
- ``v`` -- integer, size of point set - ``k`` -- integer, cardinality of each block - ``t`` -- integer, cardinality of sets being covered
OUTPUT:
`(v,k,t)` covering design
EXAMPLES::
sage: C = trivial_covering_design(8,3,1) sage: print(C) C(8,3,1) = 3 Method: Trivial 0 1 2 0 6 7 3 4 5 sage: C = trivial_covering_design(5,3,2) sage: print(C) 4 <= C(5,3,2) <= 10 Method: Trivial 0 1 2 0 1 3 0 1 4 0 2 3 0 2 4 0 3 4 1 2 3 1 2 4 1 3 4 2 3 4
NOTES:
Cases are:
* `t=0`: This could be empty, but it's a useful convention to have one block (which is empty if $k=0$).
* `t=1` : This contains `\lceil v/k \rceil` blocks: `[0,...,k-1],[k,...,2k-1],...`. The last block wraps around if `k` does not divide `v`.
* anything else: Just use every `k`-subset of `[0,1,...,v-1]`.
""" blk=[] for i in range(k): blk.append(i) return CoveringDesign(v,k,t,1,range(v),[blk],1,"Trivial")
# default case, all k-subsets
class CoveringDesign(SageObject): """ Covering design.
INPUT:
- ``v,k,t`` -- integer parameters of the covering design.
- ``size`` (integer)
- ``points`` -- list of points (default points are `[0,...v-1]`).
- ``blocks``
- ``low_bd`` (integer) -- lower bound for such a design
- ``method, creator, timestamp`` -- database information. """
def __init__(self, v=0, k=0, t=0, size=0, points=[], blocks=[], low_bd=0, method='', creator ='',timestamp=''): """ EXAMPLES::
sage: C=CoveringDesign(5,4,3,4,range(5),[[0,1,2,3],[0,1,2,4],[0,1,3,4],[0,2,3,4]],4, 'Lexicographic Covering') sage: print(C) C(5,4,3) = 4 Method: Lexicographic Covering 0 1 2 3 0 1 2 4 0 1 3 4 0 2 3 4 """ else:
def __repr__(self): """ A print method, giving the parameters and any other information about the covering (but not the blocks).
EXAMPLES::
sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C (7,3,2)-covering design of size 7 Lower bound: 7 Method: Projective Plane """ self.__k, self.__t, self.__size) repr += 'Created by: %s\n' % (self.__creator) repr += 'Submitted on: %s\n' % (self.__timestamp)
def __str__(self): """ A print method, displaying a covering design's parameters and blocks.
OUTPUT:
covering design parameters and blocks, in a readable form
EXAMPLES::
sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: print(C) C(7,3,2) = 7 Method: Projective Plane 0 1 2 0 3 4 0 5 6 1 3 5 1 4 6 2 3 6 2 4 5 """ else: repr += 'Created by: %s\n'%(self.__creator) repr += 'Submitted on: %s\n'%(self.__timestamp)
def is_covering(self): """ Checks that all `t`-sets are in fact covered by the blocks of ``self``
.. NOTE::
This is very slow and wasteful of memory.
EXAMPLES::
sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C.is_covering() True sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 6]],0, 'not a covering') # last block altered sage: C.is_covering() False """
# mark all t-sets covered by each block
def v(self): """ Return `v`, the number of points in the covering design.
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C.v() 7 """
def k(self): """ Return `k`, the size of blocks of the covering design
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C.k() 3 """
def t(self): """ Return `t`, the size of sets which must be covered by the blocks of the covering design
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C.t() 2 """
def size(self): """ Return the number of blocks in the covering design
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C.size() 7 """
def low_bd(self): """ Return a lower bound for the number of blocks a covering design with these parameters could have.
Typically this is the Schonheim bound, but for some parameters better bounds have been shown.
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C.low_bd() 7 """
def method(self): """ Return the method used to create the covering design This field is optional, and is used in a database to give information about how coverings were constructed
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: C.method() 'Projective Plane' """
def creator(self): """ Return the creator of the covering design
This field is optional, and is used in a database to give attribution for the covering design It can refer to the person who submitted it, or who originally gave a construction
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane','Gino Fano') sage: C.creator() 'Gino Fano' """
def timestamp(self): """ Return the time that the covering was submitted to the database
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane','Gino Fano','1892-01-01 00:00:00') sage: C.timestamp() #Fano had an article in 1892, I don't know the date it appeared '1892-01-01 00:00:00' """
def incidence_structure(self): """ Return the incidence structure of a covering design, without all the extra parameters.
EXAMPLES::
sage: from sage.combinat.designs.covering_design import CoveringDesign sage: C=CoveringDesign(7,3,2,7,range(7),[[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]],0, 'Projective Plane') sage: D = C.incidence_structure() sage: D.ground_set() [0, 1, 2, 3, 4, 5, 6] sage: D.blocks() [[0, 1, 2], [0, 3, 4], [0, 5, 6], [1, 3, 5], [1, 4, 6], [2, 3, 6], [2, 4, 5]]
"""
def best_known_covering_design_www(v, k, t, verbose=False): r""" Gives the best known `(v,k,t)` covering design, using the database available at `<http://www.ccrwest.org/>`_
INPUT:
- ``v`` -- integer, the size of the point set for the design - ``k`` -- integer, the number of points per block - ``t`` -- integer, the size of sets covered by the blocks - ``verbose`` -- bool (default=``False``), print verbose message
OUTPUT:
A :class:`CoveringDesign` object representing the ``(v,k,t)``-covering design with smallest number of blocks available in the database.
EXAMPLES::
sage: from sage.combinat.designs.covering_design import best_known_covering_design_www sage: C = best_known_covering_design_www(7, 3, 2) # optional - internet sage: print(C) # optional - internet C(7,3,2) = 7 Method: lex covering Submitted on: 1996-12-01 00:00:00 0 1 2 0 3 4 0 5 6 1 3 5 1 4 6 2 3 6 2 4 5
This function raises a ValueError if the ``(v,k,t)`` parameters are not found in the database. """ # import compatible with py2 and py3 from six.moves.urllib.request import urlopen
from sage.misc.sage_eval import sage_eval
v = int(v) k = int(k) t = int(t)
param = ("?v=%s&k=%s&t=%s"%(v,k,t))
url = "http://www.ccrwest.org/cover/get_cover.php"+param if verbose: print("Looking up the bounds at %s" % url) f = urlopen(url) s = f.read() f.close()
if 'covering not in database' in s: #not found str = "no (%d,%d,%d) covering design in database\n"%(v,k,t) raise ValueError(str)
return sage_eval(s) |