% Copyright(c) 1998-2003 David B. Jaffe % Permission to use, copy, modify, and distribute any document (including this % one) which is part of the Split distribution is hereby granted without fee, % for any noncommercial purpose, provided that this paragraph is copied, % conspicuously referenced, that an explanation is included which % explains what portion of the Split distribution has been utilized, and that % no other person's copyright is thereby infringed. % % The following materials in the distribution are owned by other people: % Brendan McKay (the graph isomorphism package nauty; in NOT_MINE) % Keith Briggs (double-double precision arithmetic; in NOT_MINE) % Victor Shoup (ntl: a library for doing number theory; in NTL) % Free Software Foundation (prevector::sort; in CODE) % U. C. Berkeley (random.c; in NOT_MINE) % Hewlett-Packard (pair and make_pair; in CODE). define(VERSION, `0.6alpha') % Hints for selective recompilation: % % If you edit a class definition, you should probably recompile the % whole shebang. For other changes, search backwards for the string % "set_com". You will find the name of the file which needs to be % recompiled. % Hints for debugging: % % 1. Go through and activate all "#define DEBUG" lines by deleting % the "// " which preceeds them. % 2. Make SLList.h safer. % (a) Make a local copy. % (b) Modify "T& operator () (Pix p)" and the const version by adding % a line `if (!owns(p)) error("illegal Pix");'. % (c) Change #include so it fetches local copy instead. define(TEX_IN,`tex/code.tex') define(DATA_IN,`inputs/code.data') define(newresultcounter,9) include(src/MACROS) ifelse(UNAME,OPENSTEP,![DEFINE(UNAME,Openstep)]!) |-> tex/t.ista preamble "\\begin{theindexa}\n" postamble "\n\n\\end{theindexa}\n" |-> tex/t.istb preamble "\\begin{theindexb}\n" postamble "\n\n\\end{theindexb}\n" |-> tex/t.istz preamble "\\begin{theindexz}\n" postamble "\n\n\\end{theindexz}\n" |-> tex/code.tex % \second % [.stepanov lee.] \hfuzz 10pt % Create quote macros to sync with 5n character indentation in verbatim % environment. \def\quotea{\list{}{\def\leftmargin{62pt}\advance\linewidth -26pt}\item[]} \let\endquotea=\endlist \def\quoteaneg{\vspace{-0.35in}\list{}{\def\leftmargin{62pt}\advance\linewidth -26pt}\item[]} \let\endquoteaneg=\endlist \def\quoteb{\list{}{\def\leftmargin{93pt}\advance\linewidth -29pt}\item[]} \let\endquoteb=\endlist \def\quotebneg{\vspace{-0.35in}\list{}{\def\leftmargin{93pt}\advance\linewidth -29pt}\item[]} \let\endquotebneg=\endlist \def\quotec{\list{}{\def\leftmargin{124pt}\advance\linewidth -32pt}\item[]} \let\endquotec=\endlist \def\quotecneg{\vspace{-0.35in}\list{}{\def\leftmargin{124pt}\advance\linewidth -32pt}\item[]} \let\endquotecneg=\endlist \def\quoted{\list{}{\def\leftmargin{155pt}\advance\linewidth -35pt}\item[]} \let\endquoted=\endlist \def\quotee{\list{}{\def\leftmargin{186pt}\advance\linewidth -38pt}\item[]} \let\endquotee=\endlist % Set up a svb macro, which is like verbatim, but doesn't put % vertical spacing at the beginning and end. \catcode`\@=11 \begingroup \catcode `|=0 \catcode `[= 1 \catcode`]=2 \catcode `\{=12 \catcode `\}=12 \catcode`\\=12 |gdef|@xsvb#1\end{svb}[#1|end[svb]] |gdef|@sxsvb#1\end{svb*}[#1|end[svb*]] |endgroup \def\@svb{ \leftskip\@totalleftmargin\rightskip\z@ \parindent\z@\parfillskip\@flushglue\parskip\z@ \@tempswafalse \def\par{\if@tempswa\hbox{}\fi\@tempswatrue\@@par \penalty\interlinepenalty}% \obeylines \tt \catcode``=13 \@noligs \let\do\@makeother \dospecials} \def\svb{\@svb \frenchspacing\@vobeyspaces \@xsvb} \let\endsvb=\relax \def\mindex{\@bsphack\begingroup\@sanitize\@wrindexa} \catcode`\@=12 \pagestyle{empty} \vspace*{0.8in} \widepost{40}{40}{/Times-Roman findfont 40 scalefont setfont (Binary linear codes:) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \vspace{0.1in} \widepost{40}{40}{/Times-Roman findfont 40 scalefont setfont (new results on nonexistence) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \vspace{0.4in} \widepost{28}{28}{/Times-Roman findfont 28 scalefont setfont (Draft, March 21, 2000) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \vspace{-0.05in} \widepost{28}{28}{/Times-Roman findfont 28 scalefont setfont (\(Version 0.6beta\)) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \vspace{0.5in} \widepost{28}{28}{/Times-Roman findfont 28 scalefont setfont (David B. Jaffe) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \vspace{0.3in} \widepost{28}{28}{/Times-Roman findfont 28 scalefont setfont (Department of Mathematics and Statistics) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \widepost{28}{28}{/Times-Roman findfont 28 scalefont setfont (University of Nebraska) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \widepost{28}{28}{/Times-Roman findfont 28 scalefont setfont (Lincoln, NE 68588-0323) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \widepost{28}{28}{/Times-Roman findfont 28 scalefont setfont (e-mail: jaffe@cpthree.unl.edu) dup stringwidth pop 2 div neg 0 moveto 50 0 rmoveto true charpath StrokeFill} \newpage %% \ \newpage %% Insert to get even number of pages if needed. \pagestyle{plain} \def\GAPref{\protect{[.groups algorithms programming.]}} \vspace*{-0.4in} \begin{center} \LARGE\bf Preface \end{center} \addcontentsline{toc}{special}{Preface} \def\classbreak{\par\noindent\kern32pt% \hbox to 6.35in{\leaders\hbox{\vbox{\hrule width1mm height 0.5pt}}\hfil}} \newenvironment{classboxedquote}% {\vskip0.065in\par\noindent\kern31pt\begin{Sbox}\begin{minipage}{6in}}% {\end{minipage}\end{Sbox}\fbox{\TheSbox}\vskip0.065in} \def\classtext#1{\begin{classboxedquote}#1\end{classboxedquote}} \newenvironment{classboxedquotet}% {\vskip0.065in\par\noindent\kern31pt\begin{Sbox}\begin{minipage}{6in}% \begin{tabbing}}% {\end{tabbing}\end{minipage}\end{Sbox}\fbox{\TheSbox}\vskip0.065in} \def\classtextt#1{\begin{classboxedquotet}#1\end{classboxedquotet}} \newenvironment{classboxedquotefour}% {\vskip0.065in\par\noindent\begin{Sbox}\begin{minipage}{4in}}% {\end{minipage}\end{Sbox}\fbox{\TheSbox}} \vspace{0.25in} {\large This is a working draft of a report which describes a new language for proving results about binary linear codes, and moreover exhibits a program in this language which proves many new results. Source code ({\tt C++}) for the language is included. The author gratefully acknowledges partial support under NSF grants DMS-9100983 and DMS-9623205, and as well wishes to thank the NSF-sponsored Geometry Center for supercomputer access, which facilitated exploratory calculations. John Gregory, Spyros Magliveras, Eric Rains, and Neil J.\ A.\ Sloane provided helpful comments and suggestions. I thank Juriaan Simonis (and TU Delft) for supporting a stimulating visit during the second half of May 1996, for introducing me to the work of [.brouwer van eupen 1997.], and for several enlightening converations which led to the work of \S\ref{menagerie-section}. The language employs the graph isomorphism package {\tt nauty} of Brendan McKay, the double-double precision floating point arithmetic package {\tt doubledouble} of Keith Briggs [.briggs doubledouble.], and the number theory library of Victor Shoup [.shoup ntl.]. The routines {\tt prevector::sort} are in effect copyrighted by the Free Software Foundation. The definitions of {\tt pair} and \verb|make_pair| are copyrighted by Hewlett-Packard. A number of unpublished codes discovered by J.\ B.\ Shearer are included in this document, as well as one code discovered by M.\ Morii. The material on designs in \S\ref{some-unital-section}, the associated % Using {\it options} below had weird unintended consequences when using xdvi. ``options'' field in the {\tt type} command, and the implementation of the latter arose as part of joint work with Tonchev [.jaffe tonchev rank 20.]. \vspace{0.05in} To obtain this draft or the source code itself, see the World Wide \vspace{0.01in} \par\noindent Web at ``\verb|http://www.math.unl.edu/~djaffe/#coding|''. For a more leisurely introduction, see [.brief tour split main.]. } \newpage \vspace*{-0.3in} \par\noindent{\LARGE\bf Contents} \vspace{0.15in} {\footnotesize\ \catcode`\@=11 \@starttoc{toc} \catcode`\@=12} \newpage % Set up for indices. \def\indexnamez{Index of C++ classes} \def\indexnamea{Index of C++ methods} \def\indexnameb{Index of commands} \catcode`\@=11 \def\theindexz{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi \columnseprule \z@ \addcontentsline{toc}{special}{\indexnamez} \columnsep 35\p@\twocolumn[{\Large\bf Index of C++ classes}\\ \\ ]% \@mkboth{\uppercase{\indexnamez}}{\uppercase{\indexnamez}}% \thispagestyle{plain}\parindent\z@ \parskip\z@ plus.3\p@\relax\let\item\@idxitem} \def\theindexa{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi \columnseprule \z@ \addcontentsline{toc}{special}{\indexnamea} \columnsep 35\p@\twocolumn[{\Large\bf Index of C++ methods}\\ \\ This list should index all C++ methods and macros defined in the source code, except that not all constructors, destructors, and operators are included. We also do not include the {\tt execute\string_}$\ldots$ commands from \S\ref{main-program-section}, which execute particular commands. These may be found from the index of commands. \\ \\ ]% \@mkboth{\uppercase{\indexnamea}}{\uppercase{\indexnamea}}% \thispagestyle{plain}\parindent\z@ \parskip\z@ plus.3\p@\relax\let\item\@idxitem} \def\theindexb{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi \columnseprule \z@ \addcontentsline{toc}{special}{\indexnameb} \columnsep 35\p@\twocolumn[{\Large\bf Index of commands}\\ \\ For each command, we give first the page on which the command is defined, and then the corresponding page in the source code. If the body of the command is executed as a separate subroutine, a page number is also given for that, intermediate between the first two numbers. \\ \\ ]% \@mkboth{\uppercase{\indexnameb}}{\uppercase{\indexnameb}}% \thispagestyle{plain}\parindent\z@ \parskip\z@ plus.3\p@\relax\let\item\@idxitem} \def\endtheindexa{\if@restonecol\onecolumn\else\clearpage\fi} \def\endtheindexb{\if@restonecol\onecolumn\else\clearpage\fi} \catcode`\@=12 \part{Introduction} \block{Synopsis} A basic problem in coding theory is to determine the maximum number $B(n,d)$ of codewords in a binary linear code in $\F_2^n$ having minimum weight $d$. While the original motivation for this problem came from practical problems of data transmission, continuing interest is due also to the fact that binary linear codes are such basic combinatorial structures. Many proofs of bounds for specific $B(n,d)$ have as input statements of bounds for $B(n',d')$, where $n' < n$. Proofs thus have a hierarchical nature, and if one wants specific results about the $B(n,d)$, one is naturally lead to construct tables. This has been done by Helgert and Stinaff [.helgert stinaff.], Verhoeff [.verhoeff 1987.], Brouwer and Verhoeff [.brouwer verhoeff 1993.], and Bierbrauer and Edel [.bierbrauer edel parameters binary.]. But the numbers $B(n,d)$ are extremely difficult to compute and there remain gaps even for small $n$ and $d$. The problem of finding lower bounds has been addressed by a vast array of fascinating constructions. These are of ongoing interest but do not form the subject matter of this report. Rather, we address the problem of how one may find {\it upper\/} bounds. Some of the major general contributions to this problem have been (in approximate historical order) Griesmer's bound [.griesmer 1960.], Johnson's bound [.johnson unrestricted.], Delsarte's linear programming method [.delsarte bounds unrestricted.], Hill and Traynor's examples [.hill traynor.], Brouwer's generalized parity type argument [.brouwer linear programming bound.], and Simonis's use of coordinate partitions [.simonis partitions.]. In addition, many people have contributed specific results, and thus methods, more often than not. A number of software packages have been developed for computing upper (and lower) bounds for $B(n,d)$. These packages include [.code buster.], [.guava.], LINCOR [.manev lincor 1987.], [.manev petkova golemanova.], and the system used by Brouwer and Verhoeff to generate [.brouwer verhoeff 1993.]. In addition, there exists software for computing automorphism groups of codes and for determining if two codes are isomorphic. We defer discussion of this to \S\ref{automorphismisomorphismsection}. In this report\footnote{This refers not only to this document, but also to [.jaffe optimal binary 30.], which contains results for length $\leq 30$.}, we give improved upper bounds for the $B(n,d)$, in total \ref{NewResultCount} improvements. This is actually quite modest progress: whereas before the first unknown case occurred when $n = 28$, now the first unknown case occurs when $n = 32$. As an example we establish that $B(28,9) = 2^{10}$ by showing that there is no $[28,11,9]$ binary linear code.% \footnote{General background on coding theory may be found in [.macwilliams sloane book.]. Another good reference is [.lint coding theory.]. In this paper we make the slightly non-standard convention that an $[n,k,d]$ binary linear code is a sub-vector space $C$ of $\F_2^n$ having dimension $k$, such that no non-zero element of $C$ has weight $< d$. Also, by {\bf code}, we shall always mean {\bf binary linear code}.} The vehicle for these improvements is a computer language which we present. Its general purpose is to investigate binary linear codes. We exhibit a program (written in the language) which yields the aforementioned improvements to the $B(n,d)$. This program is completely self-contained, in the sense that all needed results about specific codes are proved within the confines of the program. We do this to complement rather than supplant the ``pencil and paper'' proofs which exist in some cases. This report also includes (with proof) a complete table of all known specific upper bounds, for codes of length $85$ or less, and extensive information about the weight enumerators of codes which may or may not exist. The first part of this paper is the introduction. The second part is a description of the language and its theoretical basis. The third part is a program, written in the language, which yields specific results about binary linear codes. The forth part of the paper is C++ source code for an implementation of the language. These are also available electronically from the author.% \footnote{The program should be easy to install on any Unix-based machine. The current implementation includes a provisional implementation of the simplex method, and as an alternative also includes support for a much faster commercial linear programming package, CPLEX. As of October 1995, the cost to academic users of a CPLEX ``Linear Optimizer Single CPU License'' is \$495. Mail to \verb|info@cplex.com| for more information.} Both the language and the program are ongoing projects, to which contributions are invited. \block{Basic data structures and definitions}\label{definitions-section} We describe the basic data structures of the language, in a somewhat idealized fashion. For practical reasons the actual data structures differ slightly from the descriptions we give here; most of these differences are mentioned in \S\ref{variable-section} and \S\ref{proof-command-section}. The top-level structure in the language is a {\bf code type}. It is a triple $(n,k,\cal S)$ consisting of a positive integer $n$, an integer $k$ ($1 \leq k \leq n$), and a finite set $\cal S$ of inequalities (called {\bf assumed constraints}) having the form $$a_0 y_0 \many+ a_n y_n \leq r,$$% where $\VEC a0n,r$ are integers. The variables $y_i$ (for computer input written \verb|y|$i$) are called {\bf basic global variables}. The {\bf dimension} of a code type is $k$. The {\bf realization} of a code type $(n,k,\cal S)$ is the set of all codes $C \IN \F_2^n$ of dimension $k$ such that if $y_i$ denotes the number of words of weight $i$ in $C$, then all inequalities in $\cal S$ are satisfied. (We refer to this general sort of operation as {\bf evaluation} on a code.) A code type is {\bf unrealizable} if its realization is empty, otherwise it is {\bf realizable}. A {\bf global variable} is a $\Q$-linear combination of basic global variables, whose evaluation on every $[n,k]$ code is an integer. Below each code type $(n,k,\cal S)$ lives a family of structures called {\bf configurations}. Each such structure is a quadruple $(p, D, D', \cal T\kern2pt)$ consisting of a partition% \footnote{We mean by this that $\VEC p1r \in \N$ and that $p_1 \many+ p_r = n$.} $p = (\VEC p1r)$ of $n$, two subcodes $D, D'$ of $\F_2^r$, and a finite set $\cal T$ of inequalities (again called {\bf assumed constraints}) having the form $$a_0 y_0 \many+ a_n y_n + \sum_I a_I x_I \leq r,$$% where $I = (\VEC i1r)$ is a {\bf multi-index\/} (or more precisely a {\it multi-index for $p$}, meaning that $0 \leq i_j \leq p_j$ for each $j$), and $\VEC a0n, a_I, r \in \Z$. The variables $x_I$ (for computer input written \verb|x_|$i_1$\verb|_|$\ldots$\verb|_|$i_r$) are called {\bf basic local variables}; the {\bf trivial} basic local variable is $x_{(0,\ldots,0)}$. We say that $D$ is the {\bf small code} of the configuration, and that $D'$ is the {\bf dual small code} of it. The {\bf dimension} of a configuration is defined to be $\dim(D)$. For the duration of the introduction, we fix the above notations for code types and configurations. Supposing for simplicity that $D' = 0$ and that $\cal T = \emptyset$, we may visualize the configuration by exhibiting a basis for $D$. By way of an example, let us reverse this process. Suppose we wish to study codes $C \IN \F_2^{25}$ which contain a word of weight $10$ and a word of weight $12$, intersecting along $4$ bits: \widepost{70}{35}{ {{100 26 Box {(6) BigCenterPrint} 50 6 xyput} -150 4 xyput {100 26 Box {(4) BigCenterPrint} 50 6 xyput} -50 4 xyput {100 26 Box {(4) BigCenterPrint} 50 6 xyput} -50 -30 xyput {100 26 Box {(8) BigCenterPrint} 50 6 xyput} 50 -30 xyput} 50 xput} \par\noindent We would be led to consider the partition $(6,4,8,7)$ of $25$ and the small code $D$ with basis \setof{1100,0110}. It is the picture which justifies the term {\it configuration}: it conforms to the dictionary definition as it is a {\it relative arrangement of parts}. We return to the general situation.\label{action-def} Given $d \in D$, and a multi-index $I$, define a multi-index $d(I)$ by $$d(I)_j\ =\ \cases{i_j,&if $d_j = 0$;\cr p_j - i_j,&if $d_j = 1$.}$$% Then $D$ acts on the set of multi-indices, and accordingly on basic local variables. We regard two basic local variables as {\bf equivalent} if they lie in the same orbit \WRT\ this action. We define two configurations to be {\bf equivalent} if they differ only in changing $\cal T$ by replacing some occurrences of basic local variables by equivalent ones. Given a partition $p = (\VEC p1r)$, we shall say that a partition $\loP = (\loP_1,\ldots,\loP_s)$ {\bf refines} $p$ if there exist $$0 = \beta_0 < \beta_1 < \cdots < \beta_r = s$$% such that $$p_j\ =\ \loP_{\beta_{j-1}+1} \many+ \loP_{\beta_j}$$% for all $j = 1,\ldots,r$. There is an induced map \mp[[ \varphi || \F_2^r || \F_2^s ]] given by $\varphi(e_j) = e_{\beta_{j-1}+1} \many+ e_{\beta_j}$. Now given a configuration $c = (p,D,D',{\cal T})$ as before, and given a refinement $\loP$ of $p$ as above, we define the {\bf refinement $\loC$ of $c$ induced by $\loP$} to be $\loC = (\loP,\varphi(D),\varphi(D'),\ol{\cal T})$, where $\ol{\cal T}$ is yet to be defined. First define a {\bf pullback} map \mp[[ \Psi || \setofh{multi-indices of $\loP$} || \setofh{multi-indices of $p$} ]] by $$\Psi(\oI)_j = \oI_{\beta_{j-1}+1} \many+ \oI_{\beta_j}.$$ Now given $f \in \cal T$, define $\loF$ by replacing each basic local variable $x_I$ by $\sum x_{\oI}$, where $\oI$ ranges over the multi-indices of $\loP$ with $\Psi(\oI) = I$. Then $\ol{\cal T}$ is defined to be \setof{\loF: f \in \cal T}. Given the configuration $c$, and a basic local variable $x_I$ of $c$, we define a new configuration $c|x_I$, called the {\bf subdivision of $c$ along $x_I$}, as follows. First define a partition $\loP$ by $$q_j\ =\ \cases{(p_j),&if $i_j \notin \setof{0,p_j}$;\cr (i_j, p_j - i_j),&otherwise,}$$% and $\loP = (\VEC q1r)$ (with internal parentheses removed). Let $s$ be the length of $p$. Define $v$ by $$v_j\ =\ \cases{(0),&if $i_j = 0$;\cr (1),&if $i_j = p_j$;\cr (1,0),&otherwise,}$$ $$v\ =\ (\VEC v1r)\ \ \hbox{(with internal parentheses removed)}.$$% Let $\loC = (\loP,\oD,\ol{D'},\ol{\cal T})$ be the refinement of $c$ induced by $\loP$. Then $c|x_I = (\loP, \oD + \inn{v}, \ol{D'}, \ol{\cal T})$, where $\oD + \inn{v}$ is the subspace of $\F_2^s$ generated by $\oD$ and $v$. An element of $\F_2^r$ is a {\bf small word}. Let \mp[[ \pi_i || \F_2^n || \F_2^{p_i} ]] be the ``\th{i} projection map''. A {\bf basic word} is an element $x \in \F_2^n$ such that for each $i$, $\pi_i(x)$ is either $0\ldots0$ or $1\ldots1$. Evidently there is a bijective correspondence between small words and basic words. A {\bf basic code} is a code in $\F_2^n$ consisting entirely of basic words. For any code in $\F_2^r$, there is an {\bf associated} basic code in $\F_2^n$. If $w \in \F_2^n$, the \th{i}\ weight $\abs{w}_i$ of $w$ is the weight of $\pi_i(w)$. The {\bf multiweight} of $w$ is the $r$-tuple $(\abs{w}_1,\ldots,\abs{w}_r)$; its {\bf weight} $\abs{w}$ is $\abs{w}_1 \many+ \abs{w}_r$. The {\bf realization} of the configuration is the set of all codes $C$ in the code type, which, after permuting coordinates if need be, have all of the following properties: \begin{itemize} \item for each small word in $D$, the associated basic word lies in $C$; \item for each small word in $D'$, the associated basic word lies in $C^\perp$; \item if $y_i$ denotes the number of words of weight $i$ in $C$ and $x_I$ denotes the number of words in $C$ which have multiweight $I$, then all inequalities in $\cal T$ are satisfied. \end{itemize} For $c$ a configuration, we let ${\cal R}(c)$ denote its realization, and we let $\ol{\cal R}(c)$ denote the set of isomorphism classes in ${\cal R}(c)$. The same terminology {\bf unrealizable}, {\bf realizable} applies to configurations. A {\bf local variable} is a $\Q$-linear combination of basic local variables, whose evaluation on every code in the realization of the code type is an integer. Since basic global variables are expressible as linear combinations of basic local variables (upon evaluation), the inclusion of basic global variables in the definition of assumed constraints (for a configuration) is formally superfluous. However, it turns out to be convenient and economical to formally distinguish between local and global variables in constraints. To each configuration, the language associates a list of {\bf known} constraints. Initially, this list consists of the assumed constraints for the code type and the assumed constraints for the configuration. But as a program is executed, various commands may be used to prove that other constraints hold for the configuration: these constraints are also considered to be known. For every code type, there is the {\bf base} configuration, which by definition has the trivial partition $(n)$, $D = 0$, $D' = 0$, and $\cal T = \emptyset$. Obviously the realization of the base configuration is the same as the realization of the code type. We also refer to a {\bf basal} configuration, by which we mean a configuration with the properties of a base configuration, except that $\cal T$ may be arbitrary. Call a configuration {\bf full} if its dimension equals the dimension of the code type. A {\bf terminal} configuration is a full configuration having $D' = 0$, and whose assumed constraints involve only global variables. Obviously a terminal configuration admits (up to isomorphism) at most one realization, and if there is one, it is the basic code associated to $D$. We refer to $D$ as the code {\bf corresponding} to the given terminal configuration. If a realizable terminal configuration has assumed constraints, these constraints simply give facts which are deducible from the weight enumerator of $D$. A complete classification for a code type might be construed as being an exhibition of realizable terminal configurations $\VEC c1m$ such that $${\cal R}(\hbox{base})\ =\ {\cal R}(c_1) \sqcup \cdots \sqcup {\cal R}(c_m) \ \ \hbox{(disjoint union)}.$$% As this is a desirable goal and a feasible one so long as $\abs{\ol{\cal R}(\hbox{base})}$ is small, the language facilitates logical statements holding between the sets ${\cal R}(c)$, where $c$ ranges over the configurations associated to the code type. In brief, we refer to such statements as {\it logical statements holding between the configurations}. Even in lieu of a complete classification, such statements permit partial classification, for instance up to weight enumerator. A configuration is {\bf fully refined} if its partition has the form $1,\ldots,1$. An {\bf automorphism} of a configuration $c$ is a permutation $\sigma$ of $1,\ldots,r$ such that $\sigma(c)$ is equivalent to $c$. We let $\Aut(c)$ denote the group of all automorphisms of $c$. In case $c$ is realizable and terminal, and $p_i = 1$ for all $i$, we have $\Aut(c) = \Aut(D)$. \block{Method: finding automorphisms and isomorphisms of codes}% \label{automorphismisomorphismsection} The problem is to find generators for the automorphism group of a code $C$, and to determine if two given codes are isomorphic. There are two established schemes for solving such problems. For both schemes, one must start with a subset $S$ of $C$ which is stable under the action of $\Aut(C)$, and which is ``sufficiently large''. Here we take this to mean that $S$ generates $C$ as a vector space. In practice, one should expect the size of $S$ to grow exponentially as a function of $\dim(C)$. Thus both schemes will yield algorithms whose execution time grows exponentially, and not just for the worst cases. It remains an open problem to find algorithms whose execution time (on average, at least) is polynomial in $n$ (the length) and $k$ (the dimension). The first scheme proceeds by reducing to the analogous problems for graphs.% \footnote{This approach seems to be well-known but the author is indebted to D.\ Stinson and V.\ Tonchev for independently pointing it out to him.} One may form a zero-one matrix, with one row for each $x \in S$, by writing out $x$ as an element of $\F_2^n$. This matrix may be regarded as defining a bipartite graph $G$, and clearly $\Aut(G) = \Aut(C)$. If $C'$ is another code of length $n$, and a bipartite graph $G'$ is constructed in the same way, then $C \iso C'\ \Longleftrightarrow\ G \iso G'$. The complexity of the graph isomorphism problem is not well understood; more specifically, it is not known if the problem admits a polynomial-time algorithm, nor is it known if it is NP-complete. There do exist algorithms whose reported average running time is quadratic as a function of the number of vertices. McKay has implemented such an algorithm ([.practical graph isomorphism.], [.nauty guide onepointfive.]) and we employ his program {\tt nauty} here. The second scheme is that of Leon [.leon computing automorphism groups 1982.], [.leon computing automorphism groups 1984.]. It has the advantage of working with all linear codes, not just binary ones. The implementation [.leon partition backtrack manual.], [.leon partition backtrack source.], [.leon partition backtrack examples.] is a very impressive piece of work, over $25,000$ lines of code, the accessibility of which would be greatly enhanced by additional documentation. \block{Method: split linear programming}\label{split-intro-section} Now we turn to a method which we call {\bf split linear programming}. While the author came to this independently by combining the notion of split weight enumerator ([.macwilliams sloane book.]\ pp.\ 149-150) with Delsarte's linear programming method [.delsarte bounds unrestricted.], credit for the concept is due to Simonis [.simonis partitions.], and in fact the idea had been used successfully prior to the author by Heijnen [.heijnen.]. Having fixed a partition $(\VEC p1r)$ of $n$, let $C \IN \F_2^n$ be a code. For $I = (\VEC i1r)$ a multi-index, let $t^I$ denote $t_1^{i_1} \manycdot t_r^{i_r}$, where $\VEC t1r$ are indeterminates. An {\bf $I$-word\/} is a word of multiweight $I$; we let $x_I$ denote the number of $I$-words in $C$. Then the {\bf split weight enumerator} of $C$ is $$\sum_I x_I t^I,$$% where $I$ ranges over all multi-indices. We will show that the split weight enumerator of $C^\perp$ is $${1 \over \abs{C}} \sum_{I = (\VEC i1r)} x_I \prod_{j=1}^r (1+t_j)^{p_j - i_j} (1-t_j)^{i_j}.$$% This is not difficult to prove, and in fact the case where the partition is $(m,m)$ for some $m$ may be found as an exercise in [.macwilliams sloane book.], on p.\ 150. Regard this expression as a polynomial in $\VEC t1r$; its coefficients (say $m_I$) are $\Q$-linear combinations of the variables $x_I$. As these coefficients are evidently nonnegative, we arrive immediately at a linear programming problem, just as one would arrive at such a problem via Delsarte's original linear programming method. To actually use this method, one should start with a configuration, and not just a partition. Now if two basic local variables are equivalent, they will have the same evaluation on any realization of the configuration. Therefore we may select one basic local variable from each equivalence class, and modify the linear programming problem so that only these selected variables occur. This greatly reduces the complexity of the problem. As an example, in investigating $[31,13,10]$ codes (discussed below), we arrive at a configuration with partition $(10,10,11)$. This would (a priori) give rise to a system having $1452$ variables and $1452$ constraints. But by using equivalence of basic local variables (and other ideas, to be discussed next), we reduce this to a problem involving $136$ variables and $245$ constraints. This reduction is of paramount importance. There is a second way one can reduce the number of variables. A basic local variable $x_I$ (for a configuration $c$) is {\bf inadmissible} if at least one of the following three things happens: \begin{romanlist} \item For some equivalent basic local variable $x_J$ which is equivalent to $x_I$, the constraint $x_J = 0$ is known for the configuration. \item $x_I$ is not equivalent to the trivial basic local variable, and if $d$ is the subdivision of $c$ along $x_I$, then the weight enumerator of the basic code associated to the small code of $d$ contradicts a known constraint of the form $y_i \leq r$. \item For some equivalent basic local variable $x_J$ which is equivalent to $x_I$, there exists some $d' \in D'$ such that $d' \cdot J$ (dot product) is odd. \item It would violate the zeroness of a joint variable which is known to be zero. \end{romanlist} In any realization of the configuration, the inadmissible basic local variables will evaluate to zero. Therefore we may delete the inadmissible variables from the linear programming problem. A priori we get one constraint for each multi-index $I$. In fact, no information is lost if we use only some of the constraints, as follows. First, if $I \cdot d \not= 0$ (in $\F_2$) for some $d \in D$, then the constraint associated to $I$ is identically zero, and we may omit it. Second, for $d' in D'$, we can define $d'(I)$ just as we defined $d(I)$ (p.\ \pageref{action-def}), and we arrive thusly at a notion of {\bf dual equivalence} for the variables $m_I$. It is then sufficient to use one constraint from each equivalence class. In practice, one can do better by using (in place of $D'$) an enlarged version of it (say $(D')^+)$, which includes words known by the language to be dual. Thus if the constraint $y_j = 0$ is known for every odd $j$, then the word $1\ldots1$ is in $(D')^+$, and if the constraint $y_j = 0$ is known for every $j$ not divisible by four, then all of $D$ is in $(D')^+$ as well. Now we illustrate the application of the split linear programming method by means of a real example: we show that there is no $[31,13,10]$ code. In the program we will prove the stronger statement that there is no $[29,11,10]$ code, but this is more involved. In the course of the argument we will consider three configurations, and correspondingly apply the method three times. Only the last application will be nontrivial, as the conclusion of the first two may easily be recovered by other means. The split linear programming method gets applied three times: \begin{itemize} \item There is a word of weight $20$. This calculation corresponds to considering the trivial partition $(31)$ of $31$. One finds that \verb|x_20| is nonzero. In other words, the code has a word of weight $20$. Thus far the method is a mere rephrasing of Delsarte's linear programming method. \item Use the word of weight $20$ to subdivide the original partition, yielding the partition $(20,11)$. Show that \verb|x_10_0| $\not= 0$. That is, show that there is a word of weight $10$ in the code which is contained in the word of weight $20$. This statement is also obvious. \item Subdivide again, yielding the partition $(10,10,11)$. A final application of the method yields a contradiction. \end{itemize} In this example, $D'$ is always zero. In succession, $D$ consists of the zero code (in $\F_2^1$), then the code with basis \setof{10} (in $\F_2^2$), and finally the code with basis \setof{110,100} (in $\F_2^3$). Although there are in principle oodles of configurations, only certain ones are known to the program as it executes. These get created in various ways, for instance by explicit declaration in a ``{\tt config}'' command. (See the worked example below.) Also, the program automatically knows about the base configuration. The configurations are also the vertices of a directed multigraph\label{first-multigraph-occurrence}, whose connected components correspond to logical equivalence classes: if two configurations lie in the same connected component, then they have the same realization. There are two types of edges. The first type (which we call {\bf constructive}) corresponds to a basic local variable; a nontrivial variable is used to subdivide a given configuration, yielding another (the target of the edge). The second type of edge (which we call {\bf logical}) merely establishes that the source and target configurations have the same realization. We give here a taste of what the language is like by explaining in detail the formal code for the $[31,13,10]$ example. The following code is one way (not the shortest) or writing it in our language: \begin{verbatim} ??no [25,8,10]; type [31,13,10_2]; show x_20 != 0; config 20,11 : {10}; show x_10_0 != 0; !config 10,10,11 : {110,100}; no [31,13,10]; \end{verbatim} The first command tells the program to accept without proof the fact that there is no $[25,8,10]$ code. The proof of this (previously known) fact may also be exhibited in our language, and we do so in [.jaffe optimal binary 30.]. In a complete proof one would not have such a {\tt??no} command. The third command ({\tt type}$\ldots$) declares that our code type consists of even codes $C$ in $\F_2^{31}$ of dimension $13$, having minimum weight $\geq 10$. To conform to the description of code type given earlier, we could say the type consists of all codes in $\F_2^{31}$ of dimension $13$, satisfying the constraints $$y_1 = 0,y_2=0,\ldots,y_8=0,y_9=0,y_{11}=0,y_{13}=0,\ldots,y_{31}=0,$$% but this would be cumbersome. Given the knowledge that there is no $[25,8,10]$ code, the program automatically infers that the minimum weight of $C^\perp$ is $\geq 7$. The command ``\verb|show x_20 != 0|'' is self-explanatory. As it executes the \verb|show| command, the program automatically creates a configuration, which is then (it so happens) made the current configuration via the following \verb|config| command. Also, when the program executes the first \verb|show| command, it creates a constructive edge from the base configuration to the new configuration. The next \verb|show| and \verb|config| commands are similar. Again, the show command actually creates the configuration prior to it being made current by the \verb|config| command. Thus, after executing the second \verb|show| command, the configurations form a graph $$\begin{array}{c} \rnode{a}{\psframebox{\hbox{$\vcenter{\hbox{\kern30pt(base)}\vskip3pt% \hbox{\tt 31 : \{ \} : \{ \}}}$}}}\\[1.3cm] \rnode{b}{\psframebox{\hbox{\tt 20,11 : \{10\} : \{ \}}}}\\[1cm] \rnode{c}{\psframebox{\hbox{\tt 10,10,11 : \{110,100\} : \{ \}}}} \end{array} \arrow(a,b)\arrow(b,c)$$% where we use the format partition : small basis : dual small basis. The ``\verb|!config|'' command makes the bottom configuration current, and instructs the language to try to find a contradiction. That is, the bottom configuration is unrealizable. Following the arrows back to the base configuration, we conclude that it is unrealizable, and hence that the code type is unrealizable. As there is no {\it even\/} $[31,13,10]$ code, we conclude that there is no $[31,13,10]$ code at all, thereby justifying the final command. \block{Method: split linear programming + symmetry} Sometimes symmetry of a configuration can be employed to strengthen the split linear programming method. Let $v$ be an admissible basic local variable. Suppose we have a subgroup $G$ of the automorphism group of the configuration. Then $G$ acts on the admissible basic local variables. Use split linear programming to show that the sum over $g \in G$ of $gv$ is nonzero. Then the current configuration can be subdivided (along $v$), and a logical edge can be constructed from the current configuration to the new configuration. \block{Method: passing constraints between configurations} \def\lconfig{{\tt[}$\ell$\kern1pt{\tt]}} \def\hconfig{{\tt[}$h$\kern1pt{\tt]}} \def\lorconfigs{{\tt[}$\ell_1${\tt]}\kern5pt{\tt or}\kern5pt$\ldots$\kern5pt% {\tt or}\kern5pt{\tt[}$\ell_r${\tt]}} \def\rconfig{{\tt[}$r${\tt]}} \def\rpconfig{{\tt[}$r'$\kern1pt{\tt]}} \def\sconfig{{\tt[}$s${\tt]}} \def\spconfig{{\tt[}$s'$\kern1pt{\tt]}} \def\lconfigs{{\tt[}$\ell_1${\tt]}, $\ldots$, {\tt[}$\ell_r${\tt]}} \def\mconfig{{\tt[}$m${\tt]}} \def\miconfig{{\tt[}$m_i${\tt]}} \def\mconfigs{{\tt[}$\m_1${\tt]}, $\ldots$, {\tt[}$\m_r${\tt]}} Suppose we have a constructive edge \lconfig\ $\longrightarrow$ \mconfig\ of configurations. Let $x_J$ be a basic local variable for \lconfig, and let $x_{J_1},\ldots,x_{J_r}$ be the basic local variables of \mconfig\ which pull back to $x_J$. In an appropriate sense (which we leave to the reader to make precise), $$x_J\ =\ x_{J_1} \many+ x_{J_r}.$$% Therefore some known constraints of \mconfig\ will induce known constraints of \lconfig, and conversely. For example, if $x_{J_i} \geq c$ is a known constraint of \mconfig (for some $i$), then the constraint $x_J \geq c$ holds for \lconfig. One could have full and automatic propagation of constraints along constructive edges, but at present this feature is only partially implemented in the language. \block{Method: joint linear programming} The joint weight enumerator ${\cal J}_{C,C}$ of a code $C$ with itself gives rise to a linear programming problem because the coefficients of ${\cal J}_{C, C^{\perp}}$ are nonnegative. More information can be obtained from the fact that the coefficients of ${\cal J}_{C^{\perp}, C^{\perp}}$ are as well nonnegative, but this information comes at a great cost, as the resulting linear programming problem is much larger than that which one would get by using ${\cal J}_{C, C^{\perp}}$ alone. We define a {\it basic joint variable\/} to be a variable of the form {\tt jy}$r${\tt y}$s${\tt y}$t$, which represents $\abs{\setof{(v,w) \in C \times C: \abs{v} = r, \abs{w} = s, \abs{v+w} = t}}$. Note that $r$, $s$, and $t$ may be permuted without affecting the value on any realization. A basic joint variable is {\it minimal\/} if $r \leq s \leq t$. A basic joint variable is {\it inadmissible\/} if it is known to be zero (on any realization) for one of the following reasons: \begin{itemize} \item There is no word in the code of weight $p$, $q$, or $r$. \item We have $d \leq p < 2d$ (where $d$ is the minimum distance of the codes under consideration), and we know that an $[n-p, k-1, d-p/2]$ code cannot have a word of weight $(q+r-p)/2$. Thus the variable is inadmissible by the method of residual codes. With obvious modifications this also applies with $p$ replaced by $q$ or $r$. \end{itemize} To reduce the size of the linear programming problem this method gives rise to, one should first use split linear programming to kill as many as possible of the weights in the code. For more details, see the comments in the code for the C++ method\\ \verb|generate_joint_constraints|. \block{A canned procedure for table-building}\label{canned-section} In this section we describe an automated procedure for proving the nonexistence of $[n,k,d]$ codes. As such, the procedure has as input a triple $[n,k,d]$ and as output {\tt true} if it can show there is no $[n,k,d]$ code, else {\tt false}. The procedure is allowed to access all specific results known to the program at the time of its execution. The goodness of the procedure can be measured in two ways. On the one hand, the more often it returns {\tt true}, the better it is. On the other hand, faster is better. These two criteria compete, and we have done our best to find a compromise which runs reasonably fast and yields reasonably many results.\footnote{For experimental purposes, it makes sense to deemphasize speed. See the description of the {\tt no} command for modifications to this procedure which allow for this.} Almost any general nonexistence method can be evaluated in terms of how it could contribute to the goodness of this procedure. The less computationally intense the method, the better it can make the procedure. Thus a ``traditional theorem'' which yielded new general consequences would have great merit as a new ingredient of the procedure. The body of the procedure has three stages, but before starting it, we note that by replacing $[n,k,d]$ by $[n+1,k,d+1]$ if need be, we may reduce to the case where $d$ is even. The goal of the first stage is to simultaneously check general criteria (which would yield the nonexistence of $[n,k,d]$ codes) and to similarly derive inequalities involving the global variables. Thus the first stage is very fast; it proceeds as follows: \begin{itemize} \item If $\nexists [n,k,d]$ or $\nexists [n-1,k-1,d]$, return {\tt true}. \item We may assume that $\verb|y|_i = 0$ for $i$ odd. Also deduce $\verb|y|_i = 0$ for specific $i$ by the method of residual codes. \item If the Griesmer bound is violated, return {\tt true}. \item From known nonexistence results, deduce that $\verb|mu|_i = 0$ for $i < r$, where $r$ is as large as possible. \item If $\nexists [n,n-k,r]$, return {\tt true}. \item Use known nonexistence results in conjunction with Brouwer's results to bound the number of doubly even words in the code. \end{itemize} The goal of the second stage is to show that for various $i$, we have $\verb|y|_i = 0$, by using split linear programming applied to the configuration associated to the existence of a word of weight $i$. It is this stage which usually consumes the lion's share of the execution time: \begin{romanlist} \item If it is not known that $4 \nmid i \Longrightarrow y_i = 0$, use ordinary linear programming to try to show that $y_0 + y_4 + y_8 + \cdots > {3\over4}(2^k)$. In that case, we may by Brouwer's results delete those words whose weights are not divisible by $4$. \item Use ordinary linear programming to try to show that the system of inequalities is infeasible. If so, return {\tt true}. \item Let $i$ be the highest weight which the code might have, and which has not already been tested for. Attempt to show by split linear programming that there can be no word of weight $i$. If this succeeds, go back to step (i). If it fails, repeat this step again, but on a second consecutive failure, go on to the third stage. \end{romanlist} In the case where $k < n$, we stop now, as the third stage seems never to help. The goal of the third stage is to show that for various $i$, we have $\verb|mu|_i = 0$, by using split linear programming applied to the configuration associated to the existence of a dual word of weight $i$: \begin{romanlist} \item Let $i$ be the lowest weight which the dual code might have, which has not already been tested for. Attempt to show by split linear programming that there can be no dual word of weight $i$. If this fails, repeat with the next lowest weight. On a second consecutive failure, return {\tt false}. \item If at this point we know that there is no nonzero dual word of weight $\leq i$, check to see if we also know that there is no $[n,n-k,i+1]$ code. If so, return {\tt true}. \item Use ordinary linear programming to try to show that the system of inequalities is infeasible. If so, return {\tt true}. Otherwise, go to (i). \end{romanlist} Some technical details regarding this procedure will be given when we describe the {\tt no} command. \block{Method: finding extensions of a code}\label{extension-section} We describe how to classify extensions of a given code. First we give an example of how this comes up. We will prove $(*)$ that there is no $[29,11,10]$ code. This of course supersedes the result (described in \S\ref{split-intro-section}) that there is no $[31,13,10]$ code. Now $(*)$ works by showing that a $[29,11,10]$ code must contain a dual word $w$ of weight $5$, and thus must contain a $[24,7,10]$ subcode, disjoint from $w$. We classify the $[24,7,10]$ codes (itself a new result); there are six of them. For each of these we then show that there is no extension to a $[31,13,10]$ code, thereby proving $(*)$. Here is the main idea behind the extension classifier, which is based on ideas the author gleaned from Simonis [.simonis 1987 25_15_6.]. For the above example, we would have to first add a zero bit to make a $[25,7,10]$ code. In general, starting from an $[n-r,s]$ code $D$ (here $n = 29$, $r = 4$, $s = 7$), you look for extensions to an $[n-r+1,s+1]$ code $D_1$, thence to an $[n-r+2,s+2]$ code $D_2$, and ultimately to an $[n,s+r]$ code $D_r$, hoping (in the above example) that the process fails at some point. But there is a neat trick for doing this. Form a matrix $M$ ($n-r-s \times n-r)$ whose rows form a basis for $D^\perp$. Extending from $D$ to $D_1$ corresponds to adding a column to $M$, yielding a matrix $M_1$. Then to get to $D_2$, you add another column, yielding a matrix $M_2$. These columns lie in $V := \F_2^{n-r-s}$. Choose a total order on $V$. Let $\Lex^j(V)$ denote the set of lexicographically ordered $j$-element sequences of $V$. Call such a sequence {\it admissible\/} if the corresponding code $D_j$ is ``consistent'' with the larger code type. In the example, we can require that $D_j$ is even and has no word of weight smaller than $10$. Without loss of generality, we can also assume that the word of weight $j+1$ whose last $j+1$ bits are $1$ is in $D_j^\perp$. This corresponds to the disjointness of $D$ from $w$. Suppose you have a subgroup $G$ of $\Aut(D)$. (In practice it is sometimes convenient to let $G$ be a mere subset of $\Aut(D)$, and what follows will make sense in this setting.) There is an induced contravariant action of $G$ on $V$, as follows. For $\sigma \in \Aut(D)$, let $P$ be the associated permutation matrix ($n-r \times n-r$). Let $Q$ be the unique invertible $n-r-s \times n-r-s$ matrix such that $QMP = M$. Let $v \in V$. Then we define $\sigma(v)$ to be $Qv$. For the moment letting $|$ denote horizontal concatenation of matrices, we see that $M|v \sim MP|v \sim QMP|Qv = M|Qv$, where these matrices are equivalent in the sense that they define isomorphic codes. From the action of $G$ on $V$ we get an action of $G$ on $\Lex^j(V)$, by acting individually on the elements of a sequence, and then sorting. For $g \in G$, $M|x \sim M|gx$. Call an element $x$ of $\Lex^j(V)$ {\it $G$-minimal\/} if $gx \geq x$ for all $g \in G$. Then it is enough to find $$\Gamma_j\ :=\ \setof{G\hbox{-minimal, admissible elements of\ }\Lex^j(V)}.$$% Fortunately, if you take some $x \in \Gamma_j$, and discard its rightmost element, you get an element of $\Gamma_{j-1}$. Therefore the ``extension'' algorithm boils down to computing in succession $\Gamma_1,\Gamma_2,\ldots,\Gamma_r$. However, exactly how to compute $\Gamma_j$ from $\Gamma_{j-1}$ in an efficient way is an interesting problem open to further investigation. In the case where $\Gamma_r$ is nonempty, the user needs to provide in advance a list of configurations which the elements of $\Gamma_r$ can be tested against. Thus (for example) when we classify $[24,7,10]$ codes, we classify the extensions of one of the two $[21,5,10]$ codes by means of the command \begin{verbatim} via extension [21_5_10.a] implies [c], [d], [e0], [f]; \end{verbatim} To make full sense out of this one has to see the configurations labelled {\tt[c]}, and so forth. The method of this section is limited by the exponential growth of its execution time. In the present implementation, it takes roughly a small constant times $(2^{n-r-s})(n-r+1)(s)$ operations to find $\Lex^1(V)$. Thus for example, whereas it is practical to find extensions from $[24,7,10]$ to $[29,11,10]$, it is not practical to find extensions from $[35,4,18]$ to $[38,6,18]$, which would require almost 60,000 times the execution time of the $[24,7,10]$ case. Although one could almost certainly make the $\Lex^1(V)$ calculation much faster, it is not clear that the method can be made acceptably fast as a whole. \block{Method: finding the minimum weight of a code} In our extension algorithm, we have to repeatedly check partial extensions, with the goal of ruling out those whose minimum weight is too small. At present we do this by literally checking every element in the partial extension. This is almost certainly not optimal. Much faster probabilistic methods have been invented by Leon [.leon probabilistic algorithm.] and Stern [.stern codewords small weight.]; an analysis of these has been given by Chabaud [.chabaud asymptotic analysis.]. Since no harm will come if an occasional partial extension squeaks past this checker, such a method would probably speed up our algorithm. \newpage \part{Background and language structure} \block{The split weight enumerator of the dual code} We establish the formula for the split weight enumerator of $C^\perp$. This is just an elaboration on an exercise in [.macwilliams sloane book.]. Let $(\VEC p1r)$ be a partition of $n$. Define \mp[[ f || \F_2^n || \Z[\VEC t1r] ]] by $f(v) = \prod_{i=1}^r t_i^{\abs{v}_i}$. Let \mp[[ \lhF || \F_2^n || \Z[\VEC t1r] ]] be the Hadamard transform of $f$ ([.macwilliams sloane book.]\ pp.\ 54, 127) defined by $$\lhF(w) = \sum_{v \in \F_2^n} (-1)^{w \cdot v} f(v).$$% By (op.\ cit.\ Ch.\ 5, \S2, Lemma 2) we know that $$\sum_{w \in C^\perp} f(w)\ =\ {1 \over \abs{C}} \sum_{w \in C} \lhF(w).$$% So to prove the split weight enumerator formula, it is enough to show that $$\lhF(w) = \prod_{i=1}^r (1+t_i)^{p_i - \abs{w}_i} (1-t_i)^{\abs{w}_i}.$$% We proceed to prove this: \begin{eqnarray*} \lhF(w) & = & \sum_{v \in \F_2^n} (-1)^{w_1 v_1 \many+ w_n v_n} \prod_{i=1}^r t_i^{\abs{v}_i}\\ & = & \sum_{v \in \F_2^n} (-1)^{w_1 v_1 \many+ w_n v_n} \left( \prod_{i=1}^{p_1} t_1^{v_i} \right) \left( \prod_{i=p_1+1}^{p_1+p_2} t_2^{v_i} \right) \manycdot \left( \prod_{i=p_1 \many+ p_{r-1} +1}^n t_r^{v_i} \right)\\ & = & \sum_{v_1=0}^1 \sum_{v_2=0}^1 \cdots \sum_{v_n=0}^1 \left( \prod_{i=1}^{p_1} (-1)^{w_i v_i} t_1^{v_i} \right) \left( \prod_{i=p_1+1}^{p_1+p_2} (-1)^{w_i v_i} t_2^{v_i} \right) \manycdot \left( \prod_{i=p_1 \many+ p_{r-1} +1}^n (-1)^{w_i v_i} t_r^{v_i} \right)\\ & = & \left( \prod_{i=1}^{p_1} \sum_{u=0}^1 (-1)^{w_i u} t_1^u \right) \left( \prod_{i=p_1+1}^{p_1+p_2} \sum_{u=0}^1 (-1)^{w_i u} t_2^u \right) \manycdot \left( \prod_{i=p_1 \many+ p_{r-1} +1}^n \sum_{u=0}^1 (-1)^{w_i u} t_r^u \right)\\ & = & \left( \prod_{i=1}^{p_1} \left[ 1 + (-1)^{w_i} t_1 \right] \right) \left( \prod_{i=p_1+1}^{p_1+p_2} \left[ 1 + (-1)^{w_i} t_2 \right] \right) \manycdot \left( \prod_{i=p_1 \many+ p_{r-1} +1}^n \left[ 1 + (-1)^{w_i} t_r \right] \right)\\ & = & \prod_{i=1}^r (1+t_i)^{p_i - \abs{w}_i}(1-t_i)^{\abs{w}_i}. \kern1in \square \end{eqnarray*} \block{Exact linear programming} The split linear programming method leads to a system of linear inequalities, which we may write in the form $Ax \geq b$, where for some $r,s$ we have $A \in \Mat_{r \times s}(\Z)$ and $b \in \Z^r$; the solution set is $${\cal S}\ =\ \setof{x \in \Z^s: x \geq 0 \hbox{\ and\ } Ax \geq b}.$$% The basic problem is to prove that $\cal S$ is empty. This is because solutions have integer components, and thus to show that all solutions satisfy some inequality (e.g. $x_3 \geq 53$), we can always proceed by adjoining an additional constraint to the original system (e.g.\ $x_3 \leq 52$), and then showing that the new system has no solutions. While in practice this may not be efficient, it seems reasonable for purposes of discussion to consider only the case of showing ${\cal S} = \emptyset$. Beyond aiding in this simplification, the constraint that solutions have integer coefficients is not as useful as it might look: the analysis of integer solutions ({\it integer linear programming}) is computationally much more complex than the analysis of rational solutions. The simplex algorithm can in principle be used to directly show that a system has no solutions. But to actually get a proof from the algorithm, one would have to do exact arithmetic, rather than floating point calculation. As such, we do not know of an implementation which is acceptably fast. Indeed, we doubt it is possible, and offer the following heuristic argument as an explanation. Consider a random $n \times n$ matrix $M$ whose entries are $d$-digit (or less) integers, i.e.\ whose entries are chosen uniformly from $[-(10^d - 1), 10^d - 1]$. One would expect $\det(M)$ to have about $nd$ digits. Similarly, if one tries to compute $M^{-1}$ or an $LU$ decomposition of $M$, one would expect the average number of digits% \footnote{Define the {\it number of digits\/} in a rational number $a/b$ to be the maximum of the number of digits in $a$ and $b$, supposing of course that $\gcd(a,b) = 1$. Generally, we use base $10$ just for illustration.} in the entries of these matrices to have a comparable growth rate. Now fixing the number of digits, one should expect (for example) that computing the ``floating-point inverse'' of an $n \times n$ integer matrix will require $O(n^3)$ operations, but computing its exact inverse will require $O(n^4)$ operations; the extra $n$ comes from the $n$ in $nd$. But it may be difficult to make such statements precise, since (e.g.) $O(n^3)$ is not optimal for matrix inversion. The remarks of this paragraph are obviously provisional. A lemma of Farkas [.farkas 1902.] (see e.g.{\ }[.schrijver.] Corollary 7.1f) asserts that $${\cal S}_\Q\ :=\ \setof{x \in \Q^s: x \geq 0 \hbox{\ and\ } Ax \geq b}.$$% is empty \IFF\ there exists a $y \geq 0$ such that $A^T y \geq 0$ and $y \cdot b < 0$. Otherwise said, if the system is inconsistent, then one can find a nonnegative linear combination of the constraints which is in and of itself contradictory. (This may also be viewed as a consequence of duality.) Moreover, the simplex algorithm produces such a $y$. If an algorithm (via floating point calculations) can produce a $y$ as above, then we can form the corresponding {\it exact\/} linear combination of constraints and try to show (independently) that it gives rise to a contradiction. This turns out to work very nicely in practice. Here then is our approach. Given the original system (with integer coefficients), find a floating point $y$ which numerically appears to satisfy $A^T y \geq 0$ and $y \cdot b < 0$. Let $\loY$ be the best rational approximation to $y$. If $\VEC c1r$ are the original constraints, then we get a new constraint $\loY_1 c_1 \many+ \loY_r c_r$, which although perhaps not inherently contradictory, can be used to deduce a contradiction. Indeed the negative coefficients of variables (if any) on the \LHS\ will be small (close to $0$), and we have a priori upper bounds on the variables, so (barring misfortune) we will be able to prove that the original system is infeasible. The worst that can happen is that we will be forced to report that the calculation is inconclusive. Note too that the proof step is simple and moreover thoroughly insulated from the intricacies of linear programming calculation. The current implementation of the program contains both a provisional implementation of the simplex algorithm, and the ability as well to use a commercial solver, CPLEX, which is both faster and more robust. The included implementation however has the advantage of being able to use higher precision floating point arithmetic, which becomes critical when investigating codes of length about $70$ or greater. Aside from being slow, the included implementation has the disadvantage that it handles ``numerical anomalies'' poorly, and thus (depending on the state of an internal random number generator) will sometimes (but very infrequently) stop in the middle of a simplex calculation, and issue an error message indicating that the calculation has failed. For further information, we refer to a small subset the vast literature on linear programming: [.chvatal.], [.goldfarb todd.], [.gregory faq.], [.karloff linear programming.], [.more wright.], and [.murtagh advanced.] \block{Variables and constraints}\label{variable-section} There are three kinds of variables in the language: {\it local}, {\it global}, and {\it joint}. The first two have already been discussed in \S\ref{definitions-section}. In the language, a {\bf variable} will always mean a specific, predefined variable, global, local, or joint, and these are exhibited below. In discussing these, we refer to a code $C$, which is to be a code in the realization of the particular configuration one is working with. The basic global variables are \begin{center} {\tt y0},\ {\tt y1},\ $\ldots$,\ {\tt y}$n$ \end{center} where $n$ is the length of $C$; {\tt y}$i$ gives the number of words of weight $i$ in $C$. Other global variables are \begin{center} {\tt mu0},\ {\tt mu1},\ $\ldots$,\ {\tt mu}\kern1pt$n$ \end{center} which give the number of words of given weight in $C^\perp$. The last global variables are \begin{center} {\tt div2},\ {\tt div4},\ {\tt div8},\ $\ldots$, \end{center} which give the number of words in $C$ whose weight is divisible by the given power of $2$. Now we come to {\it local\/} variables. For a given configuration, the basic local variables have the form \begin{center} \verb|x_|$a_1$\verb|_|$\ldots$\verb|_|$a_r,$ \end{center} where $r$ is the number of parts in the partition of the configuration. Such a basic local variable must be {\it admissible}. If $\VEC a1r$ are all single digits, such a basic local variable may also be written as \begin{center} \verb|x|\kern1pt$a_1a_2 \ldots a_r$. \end{center} In addition to this formatting choice, each basic local variable has a number of equivalent forms, since the smallcode acts on wordtypes. For internal purposes, we select a canonical form for each basic local variable, which we call {\bf minimal}. Of course we could take minimal to mean lexicographically minimal, but this turns out to be computationally inconvenient. The actual definition is somewhat technical and of limited significance. \label{minimal-promise}We defer the details to \S\ref{partition-wordtype-mawhome-section}. Again for internal purposes, the minimal form is further translated to {\tt v}$i$, for some $i$, so that the basic local variables are (up to equivalence) \begin{center} {\tt v1}, {\tt v2}, $\ldots$, {\tt v}$t$. \end{center} To discourage reliance on the internal ordering scheme used for these variables, their use in the language is not permitted. By convention, {\tt v1} is the trivial basic local variable. See also the discussion of {\it basic joint variables}, below. There are various local variables which are derived from the basic local variables. The variable \begin{center} \verb|z_|$a_1$\verb|_|$\ldots$\verb|_|$a_r$ \end{center} denotes the number of words of multiweight $(\VEC a1r)$ in $C^\perp$. As with basic local variables, there is an abbreviated form without underscores. Now for each $i$ ($1 \leq i \leq r$), let $a_i$ be either an integer (between $0$ and $p_i$) or else the character {\tt z}. Then \begin{center} \verb|q_|$a_1$\verb|_|$\ldots$\verb|_|$a_r$ \end{center} is a local variable. To see what it represents, consider the subcode $D$ of $C$ consisting of words having zeroes in at least the positions marked by {\tt z} in the variable. (We regard $D$ as a code of length shorter than $C$ -- it is supported on the non-{\tt z} positions.) Let $I = (\VEC a1r)|_{\hbox{\small\tt z} \mapsto 0}$: each {\tt z} is replaced by a $0$. Then \verb|q_|$a_1$\verb|_|$\ldots$\verb|_|$a_r$ represents $\abs{D} \cdot \abs{\setofh{$I$-words in $D^\perp$}}$. Such variables arise during the processing of {\tt incorporate} commands. There is also an abbreviated form without underscores. Note that if $\VEC a1r$ are all integers, then \verb|q_|$a_1$\verb|_|$\ldots$\verb|_|$a_r$ = $\abs{C} \cdot$ \verb|z_|$a_1$\verb|_|$\ldots$\verb|_|$a_r$ in any realization. This introduces an apparent redundancy, which is needed because (in general) we do not know the value of $\abs{D}$, and we want every variable to take on only integer values. Relative to the current configuration, if $w$ is a small word (represented by a string of {\tt0}'s and {\tt1}'s), then \begin{center} {\tt sub}$w$ \hbox{\ \ and\ \ } {\tt sub}$w$\verb|_|$k$ \end{center} denote respectively the number of words in the subcode of $C$ supported on $w$, and the number of words of weight $k$ in that subcode. For a configuration whose partition has only one part, the basic local variable \verb|x_|$i$ will have the same evaluation as the basic global variable \verb|y|$i$. While this does not mean that \verb|x_|$i$ and \verb|y|$i$ may be used interchangeably, we have tried to minimize the number of places where the use of one variable as opposed to the other will make a difference. We have already defined basic joint variables. The minimal admissible basic joint variables are represented internally as as {\tt v1}, {\tt v2}, and so forth. Another joint variable is {\tt jy}$r${\tt d}$s${\tt i}$t$, which represents $$\abs{\setof{(v,w) \in C \times C^\perp: \abs{v} = r, \abs{w} = s, \abs{v \cap w} = t}}.$$% We also allow {\tt jy}$r${\tt d}$s$, which equals {\tt jy}$r${\tt d}$s${\tt i}$0$. The variable {\tt co}$r$ is defined to be equal to {\tt jy}$r${\tt d}$r${\tt i}$r$, and the variable {\tt co} is defined to be equal to $\sum_{j=0}^n \verb|co|j$, so $\verb|co| = \abs{C \cap C^\perp}$. The joint variable {\tt jd}$r${\tt d}$s${\tt d}$t$ represents $\abs{\setof{(v,w) \in C^\perp \times C^\perp: \abs{v} = r, \abs{w} = s, \abs{v + w} = t}}$. The joint variable {\tt jdiv2} represents $\abs{\setofh{$(v,w) \in C^2$: $v$, $w$, and $v \cap w$ all have even weight}}$. For purposes of data entry, a {\bf constraint} is a linear inequality or equality involving any of the above variables, with $\Z$-coefficients. Examples of the allowed forms are: \vspace{0.1in} \leavevmode\kern0.5in\begin{tabular}{ll} \verb|4y3 + 6x_2_5 >= 9| \\ \verb|-8y3 + y10 - 2y4 <= 40| \\ \verb|y32 = 1| \\ \verb|5y10 < 100| & (equivalent to \verb|5y10 <= 99|) \\ \verb|5y10 > 100| & (equivalent to \verb|5y10 >= 101|) \\ \verb|y6 != 0| & (equivalent to \verb|y6 >= 1|; \\ & \LHS\ must be a variable). \end{tabular} \vspace{0.1in} Note that the \RHS\ is always an integer, and you can't put an integer on the \LHS, unless it is used as a coefficient of a variable. We call a constraint {\bf simple} if its \LHS\ is a variable. Local and joint variables may not appear in the same constraint. Constraints are stored as is, and not converted to constraints involving only basic global and local variables, as would appear to be the case from the definitions in \S\ref{definitions-section}. Moreover, the order in which the terms are entered matters. Thus if {\tt y10 + y12 <= 20} is known, it does not follow that {\tt y12 + y10 <= 20} is known. This is a dorky ``feature'', but is unlikely to cause problems. A {\bf constraint list} is a list of zero or more constraints, separated by commas. However, certain compound forms are allowed, as in \par\noindent\kern0.5in\verb|5 <= y10 + y12 <= 20|; \par\noindent one or both of the inequalities may be replaced by strict inequalities, with the expected effect. \block{Language structure}\label{proof-command-section} Statements in the language could be divided into two general classes: {\bf proof} statements and {\bf exploratory} statements; in a finished proof one should have only proof statements. There are three main functions of proof statements: (1) establish a logical statement between configurations; (2) establish that a given configuration must satisfy a particular constraint; (3) establish that a given permutation is an automorphism of a given configuration. In addition the language permits the definition of constructive connections between configurations, as discussed in \S\ref{split-intro-section}. Before considering the commands themselves, we describe more carefully the data kept by the program. The abstract notion of {\it code type} is realized by the class {\tt codehome} and the abstract notion of {\it configuration} is realized by the class {\tt config}. Part of the {\tt codehome} definition is an {\bf assumed weight list}, a list of nonnegative integers which the weight sets of the codes are supposed to form subsets of. This would be formally equivalent to including assumed constraints of the form $y_i = 0$, but it is more efficient and convenient to keep track of weights instead. However, for the remainder of this report, if we say that a codehome has ``no assumed constraints'', we do not by this imply anything about its assumed weight list. Similarly, for each configuration, there is a {\bf working weight list}, which is a possibly smaller list of weights, such that each code realizing the configuration has weights in the smaller list. The {\tt codehome} definition also includes a directed multigraph as discussed on p.\ \pageref{first-multigraph-occurrence}; the graph structure is realized by a {\tt ShareGraph} object. Path components in this graph are realizability equivalence classes. To facilitate sharing, each path component has associated to it a \verb|config_share| object, which carries various pieces of information known about the configurations. For example, each \verb|config_share| object has a \verb|realizable| flag which indicates if the configurations are known to be realizable or unrealizable. Logical edges in the digraph are not explicitly recorded as data items. Rather, if we wish to ``add a logical edge'' from one configuration to another, we merge their \verb|config_share| objects. Constructive edges are labelled by the corresponding basic local variable (which is known to be nonzero); going from head to tail of the edge corresponds to subdivision. Labels may be associated by the user to code types, configurations, automorphisms, and {\tt incorporate} commands, to be described later. The latter command also creates new labels. When created by the user, a label is allowed to be any non-null sequence of letters, digits, and underscores, enclosed in square brackets. It is also permissible to use a configuration label of the form {\tt[}$a${\tt:}$b${\tt]}, where {\tt[}$a${\tt]} is the name of a code type (of the same length as the current code type) and {\tt[}$b${\tt]} is the name of a configuration of {\tt[}$a${\tt]}. The first time this is used, configuration {\tt[}$b${\tt]} is copied to the current code type. (Known facts cannot be copied.) In usage thereafter, the configuration {\tt[}$a${\tt:}$b${\tt]}, will be treated just like any other configuration of the current code type. A {\it\bf configuration-list} is a comma-separated sequence of zero or more configuration labels, except that amongst these, some configuration labels may be replaced by certain compound constructions, which we illustrate by examples: \begin{itemize} \item \verb|[xy*]| expands to all user-defined configuration labels which start with {\tt xy}. \item \verb|[21{r,s,tt}]| expands to \verb|[21r]|, \verb|[21s]|, \verb|[21tt]|. \item \verb|[21_8.{x*,y*,z}]| expands to \verb|[21_8.z]| and all user-defined configuration labels which start with either \verb|[21_8.x| or \verb|[21_8.y|. \item \verb|a2..15| expands to \verb|[a2]|, \verb|[a3]|, \ldots, \verb|[a15]|. \end{itemize} The {\tt*} construction never matches {\tt[base]} or {\tt[current]}, nor does the {\tt*} part ever match a string containing ``{\tt!}''. In the description of commands that follows, $n$ will always denote the dimension of the ambient space (i.e.\ the length of the codes under consideration), and $k$ will denote the dimension of the codes. All commands are terminated by a semicolon. White space is always irrelevant. Any command preceeded by ``??'' will be accepted without verification, as if a ``{\tt set gullible}'' command had been used. Any block of commands may bracketed as in the following example: \begin{verbatim} ... config 8,10,4,5 : {1100,1010} :: {y12 >= 31, y13 = 0, y14 >= 1}; { show div4 >= 44; ... show x1524 = 0, x2415 = 0, x2433 = 0, x2514 = 0, x2525 = 0, x3324 = 0, x3405 = 0, x3423 = 0, x3425 = 0, x3434 = 0, x3443 = 0, x3504 = 0 }; config from x4422; via building [current] implies ; ... \end{verbatim} The bracketed code is treated in the following way. In gullible mode, it is completely ignored. Otherwise, the code is executed as usual. In this way, code which executes slowly in gullible mode can be completely skipped over. Any command may be postfixed (before the semicolon) with ``{\tt<}{\it parameters}{\tt>}'', where {\it parameters\/} is a comma-separated list of parameters as in (for example) \begin{verbatim} no [43,20,12]; \end{verbatim} The given parameters are set prior to execution of the command and then restored to their original value at the end. See the {\tt set} command for the list of allowed parameters; one may not use {\tt gullible}, {\tt gullible commands}, or {\tt test mask} in this way. Do not use this option with a command which is expanded into a list of other commands, such as {\tt n =}. \def\config#1{{\tt[}$#1${\tt]}} \def\cconfig{{\tt[}$c${\tt]}} \def\mconfig{{\tt[}$m${\tt]}} \def\czconfig{{\tt[}$c_0${\tt]}} \def\coconfig{{\tt[}$c_1${\tt]}} \def\ctconfig{{\tt[}$c_2${\tt]}} \def\ciconfig{{\tt[}$c_i${\tt]}} \block{How to define a code type} A code type is defined with the {\tt type} command, as follows: \newenvironment{commanddeclaration}% {\vspace{0.1in}\begin{center}\begin{Sbox}\kern2pt}% {\end{Sbox}\psshadowbox{\TheSbox}\end{center}\vspace{0.1in}} \def\superopt#1{$\displaystyle{\overbrace{#1}^{\hbox{optional}}}$} \def\subopt#1{$\displaystyle{\underbrace{#1}_{\hbox{optional}}}$} \indexb{type} \begin{commanddeclaration} \subopt{\hbox{\lconfig}} {\tt type[}\kern2pt{\it length}{\tt, }{\it dimension}{\tt, }{\it weights}% \superopt{{\tt, }{\it dual weights}}\kern2pt{\tt]} \subopt{{\tt\{}\kern5pt{\it constraint list}\kern5pt{\tt\}}} \superopt{{\tt/}\kern5pt{\it options}\kern5pt{\tt/}}{\tt;} \end{commanddeclaration} Here {\it length\/} is the length of the code, i.e.\ $n$ if the code lives in $\F_2^n$; the {\it dimension\/} is the dimension $k$ of the code; {\it weights\/} represents a list $w$ of weights, and has several allowed formats: \vspace{0.05in} \begin{tabular}{lll} \verb|{|$w_1$\verb|,|$\ldots$\verb|,|$w_m$\verb|}|& -- & all weights in the given set, which should be in increasing order\\ & & (also $0$, which should not be listed)\\ $d$ & -- & $0$ and all weights $\geq d$\\ $d$\verb|_|$r$ & -- & $0$ and all weights $\geq d$ which are divisible by $r$\\ $d$ \verb| - {|$w_1$\verb|,|$\ldots$\verb|,|$w_m$\verb|}|& -- & $0$ and all weights $\geq d$, except $\VEC w1m$\\ $d$\verb|_|$r$ \verb| - {|$w_1$\verb|,|$\ldots$\verb|,|$w_m$\verb|}|& -- & $0$ and all weights $\geq d$ which are divisible by $r$,\\ & & except $\VEC w1m$ \end{tabular} \vspace{0.05in} Dual weights has the same format, defaulting to all weights. It is permissable to use ellipsis in the above situations, for example \begin{center} ``\verb|66_2 - {98,114,118..138}|'' \end{center} denotes all even weights $\geq 66$, except $98$, $114$, and those numbers lying between $118$ and $138$. \vspace{0.05in} As an example of a {\tt type} command, ``\verb|type [29,11,6_2]|'' would cause the program to think about even codes of dimension $11$ in $\F_2^{26}$, having minimum weight $\geq 6$. The program will automatically use the method of residual codes to infer that certain weights cannot occur. Let $d$ be the minimum weight in the weightlist. Suppose that $i$ satisfies $d \leq i < 2d$. Suppose that we know there is no code of type $[n-i,k-1,d - \floor{i/2}]$. Then weight $i$ does not occur. If the code is at the Griesmer bound, and its minimum weight is even, all its words have even weight ([.tilborg griesmer 1980.] 1.11). This is automatically known to the program. In the case of an even code, we automatically include lower and upper bounds on the number of words whose weights are divisible by $4$, in accordance with the results of Brouwer [.brouwer linear programming bound.]. If for a given $d'$, it is known that there is no $[n-(d'-1),k-(d'-1)+1,w]$ code, then it is automatically inferred that the minimum weight of the dual code is at least $d'$. The optional {\it constraint list\/} is a list of constraints, which all codes $C$ in the type are to satisfy. The optional argument \lconfig\ if present assigns the label \lconfig\ to the code type for future reference. The same label may not be used for two code types. The {\it options} field is a comma-separated list of fields. At this point there are five allowed fields, each of which may appear only once. The first field is: \par\noindent\kern0.5in\verb|dual_may_be_code_of_design(t = 2, k = |$\kappa$% \verb|, lambda = |$\lambda$\verb|)|. \par\noindent The effect of this option is to check that $C^\perp$ satisfies certain conditions which are necessary (but not sufficient) for it to be generated by a $t$-design $D$ with the given parameters. (We use $\kappa$ to avoid conflict with our convention that $k$ is the dimension of the code.) To explain these conditions, let $S(2)$ denote the set of all $2$-words in $\F_2^n$, and let $T(\kappa)$ denote the set of all $\kappa$-words in $C^\perp$. If $\lambda > 1$, we check only that every element of $S(2)$ is contained in at least $\lambda$ elements of $T(\kappa)$. In the case where $\lambda = 1$, we check the following more elaborate condition\label{elaborate-design-condition}: \vspace{0.1in} \par\noindent $A := S(2)$;\\ $B := T(\kappa)$;\\ $E := \emptyset$;\\ \begin{tabular}{ll} \kern-6pt repeat \{\ \ \ \ & (At this point every $a \in A$ lies in some element of $D \cap B$.)\\ & if $(\kern4pt \exists\kern1pt a \in A \hbox{\ not contained in any\ } b \in B\kern4pt )$ return false;\\ & $U := \setof{a \in A: \exists! \kern4pt b \in B \hbox{\ containing\ } a}$;\\ & if $( \kern4pt U = \emptyset \kern4pt )$ return (($\abs{E} \not= {n \choose 2}/{\kappa \choose 2}$) or ($E$ generates $C^\perp$));\\ & $F := \setof{b \in B \hbox{\ which contains an element\ } u \in U}$;\\ & (Note that $F \IN D$.)\\ & $E := E \cup F$;\\ & if $(\kern4pt \exists f_1, f_2 \in F \hbox{\ such that\ } \abs{f_1 \cap f_2} \geq 2\kern4pt )$ return false;\\ & $A_0 := \setof{a \in A: a \hbox{\ is contained in some\ } f \in F}$;\\ & $A := A - A_0$;\\ & $B := \setof{b \in B: b \hbox{\ contains no element of\ } A_0}$; \kern0.9cm\} \end{tabular} \vspace{0.1in} \par\noindent The second condition is \par\noindent\kern0.5in\verb|partition_of_word_by_dual_words(weight = |$w$% \verb|, dual_weight = |$d$\verb|)|. \par\noindent For this condition to be satisfied, every word of weight $w$ in $C$ must admit a nonoverlapping cover by words of weight $d$ in $C^\perp$. If both conditions (\verb|partition_of_word_by_dual_words|, \verb|dual_may_be_code_of_design|) are employed, $\lambda = 1$, and $d = \kappa$, the meaning of the two conditions is modified and the above tests are combined and strengthened, as follows. First, the change in meaning is that now we require that there exists a $t$-design $D$ with the given parameters, generating $C^\perp$, such that moreover every word of weight $w$ in $C$ admits a nonoverlapping cover by elements of $D$. As for the change in tests, make the following definition. A {\it covering plan\/} is a choice, for each word of weight $w$ in $C$, of a nonoverlapping cover by words of weight $\kappa$ in $C^\perp$, in such a way that no two words in the covering plan meet at more than one position. We cycle through all covering plans $\cal D$, and for each, we execute the condition outlined above, except that the initial choices for $A$, $B$, and $E$ are modified as follows: \begin{itemize} \item $A = \setof{w \in S(2):\ w \hbox{\ is not contained in any\ } d \in \cal D}$; \item $B = \setofh{words in $T(\kappa)$ not meeting any $d \in {\cal D}$ along more than one bit}$; \item $E = \cal D$. \end{itemize} In the above, we have used ${\cal D}$ to denote the set of all dual words appearing in the given covering plan. The third field is \par\noindent\kern0.5in\verb|doubly_even_part_is_subcode|. \par\noindent This condition says that the set $D$ of words in the code whose weight is divisible by four must constitute a subcode of $C$. This is equivalent to saying that $D \IN C^\perp$. The fourth field is \par\noindent\kern0.5in\verb|dual covering radius <= |$r$, \par\noindent where $r$ is a positive integer. This condition says that the covering radius of the dual code must not exceed $r$. The fifth field is \par\noindent\kern0.5in\verb|maybe subcode of |\lconfig, \par\noindent where \lconfig\ is a code type which has been defined already. The effect of this is to draw certain conclusions which would be known for subcodes of codes realizing type \lconfig. (Here {\it subcode\/} allows both for smaller dimension and shorter length.) Specifically, any constraints from \lconfig\ which set a basic local variable or basic global variable to zero are copied (and treated as assumed constraints) for the current type. If \verb|dual covering radius <= |$r$ was chosen for \lconfig, appropriate deductions are made for the current type. The possibility of drawing other conclusions is left open for future versions of the program. \vspace{0.1in} If at some point it is found that the code type is unrealizable, the language interpreter will discard all information about the code type except this fact. After a {\tt type} command is entered, that type remains in effect until the next {\tt type} command (or some other command which changes the type, such as ``{\tt no}''). See also the ``{\tt at}'' command. \block{Expressions}\label{matrix-descriptor-section} In this section, we define an {\it expression}. This is a string which can be evaluated to yield a mathematical object, subject to certain rules we shall give. All of this is in flux! Warning! See the directory {\tt functions} for more information about operators on expressions. The documentation to be found there will ultimately appear in this document. The following table presents the currently extant object types, along with the internal types which represent them: \def\dtext#1#2{\vbox{\hbox{\tt #1}\kern3pt\hbox{\tt #2}}} \def\dtextp#1#2{\vbox{\kern5pt\hbox{\tt #1}\kern3pt\hbox{\tt #2}}} \def\ttext#1#2#3{\vbox{\hbox{\tt #1}\kern3pt\hbox{\tt #2}\kern3pt\hbox{\tt #3}}} \def\ttextp#1#2#3{\vbox{\kern5pt\hbox{\tt #1}\kern3pt\hbox{\tt #2}\kern3pt% \hbox{\tt #3}}} \def\ftext#1#2#3#4{\vbox{\hbox{\tt #1}\kern3pt\hbox{\tt #2}\kern3pt% \hbox{\tt #3}\kern3pt\hbox{\tt #4}}} \begin{center} \begin{tabular}{|l|l|}\hline {\bf name} & {\bf meaning}\\ \hline\hline {\tt F2} & an element of $\F_2$\\ \hline {\tt MatF2} & a matrix over $\F_2$\\ \hline {\tt PVSF2} & \ttext{a partitioned vector space over $\F_2$,}% {represented by a list of lists of elements of $\F_2^n$,}% {which define a partition of it}\\ \hline {\tt Group} &\dtext{a finite group, given by generators}% {and transformation rules}\\ \hline {\tt Int} & an integer\\ \hline {\tt MatInt} & a matrix of integers\\ \hline {\tt Rat} & a rational\\ \hline {\tt MatRat} & a matrix of rationals\\ \hline {\tt Bool} & {\tt true} or {\tt false}\\ \hline {\tt LinearProgram} & a system of inequalities with integer coefficients\\ \hline {\tt String} & a string\\ \hline \end{tabular} \end{center} In addition, if $\alpha$ is an object type, $\verb|List(|\alpha\verb|)|$ denotes an ordered list (i.e.\ vector) of objects of type $\alpha$. There are as well attributes assigned to some types: for {\tt MatF2} there are potential attributes {\tt reduced} (meaning in \RREF, and having no zero rows) and {\tt invertible}. A {\tt List} of {\tt MatF2}'s has the potential attribute {\tt homogeneous}, meaning that the list is nonempty and all the matrices have the same size. The way that attributes may be indicated is illustrated by the following examples, both of which are so frequently used that we give an abbreviation: \vspace{0.1in} \par\noindent abbreviation: {\tt MatrixGroup(F2)} \par\noindent type name: \verb|List(MatF2{invertible}){homogeneous}| \par\noindent what it is: A nonempty list of invertible matrices (over $\F_2$) having the same size. \vspace{0.1in} \par\noindent abbreviation: {\tt HList(MatF2)} \par\noindent type name: \verb|List(MatF2){homogeneous}| \par\noindent what it is: A nonempty list of matrices (over $\F_2$) having the same size. \vspace{0.1in} There are a number of binary operators, and as a rule, there is no guarantee how ambiguous expressions (like $\alpha \kern5pt {\tt\#} \kern5pt \beta \kern5pt {\tt\-} \kern5pt \gamma$) are handled. Use parentheses. There is one exception: the \verb=|= operator has lowest precedence. Otherwise, evaluation tends to be from left to right. By {\it reducing\/} a matrix, we mean that it is converted to \RREF\ and moreover that its zero rows are removed. Some of the operators appear to return a finite graph. In such cases what we really mean is that a matrix having only weight two columns (one for each edge in the graph) is returned. We make the convention that when we refer to a column number of a matrix with $n$ columns, the number will be between $1$ and $n$. (And not between $0$ and $n-1$.) \vspace{0.1in} \par\noindent{\Large\bf Expression list \circno1} \vspace{0.1in} The following expressions are functions of one or more variables, but the arguments are not themselves objects. All the functions in this list yield as output an object of type {\tt MatF2}. \begin{itemize} \item $\verb|Choose|(n,\setof{\VEC k1r})$, representing the horizontal concatenation of $$\verb|Choose|(n, k_1), \verb|Choose|(n, k_2), \ldots, \verb|Choose|(n, k_r).$$ \item $\verb|AntiCode(|k,\vec T1r\verb|)|$, where $T_i \IN {\cal P}(\setof{1,\ldots,k})$ for all $i$. This represents the horizontal concatenation of certain matrices, one for each $i$. For a given $i$, first form the matrix which has all nonzero columns of length $k$, with entries in $\F_2$. Then for each $T_{ij}$ in $T_i$, delete those columns which lie in $\SPAN\setof{e_\ell : \ell \in T_{ij}}$. The codes having generator matrices of this type are modelled after the codes of Solomon and Stiffler [.solomon stiffler.]. \item $\verb|BCH(|r\verb|, |n\verb|, |${\it first}\verb|..|{\it last}% \verb|)|, representing the matrix of the BCH code of length $n$ over $\F_2$, associated to the powers $\hbox{\it first},\ldots,\hbox{\it last}$ of a primitive element in $\F_{2^r}$. \item $\verb|Coset(2^|m\verb|, |r\verb|, n = |n\verb|)|$, representing the matrix associated to the cyclic code of length $n$ associated to the union of $\setof{0}$ and the cyclotomic coset mod $2^m - 1$ generated by $r$. \item $\verb|Col(|i_1\verb|,|\ldots\verb|,|i_r\verb|)|$, representing a column vector having nonzero entries in positions $\VEC i1r$, where $1$ represents the top position. Here $\VEC i1r$ should be distinct, positive integers. The length of the column vector will equal $\max\setof{\VEC i1r}$. \item $\verb|MulMod(|f\verb|,|g\verb|)|$, representing the matrix of multiplication by $g$, in the ring $\F_2[t]/(f)$, relative to the standard basis $t^0, t^1, \ldots, t^{d-1}$, where $d$ is the degree of $f$. \end{itemize} \par\noindent{\Large\bf Expression list \circno2} \vspace{0.1in} The following expressions are irregular. They do not have objects as arguments. Except as noted, they yield as output an object of type {\tt MatF2}. \begin{itemize} \item \verb|{|$\VEC r1k$\verb|}|, where $\VEC r1k$ are zero-one vectors (e.g.\ $010001110$) which comprise the rows of the matrix to be defined. \item a nonnegative integer, yielding an {\tt Int} (note unresolved ambiguity with the previous item) \item {\tt[}$c.m${\tt]}, where \cconfig\ is a code type and \mconfig\ is a configuration for \cconfig\ having the same dimension as it. The associated matrix is the reduced generator matrix for the basic code associated to \mconfig. Some facility for lists of configurations is implemented in a similar way to the definition of configuration-list. Output type: {\tt HList(MatF2)}. \item {\tt[}$c.m${\tt-}$r${\tt]}, shorthand for {\tt[}$c.m${\tt] - column}\kern5pt$r$. \item $p$, a permutation, which represents the corresponding permutation matrix. The permutation $p$ is to be given as a product of cycles, e.g.\ as ``\verb|(1,4,5)(2,3)(6,8,7)|''. The size of the matrix is $r \times r$, where $r$ is the largest integer appearing in $p$. To avoid notational ambiguities, a permutation must be presented as the product of at least two cycles. \end{itemize} \par\noindent{\Large\bf Expression list \circno4} \vspace{0.1in} All the expressions in this list are binary operators, whose operands (labelled here $M$ and $N$) have type {\tt MatF2} and whose output has type {\tt MatF2}. \begin{itemize} \item {\bf[sharp]} $M \verb|#| N$ is defined in the following way. First let $A$ be the horizontal concatenation of $N\verb|.ncols|$ copies of $M$. Then let $B$ be obtained from $N$ by replicating each column $M\verb|.ncols|$ times. Finally $M \verb|#| N$ is the vertical concatenation of $A$ and $B$. \item {\bf[horizontal concatenation]} $M \verb=|= N$ is the horizontal concatenation of $M$ and $N$. If necessary, zero rows are first added to be bottom of $M$ (or $N$) to equalize the number of rows. \item {\bf[column complement]} Assume that $M$ and $N$ have the same number of rows. Then $M \verb|-| N$ is obtained from $M$ by deleting every column which appears in $N$. \end{itemize} \par\noindent{\Large\bf Expression list \circno5} \vspace{0.1in} All the expressions in this list are special binary operators. The left operand is an object of type {\tt MatF2} (which we label here $M$). The right operand does not have any objects in it. The output type is {\tt MatF2}. \begin{itemize} \item {\bf[parity check]} Let $C$ be the rowspace of $M$. Assume that $C$ has a word of odd weight. Then $M\verb| + check|$ is obtained from $M$ by adjoining a parity check as the last column. \item {\bf[column duplication]} Let $r$ be an integer between $1$ and $M\verb|.ncols|$. Then $M\verb| + column |r$ is obtained from $M$ by duplicating column $r$. \item {\bf[column deletion]} Let $r$ be an integer between $1$ and $M\verb|.ncols|$. Then $M\verb| - column |r$ is obtained from $M$ by deleting column $r$. Similarly, if $\VEC r1s \in \setof{1,\ldots,n}$, then $M\verb| - columns {|r_1\verb|,|\ldots\verb|,|r_s\verb|}|$ is obtained from $M$ by deleting columns $\VEC r1s$. It is also permissable to use {\tt..} to abbreviate a consecutive sequence, as in \verb|{1..4,9..12}|, which is equivalent to \verb|{1,2,3,4,9,12}|. \item {\bf[subcode disjoint from a bit]} Let $r$ be an integer between $1$ and $M\verb|.ncols|$. Then $M\verb| ~ column |r$ is obtained from $M$ by forming the reduced matrix spanning the subspace of the rowspace which is zero along column $r$; this column is deleted. \end{itemize} \par\noindent{\Large\bf Expression list \circno6} \vspace{0.1in} All the expressions in this list are special binary operators. The left operand is an object of type {\tt MatF2} (which we label here $M$). The right operand does not have any objects in it. The output type is {\tt HList(MatF2)}. \begin{itemize} \item {\bf[dual word deletion]} Let $r$ be an integer between $1$ and $M\verb|.ncols|$. Then \begin{center} $M\verb| - dual word of weight |r$ \end{center} represents the list of isomorphism classes of matrices obtainable from $M$ by deleting the columns corresponding to a word of weight $r$ dual to the rowspace of $M$, and then reducing. You can also do this with $M$ of type {\tt List(MatF2)}. \item {\bf[subcode disjoint from a dual word]} Let $r$ be an integer between $1$ and $M\verb|.ncols|$. Then $M\verb| ~ dual word of weight |r$ is obtained from $M$ by forming the reduced matrix spanning the subspace of the rowspace which is disjoint from a dual word $w$ of weight $r$; the corresponding columns are deleted. As $w$ varies, one obtains a list of matrices; a sublist of isomorphism class representatives is returned. You can also do this with $M$ of type {\tt List(MatF2)}. \item {\bf[dual word addition]} First reduce $M$. Let $r \in \setof{3,4}$. Then \begin{center} $M\verb| + dual word of weight |r$ \end{center} represents the list of isomorphism classes of matrices $M^+$ obtainable from $M$ by adding $r$ columns to it (and reducing), in such a way that the new codes $D := \Rowspace(M^+)$ have minimum distance two greater than $\Rowspace(M)$, and such that the weight $r$ word corresponding to the $r$ columns lies in $D^\perp$. You can also do this with $M$ of type {\tt List(MatF2)}. \end{itemize} \par\noindent{\Large\bf Expression list \circno7} \begin{itemize} \item{\bf[LinearProgram]} Let $f$ be of type \verb|String|, naming a file which contains a linear program, with integer coefficients. Then $\verb|LinearProgram($f\verb|)|$ is an internal representation of that linear program. \item{\bf[Bound]} Let $P$ be a {\tt LinearProgram}. Let $v$ be a variable which appears in $P$. Then $\verb|Bound(|P\verb|,|v\verb|)|$ returns {\it unverified\/} bounds (type \verb|List(Rat)|) on $v$ obtained by applying the simplex method to $P$. \item{\bf[{.}{.}]} Let $a$ and $b$ be of type {\tt Int}, $a \leq b$. Then $a\verb|..|b$ expands to $a,a+1,\ldots,b$. \item{\bf[-]} Let $n$ be of type {\tt Int}. Then $\verb|-|n$ is its negation. \item{\bf[AsConfig]} Let $M$ be of type {\tt MatF2}. Then APPLY1(AsConfig,M) is a {\tt String} which indicates how $M$ might be defined by a {\tt config} command. The columns are sorted and repeated columns are contracted. \item{\bf[WeightEnumerator]} Let $M$ be of type {\tt MatF2}. Then APPLY1(WeightEnumerator,M) is the weight enumerator of the rowspace of $M$, as a list of integers. This may also be applied to an object of type {\tt List(MatF2)}. \item{\bf[AsPoly]} Convert an object of type {\tt List(Int)} into a polynomial in $t$, returning an object of type {\tt String}. Similarly convert {\tt List(List(Int))} to {\tt List(String)}. \item{\bf[WE]} Equivalent to $\verb|AsPoly| \circ \verb|WeightEnumerator|$. \item{\bf[Build]} Let \hconfig\ be a code type. Let \lconfig\ be a configuration for \hconfig. Then \verb|Build( |\hconfig, \lconfig\verb| )| returns the matrices that would have been obtained if a command of the form {\tt via building }\lconfig\ $= \ldots$ had been used from type \hconfig. \item{\bf[Random]} The syntax is \verb|Random( |{\it type}\verb|, |{\it size}\verb|, |{\it range}\verb|, |% {\it seed}\verb| )| where \begin{itemize} \item {\it type\/} is {\tt List(Int)} or {\tt MatInt} \item {\it size\/} is a single integer (if {\it type\/} $=$ {\tt List(Int)}) or two integers (separated by a comma) (if {\it type\/} $=$ {\tt MatInt}) \item {\it range\/} is two integers (separated by a comma), indicated low and high values for the random entries \item {\it seed\/} is a number to be used as a seed for the random number generator. \end{itemize} \item{\bf[A\_inverse\_b]} Let $A$ be of type {\tt MatInt}, which we assume is invertible. Let $b$ be of type {\tt List(Int)}. Then $\verb|A_inverse_b( |A\verb|, |b\verb| )|$ returns $A^{-1}b$, which is of type \verb|List(Rat)|. (This is experimental. Currently there is a third argument, the version number, which may be $0$ or $1$.) \item {\bf[Read]} The syntax is \verb|Read( |{\it type}\verb|, |{\it file name}\verb| )|, where {\it type\/} is the type of the object to be read and {\it file name\/} is the name of the file it is in. It must be at the beginning of the file. The only types which are currently allowed are {\tt List(Int)} and {\tt MatInt}. \item {\bf[Cyclic]} The syntax is $\verb|Cyclic(|c\verb|, |n\verb|, |k\verb|, |% {\it generator}\verb|, |{\it extra word}\verb|)|$. This yields a {\tt MatF2} $M$ of size $k \times n$, as follows. First one can define the {\it standard permutation\/} on $n$ of cycle type $(a_1,\ldots,a_r)$. By way of example, the standard permutation on $10$ of cycle type $(3,2)$ is given as a product of disjoint cycles by $(1,2,3)(4,5)$. Now the argument $c$ describes a permutation $\sigma$. It is the standard permutation on $n$ of a certain cycle type. First, if $c$ is a positive integer dividing $n$, the cycle type is $(n/c, \ldots, n/c)$, with $n/c$ appearing $c$ times. Otherwise, $c$ must itself be the cycle type. The generator and the extra word (if present) are to be zero-one vectors of length $\leq n$. Pad on the right with zeros to form vectors $v$ and $w$ of length $n$. If the extra word is not present, let $M$ have rows $\setof{v, \sigma(v), \ldots, \sigma^{k-1}(v)}$. Otherwise let the rows be $\setof{v, \sigma(v), \ldots, \sigma^{k-2}(v),w}$. Note that there is no guarantee that $\sigma$ is an automorphism of $M$. \item {\bf[OrbitCount]} If $G$ is a {\tt MatrixGroup(F2)}, then APPLY1(OrbitCount,G) returns the number of orbits of $G$ under its natural action on $\F_2^n$. In fact, \verb|OrbitCount| does more: it finds a system of orbit representatives. This information is not returned. \item {\bf[OrbitReps]} If $G$ is a {\tt MatrixGroup(F2)}, then APPLY1(OrbitReps,G) returns a matrix whose rows form a system of orbit representatives for $G$ under its natural action on $\F_2^n$. \item {\bf[DelsartePair]} $\verb|DelsartePair(|n\verb|,|k\verb|,|w\verb|,|r\verb|,{|c\verb|})|$ is the linear program associated to a the pair of linear codes consisting of an $[n,k,w]$ code, where $w$ is a list of integers, containing an $[n,k-1,r]$ code (where $r$ is a list of integers), subject to the constraint list $c$, involving global variables $Y_i$ for the larger code and $y_i$ for the smaller code. \item {\bf[Realizable]} Let $L$ be a list of matrices. Let \hconfig\ be a code type. Then $\verb|Realizable(|\hconfig\verb|, |L\verb|)|$ selects those matrices $L_i$ which realize the code type $L$. (In particular, their rowspaces must have the right dimension.) \item {\bf[Unresidue]} Let $L$ be a list of matrices. Let \hconfig\ be a code type and let \cconfig\ be a basal configuration for it. Then $\verb|Unresidue(|\hconfig\verb|, |\cconfig\verb|, |L\verb|)|$ returns a list of generator matrices for those codes (up to isomorphism) in \hconfig\ which satisfy the constraints of \cconfig and could have a residual code generated by a matrix in $L$. There is an optional fourth argument, a positive integer $r$, which causes computation to stop after $r$ codes, for each matrix in $L$. See also the parameters \verb|unresidue ! show all configs| and \verb|unresidue ! show extra info|. \item {\bf[Select]} Let $L$ be a list of matrices. Let $f$ be a constraint, or set-bracket-enclosed list of constraints, whose \LHS's are integer linear combinations of global variables, and whose \RHS's are integers. Then $\verb|Select(|L\verb|, |f\verb|)|$ selects those matrices $L_i$ whose rowspace (as a code) satisfies $f$. \item {\bf[subcodes disjoint from a bit]} If $M$ is of type {\tt MatF2}, then $M\verb| ~ column|$ is the list obtained by choosing isomorphism class members from $M\verb| ~ column |r$, as $r$ varies. Alternatively, $M$ may be of type {\tt List(MatF2)}, in which case $M_i\verb| ~ column|$ is computed and the lists are merged (taking only isomorphism class members). \item {\bf[Group]} Define an object of type {\tt Group}. given by generators and relations. We illustrate by examples. \begin{verbatim} Group( x, y : x^21, y^3, yx -> xy ) Group( x : x^65 ) Group( x, y, z : x^3, y^3, z^7, yx -> xy, zx -> xz, zy -> yz^2 ) \end{verbatim} Note the following. The generators must be letters. Positive powers of each generator (to be set equal to the identity) must always be given, immediately after the generators and in the same order. The other relations are given as replacement rules, as shown. These rules operate on words in the generators. It is the users responsibility to be sure that they work in the following sense: \begin{itemize} \item There are no infinite sequences of transformations. \item If $\alpha\verb| -> ... -> |\beta_1$ and $\alpha\verb| -> ... -> |\beta_2$, and $\beta_1$, $\beta_2$ are terminal (admitting no further transformations), then $\beta_1 = \beta_2$. \item The group is finite. \end{itemize} An error will be issued (perhaps later) if the group is larger than $1000$ or ``too many'' transformations seem to have occurred. \item {\bf[RegularRep]} For an object $G$ of type {\tt Group}, This generates the regular representation (over $\F_2$) of a finite group, given by generators and relations. We illustrate by examples. \begin{verbatim} RegularRep( x, y : x^21, y^3, yx -> xy ) RegularRep( x : x^65 ) RegularRep( x, y, z : x^3, y^3, z^7, yx -> xy, zx -> xz, zy -> yz^2 ) \end{verbatim} Note the following. The generators must be letters. Positive powers of each generator (to be set equal to the identity) must always be given, immediately after the generators and in the same order. The other relations are given as replacement rules, as shown. These rules operate on words in the generators. It is the users responsibility to be sure that they work in the following sense: \begin{itemize} \item There are no infinite sequences of transformations. \item If $\alpha\verb| -> ... -> |\beta_1$ and $\alpha\verb| -> ... -> |\beta_2$, and $\beta_1$, $\beta_2$ are terminal (admitting no further transformations), then $\beta_1 = \beta_2$. \item The group is finite. \end{itemize} An error will be issued if the group is larger than $1000$ or ``too many'' transformations seem to have occurred. \item {\bf[For]} Let $\verb|[|i\verb|]|$ be an indeterminate. This means that $i$ is a string that starts with a letter and is followed by zero or more alphanumeric characters (or underscores), and that $\verb|[|i\verb|]|$ is not already defined. Let $L$ be some sort of list. [So its type is $\verb|List(|\ldots\verb|)|$.] Let $s$ be any expression. Then $\verb|For( [|i\verb|], |L\verb|, |s\verb| )|$ is $\verb|{| s|_{[i] \mapsto L_1}, \ldots, s|_{[i] \mapsto L_n} \verb|}|$. \item {\bf[Transpose]} Assuming that $x$ has type $\verb|List(List(|\ldots\verb|)|$, APPLY1(Transpose,x) returns its transpose, assuming that it makes sense. \item {\bf[Reduce]} Let $M$ be of type {\tt MatF2}. Then APPLY1(Reduce,M) is the {\tt MatF2} obtained from $M$ by converting to \RREF\ and removing any zero rows. Also {\tt Reduce} may be applied to a {\tt List(MatF2)}, yielding another {\tt List(MatF2)}. \item {\bf[Orbits]} Let $L$ be of type {\tt MatrixGroup(F2)}, generating a group of $n \times n$ matrices $G$. Then $\verb|Orbits(|L\verb|)|$ is the set of orbits of $\F_2^n$ under the action of $G$. The output type is {\tt PVSF2}. Alternatively, if $L$ is of type {\tt List(MatrixGroup(F2))}, $\verb|{ Orbits(|L_1\verb|), |\ldots\verb|, Orbits(|L_n\verb|) }|$ is returned, which is of type {\tt List(PVSF2)}. \item {\bf[Diag]} If $\vec M1n$ are matrices (type {\tt MatF2}), then $\verb|Diag(|\vec M1n\verb|)|$ is their direct sum, i.e.\ the matrix (type {\tt MatF2}) associated to the direct sum of the associated linear maps, \WRT\ the standard bases. If $\vec M1n$ instead have type {\tt List(MatF2)}, and each list has the same length, apply \verb|Diag| to their members in parallel, yielding a {\tt List(MatF2)}). \item {\bf[Length]} Let $L$ be a list (of some sort). Then APPLY1(Length,L) is the number of elements in the list, an object of type {\tt Int}. \item {\bf[P]} Let $M$ be of type {\tt MatF2}, which is replaced by its reduction. Let $\Simp$ be short for $\Simp({\tt M.nrows} - 1)$. Then APPLY1(P,M) is the reduction of $\BRMAT{1&0\cr\Simp&M}$. Also {\tt P} may be applied to an object of type {\tt HList(MatF2)}. \item {\bf[column deletion (without the column number)]} Let $M$ be of type {\tt MatF2}. Then $M\verb| - column|$ is obtained from $M$ by considering the list of all matrices obtainable from $M$ by deleting a column, and then choosing a sublist of isomorphism class representatives. In place of $M$, one may give a list of matrices, in which case the corresponding lists are merged, and again a sublist of isomorphism class representatives is returned. The output type is {\tt HList(MatF2)}. \item {\bf[perturbation]} For purposes of this paragraph, call one matrix a {\it perturbation\/} of another matrix if they have the same size and having differing entries in at most one column. Now let $M$ be of type {\tt MatF2}. Let $d$ be the minimum distance of the row space of $M$. For purposes of this paragraph, call a perturbation of some matrix {\it good\/} if its row space has minimum distance at least $d$. Then $\verb|Pert(|M\verb|)|$ is the list of all matrices (up to isomorphism) which are obtainable from $M$ via a sequence of good perturbations. The output type is {\tt HList(MatF2)}. There is an optional argument ``\verb|mu filter|'' which if used has the following effect. A perturbation $N$ is not used unless the code dual to its rowspace has a word of weight one or two. The input to $\verb|Pert|$ may be a list of matrices (generated by another operator). \item {\bf[double perturbation]} For $M$ of type {\tt MatF2}, $\verb|PertTwo(|M\verb|)|$ is defined in the same way as $\verb|Pert(|M\verb|)|$, except that here we use a different notion of perturbation: A matrix $N$ is a {\it perturbation\/} of a matrix $M$ if they have the same size, have differing entries in at most two columns (say $i$, $j$), and moreover $N^i - M^i = N^j - M^j$, where superscripts select columns. The optional argument ``\verb|mu filter|'' works the same way as it does for \verb|Pert|. There is also an optional argument ``\verb|ex triples|'' which if used has the following effect. Each time we consider making a perturbation a long columns $i$ and $j$, we check to see if there exists a dual word of weight $3$ whose support contains $i$ and $j$. If so, we do not make the perturbation. Usually when this option is used, one gets the same list of codes, but in a different order, and faster. There is also an optional argument of the form ``$\verb|stop after |r\verb| codes|$'', where $r$ is a positive integer, which will cause the perturbations to stop after a total of $r$ nonisomorphic matrices have been found. Example: $\verb|PertTwo(|M\verb|, stop after 10 codes)|$. The input to $\verb|PertTwo|$ may be a list of matrices (generated by another operator). A last option of the form {\tt start = }$r$ is allowed, which instructs the program to assume that perturbations of the first $r-1$ matrices are already included in the list. Note the following equivalent version of the perturbation employed by \verb|PertTwo|, provided that the rowspace of $M$ is an even code. In effect, you delete two columns from $M$, add a completely arbitrary column, and then add a parity check column. \item {\bf[macro substitution]} An expression of the type \begin{center} $\verb|Sub( {|\hbox{\it definition}_1,\ldots,\hbox{\it definition}_n\verb|}, |% \hbox{\it body}\verb| )|$ \end{center} is processed by substituting the given definitions into the body. A definition takes either the constant form \par\noindent \kern0.5in \hbox{\it name}\verb| := |{\it definition-body} \par\noindent or the variable form \par\noindent \kern0.5in \hbox{\it name}$\verb|(%1|,\ldots,\verb|%|n% \verb|) := |$\hbox{\it definition-body} \par\noindent where in the second case, the definition body may include the $\verb|%|i$'s. A {\it name\/} is to be an alphanumeric string (allowing underscores), which starts with a letter. Up to nine parameters are allowed. The output of a substitution is automatically enclosed in parentheses. \item {\bf[Isomorphic]} Let $A$ and $B$ be of type {\tt MatF2}. Then $\verb|Isomorphic(|A\verb|,|B\verb|)|$ is of type {\tt Bool}. It is {\tt true} \IFF\ $A \iso B$, meaning that after applying some permutation to the columns of $A$, it has the same rowspace as $B$. \item {\bf[Isomorphic]} Let $G$ and $H$ be of type {\tt MatrixGroup(F2)}. Then $\verb|Isomorphic(|G\verb|,|H\verb|)|$ is of type {\tt Bool}. It is {\tt true} \IFF\ $A \iso B$, meaning that the representations defined by $G$ and $H$ are isomorphic. However, this only works with semisimple representations $G$ and $H$. Otherwise an error will be issued. \item {\bf[Classify]} Let $L$ be of type {\tt List(MatrixGroup(F2))}. Then APPLY1(Classify,L) is of type {\tt List(Int)}. It is a list $v$ of positive integers, such that $\setof{A_i}_{i \in v}$ comprise a complete set of isomorphism class representatives (for the $L_i$, viewed as representations). The $L_i$ must all be semisimple. \item {\bf[Isomorphic]} Let $A$ and $B$ be of type {\tt PVSF2}. Then $\verb|Isomorphic(|A\verb|,|B\verb|)|$ is of type {\tt Bool}. It is {\tt true} \IFF\ $A \iso B$, meaning that both $A$ and $B$ are partitions of $\F_2^n$ and there exists a linear automorphism of $\F_2^n$ moving one partition to the other. \item {\bf[Classify]} Let $A$ be of type {\tt List(PVSF2)}. Then APPLY1(Classify,A) classifies $\vec A1n$ up to isomorphism, returning a {\tt List(Int)} $v$ of positive integers, such that $\setof{A_i}_{i \in v}$ comprise a complete set of isomorphism class representatives. \item {\bf[list]} Let $\vec A1n$ be objects of type $\alpha$. Then $\verb|{|A_1\verb|,|\ldots\verb|,|A_n|\verb|}|$ is of type $\verb|List(|\alpha\verb|)|$, provided that the latter type has been defined in the class \verb|generic_object|. \end{itemize} \par\noindent{\Large\bf Expression list \circno8} \midhead{The dual transform} Let $M$ be of type {\tt MatF2}, which is first reduced. The syntax of this operator is \begin{center} $M$\verb|^T using|\kern5pt$\setof{\VEC w1r}$, \end{center} where the $w_i$ are yet to be defined. Let $C$ be $M$'s row space. Each $w_i$ defines a certain subset $S_i$ of $C$, as follows. If $w_i$ is a nonnegative integer, then $S_i$ is the set of words of weight $w_i$ in $C$. If $w_i$ has the form ``$a$\verb|_{|$\VEC b1t$\verb|}|'', where each $b_i$ is a nonzero integer, then $S_i$ is the set of words of weight $a$ which for each $j$ have a $1$ in position $b_j$ (if $b_j > 0$), and a $0$ in position $-b_j$ (if $b_j < 0$). \par\noindent{\sc Note.}\ For purposes of display in the program part of this report, we will write (e.g.) $\ldots$\ {\tt using} $\{10,12_{\ol{1},2,\ol{5}},20\}$ instead of $\ldots$\ {\tt using} \verb|{10,12_{-1,2,-5},20}|. Let $S$ be the multiset $\bigcup_{i=1^r} S_i$. For $s \in S$, let $\lambda(s)$ denote its coordinate vector \WRT\ the ordered basis given by the rows of $M$. The value of the dual transform operator is the reduction of the matrix whose columns are $\setof{\lambda(s)}_{s \in S}$, in lexicographical order (for definiteness). The output type is {\tt MatF2}. \midhead{The dual orbit transform} Let $M$ be of type {\tt MatF2}. The syntax of this operator is \begin{center} $M$\verb|^T using {|\kern5pt% $\VEC g1r$\kern5pt\verb|:|\kern5pt$\VEC c1m$\verb|}|, \end{center} where $M$ is of type {\tt MatF2}; the $g_i$ and $c_i$ are yet to be defined. Let $C$ be $M$'s row space. Each $g_i$ is to have the form $\verb|$|r$, where $r \in \N$; it represents the \th{r}\ generating automorphism of $\Aut(M)$, as computed by {\tt Split}. As such these automorphisms are perilously dependent on slight changes to internal routines which might appear in a future version of {\tt Split}. Let $\VEC c1m$ be coordinate vectors for elements $\VEC w1m \in C$, relative to the rows of $M$. Let $S$ be the orbit of $\VEC w1m$ under the given automorphisms, viewed as a subset of $C$ (or a multiset in $C$ if there is repetition amongst $\VEC w1m$). Then proceed as with the dual transform. \block{More expressions} This section contains a collection of functions. We show the source code here, in a slightly prettified form. The actual source code is generated from the prettified source via a program \verb|parse_fun.cc|, which is included in {\tt CODE}. \input functions.tex \block{How to define a configuration} There are two main ways to define a configuration: the {\tt config} command, and the {\tt :=} command. We describe these first. Then we describe some other commands which can be used to define a configuration: {\tt config from}, {\tt incorporate}, and {\tt subdivide along}. \indexb{config} \begin{commanddeclaration} \vbox{\hbox{% $\displaystyle{\overbrace{\hbox{\tt=}}^{\hbox{optional}}} \displaystyle{\underbrace{\hbox{\lconfig}}_{\hbox{optional}}}$ {\tt config}\ \ {\it partition} {\tt:} {\it \{basis\}\/} $\displaystyle{\overbrace{\hbox{{\tt:} {\it \{dual basis\}} $\displaystyle{\underbrace{\hbox{{\tt:}\kern5pt{\tt\{}% \ {\it constraint list\/}\ {\tt\}}}}% _{\hbox{optional}}}$ }}^{\hbox{optional}}}$ {\tt;}% }% \hbox{\footnotesize{\ \ }}% \hbox{\footnotesize{\sc Note:}\ You never have to write ``{\tt\{\}}'' as part of this command -- replace it by the null string.}} \end{commanddeclaration} This command defines a {\it configuration}. We illustrate by an example: \begin{verbatim} type [32,14,10_2]; config 10,10,12 : {110,100}; \end{verbatim} These two commands tell us that we are looking at even codes of dimension $14$ in $\F_2^{32}$, which contain the following two words: \begin{verbatim} 1111111111 1111111111 000000000000 1111111111 0000000000 000000000000. \end{verbatim} (The spaces have been inserted to enhance readability.) If a dual basis is given, the dual code is expected to contain the given words. The elements of the ``basis'' are expected to be \LI, and likewise for the elements of the ``dual basis''. Use of the command \par\noindent\kern0.5in{\tt type [}$n${\tt, ...];} automatically generates the base configuration, as if the command ``{\tt config}\ $n$\ \verb|: { };|'' had been executed. If the {\it constraint list\/} is present, attention is restricted to those codes which satisfy the given constraints. A weight enumerator (e.g.\ \verb|1 + 6t^10 + t^20|) may be given as a ``constraint''. If a configuration is listed in the constraint list, it is expanded out to the list of all known global and joint constraints for the given configuration. The optional \lconfig\ is a label which is associated to the configuration for future reference. Within a given code type, a configuration label may not be defined more than once. The labels {\tt[base]} and {\tt[current]} are reserved for reference to the base and current configurations of the current code type. More complicated labels are created by the ``{\tt incorporate}'' ``{\tt:=}'' commands. The optional ``{\tt=}'' will cause the ``{\tt=}'' command to be automatically invoked on the configuration defined by this command and the configuration that was current prior to it. When a {\tt config} command is entered, aside from syntax, not much is checked. The language reserves the right to flag as errors certain things that no one would do deliberately. For example, for every word in the small code, the weight of the associated basic word should be in the working weight list for the base configuration. If at the some point it is found that a configuration is unrealizable, the language interpreter will discard all information about the configuration except this fact. \indexb{:=} \begin{commanddeclaration} {\it configuration-list\/}\kern5pt\verb|:= |{\it expression}\kern5pt% $\displaystyle{\underbrace{\hbox{{\tt::}\kern5pt{\tt\{}% \ {\it constraint list\/}\ {\tt\}}}}% _{\hbox{optional}}}${\tt;} \end{commanddeclaration} Usually the {\it configuration-list\/} consists of a single configuration \lconfig. In that case, create a fully refined configuration named \lconfig\ whose associated code has the generator matrix given by the expression. If \lconfig\ is terminal, is expected to be realizable. If {\it constraint list\/} is supplied, this command also automatically creates a configuration labelled {\tt[}$\ell${\tt!]} which is basal and has {\it constraint list\/} for its assumed constraints. As well, the implication ${\cal R}(\ell) \IN {\cal R}(\ell\hbox{\tt!})$ is noted. If the constraint list is ``\verb|{!}|'', it will automatically be replaced by the list of constraints which defines the weight enumerator of the code. If {\it configuration-list\/} has more than one configuration in it, then proceed as above, but the given expression should expand out to the same number of matrices, and the {\it constraint list\/} is not allowed (except for the ``\verb|{!}|'' format). \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \def\parwa{3.3in} \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \dtext{:= !}{ingredient tracking} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, turn off a safety feature which causes a record to be made (in the {\tt hints} directory) of all configurations used as ingredients by the {\tt :=} command. If there are a huge number of these, you may want to turn off ingredient tracking. \vskip 0.05in}\\ \hline \end{longtable} \indexb{config from} \begin{commanddeclaration} $\displaystyle{\underbrace{\hbox{\lconfig}}_{\hbox{optional}}}$ {\tt config from }$v_1${\tt|}$\ldots${\tt|}$v_r${\tt;} \end{commanddeclaration} Let $v_1$ be a basic local variable for {\tt[current]}. Show that it is nonzero, and subdivide along it to obtain a new configuration, which $v_2$ should be a basic local variable for. Show that $v_2$ is nonzero, and subdivide along it. Continue in this manner. The last configuration is made current, and is named \lconfig\ if the optional label is present. \def\nconfig{{\tt[}$n${\tt]}} \indexb{incorporate} \begin{commanddeclaration} \nconfig\kern5pt{\tt incorporate}\kern5pt\lconfig\kern5pt{\tt below}% \kern5pt\mconfig\kern5pt{\tt via sub}$w${\tt;} \end{commanddeclaration} \par\noindent{\sc Idea:} \ The fact that one code is known to contain another code may be used to copy configurations from one code type to another. \vspace{0.05in}\par\noindent{\sc Requirements:} \begin{itemize} \item \lconfig\ is an existing code type, which has no joint variables in its assumed constraints, and such that none of its configurations have joint variables in their assumed constraints\footnote{Constraints which set a basic joint variable to zero are however allowed.}; \item \mconfig\ is a configuration of the current code type, which may not have local variables in its assumed constraints, except that it may have a constraint {\tt sub}$w$ {\tt=}$g$, for some $g$ (see below); \item \nconfig\ identifies the given {\tt incorporate} command; it may not be used to label any other {\tt incorporate} command within the current code type; \item $w$ is a small word (relative to \mconfig), which has weight $1$ (as a small word); \item it must be known that $\verb|sub|w \geq 2^d$, where $d$ is the dimension of the code type referred to by \lconfig; \item Let $r$ be the part of the partition corresponding to the $1$ in $w$. Then the code type referred to by \lconfig\ must have length $r$ and dimension $\log_2($\verb|sub|$w)$. Its assumed weight list must contain \mconfig's working weight list. (Weights greater than $r$ are ignored.) Its assumed constraints must lift to known constraints for \mconfig, as in the following example: \begin{verbatim} [c] type [30,10,10]{y14 >= 10}; ... [d] type [36,15,10]; ... show mu6 != 0; [x] config 30,6 :: {01}; ... show x_14_0 >= 10; infer sub10 = 1024; [u] incorporate [c] below [x] via sub10; \end{verbatim} \end{itemize} \vspace{0.05in}\par\noindent{\sc Action:} \ The {\tt incorporate} command causes more or less the entire body of information for \lconfig\ to be imported into the current code type, sort of below \mconfig. In particular, each configuration \sconfig\ of \lconfig\ is used to generate a configuration \spconfig\ of the current code type. To do this it is necessary to carry out a number of conversions: \begin{itemize} \item All variables which appear in assumed or known constraints of \sconfig\ are reconstituted in terms of appropriate variables for \spconfig. Global variables are translated into {\tt sub} variables or linear combinations of them. Known constraints involving joint variables are lost. \item Words in the dual small code of \sconfig\ do not induce words in the dual small code of \spconfig. So instead such words are converted into assumed constraints involving {\tt q} variables. \item \spconfig\ has the label {\tt[}$n${\tt->}$s${\tt]}. Iterative use of incorporate will lead to configurations whose labels have more than one {\tt->} in them. \end{itemize} Automorphism labels are unchanged in the process. Continuing the preceeding example, if code type \verb|[c]| has a configuration defined via \begin{verbatim} [a] config 8,10,12 : {110,001} :: {y6 <= 4, x_0_1_0 = 0}; \end{verbatim} then after the {\tt incorporate} command, code type \verb|[d]| will have a configuration defined as if via \begin{verbatim} [u->a] config 8,10,12,6 : {1100,0010} : {0001} : {sub1110_6 <= 4, x_0_1_0_0 = 0}; \end{verbatim} although it would not be permissable to make such a definition, since the label would not be accepted. \indexb{subdivide along} \begin{commanddeclaration} $\displaystyle{\underbrace{\hbox{\lconfig}}_{\hbox{optional}}}$ {\tt subdivide along}\kern5pt$v${\tt;} \end{commanddeclaration} Forcibly subdivide {\tt[current]} along the given basic local variable, passing all known constraints for {\tt[current]} to it. Label the new configuration \lconfig, and make it current. \block{Group manipulation commands} To each configuration, there is associated a data item which relates to automorphisms: the list of {\bf known} automorphisms. These are to be viewed as generators. Some of the automorphisms have labels. Note that whenever a constraint which sets a basic local variable $v$ to zero is proved, the program automatically computes the orbit of $v$ under the group of known automorphisms, and sets all these variables equal to zero. Here are the commands: \indexb{automorphism} \begin{commanddeclaration} $\displaystyle{\underbrace{\hbox{\lconfig}}_{\hbox{optional}}}$ {\tt automorphism }$\VEC a1r${\tt;} \end{commanddeclaration} Verify that the given permutation defines an automorphism of the current configuration. Append it to the list of known automorphisms for the current configuration. A label \lconfig\ may be given. Within a given configuration, automorphism labels may not be repeated. \indexb{group size} \begin{commanddeclaration} {\tt group size = }$m${\tt;} \end{commanddeclaration} Verify that the group generated by the list of known automorphisms has $m$ elements. The implementation is very inefficient. \indexb{full group size} \begin{commanddeclaration} {\tt full group size = }$m${\tt;} \end{commanddeclaration} Verify that the automorphism group of {\tt[current]} has $m$ elements. For this command, {\tt[current]} may not have local variables in its assumed constraints. \indexb{report group size} \begin{commanddeclaration} {\tt report group size [}$\ell_1${\tt]}, $\ldots$\kern2pt, {\tt[}$\ell_r${\tt];} \end{commanddeclaration} This is a purely exploratory command. Given automorphisms {\tt[}$\ell_1${\tt]}, $\ldots$, {\tt[}$\ell_r${\tt]}, this command reports in order the size of the group generated by {\tt[}$\ell_1${\tt]}, then the size of the group generated by {\tt[}$\ell_1${\tt]}, {\tt[}$\ell_2${\tt]}, and so forth, lastly reporting the size of the group generated by {\tt[}$\ell_1${\tt]}, $\ldots$, {\tt[}$\ell_r${\tt]}. However, if one of these groups turns out to be very large, the command may never finish. The implementation is very inefficient. \indexb{reduce variable set} \begin{commanddeclaration} {\tt reduce variable set;} \end{commanddeclaration} Compute the automorphism group of the configuration. From the list of minimal admissible basic local variables $v$ (for {\tt[current]}), find those which are carried by an automorphism to an inadmissible basic local variable, and adjoin the corresponding constraints $v = 0$ to the list of known constraints. Ideally this would be done automatically as needed. \block{Configuration relation makers} Many of the commands of the language create logical relationships between configurations. All of the commands of this section do this. The {\tt !config} command does too. In addition, certain logical relationships come for free and are automatically known to the language: \begin{itemize} \item every configuration \lconfig\ implies the base configuration, i.e.\ ${\cal R}(\ell) \IN {\cal R}(\hbox{\tt base})$. \end{itemize} All commands in this section leave the current configuration undefined upon termination. \indexb{via dual nonexistence infer} \begin{commanddeclaration} \verb|via dual nonexistence infer [base] = ;| \end{commanddeclaration} Assume that the code type has no assumed constraints. Let $d$ be the minimum weight in the working weight list $w$ for {\tt[base]}. Suppose the minimum weight of the dual code is known to be $\geq d'$. Suppose we know that no \par\noindent\kern0.5in \verb|[n, n-k, d']{mu1 = 0,|\kern5pt$\ldots$\verb|, mu|$(d-1)$\verb| = 0}| \par\noindent code exists. Then one may infer that {\tt[base]} is unrealizable. In the case where $w$ has no odd weights, it is enough to know that no \par\noindent\kern0.5in \verb|[n, n-k, d']{mu1 = 0,|\kern5pt$\ldots$\verb|, mu|$(d-1)$\verb| = 0, y|% \kern1pt$n$\verb| = 1}| \par\noindent code exists. The intended purpose of this command is to bypass numerical instability of linear programming problems arising from the split linear programming method. It is useful when $k > n/2$. \indexb{implies}\indexb{=} \begin{commanddeclaration} \vbox{% \hbox{\lconfig\kern5pt{\tt implies}\kern5pt\mconfig{\tt;}}% \hbox{\lconfig\kern5pt{\tt =}\kern5pt\mconfig{\tt;}}} \end{commanddeclaration} \def\ttvec#1#2#3{$#1_#2${\tt,}$\ldots${\tt,}$#1_#3$} Let \lconfig, \mconfig\ be configurations. These commands are placeholders for the most trivial of trivial implications, whose conclusion in the first case is that ${\cal R}(\ell) \IN {\cal R}(m)$ and in the second case that ${\cal R}(\ell) = {\cal R}(m)$. The following cases are handled at present: \begin{itemize} \item (for {\tt implies})\ \mconfig\ has the form\\ \verb| config |$n$\verb| ::: {|% \kern3pt{\it constraint list}\kern3pt\verb|}|\\ and each of its assumed constraints are known to \lconfig. \item (for {\tt implies})\ \lconfig, \mconfig\ differ only in their assumed constraints, and every assumed constraint of \mconfig\ is a known constraint of \lconfig. \item (for {\tt =})\ \lconfig\ has the form\\ \verb| config |\ttvec p1r\verb| ::: |$\cal S$\\ and \mconfig\ has the form\\ \verb| config |$n-i$\verb|, |$i$\verb| :: {01} : |$\cal T$,\\ where $\cal S$ and $\cal T$ contain only global constraints, every constraint in $\cal T$ as well as the constraint \verb|mu|\kern1pt$i$\verb| != 0| is known for \lconfig, and every constraint in $\cal S$ is either known for \mconfig\ or else is the constraint \verb|mu|\kern1pt$i$\verb| != 0|; one may reverse the roles of \lconfig\ and \mconfig. \item (for {\tt =})\ \lconfig\ has the form\\ \verb| config |\ttvec p1r\verb| ::: |$\cal S$\\ and \mconfig\ has the form\\ \verb| config |$i$\verb|, |$n-i$\verb| : {10} :: |$\cal T$,\\ where $\cal S$ and $\cal T$ contain only global constraints, every constraint in $\cal T$ as well as the constraint \verb|y|\kern1pt$i$\verb| != 0| is known for \lconfig, and every constraint in $\cal S$ is either known for \mconfig\ or else is the constraint \verb|y|\kern1pt$i$\verb| != 0|; one may reverse the roles of \lconfig\ and \mconfig. The obvious variant when $i = n$ is also allowed. \item (for {\tt =})\ \mconfig\ is some refinement of \lconfig. For example, one could use: \begin{verbatim} [l] config 5,4,6 : {100,010} : {001}; [m] config 5,1,3,6 : {1000,0110} : {0001}; \end{verbatim} No local variables are permitted in the assumed constraints of the configurations. \item (for {\tt=})\ \lconfig\ and \mconfig\ are realizable full configurations, and their associated basic codes are isomorphic. \end{itemize} A large number of the commands in this section have the following general form: \begin{commanddeclaration} {\tt via}\kern5pt{\it method}\kern5pt\lconfig\kern5pt{\tt=}\kern5pt% {\it configuration-list}{\tt;} \end{commanddeclaration} Let the configuration-list expand out to \lconfigs. By the given method, show that the class of codes corresponding to configuration \lconfig\ equals the union of the classes of codes corresponding to configurations labelled \lconfigs. In the degenerate case ``\lconfig\ {\tt=}\ {\tt;}'' one in effect shows that no codes have configuration \lconfig. The case ``\lconfig\ {\tt=}\ {\tt[}$\ell_1${\tt];}'' is also in general permissable. Note however that you cannot in general replace this by ``{\tt[}$\ell_1${\tt]}\ {\tt=}\ \lconfig'': the conclusion would be the same, but the method may not be smart enough to handle the reversal. \indexb{via lp} \begin{commanddeclaration} {\tt via lp}\kern5pt\superopt{{\tt(}\it lp-specifier{\tt)}}\kern5pt% {\it configuration-list}\kern5pt{\tt= ;} \end{commanddeclaration} The optional {\it lp-specifier\/} should be a comma-separated list of one or more of the following optional arguments: \begin{itemize} \item ``{\tt joint}'' or ``{\tt joint:}$r$'', where $r \geq 0$ \item ``{\tt common}'' \item ``{\tt iterate<}{\it variable list}{\tt>}'', where {\it variable list} is a comma-separated list of variables, allowing for the abbreviation {\tt y*}. \end{itemize} For each configuration \lconfig\ in the expansion of the configuration-list, proceed as follows. If the optional joint argument is present, use joint linear programming to deduce (if possible) that \lconfig\ leads to a contradiction. (If the second form of the joint argument is used, the parameter ``{\tt use dual dual for joint}'' is set to $r$ prior to executing the {\tt show}, and then restored to its original value afterwards.) Otherwise, try to do this with split linear programming. However, to save time, the program will first attempt to determine if some known constraints are ``blatantly'' contradictory. Thus if we know that $y_{10} \geq 80$ and $y_{10} \leq 79$, then no calculation is required. For example, one might use a command sequence of the form \begin{verbatim} config ... ; show 79 < y10 < 80; via lp [current] = ; \end{verbatim} to exploit the fact that a variable does not take on an integer value. Similarly, if there is a known constraint of the form {\tt y}$i$ {\tt != 0}, where $i$ is not in the working weight list of {\tt[current]}, then no calculation is required. If the optional iterate argument is present, use integer linear programming to get a contradiction, by successively bounding the given variables. If the {\tt common} option is used, use both joint and split linear programming. \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead {\tt via lp ! quiet} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, show information about what is happening during execution of the command. \vskip 0.05in}\\ \hline \end{longtable} \indexb{via lp} \begin{commanddeclaration} {\tt !via lp}\kern5pt\lconfig\kern5pt{\tt= ;} \end{commanddeclaration} Run ``{\tt via lp}\kern5pt\lconfig\kern5pt{\tt= ;}'' with the expectation that it will fail, and confirm that failure, by temporarily turning on the parameter ``{\tt verify feasibility}''. \def\lpconfig{{\tt[}$\ell'${\tt]}} \indexb{via variable split} \begin{commanddeclaration} {\tt via variable split}\kern5pt\lconfig\kern5pt{\tt =}\kern5pt% {\tt[}$\ell_1${\tt]}\kern5pt{\tt or}\kern5pt$\ldots$\kern5pt{\tt or}% \kern5pt{\tt[}$\ell_r${\tt];} \end{commanddeclaration} \def\liconfig{{\tt[}$\ell_i${\tt]}} \def\ljconfig{{\tt[}$\ell_j${\tt]}} \par\noindent{\sc Idea:} \ A given configuration \lconfig\ may be broken up into several cases by making assumptions about the values of specified variables. \vspace{0.05in}\par\noindent{\sc Requirements:} \ The given configurations \lconfig, \lconfigs\ may differ only in their assumed constraints. Every assumed constraint of \lconfig\ must also be an assumed constraint of \liconfig, for each $i$. Apart from these shared constraints, all assumed constraints must be simple. \vspace{0.05in}\par\noindent{\sc Action:} \ Analyze the constraints not shared by all of \lconfig, \lconfigs, and deduce from these that ${\cal R}(\ell) = {\cal R}(\ell_1) \manycup {\cal R}(\ell_r)$. \def\clabel{{\tt[}$c${\tt]}} \def\yieqr{{\tt y}$i${\tt\ = }$r$} \indexb{via configuration search} \begin{commanddeclaration} {\tt via configuration search}\kern5pt\lconfig\kern5pt{\tt implies}% \kern5pt\mconfig{\tt;} \end{commanddeclaration} \par\noindent{\sc Idea:}\ One can check to see if a code realizes a particular $r$-dimensional configuration by explicitly checking each $r$-tuple of elements of the code. \vspace{0.05in}\par\noindent{\sc Requirements:}\ The configuration \lconfig\ must be terminal. The configuration \mconfig\ must have zero dual small code, and each of its assumed constraints must be known to \lconfig. \vspace{0.05in}\par\noindent{\sc Action:}\ Let $C$ be the code associated to \lconfig. Let $\VEC w1r$ be the basic words associated to the basis elements for the small code of \mconfig. Call an $r$-tuple $\VEC v1r \in C$ an \mconfig-{\it configuration\/} if for all subsets $S \IN \setof{1,\ldots,r}$, we have $\abs{\cap_{i \in S} v_i} = \abs{\cap_{i \in S} w_i}$. By an explicit search, determine if $C$ has an \mconfig-configuration. If it does, conclude that ${\cal R}(\ell) \IN {\cal R}(m)$. Otherwise ${\cal R}(\ell) \notIN {\cal R}(m)$ and the command fails. The current implementation is deathly slow if $r$ is large. \vspace{0.05in}\par\noindent{\sc Notes:}\ Let $\lambda_C(m) = $ the number of \mconfig-configurations in $C$. As \mconfig\ ranges over all one-dimensional configurations, the information carried by $\lambda_C(m)$ is equivalent to the information carried by the weight enumerator of $C$. As \mconfig\ ranges over two-dimensional configurations, we similarly obtain the information carried by the joint weight enumerator of $C$ with itself (see [.macwilliams sloane book.]\ p.\ 147 for the definition of joint weight enumerator). This command will utilize the ordered basis given explicitly for \mconfig, if possible, instead of the \RREF\ basis which is automatically computed for each configuration. \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \ttext{via configuration}{search !}{go to end} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, do not stop after finding a single configuration. \vskip 0.05in}\\ \hline \ttext{via configuration}{search !}{group level} & $\geq 0$ & $1$ & \parbox{\parwa}{\vskip 0.05in This governs the extent to which automorphisms will be used to prune the search. If set to $0$, not at all. If set to $1$, generators for the automorphism group are computed and used at the first stage. If set to $\geq 2$, the full automorphism group is computed and used up to the indicated stage. \vskip 0.05in}\\ \hline \ttext{via configuration}{search !}{group size cap} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a positive value, when computing the full automorphism group, stop after the given number of elements. \vskip 0.05in}\\ \hline \ttext{via configuration}{search !}{show example} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, exhibit an example of the configuration, if it exists. \vskip 0.05in}\\ \hline \ttext{via configuration}{search !}{expand final count} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, compute the total number of subcodes of \lconfig\ which are isomorphic to \mconfig. You must use ``{\tt go to end}'' (see above) for this to take effect. In addition, you should have a positive value set for ``{\tt group level}'' (see above), as otherwise the expansion would not have any effect. \vskip 0.05in}\\ \hline \ttext{via configuration}{search !}{print final list} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, print the final list, expanded if ``{\tt expand final count}'' (see above) was used. \vskip 0.05in}\\ \hline \end{longtable} \indexb{via unique wordtypes} \begin{commanddeclaration} {\tt via unique wordtypes}\kern5pt\lconfig\kern5pt{\tt implies}\kern5pt% \mconfig{\tt;} \end{commanddeclaration} The conclusion is that ${\cal R}(\ell) \IN {\cal R}(m)$. The configuration \mconfig\ must be terminal and realizable, and it must be known already that ${\cal R}(m) \IN {\cal R}(\ell)$. It must be known that the basic code associated to \lconfig\ contains all possible codewords, except for words of one weight. The justification for this command is: \begin{lemma} Let $C$ be a code in $\F_2^n$. Then for fixed $k$ and $q$, there exists (up to isomorphism) at most one $k$-dimensional code $D$ in $\F_2^n$ which contains $C$ and which has the property that $\abs{v} = q$ for all $v \in D - C$. \end{lemma} \begin{proof} First consider a projective code $E \IN \F_2^r$ of dimension $m$. Form the zero-one matrix $M$ whose rows are the nonzero elements of $E$. I claim that if one regards the columns of $M$ as vectors over $\Q$, they are independent. To see this, let $B$ be a generator matrix for $E$. By adding columns to $B$, we obtain a matrix $B'$ in which each nonzero element of $\F_2^m$ appears as a column exactly once. Let $M'$ be the zero-one matrix whose rows are the nonzero elements of the row space of $B'$. It is enough to show that the columns of $M'$ are $\Q$-independent. But $M'$ is square, so it is enough to show that its rows are $\Q$-independent. Now consider the set $S$ of functions \mapx[[ \F_2^m - \setof{0} || \F_2 ]] which are given by a nonzero, homogeneous, degree one element of $\F_2[\VEC x1m]$. Form the zero-one matrix $N'$ whose rows correspond to the elements of $S$. (One has to choose an order for the elements of $\F_2^m - \setof{0}$.) As an $\F_2$-basis for $S \cup \setof{0}$ is given by $\VEC x1m$, we see the rows of $N'$ corresponding to this basis are the same (up to permutation of columns) as the rows of $B'$, and hence $N' = M'$, modulo permutation of columns. Thinking in characteristic zero, view $\setof{0,1}$ as a subset of $\Q$, and regard the elements of $S$ as functions \mapx[[ \setof{0,1}^m - \setof{0} || \setof{0,1} ]]. I claim that these functions are $\Q$-linearly independent. The idea is as follows. The function $x_1$ over $\F_2$ is also represented by $x_1$ over $\Q$. The function $x_1+x_2$ over $\F_2$ is represented by $x_1+x_2-2x_1x_2$ over $\Q$. The function $x_1+x_2+x_3$ over $\F_2$ is represented by $x_1+x_2+x_3-2x_1x_2-2x_2x_3-2x_1x_3+4x_1x_2x_3$ over $\Q$. The function $x_1+x_2+x_3+x_4$ over $\F_2$ is represented by $x_1+x_2+x_3+x_4-2x_1x_2-2x_1x_3-2x_1x_4-2x_2x_3-2x_2x_4-2x_3x_4 +4(x_1x_2x_3 + x_1x_3x_4 + x_1x_2x_4 + x_2x_3x_4 ) - 8x_1x_2x_3x_4$ over $\Q$. Let $V$ be the subspace of $\Q[\VEC x1m]$ having as a basis the monomials of degree $d$ ($1 \leq d \leq m$) in which no exponent greater than $1$ appears. Note that if $f \in V$ induces the zero function \mapx[[ \setof{0,1}^m - \setof{0} || \setof{0,1} ]], then $f = 0$. Thus we see that the elements of the $\Q$-linear span of $S$ may be identified with the elements of $V$. But $\dim(V) = \abs{S}$, so it follows that the elements of $S$ are $\Q$-linearly independent. Hence the rows of $M'$ are independent over $\Q$, and so the columns of $M$ are $\Q$-independent. Now choose an ordered basis for $C$ and use it to define a configuration, whose small code $E$ is projective. I claim that this configuration has at most one nontrivial wordtype, up to equivalence. Indeed, a nontrivial wordtype for this configuration [say $(\VEC w1r)$] must satisfy one equation for each nonzero element $x$ of $E$: $\sum_{i=1}^r x_i w_i = \abs{x}/2$, where $\abs{x}$ is the weight of the basic word associated to $x$. The coefficient matrix of this system of equations is $M$, which we have shown has $\Q$-independent columns. Hence the system has at most one solution, which proves the lemma in the case where $k = \dim(C) + 1$. The general case follows by induction. \qed \end{proof} \indexb{via extension} \begin{commanddeclaration} {\tt via extension}\kern5pt$\hbox{\it configuration-list}_1$% \kern5pt{\tt implies}\kern5pt$\hbox{\it configuration-list}_2${\tt;} \end{commanddeclaration} The program expands $\hbox{\it configuration-list}_1$ and runs the command once with \lconfig\ set to an element of this list. Let $\hbox{\it configuration-list}_2$ expand to \lconfigs. The last configuration {\tt[}$\ell_r${\tt]} may have the form {\tt[}$\alpha$\verb|#]|, which is explained below. Let $D$ be the subcode associated to the small code of \lconfig. Search for all extensions of $D$ to codes which realize the code type, and using this information, attempt to show that $${\cal R}(\ell) \IN {\cal R}(\ell_1) \manycup {\cal R}(\ell_r).$$% However, in the special case where {\tt[}$\ell_r${\tt]} has the form {\tt[}$\alpha$\verb|#]|, any codes in ${\cal R}(\ell)$ which do not lie in ${\cal R}(\ell_1) \manycup {\cal R}(\ell_{r-1})$ are placed in (newly created) terminal configurations {\tt[}$\alpha${\tt1]}, {\tt[}$\alpha${\tt2]}, $\ldots$. (One should not rely on the ordering of these.) To use this command, the partition of \lconfig\ must have the form $1,\ldots,1,r$, for some $r$, and the smallcode of \lconfig\ must be confined to the first $n-r$ bits. Also it must be the case that $$r + \dim(\hbox{\lconfig}) \geq k.\eqno(*)$$% When the extensions have been found, their weight enumerators are computed, and the extensions are matched against the given configurations, according to the following scheme: \begin{itemize} \item Any of the extensions which match a given basal configuration are checked off. \item If there are any configurations which are neither basal or terminal, we determine if any of the extensions match them by means of a configuration search. \item The terminal configurations in \lconfigs\ are then compared with the remaining extensions. \end{itemize} The right hand side of the command could be empty, in which case it is expected that no extensions will be found. If the inequality in $(*)$ is strict, refine to get a partition $1,\ldots,1,r-1$ or $1,\ldots,1,r-2$, etc. Then after adjusting $r$, \WMAT\ $(*)$ is an equality. We then apply the method of \S\ref{extension-section}. Note that to be admissible, the weight list of $D_j$ must be contained in the working weight list \lconfig. We do not know of any practical rules to help pick the group $G$, beyond the obvious comment that it is advantageous for it to be large, but not too large. In the current version of the program, if ``{\tt alternate extension method}'' is set, we use the known automorphism group for $G$. Otherwise, we use $200$ elements of it (after the first step), and we also use a slightly different method for determining minimality. \par\noindent{\sc Note.}\ To use this command as an exploratory tool, first ``{\tt unset warnings are fatal}'', and then use \par\noindent\kern0.5in {\tt via extension}\kern5pt\lconfig\kern5pt{\tt implies ;} \par\noindent if you only want to know the weight enumerators of the extensions, or \par\noindent\kern0.5in {\tt via extension}\kern5pt\lconfig\kern5pt{\tt implies [base];} \par\noindent if you want to see all the extensions. \indexb{via building} \begin{commanddeclaration} {\tt via building}\kern5pt$\hbox{\it configuration-list}_1$% \kern5pt{\tt implies}\kern5pt$\hbox{\it configuration-list}_2${\tt;} \end{commanddeclaration} The command is repeated with \mconfig\ ranging over the elements of $\hbox{\it configuration-list}_1$. Let $\hbox{\it configuration-list}_2$ expand to \lconfigs. The last configuration {\tt[}$\ell_r${\tt]} may have the form {\tt[}$\alpha$\verb|#]|, as in the \verb|via extension| command. In that case the newly created configurations will always be converted to refined configurations. \vspace{0.05in}\par\noindent{\sc Goal:}\ Show that $${\cal R}(m) \IN {\cal R}(\ell_1) \manycup {\cal R}(\ell_r).$$% Do this by constructing a complete set $S$ of isomorphism class representatives for configurations which can be obtained by iterated subdivision of {\tt[current]}. (Obviously, if $S$ is gargantuan, the program will run out of memory.) For those configurations which are terminal, proceed as in the ``{\tt via extension}'' command to match them with \lorconfigs. In outline, here is the algorithm used to find the set of isomorphism class representatives: \begin{verbatim} list := { ( [m], {nontrivial minimal admissible wordtypes for [m]}, true ) }; repeat { pick p from those members of list whose 3rd member is true; (Exit if there isn't one.) wt := p.2nd, modulo the action of Aut( p.1st ); loop over w in wt { c := subdivision of p.1st along w; s := {nontrivial minimal admissible wordtypes for c}; (Obtained by considering those wordtypes of c which subdivide an element of p.2nd.) if ( c is not isomorphic to any config in list ) append (c, s, false) to list; } p.3rd = false; } \end{verbatim} \vspace{0.1in} \par\noindent Each configuration is printed as it is encountered. Known assumed and local constraints for \mconfig\ are ignored, except at the first step. In case $r = 1$ and the single configuration \config{\ell_1} is basal with a single assumed constraint of the form $y_i \leq m$, the procedure is modified, as follows. When we first compute {\tt list}, instead of using all nontrivial minimal admissible wordtypes for \mconfig, we use only those which are equivalent to a wordtype of weight $i$. As a result, {\tt s} gets modified in the same way. If we ever encounter a configuration with $y_i > m$, exit with error. \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \dtext{via building !}{show terminals} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, show terminal configurations as they are encountered. \vskip 0.05in}\\ \hline \dtext{via building !}{show all configs} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, show all configurations as they are encountered. \vskip 0.05in}\\ \hline \dtext{via building !}{show extra info} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, issue various informative messages as configurations are processed. Verbose. \vskip 0.05in}\\ \hline \dtext{via building !}{auto macaulay} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, terminal configurations will be piped to the {\tt macaulay} command. This option turns on the ``{\tt show terminals option}''. \vskip 0.05in}\\ \hline \dtext{via building !}{depth first} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, always process the highest dimensional outstanding configuration first. This conceivably could be useful for finding examples. \vskip 0.05in}\\ \hline \dtext{via building !}{use joint variables} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, use information about joint variables to prune the search. \vskip 0.05in}\\ \hline \dtext{via building !}{max create} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value, do not allow the creation of more than the given number of configurations, as in the {\tt[}$\alpha${\tt\#]} form. \vskip 0.05in}\\ \hline \end{longtable} \indexb{via varying} \begin{commanddeclaration} {\tt via varying y}$i$\kern5pt{\tt[current] implies}\kern5pt {\tt[}$\ell_1${\tt]}\kern5pt{\tt or}\kern5pt$\ldots$\kern5pt{\tt or}% \kern5pt{\tt[}$\ell_r${\tt];} \end{commanddeclaration} This is an extremely primitive facility for analyzing the integer solutions of the system of inequalities associated by split linear programming to {\tt[current]}. Each \ljconfig\ must be basal. Each must have an assumed constraint of the form $\hbox{\tt y}_i = m_j$. The $m_j$'s must all be distinct, and must form a list of consecutive integers (after reordering if necessary). For purposes of explanation, assume that they are already in order. First show that $m_1 \leq \hbox{\tt y}_i \leq m_r$. Then show that for each $j$, if one assumes that $\hbox{\tt y}_i = m_j$, then all the other assumed constraints of \ljconfig\ are satisfied. In total, the calculation is equivalent to $r+1$ {\tt show} commands. \indexb{disjoint} \begin{commanddeclaration} {\tt disjoint }{\it configuration-list}{\tt;} \end{commanddeclaration} Let {\it configuration-list\/} expand out to \lconfigs. Verify that for each $i \not= j$, ${\cal R}(\ell_i) \cap {\cal R}(\ell_j) = \emptyset$, using the following procedure: \begin{itemize} \item Attempt to show that known constraints of \liconfig\ contradict known constraints of \ljconfig. The program will only find explicit single variable contradictions, e.g.\ if \liconfig\ has \verb|y10 = 4| but \ljconfig\ has \verb|y10 >= 11|. If a contradiction is found, we're done. (A better way to do this would be to merge the known constraints from the two configurations, and apply linear programming, expecting a contradiction.) \item In case both configurations are terminal, show that they are not isomorphic. \item Assuming that one of the two configurations (\WLOG\ \liconfig) is terminal, by explicit search obtain a contradiction from the small code of \ljconfig. This is only practical if the dimension of \ljconfig\ is very small. The current implementation is very inefficient. \end{itemize} The command will fail if a contradiction is not obtained by one of the above steps. \indexb{classification of} \begin{commanddeclaration} {\tt classification of }\mconfig{\tt:}\kern7pt% \superopt{\hbox{{\it justification}\kern5pt$\Longrightarrow$}}% \kern5pt{\it configuration-list}{\tt;} \end{commanddeclaration} The configuration-list is expanded out to \lconfigs. We first describe what the command does when the optional part is absent. It will make a logical deduction from known facts, by verifying that ${\cal R}(m)$ is the disjoint union of ${\cal R}(\ell_1),\ldots {\cal R}(\ell_r)$ and moreover that each ${\cal R}(\ell_i)$ is nonempty. If needed, this command will invoke {\tt disjoint} for {\tt[}$\ell_1${\tt]}, $\ldots$, {\tt[}$\ell_r${\tt]}, and moreover try to show that they are all realizable. The classification command (as implemented) does not generally add logical data to the current configuration. However, in the special case where $r = 0$, the command will set configuration \mconfig\ to unrealizable, and in the special case where $r = 1$, the command will take note of the corresponding implication. Any elements of the working weightlist of \mconfig\ which do not appear in any of the working weightlists of {\tt[}$\ell_1${\tt]}, $\ldots$, {\tt[}$\ell_r${\tt]} are deleted from the working weightlist of \mconfig. Now suppose that the optional part is present, and the {\it justification\/} has the form ``$v_1${\tt|}$\ldots${\tt|}$v_r$''. Then the command is expanded to: \par\noindent\kern0.5in{\tt at }\mconfig{\tt;} \par\noindent\kern0.5in{\tt config from }$v_1${\tt|}$\ldots${\tt|}$v_r${\tt;} \par\noindent\kern0.5in{\tt via building [current] implies }\lconfigs{\tt;} \par\noindent\kern0.5in{\tt classification of }\mconfig{\tt:}\kern5pt% \lconfigs{\tt;} \par\noindent For input to {\tt Split}, the symbol $\Longrightarrow$ should be encoded as the ascii sequence ``{\tt -->}''. Now suppose that the optional part is present, and the {\it justification\/} has the form {\tt[}{\it type}{\tt->}{\it config list}{\tt]}, where {\it type\/} is the name of a preexisting code type with parameters $[n0, k0]$, and {\it config list\/} is a list of configurations for it; the following are examples of the allowed formats: \verb|[17_5_8->a]|, \verb|[17_5_8->{a,b,c}]|, \verb|[28_10_10->g*]|, \verb|[28_10_10->{g*.a}]|. In this case, \mconfig\ must be basal; let $\cal T$ be its assumed constraints. Let $r = n-n0$; we require that $r = k-k0$ or $r = k-k0+1$. Then the command is expanded to: \par\noindent\kern0.5in\verb|at|\kern5pt\mconfig; \par\noindent\kern0.5in\verb|show mu|$r$\kern5pt\verb|!= 0;|% \kern1in(if $r = k - k0 + 1$) \par\noindent\kern0.5in\verb|=config n0, n - n0 ::: {|$\cal T$\verb|};|% \kern1in(if $r = k - k0$) \par\noindent\kern0.5in\verb|=config n0, n - n0 :: {01} : {|$\cal T$\verb|};|% \kern1in(if $r = k - k0 + 1$) \par\noindent\kern0.5in{\tt[}{\it type}{\tt] incorporate [}{\it type}% {\tt] below [current] via sub10;} \par\noindent\kern0.5in{\tt via extension [}{\it type}{\tt->}{\it config list}% {\tt] implies}\kern5pt\lconfigs{\tt;} \par\noindent\kern0.5in{\tt classification of }\mconfig{\tt:}\kern5pt% \lconfigs{\tt;} Finally suppose that the optional part is present, that the {\it justification\/} has the form $\verb|Unresidue(|\ldots\verb|)|$, and that {\it configuration-list\/} is empty. The the program will attempt to show that the expression $\verb|Unresidue(|\ldots\verb|)|$ is an empty list of matrices and attempt to thereby deduce that \mconfig is unrealizable. Here is a special situation which the ``{\tt classification of}'' command checks for. Suppose it is known (or can be shown easily) that codes in the code type are projective and that they all have a word of weight $2^{k-1}$. Let $d$ be the minimum weight appearing in the weightlist of the codetype's definition. Suppose that $[n - 2^{k-1}, k - 1, d - 2^{k-2}]$ codes have been classified: $\VEC C1r$. Then a complete classification for the base configuration of the current codetype is obtained from the list $\verb|P(|C_1\verb|)|, \ldots, \verb|P(|C_r\verb|)|$ by dropping isomorphic codes and dropping unrealizable codes. The command also checks for certain $[n,k,d]$ Griesmer codes (i.e.\ codes at the Griesmer bound) which are known to be unique: \begin{itemize} \item $d = 2^{k-2} + 2$, where $k \geq 3$ and $k \not= 5$. Uniqueness was proved by van Tilborg [.tilborg griesmer 1980.]. This code can be described in {\tt Split} by $\verb|P(Even(|k-1\verb|))|$. \item $d = 2^{k-1} - 2^{u-1}$, where $1 \leq u \leq k-1$. Uniqueness was proved by van Tilborg [.tilborg griesmer 1980.]. \item $d = 2^{k-1} - 2^{a-1} - 2^{b-1}$, where $a > b > 0$, $k \geq a + b$, and $(a,b) \not= (3,2)$. Then there is a unique such code. This code is a very simple sort of Solomon-Stiffler code, which can be described in {\tt Split} by \par\noindent\kern0.5in% $\verb|P(|\cdots\verb|P( Simp(|a\verb|) # Simp(|b\verb|) )|\cdots\verb|)|$ \par\noindent where there are $k - a - b$ \verb|P|'s or $\verb|Off(Diag(Proj(|a\verb|),Proj(|b\verb|),{0},|\ldots\verb|,{0}))|$, \par\noindent where there are $k - a - b$ copies of \verb|{0}|. \end{itemize} If {\it configuration-list\/} has the form {\tt[}$\alpha${\tt1..}$r${\tt]} for some alphabetic string $\alpha$, and some $r > 1$, and exactly this configuration-list has been previously defined via a {\tt :=} command to be something of the form $\verb|Unresidue(| \ldots \verb|)|$, or $\verb|Build(| \ldots \verb|)|$, or $\ldots \verb| - column|$, and if one should be able to deduce the classification from this, then one can. \indexb{$\Longleftrightarrow$} \begin{commanddeclaration} \lconfig\ $\Longleftrightarrow$\ \mconfigs\ {\tt :=}\ {\it stuff\/}{\tt;} \end{commanddeclaration} This is an abbreviation, which expands into \vspace{0.1in} \par\noindent\mconfig\ {\tt :=}\ {\it stuff\/}{\tt;} \par\noindent\verb|classification of |\lconfig\verb|: |\mconfigs{\tt;} \vspace{0.1in} The $\Longleftrightarrow$ is actually ``{\tt <-->}''. \block{Constraint generators and weight killers} The commands of this section use various methods to prove that certain constraints hold for the current configuration. Some also create other configurations, and create edges from the current configuration to these new ones. The current configuration is still current upon completion. When a command from this section shows that a basic local variable is nonzero, the current (parent) configuration is subdivided, and thus a new (child) configuration is created. A constructive edge is created from the parent configuration to the child configuration. To a very limited extent, constraints involving local variables are translated from the parent configuration to the child configuration. Specifically, any constraint of the form $v = 0$ ($v$ a basic local variable), which is known at the time the child configuration is created, gets passed to it, and is used to reduce the number of admissible basic local variables for the child configuration. \def\constraintor{$\hbox{\it constraint}_1, \ldots, \hbox{\it constraint\kern1pt}_r$} \def\constrainti{$\hbox{\it constraint\kern1pt}_i$} \indexb{show} \begin{commanddeclaration} {\tt show}\kern5pt\superopt{{\tt(}{\it optional\ arguments}{\tt)}}% \kern5pt\constraintor{\tt;} \end{commanddeclaration} The optional arguments are to be a comma-separated list of items, selected from ``{\tt iterate}'', ``{\tt common}'', ``{\tt joint}'', and ``{\tt joint:}$r$'', where $r \geq 0$. This command causes the program to attempt to simultaneously verify the given constraints by split linear programming (or joint linear programming, if the joint argument is present). In the joint case, if the second form of the joint argument is used, the parameter ``{\tt use dual dual for joint}'' is set to $r$ prior to executing the {\tt show}, and then restored to its original value afterwards. The order of the constraints is irrelevant; one may use separate ``{\tt show}'' commands if the verification of one constraint depends on knowledge of another. (This will be slower.) Assuming that verification succeeds, the constraints are then added to the list of constraints known for the current configuration. If verification fails, execution is terminated. Some short cuts are employed to avoid linear programming. First, if {\tt[current]} has up to equivalence exactly one admissible basic local variable $v$ aside from the trivial basic local variable, and the dimension of {\tt[current]} is less than the dimension of the code type, then a constraint of the form $v != 0$ will be accepted without split linear programming, since it is true. Second, suppose that every admissible local variable of weight $i$ except one (say $v$) is equivalent to the trivial basic local variable, and it is known that $y_i$ exceeds the number of words of weight $i$ in the basic code associated to the small code. Then $v != 0$ will be accepted without split linear programming. Third, suppose that there are $r$ words of weight $i$ in the basic code associated to the small code, and that every admissible basic local variable of weight $i$ is equivalent to the trivial basic local variable. Then the constraint {\tt y}$i$\verb| <= |$r$ will be accepted without split linear programming. (If $r = 0$, one can write ``\verb|=|'' instead of ``\verb|<=|''.) If the optional argument ``{\tt iterate}'' is present, the program will attempt to arrive at the given constraints by a sequence of steps, yielding successively stronger bounds on the variables (appearing in the given constraints) until the given constraints are arrived at. If the optional argument ``{\tt common}'' is present, the ``{\tt iterate}'' option is automatically invoked, but in doing its iterations, the program will attempt to use both joint and split linear programming. \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead {\tt show ! quiet} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, show information about what is happening during execution of the command. \vskip 0.05in}\\ \hline \end{longtable} \indexb{check secondary residuals} \begin{commanddeclaration} {\tt check secondary residuals;} \end{commanddeclaration} This does nothing unless the parameter ``{\tt secondary plus}'' is set. In that case, let $v$ be a basic local variable for {\tt[current]}. Let \lconfig\ be the subdivision of {\tt[current]} along $v$. Form a list $L$ of all admissible basic local variables for \lconfig. Let $r$ be the number of parts in the partition of \lconfig. For each $w \in \F_2^r$, consider the subcode $S$ of $C$ supported on $w$, and the projection $P$ of $C$ onto the complement of $w$. Find all variables in $L$ supported on $S$, and use this to get a lower bound on the minimum distance of $S$. Then use known nonexistence results for codes with particular parameters to obtain an upper bound for $\dim(S)$. This gives a lower bound (say $k_P$) on $\dim(P)$. Again look through $L$ to get a lower bound $d_P$ on the minimum distance of $P$. Let $n_P$ denote the length of $P$. If we know that there is no $[n_P,k_P,d_P]$ code, we deduce that $v = 0$. The process of the preceding paragraph is carried out for each $v$, and in the event of a single success, it is repeated (over and over if need be). This is necessary in the interest of robustness, as otherwise the ordering of the basic local variables for {\tt[current]} could effect the outcome. Note also that in the interest of efficiency, we do not actually compute \lconfig, and instead work with a set of basic local variables for it which may include some inadmissible ones. \indexb{infer} \begin{commanddeclaration} \subopt{\hbox{{\tt@}\lconfig}}\kern5pt{\tt infer}\ \constraintor{\tt;} \end{commanddeclaration} If {\tt@}\lconfig\ is used, first set the current configuration to \lconfig. Then use accumulated data on nonexistence of codes or configurations to deduce that ${\it constraint}_i$ holds for {\tt[current]}, for each $i$. Various methods of deduction are known to this program: \begin{itemize} \item Suppose that the constraint $\alpha \geq r$ is known for {\tt[current]}, for some variable $\alpha$ and some integer $r$, and that the configuration obtained from {\tt[current]} by adjoining the constraint $\alpha = r$ is known to be unrealizable. Then one may infer the constraint $\alpha \geq r + 1$. \item Suppose that the constraint $\alpha \leq r$ is known for {\tt[current]}, for some variable $\alpha$ and some integer $r$, and that the configuration obtained from {\tt[current]} by adjoining the constraint $\alpha = r$ is known to be unrealizable. Then one may infer the constraint $\alpha \leq r - 1$. A similar inference is possible when $\leq$ is replaced by $\geq$. \item Let $d' \in \N$. If the configuration $n-d'${\tt, }$d'$\verb| :: {01}| is known to be unrealizable, then one can infer \verb|mu|\kern1pt$d'\verb| = 0|$. \item If the configuration $i$\verb|,|\kern5pt$n-i$\verb| : {10}| is known to be unrealizable, then one can infer \verb|y|$i$\verb| = 0|. \item You can infer that $\verb|div2| \geq 2^{k-1}$. If you know that $\verb|div2| > 2^{k-1}$, then you can infer that $\verb|div2| = 2^k$. \item Let $S$ be the working weight list for the current configuration. Suppose that $S \IN 2\Z$. A result of Brouwer ([.brouwer linear programming bound.], IV, Proposition) gives us information about {\tt div4}. First, {\tt div4} must lie in the set $$2^{k-1} - 2^{k-2}, 2^{k-1} - 2^{k-3}, \ldots, 2^{k-1} - 2^0, 2^{k-1}, 2^{k-1} + 2^0, 2^{k-1} + 2^1, \ldots, 2^{k-1} + 2^{k-1}.$$% If we know that there is no $[n,k,S \cap 4\Z]$ code, then of course the last possibility may be ruled out. Further, if for some $r \leq k-1$ we know that there is no $[n,r,S \cap 4\Z]$ code, it follows that {\tt div4} must lie in the set $$2^{k-1} - 2^{r-1}, 2^{k-1} - 2^{r-2}, \ldots, 2^{k-1} - 2^0, 2^{k-1}, 2^{k-1} + 2^0, 2^{k-1} + 2^1, \ldots, 2^{k-1} + 2^{r-2}.$$% Any constraint whose \LHS\ is {\tt div4} and which follows from these restrictions (and/or from known constraints on {\tt div4}) may be inferred. \item If $\verb|div8| > 2^k - 2^{k-3}$, by a result of Brouwer one may infer that $\verb|div8| = 2^k$. \item Let the working weight list for the current configuration be (in order) $0, d_1, d_2, \ldots$. Suppose that $\sum_{i=0}^{k-1} \ceiling{d_2/2^i} > n$. Then by the Griesmer bound, one may infer the constraint $y_{d_1}$ {\tt != 0}. \item Let $v$ be a basic local variable for the current configuration. Suppose that subdividing along $v$ would yield a configuration which is known to be unrealizable. Then one may infer the constraint $v$\kern5pt{\tt = 0}. \item Let $v$ be a basic local variable for \verb|[current]|. Suppose there is a constructive edge \verb|[current]| $\rightarrow$ \lconfig, that $w$ is a basic local variable for \lconfig, and that $w$ pulls back to $v$. (This pull back is verbatim, and does not take into account equivalence of basic local variables.) Suppose that the constraint $w \geq r$ is known for \lconfig. Then one can infer the constraint $v \geq r$ for \verb|[current]|. \item For any $w$, {\tt sub}$w$ is a power of $2$. If the complement $\loW$ of $w$ lies in the dual small code, then $\log_2(\hbox{\tt sub}w) \geq n - \abs{v} + 1$. On the other hand, if we know that codes of a particular type do not exist, we get an inequality going the other way. Suppose $w$ lies in the small code and that by weight considerations, no nonzero word of the code can be properly contained in the basic word associated to $w$. Then one may infer that \verb|sub|$w = 2$. \item If \verb|sub|$w$\verb|_|$k \geq r$ is known (for some $w$, $k$, $r$), one may infer \verb|y|$k \geq r$. \end{itemize} \indexb{up to isomorphism show} \begin{commanddeclaration} {\tt up to isomorphism show}\kern5pt$v$\kern5pt{\tt != 0;} \end{commanddeclaration} Let $v$ be an admissible basic local variable. Consider its orbit under the automorphism group of {\tt[current]}. Use split linear programming to show that the sum of the variables in the orbit is nonzero. This implies that if $v$ is used to subdivide the current configuration, then all codes of the given type have the current configuration \IFF\ they have the new configuration. Therefore a {\it logical\/} link is created between the current configuration and the new configuration. The following special case is handled without linear programming. Suppose that the dimension of {\tt[current]} is less than the dimension of the code type. Suppose that under the action of the known automorphisms of {\tt[current]} on admissible basic local variables, there are exactly two orbits. Then if $v$ is any admissible basic local variable (that is not equivalent to the trivial basic local variable), no calculation is required. \indexb{kill} \begin{commanddeclaration} {\tt kill}\kern5pt$v_1$\kern5pt% $\displaystyle{\overbrace{\hbox{by {\it local-variable-sequence}}_1}% ^{\hbox{optional}}}${\tt,}$\ldots${\tt,}\kern5pt$v_s$\kern5pt% $\displaystyle{\overbrace{\hbox{by {\it local-variable-sequence}}_s}% ^{\hbox{optional}}}${\tt;} \end{commanddeclaration} \par\noindent{\sc Syntax:}\ Let \czconfig\ denote the current configuration. Each $v_i$ is a basic joint, global, a local variable for \czconfig, ``{\tt ndiv4}'', ``{\tt ndiv8}'', ``$\verb|co|r$'' for some $r$, or a configuration label. Each $\hbox{\it local-variable-sequence}_i$ has the form \vspace{0.05in} \par\noindent\kern0.5in\verb|(|$w_1${\tt|}$\ldots${\tt|}$w_r$\verb|)| or \par\noindent\kern0.5in\verb|(|$w_1${\tt,}$\ldots${\tt,}$w_r$\verb|)| or \par\noindent\kern0.5in$w_1$ (equivalent to ``{\tt(}$w_1${\tt)}'') \vspace{0.05in} \par\noindent where $\VEC w1r$ are basic local variables for certain configurations described below. \vspace{0.05in}\par\noindent{\sc Goal:}\ By one or more subdivisions and applications of split linear programming, show in succession that $v_1 = 0, \ldots, v_s = 0$, or in the case where $v_i$ is a configuration, show that it is unrealizable. \vspace{0.05in}\par\noindent{\sc Action:}\ It depends! Read what follows. \vspace{0.05in}\par\noindent\circno1\ The cases where $v_i$ is \verb|ndiv4| or \verb|ndiv8| are special. The optional {\tt by}$\ldots$ stuff may not be used. If $v_i = \verb|ndiv4|$, we show that $\verb|div4| > {3\over4}2^k$ and deduce (via a theorem of Brouwer) that all words have doubly even weight. Similarly if $v_i = \verb|ndiv8|$, we show that $\verb|div8| > {7\over8}2^k$ and deduce that all words have weight divisible by $8$. \vspace{0.05in}\par\noindent\circno2\ Otherwise, we first use $v_i$ to create one or more new configurations \coconfig. There are several cases: \begin{itemize} \item If $v_i$ is a basic local variable, subdivide \czconfig\ along $v_i$ to obtain \coconfig. \item If $v_i$ is a basic global variable (say $= y_t$), find all basic local variables of weight $t$ and subdivide \czconfig\ along them to obtain various configurations \coconfig. \item If $v_i$ is a basic joint variable, let \coconfig\ be the configuration associated to $v_i$ (which is usually two-dimensional), which has all global and joint constraints for \czconfig\ adjoined to it as assumed constraints. \item If $v_i$ is $\verb|co|r$, let \coconfig\ be the configuration associated to $v_i$ (which is usually one-dimensional), which has all global and joint constraints for \czconfig\ adjoined to it as assumed constraints. \item If $v_i$ is itself a configuration label, \coconfig is set equal to it. \end{itemize} \vspace{0.05in}\par\noindent\circno3\ If ``{\tt by }$\ldots$'' is absent, kill the configuration(s) \coconfig\ by split linear programming. In any case, we first attempt to reduce the number of basic local variables as if via ``{\tt check secondary residuals}''. \vspace{0.05in}\par\noindent\circno4\ Otherwise suppose $\hbox{\it local-variable-sequence}_i$ = \verb|(|$w_1${\tt|}$\ldots${\tt|}$w_r$\verb|)|. Let \config{c_1} $=$ \coconfig. Let $w_1$ be a basic local variable for \config{c_1}. Show by split linear programming that $w_1 \not= 0$. Let \config{c_2} be obtained by subdividing \config{c_1} along $w_1$. If $r = 1$, use split linear programming to show that \config{c_2} is unrealizable. If $r > 1$, $w_2$ should be a basic local variable for \config{c_2}. One then shows by split linear programming that $w_2 \not= 0$, and continues as above, constructing configurations \config{c_3},$\ldots$,\config{c_{r+1}}. From the ultimate finding that \config{c_{r+1}} is unrealizable, one deduces that \coconfig is unrealizable. \vspace{0.05in}\par\noindent\circno5\ Otherwise we have $\hbox{\it local-variable-sequence}_i$ = \verb|(|$w_1${\tt,}$\ldots${\tt,}$w_r$\verb|)|. Let $\VEC w1r$ be basic local variables for \coconfig. For $j = 1,\ldots,r$, show in succession by split linear programming that the configuration obtained from \coconfig by subdividing along $w_j$ is unrealizable. Then show by split linear programming that \coconfig is unrealizable. The current configuration is restored to what it was prior to the command. \indexb{bound} \begin{commanddeclaration} {\tt bound}\kern5pt\superopt{{\tt(}\it lp-specifier{\tt)}}% \kern5pt\ttvec f1r{\tt;} \end{commanddeclaration} The optional {\it lp-specifier\/} should be a comma-separated list of one or more of ``{\tt joint}'', ``{\tt common}'', or ``{\tt iterate}''. For each $i$, $f_i$ must have one of the following forms: \begin{itemize} \item a homogeneous $\Z$-linear combination of variables (but you can't have both local and joint variables in the same combination); \item {\tt y*}, which expands to the list of all basic global variables {\tt y}$i$ ($i > 0$) which are not known to be zero; \item {\tt x*}, which expands to the list of all nonzero minimal admissible basic local variables, modulo the action of $\Aut(\hbox{\tt[current]})$, if it can be computed; \item \verb|~x*|, same as {\tt x*}, but instead expand to the sums over the orbits of the {\tt x}'s, under the action of the configuration's automorphism group\footnote{For this, the assumed constraints of {\tt[current]} should not have any local variables in them.}; \item {\tt mu*}, which expands to {\tt mu1}, {\tt mu2}, $\ldots$; \item {\tt j*}, which expands to the list of all minimal basic joint variables; \item {\tt jyd*}, expands to the list of all variables of the form \verb|jy|$r$\verb|d|$s$; \item Any of the above, but enclosed in brackets ({\tt[}, {\tt]}). \end{itemize} This command gets numerical bounds on the given variables, \WRT\ the current configuration. If the bracket form is used, do not report anything unless the variable is found either to be zero or nonzero. (We use $10^{-6}$ as a threshold.) If the optional ``{\tt(joint)}'' is present, joint linear programming will be used instead of split linear programming. If ``{\tt iterate}'' is present, iteratively bound variables until no further improvement can be achieved. The argument ``{\tt common}'' implies {\tt iterate} and moreover that both split and joint linear programming should be used. \par\noindent{\sc Note.}\ This is an exploratory command, and is not intended to prove anything. Do not rely on its results! The implementation of this command which runs with the ``{\tt homebrew}'' option on is tentative and provisional. It can be extremely slow, and is useless in situations where there are a small number of variables and a large number of constraints. \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead {\tt bound ! quiet} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, show information about what is happening during execution of the command. Not fully implemented. \vskip 0.05in}\\ \hline {\tt bound ! verify} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, verify bounds computed with the {\tt iterate} option. \vskip 0.05in}\\ \hline \dtext{bound !}{dual search} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, bounds are carried out by a completely different procedure, which involves gradually trapping the argument (and using dual simplex). This can be very slow, but will work sometimes when the ordinary use of {\tt bound} fails. \vskip 0.05in}\\ \hline \end{longtable} \indexb{load constraints by parity check from} \begin{commanddeclaration} {\tt load constraints by parity check from }\cconfig{\tt;} \end{commanddeclaration} \par\noindent{\sc Idea:} \ Any constraint on $[n,k,d]$ codes, where $d$ is even, induces a constraint on $[n-1,k,d-1]$ codes. \vspace{0.05in}\par\noindent{\sc Requirements:} \ The current code type should not have any assumed constraints, nor should the code type \cconfig. The current configuration should be the base configuration. The code type \cconfig\ should have the same dimension as the current code type, and should be exactly one bit longer. For each weight $w$ in the working weight list for the base configuration of the current code type, $w'$ must be in the assumed weight list for \cconfig, where $w'$ is obtained by rounding $w$ up to the nearest even integer. \vspace{0.05in}\par\noindent{\sc Action:} \ For each known constraint of the base configuration of \cconfig, a translated constraint is inferred for the base configuration of the current code type. This translation is accomplished by $$y_i\ \mapsto\ \cases{0,&if $i$ is odd;\cr y_0,&if $i = 0$;\cr y_{i-1} + y_i,&if $i$ is even and positive.}$$ If for $i$ even, $i$ is not in the working weight list for the base configuration of \cconfig, it is inferred that neither $i$ nor $i-1$ is in the working weight list for the base configuration of the current code type. \block{Other commands} \indexb{credit} \begin{commanddeclaration} {\tt credit: }{\it thing\/}\kern5pt{\tt due to} {\it name or reference}{\tt;} \end{commanddeclaration} Associate some credit to the current configuration. Here {\it thing\/} is {\tt existence}, {\tt nonexistence}, {\tt uniqueness}, or {\tt classification}. In the case of {\tt existence}, give credit for the existence of a particular configuration. If associated to {\tt[base]}, this indicates credit for the realizability of the code type. All the remaining {\it things\/} must be associated to the base configuration. In the case of {\tt uniqueness}, give credit for there being a unique code in the code type. In the case of {\tt classification}, give credit for the classification of the codes in the code type. In the case of {\tt nonexistence}, give credit for the nonexistence of the code type. One can also give credit for multiple things as in \par\noindent{\tt credit: }{\it thing1\/}\kern5pt{\tt due to}% {\it name or reference} {\tt,} {\it thing2\/}\kern5pt{\tt due to} {\it name or reference}{\tt;} \indexb{note} \begin{commanddeclaration} {\tt note:} {\it text}{\tt;} \end{commanddeclaration} Assign a note to particular configuration. Such a note may be utilized by the ``{\tt build web directory}'' command. \indexb{flags} \begin{commanddeclaration} {\tt flags: }${\it flag}_1,\ldots,{\it flag}_n${\tt;} \end{commanddeclaration} Associate certain flags to the current configuration, which must be {\tt[base]}: \begin{itemize} \item {\tt find no more}: tell {\tt Split} that when it is looking for new codes, it should not look for any new ones in this code type. In the current version, only the parameters of the code are looked at. \item {\tt no automorphism group computation}: inhibits automatic computation of the automorphism group (under certain circumstances). \end{itemize} \indexb{at} \begin{commanddeclaration} {\tt at}\kern5pt\superopt{type}\kern5pt\lconfig{\tt;} \end{commanddeclaration} If ``{\tt type}'' is present, reenter the code type \lconfig. Otherwise, set the current configuration to \lconfig. \indexb{help} \begin{commanddeclaration} {\tt help}\kern5pt{\it command name}{\tt;} \end{commanddeclaration} This command will only work if you have {\tt xdvi} installed. Search the LaTeX index file for the given command name. Then use {\tt xdvi} to open this document at the appropriate page. \indexb{status} \begin{commanddeclaration} {\tt status:}\kern5pt$\hbox{\it fact}_1, \ldots, \hbox{\it fact}_r${\tt;} \end{commanddeclaration} This command asserts certain facts about the base configuration. If the command is encountered while the program is in {\tt gullible} mode, these facts are accepted as true. This is particularly useful in connection with the {\tt tables only} parameter. We describe now the allowed fact types, and how they are treated if encountered when the program is not in {\tt gullible} mode. \begin{itemize} \item {\tt realizable} -- Check that the code type is known to be realizable. \item {\tt classified} -- Check that the code type is realizable and that the codes in the realization of the code type have been classified up to isomorphism; this is established by the ``{\tt classification of}'' command. \item {\tt unique} -- Check that the code type has (up to isomorphism) exactly one realization. \item {\tt weights =}\kern5pt$w$ -- Here $w$ is formatted as with a list of weights for the type command. Let $\lambda$ be the working weight list of {\tt[base]}. If $w \notIN \lambda$, issue a warning. If $\lambda \notIN w$, issue a {\tt kill} command for the weights in $\lambda - w$, in descending order. If that doesn't work, use joint linear programming, with {\tt use dual dual for joint} = 5. \item {\tt enumerator =}\kern5pt{\it weight enumerator} -- Here the {\it weight enumerator\/} is to be the weight enumerator of all codes (if any) in the realization of the code type, e.g. $$\hbox{``\verb|1 + 190t^12 + 255t^16 + 66t^20|''}.$$% In this report, we display the exponents using superscripts. If the weight enumerator is not known to be {\it weight enumerator}, first try to kill (in descending order) any weights which have zero coefficient in {\it weight enumerator}. Then try to show that each of the nonzero coefficients are correct, as if via ``{\tt show}''. First use split linear programming, and if that doesn't work, use iterative joint linear programming. \item \verb|constraints = {|$\VEC h1r$\verb|}| -- Check that the given constraints $\VEC h1r$ (involving only global and joint variables) are known to hold for the base configuration. If not, try to prove by iterated joint linear programming. \end{itemize} \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead {\tt status ! quiet} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, show information about what is happening during execution of the command. \vskip 0.05in}\\ \hline \end{longtable} \indexb{build tables} \begin{commanddeclaration} {\tt build tables for}\kern5pt$n_0$\kern5pt{\tt<= n <=}\kern5pt$n_1$% {\tt,}\kern5pt$k_0$\kern5pt{\tt<= k <=}\kern5pt$k_1${\tt;} \end{commanddeclaration} For the given range, build minimum distance tables of {\it upper bounds\/} for $[n,k]$ codes, writing the output in the form of an {\tt n = } command, prefixed by an exclamation point. Some {\tt status} commands may be written out first, also prefixed by exclamation points. \indexb{build web directory} \begin{commanddeclaration} {\tt build web directory for}\kern5pt$n_0$\kern5pt{\tt<= n <=}\kern5pt$n_1$% {\tt,}\kern5pt$k_0$\kern5pt{\tt<= k <=}\kern5pt$k_1${\tt;} \end{commanddeclaration} This is provisional implementation. For the given range of $[n,k]$, generate some information about $[n,k]$ codes, and put this in files in the {\tt web} directory. The file {\tt webcodes/install} installs this in a publicly accessible location. \indexb{alias} \begin{commanddeclaration} {\tt alias}\kern5pt{\it short-form}\kern5pt{\tt=}\kern5pt{\it long-form}{\tt;} \end{commanddeclaration} After using this command, any subsequently entered command starting with the string {\it short-form\/} will have that string replaced by {\it long-form}. \indexb{print} \begin{commanddeclaration} {\tt print}\kern5pt{\it print-item}{\tt;} \end{commanddeclaration} The allowed choices for {\it print-item\/} are given in the following table. We let $C$ denote the basic code associated to the small code of the current configuration. \begin{center} \begin{longtable}{|l|l|}\hline {\bf print-item} & {\bf effect} \\ \hline\hline {\tt dual weight enumerator} & \parbox{4.2in}{\vskip 0.05in Print the weight enumerator of $C^\perp$. \vskip 0.05in}\\ \hline {\tt intersection weight enumerator} & \parbox{4.2in}{\vskip 0.05in Print the weight enumerator of $C \cap C^\perp$. \vskip 0.05in}\\ \hline {\tt joint weight enumerator} & \parbox{4.2in}{\vskip 0.05in What this actually does is print the values of the nonzero joint variables. \vskip 0.05in}\\ \hline {\tt config} & \parbox{4.2in}{\vskip 0.05in Print some information about the current configuration. \vskip 0.05in}\\ \hline {\tt time used} & \parbox{4.2in}{\vskip 0.05in Print the total elapsed real time in minutes since execution started. \vskip 0.05in}\\ \hline {\tt memory usage} & \parbox{4.2in}{\vskip 0.05in Print the estimated total memory in use by the process, in kilobytes. \vskip 0.05in}\\ \hline {\tt basis} & \parbox{4.2in}{\vskip 0.05in Print a basis for $C$. \vskip 0.05in}\\ \hline {\tt reduced basis} & \parbox{4.2in}{\vskip 0.05in Remove duplicated columns from a generator matrix for $C$, and print it. \vskip 0.05in}\\ \hline {\tt dual basis} & \parbox{4.2in}{\vskip 0.05in Print a basis for $C^\perp$. \vskip 0.05in}\\ \hline {\tt intersection basis} & \parbox{4.2in}{\vskip 0.05in Print a basis for $C \cap C^\perp$. \vskip 0.05in}\\ \hline {\tt even subcode basis} & \parbox{4.2in}{\vskip 0.05in Print a basis for the subcode of $C$ consisting of all even words. \vskip 0.05in}\\ \hline {\tt variable classes} & \parbox{4.2in}{\vskip 0.05in List the equivalence classes of minimal admissible basic local variables, where the equivalence relation is induced by the automorphisms known for {\tt[current]}. \vskip 0.05in}\\ \hline {\tt variables of weight} $m$& \parbox{4.2in}{\vskip 0.05in List all admissible basic local variables of weight $m$. Equivalent variables are shown as such in the printout. \vskip 0.05in}\\ \hline {\tt dual words of weight} $m$& \parbox{4.2in}{\vskip 0.05in List all words of weight $m$ dual to the small code. \vskip 0.05in}\\ \hline {\tt codeword orbits}& \parbox{4.2in}{\vskip 0.05in Compute the orbits of the codewords (elements of small code) under the known automorphisms. \vskip 0.05in}\\ \hline {\tt punctured codes}& \parbox{4.2in}{\vskip 0.05in Classify up to isomorphism the codes which can be obtained by deleting a column from $C$. \vskip 0.05in}\\ \hline \dtext{projections onto}{words of weight $m$} & \parbox{4.2in}{\vskip 0.05in Classify, up to isomorphism, the codes obtained by projecting onto a codeword of weight $m$. \vskip 0.05in}\\ \hline {\tt automorphism group generators}& \parbox{4.2in}{\vskip 0.05in Print generators for the automorphism group of the current configuration. Also report the group size. For this print-item, {\tt[current]} may not have local variables in its assumed constraints. \vskip 0.05in}\\ \hline {\tt automorphism group}& \parbox{4.2in}{\vskip 0.05in Find and print all the elements of the automorphism group of the current configuration. For this print-item, {\tt[current]} may not have local variables in its assumed constraints. \vskip 0.05in}\\ \hline \ttext{dimension of code}{spanned by dual}{words of weight $r$} & \parbox{4.2in}{\vskip 0.05in Self-explanatory! \vskip 0.05in}\\ \hline \dtext{words of weight $m$,}{showing orbit groups} & \parbox{4.2in}{\vskip 0.05in List all words of weight $m$ in the small code, but permute the columns so that they are grouped into orbits under the action of the automorphism group. \vskip 0.05in}\\ \hline \dtext{split variables}{for weight $m$} & \parbox{4.2in}{\vskip 0.05in For each word $w$ of weight $m$ in $C$, determine the values the variables $\verb|x\_|i\verb|\_|j$, which represent the number of words of weight $i + j$ meeting $w$ along $i$ ones. Print out one line for each possible collection of values of these variables. (For example, if $\Aut(C)$ acts transitively on the words of weight $m$, there will be only one line.) \vskip 0.05in}\\ \hline \end{longtable} \end{center} \indexb{eval} \begin{commanddeclaration} {\tt eval}\kern5pt{\it expression}{\tt;} \end{commanddeclaration} Evaluate an expression, as in \S\ref{matrix-descriptor-section}. \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead {\tt eval ! input form} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, the output of eval is given in a form that is itself an expression. Only partially implemented. \vskip 0.05in}\\ \hline \end{longtable} \indexb{!config} \begin{commanddeclaration} {\tt!config} $\ldots$ {\tt;} \end{commanddeclaration} This is expanded out to: \par\noindent\kern0.5in{\tt config} $\ldots$ {\tt;} \par\noindent\kern0.5in{\tt via lp [current] = ;} \indexb{no} \begin{commanddeclaration} {\tt no [}\kern3pt$n${\tt,}\kern4pt$k${\tt,}\kern4pt$d$\kern3pt{\tt];} \end{commanddeclaration} This command implements approximately the procedure described in \S\ref{canned-section} for showing that there is no $[n,k,d]$ code. Here we describe some technical details and differences between what we actually do and what was described in \S\ref{canned-section}. Not all of the differences are mentioned here, and it is (at this point) necessary to refer to the code to see exactly what is done. The parameter $d$ may either be an integer, or else it may have the form $s$\verb|_4|, in which case attention is restricted to doubly even codes. In the second stage, when we attempt to show that there is no word of weight $i$ by split linear programming, we proceed as if via the command ``{\tt kill y}$i$'', except that code equivalent to ``{\tt check secondary residuals}'' is used in executing the {\tt kill} if $k \leq n/2$. In the third stage, when we try to show that there is no dual word of weight $i$, we do this by trying to show that the configuration ``$n-i${\tt, }$i$\verb| : { } : {01}|'' gives a contradiction by split linear programming. A more intensive attempt to prove the nonexistence of $[n,k,d]$ codes may be invoked by using a larger value for the {\tt allowed failures} parameter. (The default is $2$.) For all of the linear programming calculations, if $k > n/2$, we convert the problem to a problem about the dual code, and work with that instead, because it is numerically more stable. The code type is left undefined at the completion of the command. \indexb{test} \begin{commanddeclaration} {\tt test [}\kern3pt$n${\tt,}\kern4pt$k${\tt,}\kern4pt$d$\kern3pt{\tt];} \end{commanddeclaration} This exploratory command proceeds as with ``{\tt no [}\kern3pt$n${\tt,}\kern4pt$k${\tt,}\kern4pt$d$\kern3pt{\tt];}'' but interprets the outcome differently. If ``{\tt no}'' would succeed, issue a warning message. Otherwise, take no action. Also, the command is treated as a null command if it is not known that there is no $[n-1,k,d]$ command. In any case, the code type is left undefined upon completion. \indexb{test yes} \begin{commanddeclaration} {\tt test yes [}\kern3pt$n${\tt,}\kern4pt$k${\tt,}\kern4pt$d$\kern3pt{\tt];} \end{commanddeclaration} This exploratory command proceeds as with ``{\tt yes [}\kern3pt$n${\tt,}\kern4pt$k${\tt,}\kern4pt$d$\kern3pt{\tt];}'' but interprets the outcome differently. If ``{\tt yes}'' would succeed, issue a warning message. Otherwise, take no action. The code type is left undefined upon completion. \indexb{yes} \begin{commanddeclaration} {\tt yes [}\kern3pt$n${\tt,}\kern4pt$k${\tt,}\kern4pt$d$\kern3pt{\tt];} \end{commanddeclaration} This command implements a primitive facility for showing that an $[n,k,d]$ code exists. All it will do is use known results together with the following rules of inference: \def\existsk{\exists\kern1pt} \begin{itemize} \item $\existsk [n,n,1]$ \item $\existsk [n,k,d]$, $d$ odd $\Longrightarrow \existsk [n+1,k,d+1]$ \item $\existsk [n,k,d] \Longrightarrow \existsk [n-a,k-b,d-\max(a-b,0)]$ for all $a \in \Z$ and all $b \geq 0$ \item $\existsk [n_1,k,d_1], [n_2,k,d_2] \Longrightarrow \existsk [n_1 + n_2, k, d_1 + d_2]$ \item $\existsk [n,k_1,d_1], [n,k_2,d_2] \Longrightarrow \existsk [2n, k_1 + k_2, \min\setof{2d_1,d_2}]$ \item $\existsk [n,k,d] \Longrightarrow \existsk [n + 2^k, k + 1, \min( d + 2^{k-1}, 2^k )]$. \end{itemize} The next to the last rule comes from the ``$|u|u+v|$'' construction ([.macwilliams sloane book.]\ p. 76). The last rule comes from construction {\tt P} (see matrix-descriptor section). In fact, we only make partial use of these inferences, so some valid deductions may not be known to the command. \indexb{n =} \begin{commanddeclaration} {\tt n = $n$, k >= $k$: $I_k$, $I_{k+1}$, $\ldots$, $I_r$;} \end{commanddeclaration} \vspace{0.05in}\par\noindent{\sc Requirements:}\ One must have $r < n$. Each $I_k$ is to be $a${\tt-}$b$ (or an abbreviated form; see below), where $a \leq b$ are positive integers. The abbreviated forms are $b$ (abbreviating $b${\tt-}$b$), {\tt-}$b$ (abbreviating $1${\tt-}$b$), and $a${\tt-} (abbreviating $a${\tt-}$n$). \vspace{0.05in}\par\noindent{\sc Action:}\ For $i = 0, \ldots, r - k$ in succession, invoke the commands \par\noindent\kern1.5cm {\tt no [}\kern3pt$n${\tt,}\kern4pt$k+i${\tt,}\kern4pt$d_{k+i}+1$% \kern3pt{\tt];} and \par\noindent\kern1.5cm {\tt yes [}\kern3pt$n${\tt,}\kern4pt$k+i${\tt,}\kern4pt$d_{k+i}$% \kern3pt{\tt];}. \par\noindent Follow each of the above pairs for which $d_{k+i}$ is even with ``{\tt test [}\kern3pt$n${\tt,}\kern4pt$k+i${\tt,}\kern4pt$d_{k+i}$% \kern3pt{\tt];}'' and follow each pair with ``{\tt test yes [}\kern3pt$n${\tt,}\kern4pt$k+i${\tt,}\kern4pt$d_{k+i}+1$% \kern3pt{\tt];}''. Leave the code type undefined upon completion. \vspace{0.05in}\par\noindent{\sc Effect of parameters:}\ If the parameter ``{\tt optimal}'' is not set, the ``{\tt test}'' and ``{\tt test yes}'' commands will not be carried out. If the parameter ``{\tt lower bound check}'' is not set, the ``{\tt yes}'' and ``{\tt test yes}'' commands will not be carried out. The {\tt test mask} parameter may be used to restrict the scope of these tests. \indexb{set}\indexb{unset} \begin{commanddeclaration} \vbox{% \hbox{{\tt set}\kern5pt{\it parameter}\kern5pt$=$\kern5pt{\it value}{\tt;}}% \hbox{{\tt set}\kern5pt{\it parameter}{\tt;}}% \hbox{{\tt unset}\kern5pt{\it parameter}{\tt;}}} \end{commanddeclaration} The first form sets the given {\it parameter\/} to {\it value}. The second form sets it to $1$, and the third form sets it to $0$. Most of the allowed parameters are shown below. A few others (of the form {\it command name\/} {\tt!} {\it something-or-other}) are included in the documentation for the corresponding commands. The remaining parameters are shown in \S\ref{identify-find-section}. \begin{center} \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead {\tt secondary echo} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, and a command (e.g.\ {\tt n=}) causes other commands to be executed, they will not be echoed to standard output\vskip 0.05in}\\ \hline {\tt optimal} & $0$, $1$ & $0$ & See ``{\tt n=}'' command.\\ \hline {\tt warnings are fatal} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, recoverable errors will not be regarded as fatal. Use with caution.\vskip 0.05in}\\ \hline {\tt gullible} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, commands that follow are accepted without verification. This facilitates incremental verification of results.\vskip 0.05in}\\ \hline {\tt gullible commands} & \vbox{\hbox{\tt list of}\kern3pt\hbox{\tt strings}} & {\tt null} & \parbox{\parwa}{\vskip 0.05in Those commands which (aside from a label or labels) start with one of the given strings are executed in gullible mode. Thus one might use ``{\tt set gullible commands = no}'' or ``{\tt set gullible commands = via ext, via build}''. \vskip 0.05in}\\ \hline \vbox{\hbox{\tt show terminals}\kern3pt\hbox{\tt only}} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, when a ``{\tt via building}'' command is invoked, all configurations (and not just terminal ones) will be printed out as they are encountered. \vskip 0.05in}\\ \hline {\tt allowed failures} & $\geq 0$ & $2$ & \parbox{\parwa}{\vskip 0.05in If set to a number $> 2$, certain steps in the {\tt no} command are allowed to fail more than twice. If set to $0$, there is no limit on failures. If set to $-1$, there is no limit on failures and {\tt no} will try again too (under certain circumstances). This is an exploratory feature. \vskip 0.05in}\\ \hline {\tt repeat loop} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, the {\tt no} command will keep trying to kill weights after killing some but failing (as in {\tt allowed failures}). Starts over a top of kill list. \vskip 0.05in}\\ \hline {\tt verify feasibility} & $0$, $1$, $2$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$ or $2$, failed attempts to prove infeasibility will be {\it verified\/} by confirming that in fact the given linear program is feasible. If set to $2$, when verification fails, the calculation will be repeated using higher precision arithmetic. \vskip 0.05in}\\ \hline {\tt nauty vocal} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, print a message whenever Brendan McKay's graph isomorphism program {\tt nauty} is invoked. \vskip 0.05in}\\ \hline {\tt sort} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, the constraints generated by split linear programming will not be piped through a unique sort. \vskip 0.05in}\\ \hline {\tt secondary plus} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in See the ``{\tt check secondary residuals}'' command. This option indirectly affects the ``{\tt kill}'', ``{\tt no}'', and ``{\tt test}'' commands. \vskip 0.05in}\\ \hline {\tt auto round} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, automatically invoke the command {\tt round local variables} prior to attempting to prove infeasibility by split linear programming. For experimental use only. In the current version, CPLEX will be used, and so this option will only have an effect if ${n \choose k}$ is small enough to allow CPLEX to be invoked reliably. \vskip 0.05in}\\ \hline {\tt tables only } & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, only {\tt n=}, {\tt no}, {\tt yes}, {\tt type}, {\tt at type}, {\tt status}, {\tt set}, {\tt unset}, and {\tt exit} commands will be executed; {\tt no}, {\tt yes}, and {\tt status} commands will be executed in the gullible mode. This option can be used to test just the tables defined by the {\tt n=} command. To use it, be sure that each calculation which proves the (non)existence of a code type or limits its weights is followed by an appropriate ``{\tt no}'' or ``{\tt status}'' command. \vskip 0.05in}\\ \hline {\tt homebrew} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, a preliminary built-in simplex routine will be used for proofs. Independent of whether this parameter is set, the built-in routine will automatically be used if ${n \choose k} > 3 \times 10^{18}$. \vskip 0.05in}\\ \hline \dtext{homebrew full}{report} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, and {\tt homebrew} is set, it will print out simplex iterations in excruciating detail. For debugging and optimization. \vskip 0.05in}\\ \hline {\tt homebrew dump} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when {\tt homebrew} simplex calculations are performed, $A_B$ and $c_B$ are dumped to files in the directory {\tt calculations}. They are first scaled by a power of two so that all entries are integers. \vskip 0.05in}\\ \hline {\tt dump cost} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when {\tt homebrew} simplex calculations are performed, dump minus the cost vector to {\tt calculations/minus\_cost}. This is presumably the optimum of the linear program, if feasible. Useful in conjunction with the option {\tt verify feasibility}. \vskip 0.05in}\\ \hline {\tt precision} & $\geq 1$ & $1$ & \parbox{\parwa}{\vskip 0.05in This parameter sets a minimum for the precision used of floating point calculations made when employing the simplex method for linear programming. If the program thinks it is needed, higher precision will automatically be used. The meaning of the precision values is indicated by the following table: \begin{tabular}{|l|l|}\hline {\tt precision} & {\bf bits in mantissa}\\ \hline $1$ & $53$\\ \hline $2$ & $106$\\ \hline $3$ & $160$\\ \hline $4$ & $224$\\ \hline $\geq 3$ & $64 * \verb|precision| - 32$\\ \hline \end{tabular} If {\tt precision} is $\geq 2$, the built-in simplex routine is employed (see the {\tt homebrew} option). If {\tt precision} is $\geq 3$, more bits are allocated for the exponent, and hence if floating point overflow occurs, you may be able to circumvent it by setting {\tt precision} to $3$. \vskip 0.05in}\\ \hline {\tt precision lock} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a positive value, this functions like {\tt precision}, but it {\it forces\/} the precision to be a particular value. However, if the built-in simplex routine reports that it is confused, the precision value is raised. \vskip 0.05in}\\ \hline \dtext{full}{reduction} & $0, 1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, each time the simplex method is to be used, a special presolve routine is invoked first in an attempt to eliminate some constraints. \vskip 0.05in}\\ \hline \dtext{refactorization}{rate} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a positive value $r$, the basis matrix for the simplex method will be refactored every $r$ iterations. \vskip 0.05in}\\ \hline \dtext{dual constraint}{bound} & $\geq -1$ & $-1$ & \parbox{\parwa}{\vskip 0.05in If set to a nonnegative value $r$, only constraints corresponding to wordtypes whose {\it first\/} part is $\leq r$ will be used in split linear programming. \vskip 0.05in}\\ \hline \dtext{total dual constraint}{bound} & $\geq -1$ & $-1$ & \parbox{\parwa}{\vskip 0.05in If set to a nonnegative value $r$, only constraints corresponding to wordtypes whose parts are $\leq r$ will be used in split linear programming. \vskip 0.05in}\\ \hline \dtext{dcb depth}{limit} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a positive value $r$, the ``{\tt dual constraint bound}'' restriction will only apply to configurations whose partitions have length $\leq r$. \vskip 0.05in}\\ \hline \ttextp{alternate}{extension}{method} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, an alternate (conceivably faster) method will be used by the ``{\tt via extension}'' command. \vskip 0.05in}\\ \hline \dtext{auto group}{computation} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when a ``{\tt config}'' command is encountered (having no local variables in its assumed constraints), automatically compute the automorphism group of the configuration, and associate generators for the group to the configuration, as if via the ``{\tt automorphism}'' command. \vskip 0.05in}\\ \hline {\tt smart dual} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, every split linear programming calculation will include certain constraints of the form \verb|z\_|$a_1$\verb|\_|$\ldots$\verb|\_|$a_r <= 1$, when $\sum_{i=1}^r 2\min(a_i, p_i - a_i)$ is less than the known lower bound for the minimum distance of the dual code. (Here $(\VEC p1r)$ is the partition of the configuration.) \vskip 0.05in}\\ \hline \dtext{adjoin extra}{brouwer constraints} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, every split linear programming calculation will include certain constraints which are obtained by applying Brouwer's lower bound to subcodes. \vskip 0.05in}\\ \hline {\tt silent} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, most output will be suppressed. \vskip 0.05in}\\ \hline \dtext{limited secondary}{kill} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when the {\tt no} command is executed, and $k < n/2$, and an attempt to prove $\verb|y|_i = 0$ by split linear programming fails, try again, but this time first try to kill those basic local variables for the configuration $i,n-i$ {\tt:}\kern6pt{\tt\{10\}} (or $i$ {\tt:}\kern6pt{\tt\{1\}} if $i = n$) which have only one nonzero component (e.g.\ \verb|x\_12\_0|). \vskip 0.05in}\\ \hline \dtextp{full secondary}{kill} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in Same as {\tt limited secondary kill}, but tries to kill all basic local variables. \vskip 0.05in}\\ \hline \vbox{\hbox{\tt secondary kill}\kern3pt\hbox{\tt maxvars}} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If positive, {\tt limited secondary kill} and {\tt full secondary kill} will only be applied in situations where one has $\leq$ the given number of basic local variables. \vskip 0.05in}\\ \hline {\tt test mask} & \vbox{\hbox{\tt a list of}\kern3pt\hbox{\tt constraints}} & null & \parbox{\parwa}{\vskip 0.05in The given linear constraints may involve only the variables $n$, $k$, and $d$. Whenever a {\tt test [n,k,d]} command is encountered, the constraints are checked, and if one fails, the {\tt test} command is ignored. \vskip 0.05in}\\ \hline {\tt lower bound check} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in See the {\tt n=} command. \vskip 0.05in}\\ \hline {\tt homebrew speedy} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, when doing homebrew simplex calculations, do some extra error checking. Slower but safer. \vskip 0.05in}\\ \hline {\tt show variables} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when computing the list of admissible basic local variables for the current configuration, print them out as found. \vskip 0.05in}\\ \hline {\tt doubly even test} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, whenever a ``{\tt test[n,k,d]}'' command is invoked, only process it if $4 \mid d$, and instead check for the existence of a doubly even $[n,k,d]$ code. Even so, do nothing is nonexistence follows immediately from known results. \vskip 0.05in}\\ \hline {\tt fill weight} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value $w$, and {\tt[current]} has less words of weight $w$ than the known lower bound for $y_w$, ignore configurations that have not achieved this lower bound and do not increase the number of words of weight $w$. \vskip 0.05in}\\ \hline \dtext{show config}{creation} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, do not automatically subdivide when a variable is found to be nonzero by a show command. \vskip 0.05in}\\ \hline \dtext{low memory}{joint generation} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, use less memory but more time when generating constraints for joint linear programming. \vskip 0.05in}\\ \hline \dtext{auto joint}{search} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value $r$, do joint linear programming (to bound global variables) at the end of the execution of each {\tt no} (and {\tt test}) command, if the code type has not been shown unrealizable, provided that the number of minimal basic joint variables is $\leq r$. This option is exploratory. \vskip 0.05in}\\ \hline \dtext{auto joint}{test} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value $r$, at the end of the execution of each {\tt no} (and {\tt test}) command, if the code type has not been shown unrealizable, and if $r=1$ or the number of minimal basic joint variables is $\leq r$, attempt to show by joint linear programming that the code type is unrealizable. \vskip 0.05in}\\ \hline \dtext{auto try to}{kill jvars} & $0, 1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, and {\tt auto joint search} or {\tt auto joint test} has been selected, before carrying either one out, attempt to kill joint variables as in {\tt try to kill jy*}. \vskip 0.05in}\\ \hline \dtext{use dual}{dual for joint} & $\geq 0$ & $5$ & \parbox{\parwa}{\vskip 0.05in If set to a positive value $r$, when doing joint linear programming, also use the constraints arising from the fact that the coefficients of the joint weight enumerator of $C^\perp$ with itself are nonnegative, but use only those constraints coming from dual words of weight $\leq r + {\tt dl}$, where {\tt dl} is the known lower bound for the minimum weight of the dual code. \vskip 0.05in}\\ \hline \dtext{no test}{if classified} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, do not run the {\tt test} command on code types which have been classified or for which the weight enumerator is known, because of a ``{\tt status: enumerator = } $\ldots$'' command. \vskip 0.05in}\\ \hline {\tt partial pricing} & $\geq 0$ & $50$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value $r$, when using the homebrew simplex method, do {\it partial pricing}, by (roughly) only looking at $r$ candidates for an entering variable. \vskip 0.05in}\\ \hline {\tt iteration limit} & $\geq 1000$ & $1000000$ & \parbox{\parwa}{\vskip 0.05in Set the maximum number of iterations attempted by the simplex algorithm before giving up. \vskip 0.05in}\\ \hline {\tt auto mu1} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, whenever a {\tt type} command with no assumed constraints or options is encountered, say (in effect) ``{\tt type[}$n${\tt,}$k$\verb|,\{|$d,\ldots$\verb|\}];|'', first (in effect) execute the command ``{\tt no [}$n-1${\tt,}$k${\tt,}$d${\tt]}''. \vskip 0.05in}\\ \hline {\tt debug} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, do extra checks for internal errors and print some tracing messages. \vskip 0.05in}\\ \hline {\tt gullible silent} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, do not display commands which are executed in {\tt gullible} mode. \vskip 0.05in}\\ \hline \dtext{residual check}{for kill} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when executing {\tt no} and {\tt test} commands with the {\tt limited secondary kill} or {\tt full secondary kill} options turned on, do some addtional checking, as if via the ``{\tt check secondary residuals}'' command. Very slow at present. \vskip 0.05in}\\ \hline {\tt auto projection} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when doing split linear programming, automatically adjoin certain constraints coming from the known constraints of residual codes. If ``{\tt auto projection ! show constraints}'' is set, these are printed out as they are adjoined. If ``{\tt auto projection ! show parameters}'' is set, show the parameters of codes for which the program looks for constraints about. \vskip 0.05in}\\ \hline \dtext{auto projection !}{show constraints} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in See {\tt auto projection}. \vskip 0.05in}\\ \hline \dtext{auto projection !}{show parameters} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in See {\tt auto projection}. \vskip 0.05in}\\ \hline {\tt save bounds} & $0,1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, at the end of each ``{\tt test}'' command, assume that the bounds on global variables arising from the {\tt auto joint search} option are correct, and save them. Because these numerical results are not verified, incorrect bounds may be saved! This experimental option is conceivably useful in connection with the ``{\tt auto projection}'' option. \vskip 0.05in}\\ \hline \dtext{generate}{noneven bounds} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value $r$, at the end of each ``{\tt test}'' command, proceed as if with {\tt save bounds}, but work with all codes, not just even ones. Use the given parameter $r$ in place of {\tt auto joint search}. \vskip 0.05in}\\ \hline \dtext{price}{refinement count} & $\geq 0$ & $1$ & \parbox{\parwa}{\vskip 0.05in Set the number of times which the homebrew simplex calculator refines the price vector. This choice will presumably be automated in a later version. \vskip 0.05in}\\ \hline {\tt toldj percent} & $\geq 0$ & $70$ & \parbox{\parwa}{\vskip 0.05in Set the simplex optimality tolerance, as a percent. \vskip 0.05in}\\ \hline {\tt tolpiv percent} & $\geq 0$ & $87$ & \parbox{\parwa}{\vskip 0.05in Set the simplex pivot tolerance, as a percent. \vskip 0.05in}\\ \hline \dtext{matrix isomorphism}{silent} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, the isomorphism and automorphism routines for matrices (except in trivial cases) print some information. \vskip 0.05in}\\ \hline {\tt auto joint list} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, do not automatically compute a list of joint variables for each code type. \vskip 0.05in}\\ \hline \dtext{find regular}{group element} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value, when a terminal configuration is encountered, look for automorphisms which are a product of $n/r$ disjoint $r$-cycles. If the parameter value is $1$, look for each $r$, otherwise, use the parameter value as $r$. \vskip 0.05in}\\ \hline {\tt load limit} & $\geq 1$ & $20$ & \parbox{\parwa}{\vskip 0.05in A limit, in millions, on the number of constraints times the number of basic local variables, which can occur in a linear programming problem without triggering an error. \vskip 0.05in}\\ \hline {\tt auto cyclic test} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in When the {\tt build web directory} command is executed, if the size of the automorphism group of a code is less than the value of the parameter, and it is not known to be cyclic, try to determine if it is cyclic. \vskip 0.05in}\\ \hline {\tt show residual data} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, whenever the command ``{\tt check secondary residuals}'' is invoked (perhaps indirectly by another command), messages are printed out. These messages give data about certain hypothetical codes which exist if the current configuration is realizable. It is possible that by getting additional data about these codes (especially restrictions on the weights they may have), some basic local variables may be found to be zero. \vskip 0.05in}\\ \hline \dtext{unresidue !}{show all configs} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when evaluating an expression {\tt Unresidue( ... )}, show all configurations as they are encountered. \vskip 0.05in}\\ \hline \dtext{unresidue !}{show extra info} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when evaluating an expression {\tt Unresidue( ... )}, issue various informative messages as configurations are processed. Verbose. \vskip 0.05in}\\ \hline {\tt purge joints on type exit} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, whenever a code type is exited, the tables of joint variables associated to the code type's configurations are purged. This is sometimes desirable because these tables can occupy a huge amount of memory. \vskip 0.05in}\\ \hline \end{longtable} \end{center} \indexb{try to kill} \begin{commanddeclaration} {\tt try to kill}\kern5pt{\it variable-list}{\tt;} \end{commanddeclaration} This is an exploratory command, whose behavior depends on the parameter {\it variable-list}. The currently allowed possibilities are ``{\tt x*}'', ``{\tt jy*}'', and ``$\verb|jy|r\verb|*|$''. In case the parameter is {\tt x*}, the goal is to find a proof that {\tt [current]} is unrealizable. First try split linear programming. Then make a list of all nontrivial minimal admissible basic local variables for {\tt [current]}. For each such variable $v$, compute the number $\varphi(v)$ of minimal admissible basic local variables in the subdivision of {\tt [current]} along $v$. Put the nontrivial basic local variables for {\tt [current]} in increasing order according to the values taken by $\varphi$. One-by-one, attempt to show (as in ``{\tt kill} $v$'') that each of these variables $v$ is $0$. Whenever a success occurs, try split linear programming again on {\tt [current]}. Note that successes may cause the number of basic local variables in the subdivisions to decrease. In case the parameter is {\tt jy*}, to each joint variable, associate the corresponding configuration, say \lconfig, which is usually two-dimensional. All known constraints for {\tt[current]} (involving no local variables) are taken as assumed constraints for \lconfig. Then try to kill \lconfig\ by split linear programming. In this way accumulate known facts about joint variables (i.e.\ that some are zero) for the current configuration. The case $\verb|jy|r\verb|*|$ is similar, except that only joint variables involving $\verb|y|r$ are used. If the {\tt try to kill} command is run in {\tt gullible} mode, no linear programming calculations will be made. \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are associated to this command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \dtext{try to kill !}{vocal} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, some more information may be printed out as the command executes. \vskip 0.05in}\\ \hline \dtext{try to kill !}{maxvars} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value, {\tt try to kill jy*} will never set up a linear programming problem with more than the given number of variables. \vskip 0.05in}\\ \hline \end{longtable} \indexb{(* ... *)} \begin{commanddeclaration} {\tt (* ... *);} \end{commanddeclaration} Comment. Also lines starting with {\tt %} are treated as comments so long as they are not in the middle of a command. \indexb{random weight enumerator} \begin{commanddeclaration} {\tt random weight enumerator( n = }$n${\tt, k = }$k${\tt, div = }$d$ {\tt, modulus = }$m${\tt, count = }$c${\tt\ );} \end{commanddeclaration} The approximate function of this command is to find $c$ ``random'' codes of type $[n,k]$ and print out their weight enumerators. To explain more carefully what the command does, we have to explain the parameters $d$ and $m$. First, $d$ must be in \setof{1,4}, and if $d = 4$, we look only for ``random'' doubly even codes. Second, the weight enumerators are not literally printed out. Rather, for each code we print the list $$y_0 + y_m + y_{2m} + \cdots, y_1 + y_{m+1} + y_{2m+1} + \cdots, \ldots, y_{m-1} + y_{m+(m-1)} + y_{2m+(m-1)} + \cdots.$$% If you want the actual coefficients of the weight enumerator, use $m = n+1$. \indexb{dump} \begin{commanddeclaration} {\tt dump;} \end{commanddeclaration} Print information about all the configurations known for the current code type. \indexb{round local variables} \begin{commanddeclaration} {\tt round local variables;} \end{commanddeclaration} This is an exploratory command. First use floating point linear programming (without exact verification) to get bounds on all the admissible basic local variables. Whenever one of the bounds appears to not be an integer, adjoin and print a constraint corresponding to rounding the bound (up for lower bound, down for upper bound) to an integer. The output of this command could be modified slightly to create a {\tt show} command, which could then be tentatively included in a proof. \indexb{accept} \begin{commanddeclaration} {\tt accept} $\displaystyle{\underbrace{{\tt (tables\ only)}}_{\hbox{optional}}}$% \kern5pt{\it file}{\tt;} \end{commanddeclaration} Read in the given file of commands, as if in gullible mode, and do so as quietly as possible. If the {\tt(tables only)} option is included, only read in the following commands: {\tt n =}, {\tt no}, {\tt yes}, {\tt type}, {\tt status}, {\tt set lower bound check}, and {\tt unset lower bound check}. \indexb{go to} \begin{commanddeclaration} {\tt go to}\kern5pt{\it string\/}{\tt;} \end{commanddeclaration} The given {\it string\/} may be any character string which does not contain semicolons; white space is ignored. Read downward in the command file until a command which starts with {\it string\/} is encountered, and continue execution from there. \indexb{exit} \begin{commanddeclaration} {\tt exit;} \end{commanddeclaration} Terminate execution. \indexb{find cyclic codes} \begin{commanddeclaration} {\tt find}\kern5pt% $\displaystyle{\overbrace{\hbox{$r${\tt-}}}^{\hbox{optional}}}$% {\tt cyclic codes;} \end{commanddeclaration} If ``$r${\tt-}'' is omitted, $r$ is assumed to be $1$. It must be the case that $r|n$. Let $\sigma$ be the permutation of $n$ given by $x \mapsto x+r$. Consider all binary vectors $v$ of length $n$, having zeroes in (at least) the rightmost $k-1$ positions. If the code with basis $v,\sigma(v), \ldots,\sigma^{k-1}(v)$ realizes the code type, and has not (up to isomorphism) already been printed out, print it out, giving a definition for it using the ``{\tt Cyclic}'' operator. The codes generated by this command are not necessarily cyclic! \indexb{is cyclic?} \begin{commanddeclaration} {\tt is cyclic?}\kern5pt\superopt{\hbox{\tt(use extra)}}{\tt;} \end{commanddeclaration} The current configuration must be terminal. Determine if it could be described by a ``{\tt Cyclic}'' operator. If the ``{\tt(use extra)}'' is present, the {\it extra word\/} form of the ``{\tt Cyclic}'' operator is used; otherwise it is not. The implementation is horrible. \par\noindent{\sc Note.}\ The command will not in fact find all codes that could be described by the ``{\tt Cyclic}'' operator, because the permutation $\sigma$ defined by that command is not necessarily an automorphism of the code it generates, and the ``{\tt is cyclic?}'' command restricts attention to $\sigma$'s lying in the automorphism group of the code. \block{Identifying codes and finding new ones}\label{identify-find-section} This section contains various tools for identifying codes and finding new ones. There are two commands and many parameters. More explanation will be added later. \indexb{display} \begin{commanddeclaration} \verb|matrix |$M$\verb| := |{\it matrix-descriptor}\verb|;| \end{commanddeclaration} Declare a globally defined symbol $M$ (which is to be any non-null sequence of letters, digits, and underscores) which stands for the matrix defined by {\it matrix-descriptor}. To subsequently refer to this matrix, one uses ``\verb|matrix(|$M$\verb|)|''. \indexb{alt} \begin{commanddeclaration} \verb|alt |{\it matrix-descriptor}\verb|;| \end{commanddeclaration} Give an alternate description (up to isomorphism) for the current configuration, which must be terminal. \indexb{process} \begin{commanddeclaration} \verb|process |{\it matrix-descriptor}\verb|;| \end{commanddeclaration} Attempt to make good codes from the given matrix-descriptor, doubling or deleting columns if that helps. If the string ``\verb|@1|'' appears, it will be replaced by each code known to the program. If ``\verb|@2|'' also appears, it will be replaced by each code known to the program, and $\geq$ the code substituted for ``\verb|@1|'', \WRT\ some internal ordering scheme. If the string ``\verb|@w1|'' appears, it will be replaced by each codeword for the code of \verb|@1|, except that only one codeword is used for each orbit of the codewords under the action of the automorphism group. If the string ``\verb|@i1|'' appears, it will be replaced by each integer between the parameters \verb|i1low| and \verb|i1high|. One may similarly use ``\verb|@i2|''. There is a special format. If the expression has the form $$\verb#Act( #X\verb#, @v )# \hbox{ or } M\verb# | Act( #X\verb#, @v )#,$$% where $X$ is an expression which evaluates to an object of type {\tt MatrixGroup(F2)}, generating a group $G$ of $s \times s$ matrices, then \verb|@v| will (in effect) be replaced by (in succession) each subset $S$ of $\F_2^s$ which meets each orbit of $G$ at most once. (But if $GS_1 = GS_2$, we don't use both $S_1$ and $S_2$.) If the parameter ``\verb|min vector weight|'' is set to a nonzero value, then \verb|@v| will be replaced only by sets of vectors each having weight equal to at least the given value. \midhead{Parameters which govern the behavior of the {\tt process} command} \begin{center} \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \dtext{double}{column pairs} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, consider doubling pairs of columns when this may lead to a good code. \vskip 0.05in}\\ \hline \dtext{double}{column triples} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, consider doubling triples of columns when this may lead to a good code. Unusably slow. \vskip 0.05in}\\ \hline \dtext{double}{column groups} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, consider doubling groups of columns when this may lead to a good code. \vskip 0.05in}\\ \hline {\tt delete pairs} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in Consider deleting up to the given number of pairs of bits if (in a given case) it will only lower the minimum distance of the code by $1$. \vskip 0.05in}\\ \hline {\tt delete triples} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in Consider deleting up to the given number of triples of bits if (in a given case) it will only lower the minimum distance of the code by $2$. \vskip 0.05in}\\ \hline {\tt show even if known} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when a new code is generated which has optimal parameters, show it even if it is isomorphic to a known code, and give the name of the known code, if it had one. \vskip 0.05in}\\ \hline {\tt i1low} & $ \geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in See {\tt process}. \vskip 0.05in}\\ \hline {\tt i1high} & $ \geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in See {\tt process}. \vskip 0.05in}\\ \hline {\tt i2low} & $ \geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in See {\tt process}. \vskip 0.05in}\\ \hline {\tt i2high} & $ \geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in See {\tt process}. \vskip 0.05in}\\ \hline \dtext{show distance}{optimal} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, show codes if they are merely distance-optimal, and not necessarily optimal in the strong sense. \vskip 0.05in}\\ \hline {\tt show matrix} & $0$, $1$ & $1$ & \parbox{\parwa}{\vskip 0.05in If set to $0$, don't display the generator matrix of a newly discovered code. \vskip 0.05in}\\ \hline \dtext{find parameters}{only} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, once a code with given parameters has been found, ignore all others with the same parameters. \vskip 0.05in}\\ \hline \dtext{no column}{deletion} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, don't try to improve a code by deleting columns. \vskip 0.05in}\\ \hline \dtext{limited}{deletion} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, don't try as hard to improve a code by deleting columns. \vskip 0.05in}\\ \hline \dtext{min vector}{weight} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in See the documentation for the \verb|process| command. \vskip 0.05in}\\ \hline \end{longtable} \end{center} \midhead{Parameters which cause automatic computation of residual codes} The following parameters cause certain actions to be taken whenever a full configuration is encountered via a {\tt config} or {\tt :=} command. Let $C$ be the associated code. Certain residual codes of $C$ are computed, and in effect piped through a {\tt process} command. \begin{center} \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \dtext{auto group}{residual transform} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, for each automorphism $\sigma$ of $C$, try projecting onto a union of some of the sets $S_r := \setof{i: 1 \leq i \leq n, \sigma^r(i) = i, \sigma^j(i) \not= i \hbox{\ for all\ }j\hbox{\ with\ } 1 \leq j < i}$, for $1 \leq r \leq n$, This command is not carried out if the automorphism group is too big. \vskip 0.05in}\\ \hline \ttext{auto group}{residual}{transform alt} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, for each $\sigma \in \Aut(C)$, try projecting onto a union of some of the orbits of the bits under $\sigma$. This command is not carried out if the automorphism group is too big. \vskip 0.05in}\\ \hline \dtext{auto puncture}{transform} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, sort the bits into piles according to the weight enumerator of the corresponding punctured code, and then project onto a union of some of the piles. \vskip 0.05in}\\ \hline \dtext{auto residual}{transform} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, for each $w \in C$, form the residual code. To reduce execution time, only one codeword for each orbit (under the action of the automorphism group of the code) is used. \vskip 0.05in}\\ \hline \dtext{auto dual residual}{transform} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value $r$, find up to $r$ minimum weight words of $C^\perp$, and form the residual code of $C$ \WRT\ each of them. \vskip 0.05in}\\ \hline \end{longtable} \end{center} The following parameters cause certain actions to be taken whenever a full configuration is encountered via a {\tt config} or {\tt :=} command. Let $C$ be the associated code. Certain transforms of $C$ are computed, and in effect piped through a {\tt process} command. The first two parameters are the main ones -- defining two types of transforms. The remaining parameters modify the effect of these. \begin{center} \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \dtext{auto dual}{transform} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when a {\tt config} command is encountered (or when some other command is encountered which invokes a {\tt config} command), and if the dimension of the configuration is the same as that of the code type, do a search for dual transform codes from the code defined by the configuration. (See \S\ref{matrix-descriptor-section} for the definition of dual transform.) \vskip 0.05in}\\ \hline \dtext{auto orbit}{transform} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in Like ``{\tt auto dual transform}'', but looks for ``{\tt dual orbit}'' codes instead. \vskip 0.05in}\\ \hline \dtext{auto transform}{depth} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in Let $r$ be the given value. When invoking the ``{\tt auto dual transform }'' option, sort codewords into piles according to their weight and according to how they meet $r$ fixed bits. All possible choices of $r$ bits (up to isomorphism) will be cycled over, except that we quit after ``{\tt tuple orbit max}'' choices. \vskip 0.05in}\\ \hline \dtext{auto dual}{column deletion} & $0$, $1$, $2$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, when using the ``{\tt auto dual transform}'' or ``{\tt auto orbit transform}'' option, also try deleting columns from the generator matrix of the code defined by the {\tt config} command. If set to $2$, only do this. \vskip 0.05in}\\ \hline {\tt tuple orbit max} & $\geq 1$ & $5$ & \parbox{\parwa}{\vskip 0.05in See ``{\tt auto transform depth}''. \vskip 0.05in}\\ \hline {\tt nzv length max} & $\geq 1$ & $18$ & \parbox{\parwa}{\vskip 0.05in This governs the extent of the code search carried out when the ``{\tt auto dual transform }'' or ``{\tt auto orbit transform}'' option is invoked. \vskip 0.05in}\\ \hline {\tt nzv length max2} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a positive value, this causes ``{\tt auto dual transform }'' to carry out a second tier of searches, when a code within ``{\tt transform pass level}'' of the best $d$ is found. \vskip 0.05in}\\ \hline \dtext{search vector}{weight max} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a positive value, searches will only look at search vectors of weight $\leq$ the given value. \vskip 0.05in}\\ \hline \dtext{transform}{pass level} & $\geq 0$ & $5$ & \parbox{\parwa}{\vskip 0.05in See ``{\tt nzv length max2}''. \vskip 0.05in}\\ \hline \dtext{dual transform}{length limit} & $\geq 1$ & $255$ & \parbox{\parwa}{\vskip 0.05in When using the ``{\tt auto dual transform}'' option, only look for codes of length at most the given value. \vskip 0.05in}\\ \hline \dtext{crazy code}{search} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, searches for good dual and orbit transforms are handled in a different (and strange) way. \vskip 0.05in}\\ \hline \dtext{starting}{tuple orbit} & $\geq 1$ & $1$ & \parbox{\parwa}{\vskip 0.05in The {\tt auto dual transform} command will start with the indicated tuple orbit, and then reset the parameter to $1$. \vskip 0.05in}\\ \hline {\tt random search} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, both dual transforms and orbit transforms are implemented in a different way, using a primitive form of simulated annealing. This is highly experimental. There are various parameters (given below) which effect how it works, as well as some internal parameters which can be adjusted by modifying the source code. \vskip 0.05in}\\ \hline {\tt seed count} & $\geq 0$ & $10000$ & \parbox{\parwa}{\vskip 0.05in See {\tt random search}. \vskip 0.05in}\\ \hline {\tt perturbation count} & $\geq 0$ & $100000$ & \parbox{\parwa}{\vskip 0.05in See {\tt random search}. \vskip 0.05in}\\ \hline {\tt starting length} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to a nonzero value $l$, always begin a random search by starting with a code of length $l$. \vskip 0.05in}\\ \hline \dtext{random doubling}{probability} & $\geq 0, \leq 100$ & $0$ & \parbox{\parwa}{\vskip 0.05in When doing a random code search, when randomly adding a column group, add one that already is in use, with the given probability. \vskip 0.05in}\\ \hline {\tt max doubles} & $\geq 0$ & $0$ & \parbox{\parwa}{\vskip 0.05in This defines the maximum number of doubled column groups. \vskip 0.05in}\\ \hline {\tt level two search} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, periodically do a complete search in the distance two neighborhood of the current point in the parameter space. \vskip 0.05in}\\ \hline \end{longtable} \end{center} Other parameters which effect the search for codes: \begin{center} \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead {\tt input mask} & \vbox{\hbox{\tt a list of}\kern3pt\hbox{\tt constraints}} & null & \parbox{\parwa}{\vskip 0.05in The given linear constraints may involve only the variables $n$ and $k$. Whenever a {\tt config} or {\tt :=} command gives rise to a full configuration, and a post-processing parameter such as {\tt auto dual transform} has been set, the code type will first be tested to see if it satisfies the given constraints. If one of the constraints fails, the post-processing parameter is ignored. \vskip 0.05in}\\ \hline {\tt output mask} & \vbox{\hbox{\tt a list of}\kern3pt\hbox{\tt constraints}} & null & \parbox{\parwa}{\vskip 0.05in This is similar to {\tt input mask}, but is applied to a code generated by a post-processing routine. It is inconsistently implemented. \vskip 0.05in}\\ \hline \dtext{group size}{limit} & $\geq 0$ & $10000$ & \parbox{\parwa}{\vskip 0.05in Various post-processing options will not be carried out if a code's automorphism group has size in excess of this parameter. \vskip 0.05in}\\ \hline \dtext{auto enlarge by}{dual word} & $0$, $3$, $4$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to one of the allowed nonzero values (say $r$), attempt to find new codes as with the expression operator ``\verb|+ dual word of weight| $r$''. \vskip 0.05in}\\ \hline \end{longtable} \end{center} \vspace{0.05in}\par\noindent{\sc Parameters:}\ The following parameters are also associated to the {\tt process} command: \begin{longtable}{|l|l|l|l|}\hline \parbox{1.6in}{\bf parameter} & \parbox{1.0in}{\vskip 0.05in {\bf allowed}\\ {\bf values}\vskip 0.05in } & {\bf default} & \parbox{\parwa}{\bf meaning} \\ \hline\hline \endhead \dtext{\tt process !}{clear newcodes} & $0$, $1$ & $0$ & \parbox{\parwa}{\vskip 0.05in If set to $1$, each new {\tt process} command clears the list of codes kept by the routine {\tt process\string_new\string_matrix}. \vskip 0.05in}\\ \hline \end{longtable} \block{Experimental commands} The commands of this section are not guaranteed to do what they claim to do. \indexb{macaulay} \begin{commanddeclaration} {\tt macaulay;} \end{commanddeclaration} The current configuration must be terminal, and the associated code $C$ must not have any dual words of weight one or two. Then $C$ corresponds to a set $S$ of $n$ points in $\PP^{k-1}$. Use the program {\tt Macaulay} to find generators for the homogeneous ideal defining $S$, modulo the obvious generators of the form $a^2b + ab^2$, which are always present. To use this command, {\tt Macaulay} must be executable via a command of the same name. \indexb{random macaulay} \begin{commanddeclaration} {\tt random macaulay( n = }$n${\tt, k = }$k${\tt, minimum distance >= }$d$% {\tt, count = }$c${\tt\ );} \end{commanddeclaration} Find $c$ ``random'' projective codes of type $[n,k,d]$ and pipe the output to the {\tt macaulay} command. \indexb{clean} \begin{commanddeclaration} {\tt clean <}\kern5pt{\it input file\/}\kern5pt{\tt>}\kern5pt% {\it output file}\kern5pt% $\displaystyle{\underbrace{\hbox{{\tt(}$\VEC v1s${\tt)}}}% _{\hbox{optional}}}${\tt;} \end{commanddeclaration} The {\it input file\/} is to be a file of constraints. Read it in, try to simplify, and write the resulting system to {\it output file}. If the input file contains equality constraints, they will be used to eliminate variables, preferentially avoiding $\VEC v1s$ if they are present. Constraints in the input file should not have repeated variables in them. \block{Implementation notes}\label{implementation-section} The source code is written in the language C++. Although a standard for C++ is nearing completion [.C++ working paper.], implementations have naturally lagged behind, and thus the behavior of existing compilers varies. For this reason, at this time the source code will compile only under a single compiler, the GNU (Free Software Foundation) compiler, called {\tt g++}. We also use the GNU library {\tt libg++}. Fortunately, {\tt g++} and {\tt libg++} are freely available over the network and generally easy to install. This source code should compile and run on almost any Unix machine.% \footnote{If you want to use CPLEX, obviously you are restricted to those platforms for which it is available.} We would like to say exactly how much memory the program needs, but we do not know how to compute this at present. The results were obtained on a machine with $192$ megabytes of RAM and about $270$ megabytes of swap space; it is hard to say how much of this was really used by the program. Much can be done on a machine having only $32$ megabytes of RAM. As references both for the C++ language and the GNU implementation, we refer to Stroustrup's book [.stroustrup.], the libg++ manuals [.lea users guide.], [.bothner pesch.], [.regex manual.], and the help guides [.buck faq.], [.cline faq.]. Other relevant sources are [.stallman compiler manual.], [.C++ working paper.], and [.stepanov lee.]. We make use of Brendan McKay's graph isomorphism package {\tt nauty} and Keith Briggs double-double precision package {\tt doubledouble} [.briggs doubledouble.]. For installation of the source code, we refer to the script ``{\tt INSTALL}''. It is not possible at present to compile a working TeX file for this document from the distribution. If all goes well, you can now execute with {\tt Split < prog}, where {\tt prog} is a program file. The author will be happy to assist if there are any problems! A primitive interactive mode may be entered with {\tt Split -i}. This automatically turns off the option ``warnings are fatal''. |-> prep #!/bin/csh # Usage: "prep all" (for first compilation) or "prep" or "prep main" or e.g. # "prep simplex". # # The -O1 option causes some optimization which greatly speeds up some parts of # the program. Deleting it will however cut the compilation time in half. # # The -s option reduces the size of the binary executable file. # # The -pipe option slightly speeds up compilation, but should be removed # for a machine which does not have lots of memory. # # To insure compatibility with other systems in which "char"s are by default # unsigned, it is advisable to test that the program will still compile when # the option "-funsigned-char" is used. |-> prep set DEMO= set SPLIT=Split |-> doc/dprep #!/bin/csh # "dprep all" compiles demo --> DSplit. set DEMO=-DDEMO set SPLIT=DSplit ifelse(UNAME,Linux, ![ifelse(UNAMEM,i386,![DEFINE(SFLAG,-m486 -Dx86)]!,![DEFINE(SFLAG,)]!)]!, ![ifelse(UNAME,Openstep,![DEFINE(SFLAG,-DNeXT)]!,![DEFINE(SFLAG,-DSun)]!)]!) ifelse(UNAME,Openstep,![DEFINE(STRIPFLAG,-x)]!,![DEFINE(STRIPFLAG,-s)]!) ifelse(UNAME,Openstep,![DEFINE(WFLAG,-w)]!,![DEFINE(WFLAG,)]!) ifelse(UNAME,Openstep,![DEFINE(LFLAG,-lg++)]!,![DEFINE(LFLAG,)]!) |-> prep, doc/dprep if ($1 == "all") then gcc -c -O3 -funroll-all-loops -DMAXN=8192 SFLAG cc/nauty.c -Iinc \ -o obj/nauty.o gcc -c -O3 -funroll-all-loops -DMAXN=8192 SFLAG cc/nautil.c -Iinc \ -o obj/nautil.o g++ -c -O3 -DDD_INLINE SFLAG cc/doubledouble.cc -Iinc -o obj/doubledouble.o g++ -c -O3 -DDD_INLINE SFLAG cc/math.cc -Iinc -o obj/math.o gcc -c cc/random.c -w -Drandom=randomx -Dsrandom=srandomx -o obj/random.o g++ cc/parse_fun.cc -pipe -Iinc -I. -O1 -L. -Lobj -lg++ -lgmp_local -lm \ -s -o doc/parse_fun |& c++filt -sgnu endif if ($1 != "all" && $1 != "main" && $1 != "") goto component set objs = "" foreach i (permutation constraint matgf2 matreal simplex graph process \ wordtype split extensions codetable op0 op1 op2 op3 opAI opJZ op \ execute1 execute2 execute3 config codehome opt mawhome prevec1 \ sort misc woof woof2 finite codesearch web generic solve) if ($i == "opAI" && $1 != "main") then echo "parsing functions" doc/parse_fun endif if ($1 != "main") then echo compiling $i.cc g++ -c cc/$i.cc SFLAG $DEMO -pipe -Iinc -I. -O1 -s -o obj/$i.o endif set objs = "$objs obj/$i.o" end echo "compiling main program" g++ cc/code.c $objs obj/nauty.o obj/nautil.o obj/doubledouble.o obj/math.o \ obj/random.o obj/ntl.a SFLAG WFLAG $DEMO -pipe -Iinc -I. -O1 -L. -Lobj \ -lg++ -lgmp_local -lm LFLAG -o $SPLIT STRIPFLAG |& c++filt -sgnu exit component: if ($1 == "opAI" || $1 == "opJZ" ) then echo "parsing functions" doc/parse_fun endif g++ -c cc/$1.cc SFLAG -pipe -Iinc -I. -O1 -s -o obj/$1.o |-> tex/code.tex \midhead{Execution of the proofs in this report} I describe here a battery of tests for {\tt Split}, which are carried out (on my hardware) each time a new version of {\tt Split} is released, and which you can test on your hardware. For the steps which require a significant amount of execution time, I put the location of a log file and the running time.\footnote{The calculations were performed on a Sun Ultra 1 Model 140, with 192MB of RAM. For speed comparisons with other hardware, see {\tt http://open.specbench.org}. Note that since a test of this paper's results can be divided into several smaller computations, as via the ``{\tt set gullible}'' and ``{\tt unset gullible}'' commands, any program file can be executed in segments.} \vspace{0.1in} \par\noindent\circno1\ The file {\tt inputs/code.data1} is a {\tt Split} program file for the results which appear in [.jaffe optimal binary 30.]. You can execute these results with ``{\tt Split < inputs/code.data1}''. There is one line which takes a very long time to execute on my machine, and so I put a ``{\tt??}'' in front of it to circumvent its execution. \par\noindent[logfile: {\tt log/code.data1.out}; running time: 11 hours] \vspace{0.1in} \par\noindent\circno2\ Edit {\tt inputs/code.data1} as follows, to execute the line mentioned in \circno1\kern2pt. Put \par\noindent ``\verb|set gullible; set silent;|'' at the beginning. Before the key line, put ``\verb|unset gullible; unset silent;|''. This line has been properly carried out only once, using an unreleased version of {\tt Split} slightly preceding version 0.5. \par\noindent[logfile: {\tt log/code.data1.hard.out}; running time: 115 hours] \vspace{0.1in} \par\noindent\circno3\ To execute the results contained in this document, type ``{\tt Split < inputs/code.data}''. This will automatically accept (without proof) the results of [.jaffe optimal binary 30.]. \par\noindent[logfile: {\tt log/code.data.out}; running time: 46 hours] \vspace{0.1in} \par\noindent\circno4\ You might also wish to type ``{\tt Split -i}'' (interactive), and then enter ``{\tt accept inputs/code.data1;}'' followed by ``{\tt exit;}''. \vspace{0.1in} \par\noindent\circno5\ The command ``{\tt Split < doc/code.misc.test}'' will test some exploratory commands (and miscellaneous strange things). \vspace{0.1in} \par\noindent\circno6\ Add the lines \begin{verbatim} set tables only; set optimal; set gullible commands = no, yes; \end{verbatim} to the beginning of {\tt inputs/code.data1} and again execute it. \par\noindent[logfile: {\tt log/code.data1.test.out}; running time: 5 minutes] \vspace{0.1in} \par\noindent\circno7\ Add the same lines to the beginning of {\tt inputs/code.data} (after the {\tt accept} line), and again execute it. \par\noindent[logfile: {\tt log/code.data.test.out}; running time: 9 hours] \vspace{0.1in} \par\noindent\circno8\ Run {\tt Split} on {\tt webcodes/script}. |-> doc/code.misc.test type [12,4,6]; bound y*; show y6 != 0; bound y*, [x*] ; config 6,6 : {10}; show x24 != 0; config 2,4,4,2 : {1100,1010}; bound y*, [x*] ; set optimal; set lower bound check; n=3,k>=2:2; n=4,k>=2:2,2; n=5,k>=2:3,2,2; n=6,k>=2:4,3,2,2; n=7,k>=2:4,4,3,2,2; n=8, k >= 2: 5-5, 4, 4, 2, 2, 2; unset optimal; n=8, k >= 2: 5-5, 2-4, 4-, 2, 2, 2; set gullible; n=9,k>=2:6,4,4,3,2,2,2; n=10,k>=2:6,5,4,4,3,2,2,2; n=11,k>=2:7,6,5,4,4,3,2,2,2; n=12,k>=2:8,6,6,4,4,4,3,2,2,2; n=13,k>=2:8,7,6,5,4,4,4,3,2,2,2; n=14,k>=2:9,8,7,6,5,4,4,4,3,2,2,2; n=15,k>=2:10,8,8,7,6,5,4,4,4,3,2,2,2; n=16,k>=2:10,8,8,8,6,6,5,4,4,4,2,2,2,2; unset gullible; type [21,8,8_2]; [b] := {011110000011110000000,110010110001101000000,101011010010100100000, 100111100011000010000,111111111100000000000,000100011011100001100, 001001111001000001010,010011010011000001001} :: {y8 = 89, y10 = 41, y12 = 98, y14 = 22, y16 = 4, y18 = 1, y20 = 0}; is cyclic?; type [16,8,4]; [a] := Cyclic(1, 16, 8, 000100111) :: {y4 = 55, y6 = 96, y8 = 87, y10 = 16, y12 = 1}; full group size = 3456; print automorphism group; [woof] type [12,4,6]; find 2-cyclic codes; [a] config 6,6 :: {01} : {q_z_6 = 1}; bound q_z_4, q_6_z; type [16,7,6]; show mu4 != 0; [mu4] config 12,4 :: {01}; infer sub10 = 16; [woof] incorporate [woof] below [mu4] via sub10; dump; at [woof->a]; bound y*, [x*]; accept (tables only) inputs/code.data1; accept (tables only) inputs/code.data; accept inputs/code.data1; type [24,7,10]; show mu1 = 0; print config;;print config;print config;printconfig; print time used; set homebrew; type [72,36,16_4]; bound y*, [x*]; (* Each line should look like y_i = nonnegative integer. *); random weight enumerator(n = 20, k = 8, div = 4, modulus = 8, count = 100); goto (*next*); This line does not get executed!; (* next *); type [3,1,2_2]; |-> tex/code.tex \block{Plans} As should be obvious, there are many ways in which the program could be improved. We list first some of the most obvious, with comments. \begin{itemize} \item The program could be revised to allow for an arbitrary finite base field (or ring). Although worthwhile, this is likely to be a stupendous project, as almost every aspect of the program would have to be revised. The author is interested in collaboratively pursuing this expansion with one or more other persons. A good first step would be to write just enough code to see if something new can be proved about ternary codes using split linear programming. \item Finish the included provisional implementation of the simplex algorithm and eliminate the use of CPLEX. It is not clear how hard this will be. \item Find new methods. For example, for partitions with two parts, can one use the split weight enumerator to get closed-form inequalities involving the variables $y_i$? \item Rationalize, restructure, and simplify the language and code so as to make it more readable. The importance of this should not be underestimated, as it is the readability of the code which governs the ability of other people to verify the correctness of the claims made in this report. \end{itemize} \midhead{Other projects} \par\noindent \circno1\ Simonis has pointed out that the automorphism group of a configuration can be used to reduce the size of the associated linear programming problem. Implementing this would have significant benefits. \vspace{0.1in} \par\noindent \circno2\ Within reason, convert to ``generic C++''. In particular, reduce reliance on the GNU C++ Library, and make use of the Standard Template Library (STL) where possible. Don't copy sort code from the GNU C++ Library. Use private member functions where appropriate. Do not use \verb|const_cast|. \vspace{0.1in} \par\noindent \circno3\ For codes whose dimension exceeds half their length, split linear programming problems should be automatically translated into problems about the dual code, because this greatly improves the numerical conditioning of the problem. This is at present done only for the {\tt no} and {\tt test} commands. \vspace{0.1in} \par\noindent \circno4\ At present we do a unique sort on the list of main constraints generated by the split linear programming method. In some cases this significantly reduces the length of the constraint file. Why? This is a rather fundamental question. Would it be better to turn off the sort most of the time? This is a minor practical question. \vspace{0.1in} \par\noindent \circno5\ Unnamed configurations should not be saved when a code type is left, but to implement this one has to keep track of logical relationships which use unnamed intermediaries. \vspace{0.1in} \par\noindent \circno6\ Systematically propagate constraints. The current approach is haphazard and poorly documented. \vspace{0.1in} \par\noindent \circno7\ Clean up the god-awful messes necessitated by the compiler's flaky template instantiation. These have gotten worse and worse. \vspace{0.1in} \par\noindent \circno{8}\ Check the correctness of the two key routines {\tt Isomorphic} and \verb|find_automorphism_group| (for \verb|vertex_colored_graph|'s) which invoke {\tt nauty}. \vspace{0.1in} \par\noindent \circno{9}\ Use decent algorithms for working with permutation groups. \vspace{0.1in} \par\noindent \circno{10}\ Add the capability of subdividing along dual local ({\tt z}) variables. \vspace{0.1in} \par\noindent \circno{11}\ I had planned to rewrite {\tt disect} according to the following plan: \begin{alphalist} \item Invoke m4 as before to get .infile. \item Read .infile into memory (x). \item Read through x, to compile a list of all files and compute their lengths. Allocate space (y) in memory for them. \item Build y from x. Delete x. \item For each file f, open and ask OS for length(f). If length(f) has changed, simply write y.f to f. Otherwise, do a side-by-side comparison, y.f vs. f, block by block. If identical, make no change to f. Otherwise, start writing f at the changed block. \item Disect should create directories and subdirectories as needed. \end{alphalist} \midhead{Minor issues and proposed changes} \par\noindent \circno{A}\ Program output should be automatically folded to split long lines. \vspace{0.1in} \par\noindent \circno{B}\ Make it impossible to crash the program by entering anomalous commands. \vspace{0.1in} \par\noindent \circno{C}\ Investigate memory usage by the program. Some modest changes should substantially reduce memory usage. \vspace{0.1in} \par\noindent \circno{D}\ The {\tt bound} command will not print out values using the maximum available accuracy. To fix this, the class \verb|opt_card| should somehow allow for {\tt Quad} precision min and max. \vspace{0.1in} \par\noindent \circno{E}\ One could easily add a ``{\tt verify bound}'' command to verify the assertion of the last {\tt bound} command. \vspace{0.1in} \par\noindent \circno{F}\ Check for two {\tt Split} processes running concurrently in the same directory. This can cause strange results and should not be allowed. \vspace{0.1in} \par\noindent \circno{G}\ Implement configuration-list versions of {\tt via variable split}, {\tt via varying}, and {\tt deduce}. \vspace{0.1in} \par\noindent \circno{H}\ The following bug in {\tt libg++} has been reported to \verb|bug-lib-g++@prep.ai.mit.edu|, however {\tt libg++} is no longer supported. This bug calls into question the reliability of all code which uses the ``{\tt contains}'' method. \begin{verbatim} // The following program prints 1. Shouldn't it print 0? #include #include main( ) { String swine = "y=5"; String op = "="; cerr << swine.contains(Regex(op), 0) << "\n"; } \end{verbatim} \par\noindent Similarly, the following code prints 0: \begin{verbatim} #include #include main( ) { static Regex pound_config( "\\[[a-zA-Z_0-9]+#\\]" ); String commandx = "[x#]"; cerr << commandx.contains( pound_config, -1 ) << "\n"; } \end{verbatim} \par\noindent Another example: \begin{verbatim} #include #include main( ) { static Regex brack( "\\[" ); String s = "P([3_2_2.a])"; cerr << s.contains( brack, 0 ) << "\n"; cerr << s.contains( brack, 1 ) << "\n"; cerr << s.contains( brack, 2 ) << "\n"; cerr << s.contains( brack, 3 ) << "\n"; } \end{verbatim} \par\noindent The following bug has been reported to \verb|bug-g++@prep.ai.mit.edu| (8/22/96). The following code yields internal compiler error $107$. \begin{verbatim} #include main( ) { static int noptions = 3; static Regex option_pats[noptions] = {"a", "b", "c"}; }; \end{verbatim} \newpage \part{Results on specific codes} This part is a program which proves many specific results about codes. There are seven places (sections \ref{some-unital-section}, \ref{38-27-section}, \ref{40-11-16-section}, \ref{73-12-32}, \ref{section-56-71}, \ref{section-72-80}, \ref{menagerie-section}) where we use arguments which have not yet been completely formalized in the language. These have to be checked by hand. (Also, due to an undiagnosed problem with the ``{\tt auto projection}'' option, one line under \verb|type [142,7,70_2]| must also be checked by hand.) The paper [.jaffe optimal binary 30.] naturally precedes this part of the paper. We include a number of tables which give upper bounds for the minimum distance of codes. These were constructed by first copying the tables of Brouwer and Verhoeff, adjoining a few other previously known results, and then adjoining our new results. For the tables through $n = 36$, we check the lower bounds as well as the upper bounds. We have not included references for the lower bounds. Note that Brouwer and Verhoeff's table gives both upper and lower bounds (with references). All of the tables given here are part of the program, and so each result is independently verified. For display in this paper, certain informational subscripts and superscripts have been added to the entries of the table. These do not in any way effect execution, and correspondingly may not be completely reliable. They in general do not reflect any results of other people obtained after about January 1995 or results of other people obtained before then but unknown to the author. Corrections will be gratefully accepted. A question mark as a pre-superscript indicates that the given upper bound is not known to be sharp. References are given as post-superscripts. These have been copied from [.brouwer verhoeff 1993.], and reflect only ``main results''. Often a single such result yielded many corollaries, but we do not cite the reference for each such corollary, although credit is in fact due. A diamond as a pre-subscript indicates that the bound is new. In most cases the new bound is just one better than the old bound, but in several cases $$(n,k) = (42,20), (53,12), (102,13), (168,12), (168,14),$$% the minimum distance $d$ has been improved by two. \newpage \begin{svb} data_comment( ![ \block{Some doubly even codes that do not exist} The results of this section are curiously independent of the rest of the program. In all cases (except those listed in this section), where we know that a doubly even $[n,k,d]$ code does not exist, and $4 \mid d$, we know that there are no $[n,k,d]$ codes at all. (This statement does not take account of trivial cases -- cf.\ \verb|codetable::not_exist(int, int, weightlist)|). ]! ) accept inputs/code.data.eights; no [11, 5, 4_4]; no [13, 6, 4_4]; no [27, 13, 8_4]; no [29, 14, 8_4]; no [35, 13, 12_4]; no [34, 17, 8_4]; no [38, 15, 12_4]; no [43, 13, 16_4]; no [46, 15, 16_4]; no [50, 25, 12_4]; no [51, 19, 16_4]; no [53, 20, 16_4]; no [54, 15, 20_4]; no [51, 25, 12_4]; no [59, 19, 20_4]; no [61, 20, 20_4]; no [65, 18, 24_4]; no [67, 19, 24_4]; no [69, 20, 24_4]; no [59, 25, 16_4]; no [66, 24, 20_4]; no [69, 34, 16_4]; no [73, 18, 28_4]; no [75, 19, 28_4]; no [77, 20, 28_4]; no [81, 18, 32_4]; no [84, 20, 32_4]; no [73, 23, 24_4]; no [74, 31, 20_4]; no [79, 28, 24_4]; no [82, 24, 28_4]; no [83, 39, 20_4]; no [84, 25, 28_4]; data_comment( ![ \def\simonis1896ref{\protect{[.simonis 1896 unique.]}} \def\enchevareference{\protect{[.encheva 1992 report.]}} \def\dodunekovenchevareference{\protect{[.golay subcodes 1993.]}} \def\tilborgreference{\protect{[.tilborg griesmer 1980.]}} \block{Classification of various codes at the Griesmer bound (most due to van Tilborg \tilborgreference)} In this section we classify codes with various parameters at the Griesmer bound: $[35,4,18]$, $[38,4,20]$, and $[42,4,22]$. All of these (except the $[35,4,18]$, $[38,4,20]$, and $[42,4,22]$) results are special cases of more general results which may be found in [.tilborg griesmer 1980.]. ]! ) type [35,4,18]; [1] config 1,3,2,3,1,3,2,3,3,2,3,1,3,2,3 : {100101101001011,010101011010101, 001100111100110,000011111111000} :: {y18 = 12, y20 = 2, y24 = 1}; [2] config 1,3,2,3,2,2,2,3,3,2,2,2,3,2,3 : {100101101001011,010101011010101, 001100111100110,000011111111000} :: {y18 = 11, y20 = 3, y22 = 1}; [3] config 2,2,2,3,2,2,2,3,2,3,2,2,3,2,3 : {100101101001011,010101011010101, 001100111100110,000011111111000} :: {y18 = 10, y20 = 5}; CLASSIFICATION_OF([base], x_18|x99|x4455, ![[1], [2], [3]]! ) status: classified, weights = {18,20,22,24}; type [38,4,20]; config from x_20|x_10_10; show y20 = 14, y24 = 1; [a] config from x5555|x22223333; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 14t^20 + t^24) no [41,4,22]; type [42,4,22]; config from x_22; show y22 = 12, y24 = 3, y28 = 0; [a] config from x_10_12|x4666|x23333332; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 12t^22 + 3t^24) [23_7_9] type [23,7,9]; load constraints by parity check from [24_7_10]; data_comment( ![ \def\simonis1987ref{\protect{[.simonis 1987 25_15_6.]}} \def\simoniswagnerref{\protect{[.simonis wagner unique.]}} \block{Classification of projective $[27,6,12]$ codes} ]! ) [15_5_6proj] type [15,5,6]{mu1 = 0, mu2 = 0}; [8] config from x8; [base] <--> [x1..22] := Build( [15_5_6proj], [8] ); [27_6_12proj] type [27,6,12]{mu1 = 0, mu2 = 0}; kill y27, y25; [24] config 27 ::: {y24 != 0}; [24x] config from x_24|x_12_0|x660; [24x] <--> [x1..3] := Build( [27_6_12proj], [24x] ); [26] config 27 ::: {y26 != 0}; [26x] config from x_26|x_11_1|x471; [x4] := Build( [27_6_12proj], [26x] ); via building [26x] implies [x4]; [else] config 27 ::: {y24 = 0, y26 = 0}; [else] <--> [x5..60] := Unresidue( [27_6_12proj], [else], [15_5_6proj.x1..22] ); via variable split [base] = [24] or [26] or [else]; classification of [base]: [x1..60]; data_comment( ![ \block{Some unital $[28,\geq 7,10]$ codes whose dual codes may contain designs} \label{some-unital-section} This section contains a partial classification of the codes which are the codes of $2-(28,4,1)$ designs of rank $20$ or $21$. The classification is partial because of the following: \begin{itemize} \item There may be some codes listed which are not the codes of such designs. \item There are some forced gullibilities (``{\tt ??}''), although the validity of the forced commands is trivially checked. \item We rely on facts from design theory. \end{itemize} This material is part of joint work with Tonchev [.jaffe tonchev rank 20.], which contains a classification of all $2-(28,4,1)$ designs of rank $20$ and $21$. ]! ) [28_5_10deu] type [28,5,10_4]{y28 = 1}; [1] config 1,3,1,2,3,2,1,2,3,2,2,3,2,1 : {10001100111100,01001100110011,00101001010101,00010101011010,00000011111111}; [2] config 1,1,2,1,2,2,3,1,2,2,3,4,1,1,2 : {100001100111100,010010101011010,001011001101001,000111100001111, 000000011111111}; [3] config 1,2,1,2,1,2,1,2,1,2,1,2,1,2,5,2 : {1001011001101001,0101010101010101,0011001100110011,0000111100001111, 0000000011111111}; [4] config 4,2,2,2,2,2,2,2,2,2,2,2,2 : {1000000001111,0100101101001,0010101011010,0001100111100,0000011111111}; [5] config 1,1,1,1,1,1,3,3,1,3,1,3,1,3,3,1 : {1001011001101001,0101010101010101,0011001100110011,0000111100001111, 0000000011111111}; CLASSIFICATION_OF([base], x_28|x_12, ![[1], [2], [3], [4], [5]]!) [28_6_10deu] type [28,6,10_4]{y28 = 1}; [1] config 1,3,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1 : {10000111100011111111000,01000111100011110000111,00100110001100110011001, 00010101001010101010101,00001100100110010110011,00000000011111111111111}; [2] config 1,1,2,1,2,1,2,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1 : {1000011100011111111000,0100010101010101010101,0010001001001011010010, 0001011001100110011001,0000100101100111100110,0000000011111111111111}; [3] config 1,1,2,1,2,2,1,1,1,1,1,1,1,2,1,1,1,1,2,1,2,1 : {1000011110001111111100,0100010100101010101010,0010001010100101101001, 0001011000110011001101,0000100110110011110010,0000000001111111111111}; [4] config 1,1,1,1,1,1,2,1,2,1,1,2,1,1,2,1,1,2,1,2,1,1 : {1001010110001110110101,0101010011011011011001,0011000101010101010011, 0000110101010010101011,0000001010010010010100,0000000000111111111111}; [5] config 1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 : {1001011000011110011000011,0101010010110011001100110,0011001010101101001011010, 0000111010101010110101010,0000000100101010101010101,0000000001111111111111111}; CLASSIFICATION_OF([base], x_28|x_12|x_4_8, ![[1], [2], [3], [4], [5]]!) [28_7_10deu] type [28,7,10_4]{y28 = 1}; [1] := {1000010110110001011000101100,0100010101000010100111011100, 0010000011100100110001110011,0001000011010110101101001010, 0000110011000001101100110110,0000001111110000001111111111, 0000000000001111111111111111}; [2] := {1000010110110001011000100011,0100010101000010100111010011, 0010000011100100110001110011,0001000011010110101101001010, 0000110011000001101100110110,0000001111110000001111111111, 0000000000001111111111111111}; [3] := {1000010110110101001010100100,0100010101000110110101010100, 0010000011100100110001110011,0001000011010110101101001010, 0000110011000001101100110110,0000001111110000001111111111, 0000000000001111111111111111}; [4] := {1000010111100111100011101101,0100010100010100011100011101, 0010010010010010011101100011,0001010001010001011011011010, 0000110000110000110110110110,0000001111110000001111111111, 0000000000001111111111111111}; CLASSIFICATION_OF([base], x_28|x_12|x_6_6|x2226, ![[1], [2], [3], [4]]!) type [28,8,10_2]{y28 = 1} /partition_of_word_by_dual_words(weight = 12, dual_weight = 4), dual_may_be_code_of_design(t = 2, k = 4, lambda = 1), doubly_even_part_is_subcode/; [128] config 28 ::: {div4 = 128}; via building [28_7_10deu:{1,2,3,4}] implies ; ??classification of [128]: ; [64] config 28 ::: {div4 = 64}; via building [28_6_10deu:{1,2,3,4,5}] implies ; ??classification of [64]: ; ??classification of [base]: ; type [28,7,10_2]{y28 = 1} /partition_of_word_by_dual_words(weight = 12, dual_weight = 4), dual_may_be_code_of_design(t = 2, k = 4, lambda = 1), doubly_even_part_is_subcode/; [a] := {1000010111100111100011101101,0100010100010100011100011101, 0010010010010010011101100011,0001010001010001011011011010, 0000110000110000110110110110,0000001111110000001111111111, 0000000000001111111111111111} :: {y12 = 63, y16 = 63, y28 = 1}; [b] config 1,1,1,1,2,1,1,1,1,2,2,1,1,2,1,1,2,2,1,1,1,1 : {1001001010001001101010,0101001010001110111001,0011000000000111101100, 0000100001011100100011,0000011001011011101100,0000000111000111110000, 0000000000111111111111} :: {y10 = 24, y12 = 15, y14 = 48, y16 = 15, y18 = 24, y28 = 1}; [c] config 1,3,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2 : {10000001000010110011101,01000001000010111100010,00100001101111001100001, 00010011101011010101111,00001010000111101001001,00000111100011111111000, 00000000011111111111111} :: {y10 = 24, y12 = 15, y14 = 48, y16 = 15, y18 = 24, y28 = 1}; [d] config 2,2,2,2,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1 : {1000001100101000111010,0100001100101011000101,0010001101110011000011, 0001001101001111001100,0000101001011010101010,0000010101100101011010, 0000000011111111111111} :: {y10 = 24, y12 = 15, y14 = 48, y16 = 15, y18 = 24, y28 = 1}; [e] config 2,2,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 : {100000010000101000111010,010000010000101011000101,001001010110101010011111, 000101000101011001011100,000011010011001111001100,000000110000111111110000, 000000001111111111111111} :: {y10 = 20, y12 = 15, y14 = 56, y16 = 15, y18 = 20, y28 = 1}; [f] config 2,2,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 : {100000000010101100101011,010000000010101111010100,001000100111000101101001, 000100010100110110101010,000010110011001111001100,000001110000111111110000, 000000001111111111111111} :: {y10 = 20, y12 = 15, y14 = 56, y16 = 15, y18 = 20, y28 = 1}; [g] config 4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 : {1000000000000000011111111,0100100110110100101010000,0010100000101010110010011, 0001100110011001111001100,0000010100011101010101010,0000001010011010101011010, 0000000001111111111111111} :: {y10 = 24, y12 = 15, y14 = 48, y16 = 15, y18 = 24, y28 = 1}; [h] config 1,1,1,1,1,1,2,1,2,1,1,2,1,1,2,1,1,2,1,2,1,1 : {1001010100001100011010,0101010001011001110110,0011000101010101010011, 0000110101010010101011,0000001000010000111011,0000000010000010101111, 0000000000111111111111} :: {y10 = 20, y12 = 31, y14 = 24, y16 = 31, y18 = 20, y28 = 1}; [128] config 28 ::: {div4 = 128}; CLASSIFICATION_OF([128], x_28|x_12|x_6_6|x2226, [a]) [64] config 28 ::: {div4 = 64}; { via building [28_6_10deu:{1,2,3,5}] implies ; via building [28_6_10deu:4] implies [a], [h] }; ??classification of [64]: [h]; [32] config 28 ::: {div4 = 32}; via building [28_5_10deu:{1,2,3}] implies ; via building [28_5_10deu:4] implies [a], [b], [c], [d], [e], [f], [g], [h]; via building [28_5_10deu:5] implies [a], [h]; ??classification of [32]: [b], [c], [d], [e], [f], [g]; ??classification of [base]: [a], [b], [c], [d], [e], [f], [g], [h]; data_comment(![\def\heijnenref{\protect{[.heijnen.]}} \def\hyttref{\protect{[.helleseth ytrehus 33_8_14.]}}]!) no [31,7,14]; [33_8_14] type [33,8,14]; CREDIT(existence due to Said and Palazzo, said palazzo) DHIDE( ![ Neither [a] nor [b] is cyclic. ]! ) [a] := {100000000111101100011100101101000,010000000100111011010110010100011, 001000001100010101001101010010111,000100001110110110000000100111110, 000010001101110010111011101110011,000001000011110001100111100001110, 000000100000001111100000011111111,000000010000000000011111111111110}; [b] := Act( { (1,2)(3,5)(7,9), (1,3)(2,5)(6,8), (1,2)(3,9)(4,6)(5,7) }, {000010011,000010100,000100101,000111110,001010111,010011111,111011111}); disjoint [a], [b]; status: realizable, weights = 14_2 - {28..33}, constraints = {89 <= y14 <= 99, 62 <= y16 <= 95, 6 <= y18 <= 44, 20 <= y20 <= 52, 9 <= y22 <= 30, y24 <= 5, y26 <= 2, mu3 = 0, 96 <= div4 <= 136}; [29_6_13] type [29,6,13]; load constraints by parity check from [30_6_14]; data_block(There is no $[34,9,14]$ code (Heijnen \heijnenref)) type [34,9,14_2]; { config from x_14; show y34 = 0, y22 != 0; at [base]; =config 22,12 : {10}; config from x_11_3; show mu4 != 0; [mu4] config 30,4 :: {01}; [30_6_14] incorporate [30_6_14] below [mu4] via sub10; @[30_6_14->base] infer y30 != 0; via lp [base] = }; no [34,9,14]; type [36,10,14_2]; status: constraints = {176 <= y14 <= 247, 125 <= y16 <= 321, 45 <= y18 <= 336, 72 <= y20 <= 364, 63 <= y22 <= 243, y24 <= 68, y26 <= 24, y28 <= 10, y30 <= 4, y32 <= 2, y34 <= 1}; data_comment( ![ \def\dodunekovref{\protect{[.dodunekov ytrehus 1987.]}} \block{Classification of $[36,8,16]$ codes} These have been classified up to weight enumerator by Dodunekov et.\ al.{\ }\dodunekovref. ]! ) [32_5_16] type [32,5,16]; [1] config 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 : {1001011001101001, 0101010101010101,0011001100110011,0000111100001111,0000000011111111} :: {1 + 30t^16 + t^32}; [2] config 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2 : {100101011010101001010110,010101010101101010101010, 001100001111111100001100,000011001100110011001111, 000000110011001100111111} :: {1 + 29t^16 + 2t^24}; [3] config 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2 : {1001010101101010100101010110,0101010101010110101010101010, 0011000011001100110011110011,0000110011110011000011001111, 0000001111111111111111000000} :: {1 + 27t^16 + 4t^20}; [4] config 1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1 : {100001100111100110000110011110,010010101011010101001010101101, 001011001101001011010011001011,000111100001111111100001111000, 000000011111111111111110000000} :: {1 + 23t^16 + 8t^18}; [5] config 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1 : {1001011001101001011010011001011,0101010101010101101010101010101, 0011001100110011110011001100110,0000111100001111111100001111000, 0000000011111111111111110000000} :: {1 + 15t^16 + 16t^17}; [6] config 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 : {10010110011010010110100110010110,01010101010101011010101010101010, 00110011001100111100110011001100,00001111000011111111000011110000, 00000000111111111111111100000000} :: {1 + 31t^16}; at [base]; config from x_16|x88; reduce variable set; show x3337 = 0; config from x4444; via building [current] implies [1..6]; classification of [base]: [1..6]; type [36,8,16]; CREDIT(![existence due to Dodunekov, Helleseth, Manev, and Ytrehus]!, dodunekov ytrehus 1987) [a] := Cyclic( {12,6,6,12}, 36, 8, 01010100111000100011111011011 ); [b] := Cyclic( {12,12,6,6}, 36, 8, 0001011010000011101000110111111 ); disjoint [a], [b]; at [base]; show y16 = 153, y20 = 72, y24 = 30; show (joint:0) jy24d4 != 0; show mu4 != 0; [mu4] config 32,4 :: {01}; [32_5_16] incorporate [32_5_16] below [mu4] via sub10; via building [32_5_16->2] implies [a], [b]; ??classification of [base]: [a], [b]; (* This is justified, since jy24d4 != 0, and [32_5_16->2] is the only [32,5,16] code having a word of weight 24. *); STATUS_RE_CLASS_WE(1 + 153t^16 + 72t^20 + 30t^24) data_block(Table for codes of length $32$ through $36$) type [31,25,4_2]; status: weights = 4_2 - {30}; type [36,17,10_2]; =[mu8] config 28,8 :: {01}; [28_10_10] incorporate [28_10_10] below [mu8] via sub10; via extension [28_10_10->{a,b,c,d*,e*,f,g*}] implies ; classification of [mu8]: ; no [36,17,10]; type [37,5,18_2]; status: weights = 18_2 - {34,36}; DHIDE( ![ Not cyclic: ]! ) [39_12_14] type [39,12,14]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel reed solomon) [a] := { 111100101000011111011010011000000000000, 000110111001101100110111010100000000000, 110101111101100011000001110010000000000, 010110011111010010111010100001000000000, 001011001111000111011101010000100000000, 101101000011111010110100110000010000000, 100010010101100001110011100000001000001, 001011110110110010111101100000000100001, 011111010001000010001100110000000010001, 100100011111110111010110010000000001001, 011010001000111001100011010000000000101, 101010100101101110011110110000000000011}; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel reed solomon) status: realizable; unset auto group computation; type [33,23,5]; credit: existence due to J. B. Shearer; [a] := {010100101010000000000000000000000, 110001110000000000000000000000000,011001000001100000000000000000000, 110100100001010000000000000000000,110101001001001000000000000000000, 111110000000000000000000000000000,111001000000000110000000000000000, 100100100000000101000000000000000,111100101000000100100000000000000, 101101000001000100010000000000000,110000101001000100001000000000000, 101001001100000000000000000000000,001101000000000000000110000000000, 100000101000000000000101000000000,111101101000000000000100100000000, 000001100001000000000100010000000,001100101001000000000100001000000, 110101100000000100000100000100000,101100001000000100000100000010000, 001000000001000100000100000001000,011101100001000100000100000000100, 010001001001000100000100000000010,101001101001000100000100000000001}; credit: existence due to J. B. Shearer; status: realizable; type [37,22,7]; credit: existence due to J. B. Shearer; [a] := {1110000111100000000000000000000000000,1101010110000001100000000000000000000, 1111111000000000000000000000000000000,1000110101000000011000000000000000000, 1001100110011000000000000000000000000,0110100100010000000110000000000000000, 0111000000000001010101000000000000000,0100000111010001010100100000000000000, 0101010101010100000000000000000000000,0100110110000000000000011000000000000, 1110000100000001010000010100000000000,0110010011010001010000010010000000000, 0101110000000001000100010001000000000,1010110100010001000100010000100000000, 0001100010000000010100010000010000000,0010000111000000010100010000001000000, 0010110011010010000000000000000000000,0011010110000000000000000000000110000, 0000110100000001000100000000000101000,1011100101000001000000010000000100100, 0001110001010001000000010000000100010,1101000110010000000100010000000100001}; credit: existence due to J. B. Shearer; status: realizable; type [47,36,5]; credit: existence due to J. B. Shearer; [a] := {10010100001100000000000000000000000000000000000, 10010010101010000000000000000000000000000000000, 11111000000000000000000000000000000000000000000, 11010010000001100000000000000000000000000000000, 00110110100001010000000000000000000000000000000, 11110110001001001000000000000000000000000000000, 00100100101001000100000000000000000000000000000, 01010110101001000010000000000000000000000000000, 10100110110000000000000000000000000000000000000, 11100100000000000001100000000000000000000000000, 10110100100000000001010000000000000000000000000, 11010010001000000001001000000000000000000000000, 11100000101000000001000100000000000000000000000, 00000010101000000001000010000000000000000000000, 01100000000001000001000001000000000000000000000, 01010000100001000001000000100000000000000000000, 11100010100001000001000000010000000000000000000, 10100000001001000001000000001000000000000000000, 10000110001001000001000000000100000000000000000, 10010100101001000001000000000010000000000000000, 11000111000000000000000000000000000000000000000, 10100100000000000000000000000001100000000000000, 01010010000000000000000000000001010000000000000, 01110000100000000000000000000001001000000000000, 00010100100000000000000000000001000100000000000, 01000100001000000000000000000001000010000000000, 00100010001000000000000000000001000001000000000, 11100010000001000000000000000001000000100000000, 10010000001001000000000000000001000000010000000, 11000100101001000000000000000001000000001000000, 01110100000000000001000000000001000000000100000, 10000110100000000001000000000001000000000010000, 00110100101000000001000000000001000000000001000, 10010100000001000001000000000001000000000000100, 00100110100001000001000000000001000000000000010, 00110110001001000001000000000001000000000000001}; credit: existence due to J. B. Shearer; status: realizable; type [35,16,9]; credit: existence due to J. B. Shearer; [a] := {01010101001010010101000000000000000,11110000011111000000000000000000000, 01010110001100100000110000000000000,11001100011000111000000000000000000, 01100111000110100000001100000000000,01110010010000010000101010000000000, 10000001011100110100101001000000000,11111111100000000000000000000000000, 00011111001100110100000000110000000,01001111010100010000001000101000000, 11111010001110100100101000100100000,10101010010100100110000000000000000, 10010111011100000100100000000011000,01000100010110110100001000000010100, 00110001010010100000100000100010010,10000000010010000100101000100010001}; credit: existence due to J. B. Shearer; status: realizable; type [33,12,11]; credit: existence due to J. B. Shearer; [a] := {001101101001101001001100000000000,101011010101010100101010000000000, 111110000001111110000000000000000,100111011001011001000001100000000, 110001110001110001110000000000000,011010111000111001000000011000000, 110001001101010100000001010100000,111111111110000000000000000000000, 000111101100100100101000000011000,000010101001110101000001000010100, 000001000001111100101000010010010,101001000101001001001001010010001}; credit: existence due to J. B. Shearer; status: realizable; [35_9_14] type [35,9,14]; (* to be continued later *); CREDIT(existence due to Piret, piret good block codes) [a] := Cyclic( {17,17}, 35, 9, 01111000000111101000001101001011001 ); status: realizable; type [45,16,13]; CREDIT(existence due to Dougherty and Janwa, dougherty janwa radius) [a] := Cyclic(1, 45, 16, 10110000111000100011100001101, 111110011100000010001000100000000000000000011); CREDIT(existence due to Dougherty and Janwa, dougherty janwa radius) status: realizable; type [36,14,11]; credit: existence due to Masakatu Morii; [a] := {100000000000001111111111000000000000,010000000000000110000001101110010011, 001000000000000010011110000010011011,000100000000001100001000000111101011, 000010000000000011010011010101100100,000001000000000100010100101010101110, 000000100000001111000100100101000110,000000010000001110010000011000111011, 000000001000001011001010100110110000,000000000100000101101001101001001010, 000000000010000100101110001100000111,000000000001001010000111001000110110, 000000000000100001101000011110101100,000000000000010111100101010110000101}; credit: existence due to Masakatu Morii; status: realizable; no [33,12,12]; no [35,13,12]; no [33,12,12]; type [34,12,12_2]; show (joint:5) y34 = 0 ; status: weights = {12,14,16,18,20,22,24,26,28,30,32}; type [35,7,16]; kill jy20y20y28 ; psheadx(90) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 psnext n=31, k >= 2: 20, 17, 16, 16, 15, 13coderef(tilborg 1981 discrete), 12, 12, 12, 11, 10, 9coderef(prins thesis), 8, 8, 8; sn n=32, k >= 2: 21, 18, 16, 16, 16, 14, 13, 12, 12, 12, 10, 10, 8-9, 8, 8; sn n=33, k >= 2: 22, 18, 16, 16, 16, 14, 14, 12coderef(heijnen), 12, 12, 11coderef(hill traynor), 10, 9-10, 8-9, 8; sn n=34, k >= 2: 22, 19, 17, 16, 16, 15coderef(tilborg 1981 discrete), 14, 13, 12, 12, 12, newd1()10, 10, 9-10, 8-9; sn n=35, k >= 2: 23, 20, 18, 16, 16, 16, 15, 14, 12-13, 12, 12, newd1()11, newd1()10, 10, 9-10; sn n=36, k >= 2: 24, 20, 18, 17, 16, 16, 16, 14, 13-14, 12-13, 12, 12, newd1()11, newd1k(16)10, 10; pstail pshead(90) // k = 17 18 19 20 21 22 23 24 25 26 27 28 29 30 psnext n=31, k >=17: newd()7, newd1k(21)6, 6, 6, 5, 4, 4, 4, 4, 3, 2, 2, 2, 2; sn n=32, k >=17: 8, 6-newd1()7, newd()6, 6, 6, 5, 4, 4, 4, 4, 2, 2, 2, 2; sn n=33, k >=17: 8, 7-8, 6-newd1()7, newd()6, 6, 6, 5, 4, 4, 4, 3, 2, 2, 2; sn n=34, k >=17: 8, 8, 7-8, 6-newd1()7, 6, 6, 6, 4-5, 4, 4, 4, 3, 2, 2; sn n=35, k >=17: newd()8, 8, 8, 7-8, 6-7coderef(brouwer linear programming bound), 6, 6, 5-6, 4-5, 4, 4, 4, 3, 2; sn n=36, k >=17: 8-newd1()9, newd()8, 8, 8, 7-8, 6-7, 6, 6, 5-6, 4-5, 4, 4, 4, 3; pstail pshead(80) // k = 31 32 33 34 35 psnext n=32, k >=31: 2; sn n=33, k >=31: 2, 2; sn n=34, k >=31: 2, 2, 2; sn n=35, k >=31: 2, 2, 2, 2; sn n=36, k >=31: 2, 2, 2, 2, 2; pstail \vspace{0.12in} \begin{svb} |-> tex/code.tex, inputs/code.data unset lower bound check; data_comment(![\def\tonchevquadricsref{\protect{[.tonchev designs codes quadrics.]}} \block{Classification of self-complementary $[36,7,16]$ codes (Tonchev \tonchevquadricsref)} ]! ) type [36,7,16]{y36=1}; [1] := Cyclic( {7,7,7,7,7}, 36, 7, 000111000101100101010011011101011111 ); [2] := {100001000110010101111101000101010001, 010001000101101001110010111010100001,001000011100001100110001111110001100, 000100010011001101010110010110010101,000011001100111101101000011000010110, 000000111111111100000000001111111111,000000000000000011111111111111111111}; [3] := Cyclic( {14,14,7}, 36, 7, 001011011001000101111101110100110101 ); [4] := {100001000100111000010011100011101101, 010001000111000100011100011100011101,001001011000100101100010011101100011, 000101010110110101011011011011011010,000011001101101100110110110110110110, 000000111111111100000000001111111111,000000000000000011111111111111111111}; { at [base]; =config 36 : {1}; show y17 = 0, y18 = 0, y19 = 0; config from x_16|x_6_10|x2446; via building [current] implies [1], [2], [3], [4]; disjoint [1], [2], [3], [4] }; classification of [base]: [1], [2], [3], [4]; data_comment(\block{There is no $[38,27,6]$ code}\label{38-27-section} This section contains an informal argument which has not yet been formalized in the language.) type [38,27,6_2]; show mu14 >= 2; data_comment(![ Let $C$ be an even $[38,27,6]$ code. Consider $w \in C^\perp$ of weight $14$. The subcode of $C$ disjoint from it is a $[24,14,6]$ code, which we know [.jaffe optimal binary 30.] must have a word of weight $24$. Thus for each such $w$, we can find some word of weight $24$ which is in $C \cap C^\perp$. In particular, we see that $C \cap C^\perp$ has at least two words of weight $24$. There are exactly three plausible ways in which these two words may intersect. We proceed to show that none of these may happen, and hence that no such code $C$ exists. ]!) !config 12,12,12,2 : {1100,0110} : {1100,0110}; !config 10,14,10,4 : {1100,0110} : {1100,0110}; !config 8,16,8,6 : {1100,0110} : {1100,0110}; ??classification of [base]: ; data_comment(\block{There is no $[40,11,16]$ code}\label{40-11-16-section}) [32_5_16x20x24] type [32,5,{16,20,24}]; [a] config 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2 : {100101011010101001010110,010101010101101010101010, 001100001111111100001100,000011001100110011001111, 000000110011001100111111} :: {y16 = 29, y20 = 0, y24 = 2}; [b] config 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2 : {1001010101101010100101010110,0101010101010110101010101010, 0011000011001100110011110011,0000110011110011000011001111, 0000001111111111111111000000} :: {y16 = 27, y20 = 4, y24 = 0}; [c] config 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 : {10010110011010010110100110010110,01010101010101011010101010101010, 00110011001100111100110011001100,00001111000011111111000011110000, 00000000111111111111111100000000} :: {y16 = 31, y20 = 0, y24 = 0}; CLASSIFICATION_OF([base], x_16|x88|x4444, ![[a], [b], [c]]!) type [32,6,{16,20,24}]; via lp [current] = ; [36_8_16x20x24] type [36,8,{16,20,24}]; at [base]; show mu4 != 0; [mu4] config 32,4 :: {01}; [32] incorporate [32_5_16x20x24] below [mu4] via sub10; at [base]; show y24 != 0; config 24,12 : {10}; show z_0_4 != 0; data_comment( The above calculation shows that there is a word of weight $24$ disjoint from a dual word of weight $4$. This justifies the following line: ) ??[base] = [32->a]; [1] := {100000100001000111001111100110101010, 010000010100010000111111100110100101,001001110000010101011111111001110011, 000101000101000011110101001010110011,000011110000000010100101110011001111, 000000001100001110011001110000111111,000000000011001100110011111111110000, 000000000000111101010101001111001111}; [2] := {100001110000010100100111100101010101, 010001000101000010111110100110101010,001000100000010111010111101010101100, 000100010101000001111101011001101100,000011110000000011001100110000111111, 000000001100001111110000110011001111,000000000011001100110011111111110000, 000000000000111100111100001100111111}; via building [32->a] implies [1], [2]; disjoint [1], [2]; classification of [base]: [1], [2]; type [40,11,16_2]; { kill y38, ndiv4, y36, y32, y28; show (joint:0) mu4 != 0; [mu4] config 36,4 :: {01}; [36] incorporate [36_8_16x20x24] below [mu4] via sub10; via building [36->1] implies ; via building [36->2] implies ; classification of [base]: }; no [40,11,16]; data_comment( ![ We give some information about $[39,10,16]$ codes, whose existence is unknown. ]! ) type [39,10,16_2]; show (joint, iterate) y30 = 0, y32 = 0, y34 = 0, y36 = 0, y38 = 0, div4 = 1024; status: weights = {16,20,24,28}; type [39,10,16]; status: weights = {16,20,24,28}; data_comment( ![ There is a word of weight $28$, as otherwise (by adjoining the all-ones word) one would obtain a $[39,11,15]$ code, and thence a $[40,11,16]$ code. ]! ) ??show y28 >= 1; show (joint:7) y28 = 2; show y16 = 367, y20 = 414, y24 = 240, y28 = 2, mu4 = 14; config 33,2,2,2 :: {0110,0011}; show x_24_0_2_2 = 0, x_24_2_0_2 = 0, x_24_2_2_0 = 0, x_25_1_1_1 = 0, x_26_0_0_2 = 0, x_26_0_2_0 = 0, x_26_2_0_0 = 0, x_28_0_0_0 = 0 ; kill [current] by x_10_2_2_2 ; data_comment(![ Thus two dual words of weight $4$ can't meet along $2$ bits. ]!) at [base]; ??show jd4d4d4 = 0; STATUS_WE(1 + 367t^16 + 414t^20 + 240t^24 + 2t^28) data_block(Table for codes of length $37$ through $39$) no [38,27,6]; no [38,16,12]; type [38,12,14_2]; kill y38 by x_14; status: weights = {14,16,18,20,22,24,26,28,30,32,34,36}; no [39,13,14]; no [37,9,16]; type [38,9,16_2]; { kill y38, y36, y34 by (x_12_4, x_13_3); show (joint:5) y32 = 0; show (joint:5) y30 = 0 }; status: weights = {16,18,20,22,24,26,28}; kill y26 by (x79, x_8_10, x99, x_9_11, x_10_10, x_11_7, x_12_12); kill jy16y22y28, jy18y18y28, jy18y20y28, jy18y22y22, jy18y22y28, jy18y24y28, jy22y22y22, jy16y18y28, jy18y18y18, jy18y18y22, jy18y24y24 ; show (joint:5) 192 <= y16 <= 225, y18 <= 85, 88 <= y20 <= 206, y22 <= 64, 83 <= y24 <= 102, y28 <= 2, div4 >= 372; infer div4 >= 384; kill jy16y18y24, jy16y22y24, jy18y18y20, jy18y18y24, jy18y20y20, jy18y20y22 ; show (joint:5) y18 = 0, y22 = 0; status: weights = {16,20,24,28}; type [38,9,16]; status: weights = {16,17,20,21,24,28}; type [38,12,14_2]; show (joint:0) y36 = 0; status: weights = 14_2 - {36,38}; type [38,19,10_2]; status: weights = 10_2 - {36}; psheadx(60) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=37, k >= 2: 24, 20, 19, 18, 17, 16, 16, 15coderef(hill traynor), 14, quest1()14, quest1()13, 12, 12, newdquest1()11, newd1()10, quest1()10, newdquest()9, newd()8, 8; sn n=38, k >= 2: 25, 21, 20, 18, 18, 16, 16, 16, quest1()15, 14, quest1()14, newd1()12, 12, quest1()12, newdquest1()11, newd1()10, quest1()10, newdquest()9, newd()8; sn n=39, k >= 2: 26, 22, 20, 19, 18, 17, 16, 16, quest1()16, newd1()14, 14, newdquest1()13, newd1()12, 12, quest1()12, newdquest1()11, newd1()10, quest1()10, newdquest()9; pstail pshead(60) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 psnext n=37, k >=21: 8, quest()8, quest()7, 6, 6, quest()6, newd()4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=38, k >=21: 8, 8, quest()8, quest()7, 6, 6, newd()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=39, k >=21: newd()8, 8, quest()8, quest()8, quest()7, 6, 6, 5coderef(hill traynor), 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; pstail \vspace{0.12in} \begin{svb} data_block(There is no $[42,27,8]$ code) type [42,15,14]{mu1=0, mu2=0, mu3=0, mu4=0, mu5=0, mu6=0, mu7=0, y42=1}; { =config 42 : {1}; config from x_14; kill x_0_14, x_1_13 }; via lp [current] = ; type [42,27,8_2]; via dual nonexistence infer [base] = ; no [42,27,8]; data_block(Table for codes of length $40$ through $45$) no [41,6,20]; no [43,13,16]; no [43,20,12]; no [45,18,14]; [42_8_18] type [42,8,18]; credit: existence due to Blokh and Zyablov [.blokh zyablov.]; kill y41 by x_17_1, y39 by (x_17_1, x_19_1, x_18_1, x_19_2, x_16_2), y37 by (x_16_5, x_15_5, x_18_5, x_13_5, x_17_5, x_18_0), y35 by (x_14_7, x_16_7, x_13_6, x_15_6, x_17_6, x_12_6, x_16_6, x_14_6), jy19y23y38, jy19y23y40, jy19y25y38, jy19y29y34, jy19y30y33, jy19y31y32, jy20y31y33, jy21y21y38, jy21y21y40, jy21y23y38, jy21y23y40, jy21y25y38, jy21y27y34, jy21y27y36, jy21y29y34, jy21y30y33, jy21y31y32, jy22y31y31, jy23y23y38, jy23y25y36, jy23y30y31, jy19y19y36, jy19y27y36, jy21y21y36, jy21y23y36, jy21y25y36, jy21y30y31, jy19y25y36, jy23y23y36, jy23y25y34, jy23y27y34; no [41,12,16]; type [42,12,16_2]; kill y42 by x_16; status: weights = {16,18,20,22,24,26,28,30,32,34,36,38,40}; type [44,5,22_2]; status: weights = {22,24,30,32}; type [44,10,18_2]; kill y44, y40 by (x_18_0, x_18_2, x_18_4, x_19_1, x_19_3, x_20_0); status: weights = 18_2 - {40,42,44}; type [44,13,16_2]; status: weights = 16_2 - {44}; [9_7_2] type [9,7,2]; [x002] config from x2|x02|x002; [base] <--> [x1..11] := Build( [9_7_2], [x002] ); [23_7_9] type [23,7,9]; [base] <--> [a1..29] := [24_7_10.{a,b1..3,e,f}] - column; [15_7_5] type [15,7,5]; [base] <--> [a1..6] := [16_7_6.a1..3] - column; [13_7_4] type [13,7,4]; [x04] config from x4|x04; [base] <--> [a1..47] := Build( [13_7_4], [x04] ); [11_7_3] type [11,7,3]; [base] <--> [a1..3] := [12_7_4.a1..2] - column; [20_7_8all] type [20,7,8]; [x0242] config from x8|x26|x0242; [base] <--> [a1..27] := Build( [20_7_8all], [x0242] ); [19_7_7] type [19,7,7]; [base] <--> [a1..84] := [20_7_8all.a1..27] - column; [45_8_20] type [45,8,20]; credit: existence due to Blokh and Zyablov [.blokh zyablov.]; note: [x1..200] is part of a much larger list of codes, creatable via Unresidue( [45_8_20], [de], [13_7_4.a1..47] ); kill y45, y43, y44, y41, y42, y27, y37 by (x_12_8, x_17_8, x_16_8), y38 by (x_13_7, x_14_6, x_16_4), y33 by (x_13_12, x_16_12, x_12_12, x_11_10); [29] config 45 ::: {y29 != 0}; classification of [29]: Unresidue( [45_8_20], [29], [16_7_6.a1..3] ) --> ; @[base] infer y29 = 0; [25] config 45 ::: {y25 != 0}; classification of [25]: Unresidue( [45_8_20], [25], [20_7_8all.a1..27] ) --> ; @[base] infer y25 = 0; kill y21 by x_3_18; [34] config 45 ::: {y34 != 0}; classification of [34]: Unresidue( [45_8_20], [34], [11_7_3.a1..3] ) --> ; @[base] infer y34 = 0; [26] config 45 ::: {y26 != 0}; classification of [26]: Unresidue( [45_8_20], [26], [19_7_7.a1..84] ) --> ; @[base] infer y26 = 0; status: weights = {20,22,24,28,30,32,36,40}; % Unresidue( [45_8_20], [base], [15_7_5.a1..6] ) % yields only code [a], so that is the only code having a word of weight 30. % Unresidue( [45_8_20], [base],[23_7_9.a1..29] ) % yields only code [a], so that is the only code having a word of weight 22. % Its WE is 1 + 99t^20 + 90t^22 + 15t^24 + 45t^28 + 6t^30. at [base]; [40] subdivide along x_40; config from x_20_0|x_10_10_0; show (common) y20 = 129, y24 = 90, y28 = 35, y32 = 0, y36 = 0, y40 = 1, mu2 = 0; kill jy28y28y28; type [45,11,18_2]; status: weights = 18_2 - {38..45}; kill jy18y20y36, jy18y24y36, jy18y36y36, jy20y22y36, jy20y26y36, jy20y30y36, jy20y32y36, jy20y34y36, jy22y22y36, jy22y24y36, jy22y26y36, jy22y28y36 ; show (joint:5) y36 = 0; status: weights = 18_2 - {36..45}; psheadx(90) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=40, k >= 2: 26, 22, 20, 20, 18coderef(baumert mceliece), 18, 16, 16, 16, newdquest1()15, 14, quest1()14, newdquest1()13, newd1()12, 12, quest1()12, newdquest1()11, newd1()10, quest1()10; sn n=41, k >= 2: 27, 23, 21, 20, 19, 18, 17, 16, 16, quest1()16, quest1()15coderef(hill traynor), quest1()14, quest1()14, newdquest1()13, 12, 12, quest1()12, newdquest1()11, newd1()10; sn n=42, k >= 2: 28, 24, 22, 20, 20, 19, 18, quest1()17, 16, 16, quest1()16, newd1()14, quest1()14, quest1()14, quest1()13coderef(brouwer linear programming bound), 12, 12, quest1()12, newd1()10; sn n=43, k >= 2: 28, 24, 22, 21, 20, 20, 18, quest1()18, quest1()17, 16, 16, newdquest1()15, newd1()14, quest1()14, quest1()14, quest1()13, 12, 12, newd1()11; sn n=44, k >= 2: 29, 24, 23, 22, 21, 20, 19coderef(dodunekov manev 1985), 18, quest1()18, quest1()17, 16, 16, newdquest1()15, newd1()14, quest1()14, quest1()14, newd1()12, 12, 12; sn n=45, k >= 2: 30, 25, 24, 22, 22, 20, 20, quest1()19, 18, quest1()18, newd1()16, 16, 16, newdquest1()15, quest1()14, quest1()14, newdquest1()13, newd1()12, 12; pstail pshead(90) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 psnext n=40, k >=21: newdquest()9, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, 5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=41, k >=21: quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, newd()6, 6, 6, 5, 4, 4, 4, 4, 3, 2, 2, 2, 2; sn n=42, k >=21: 10, quest1()10, newdquest()9, newd()8, 8, quest()8, newdquest()7, newd()6, 6, 6, 5, 4, 4, 4, 4, 3, 2, 2, 2; sn n=43, k >=21: newd1()10, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, newdquest()7, newd()6, 6, 6, 5, 4, 4, 4, 4, 3, 2, 2; sn n=44, k >=21: newd1()11, newd1()10, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, newdquest()7, 6, 6, 6, 5, 4, 4, 4, 4, 3, 2; sn n=45, k >=21: 12, newd1()11, newd1()10, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, quest()7coderef(brouwer linear programming bound), 6, 6, 6, 5, 4, 4, 4, 4, 3; pstail pshead(80) // k = 40 41 42 43 44 psnext n=41, k>=40: 2; sn n=42, k>=40: 2, 2; sn n=43, k>=40: 2, 2, 2; sn n=44, k>=40: 2, 2, 2, 2; sn n=45, k>=40: 2, 2, 2, 2, 2; pstail \vspace{0.12in} \begin{svb} data_comment( ![ \block{There is a unique $[48,8,22]$ code} ]! ) no [46,7,22]; [48_8_22] type [48,8,22]; CREDIT(existence due to Dodunekov and Manev, dodunekov manev 1985) DHIDE( ![ DC1P#, D3#, DC1.7# done for ]! ) [a] := {100000000001111101111111111000001111100000000001, 010000001110001101110000111011110001100001111000, 001000001101101001001110100010001001111101110100, 000100001011010100101101010001000101111011101010, 000010011101010000111011010111011000101000010110, 000001010100011101010100011000011010101111001110, 000000111111111100000011111111111111111111000000, 000000000000000011111111111111111111111111111111}; CREDIT(existence due to Dodunekov and Manev, dodunekov manev 1985) (* [a] := Cyclic(6, 48, 8, 00111111001110101011011011010000110001001) *); (* [a] := [51_8_24.a] - dual word of weight 3 *); at [base]; show y48 = 0; show (joint:0) y22 = 144, y24 = 60, y28 = 0, y30 = 48, y32 = 3; config 32,16 : {10}; kill x_16_14; show (common) y22 = 144, y24 = 60, y30 = 48, y32 = 3; config from x_16_16|x_6_6_10; via building [current] implies [a]; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 144t^22 + 60t^24 + 48t^30 + 3t^32) data_block(There is no $[48,11,20]$ code}\label{section-48-11) type [48,11,20_2]; { show y42 = 0, y44 = 0, y46 = 0, y48 = 0; kill y40, y38, y34, y26; show y32 != 0; config 32,16 : {10}; kill x_16_16, x_12_16, x_10_14; via lp [current] = }; no [48,11,20]; data_block(Table for codes of length $46$ through $50$) type [51,9,22_2]; show (joint:5) y50 = 0; status: weights = 22_2 - {50}; no [51,10,22]; no [49,18,16]; type [46,9,20_2]; kill y46, y30, y40; status: weights = {20,24,28,32,36}; type [46,9,20]; status: weights = {20,24,28,32,36}; type [47,7,22]; status: weights = {22,24,30,32}; status: enumerator = 1 + 78t^22 + 30t^24 + 18t^30 + t^32; type [47,10,20]; status: weights = {20,24,28,32,36}, constraints = {418 <= y20 <= 419, 313 <= y24 <= 318, 278 <= y28 <= 284, 5 <= y32 <= 9, y36 <= 1}; type [48,13,18_2]; status: weights = 18_2 - {48}; no [48,11,20]; type [49,11,20_2]; kill y46 by x_20_0 ; status: weights = {20,22,24,26,28,30,32,34,36,38,40,42,44,48}; kill jy20y26y42, jy20y26y44, jy20y28y42, jy20y30y42, jy20y30y44, jy20y32y42, jy20y34y42, jy20y34y44, jy20y36y42, jy20y38y40, jy22y22y42, jy22y24y42 ; show (joint:5) y42 = 0; kill jy22y32y44, jy24y26y44, jy24y30y44, jy26y26y44, jy26y28y44 ; status: weights = {20,22,24,26,28,30,32,34,36,38,40,44,48}; type [50,4,26_2]; status: weights = {26,28,30,32}; no [49,9,22]; no [50,9,22] ; type [50,12,20]; kill y50 by x_20, y48 by x_18_2, y38, y34, y30, y26; status: weights = {20,24,28,32,36,40,44}; TYPE_WE(50,7,24,1 + 108t^24 + 19t^32) psheadx(80) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=46, k >= 2: 30, 26, 24, 23, 22, 21, 20, quest1()20, quest1()19, quest1()18, newdquest1()17, newd1()16, 16, quest1()16, quest1()15coderef(daskalov kapralov), quest1()14, quest1()14, newdquest1()13, newd1()12; sn n=47, k >= 2: 31, 26, 24, 24, 23, 22, 21, 20, quest1()20, newd1()18, quest1()18, newdquest1()17, 16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, newdquest1()13; sn n=48, k >= 2: 32, 27, 24, 24, 24, 22, 22, 20, quest1()20, newdquest1()19, quest1()18, quest1()18, quest1()17, 16, quest1()16, quest1()16, newdquest1()14, quest1()14, quest1()14; sn n=49, k >= 2: 32, 28, 25, 24, 24, 23, 22, newdquest1()20, 20, quest1()20, quest1()19coderef(hill traynor), quest1()18, quest1()18, quest1()17, 16, quest1()16, newdquest1()15, newdquest1()14, quest1()14; sn n=50, k >= 2: 33, 28, 26, 24, 24, 24, 23, newdquest1()21, newd1()20, 20, quest1()20, quest1()19, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, newdquest1()15, newdquest1()14; pstail pshead(80) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 psnext n=46, k >=21: 12, 12, newd1()11, newd1()10, quest1()10, quest1()10, newdquest()9, 8, 8, quest()8, quest()7, 6, 6, 6, 5, 4, 4, 4, 4; sn n=47, k >=21: newd1()12, 12, 12, newd1()11, newdquest1()10, quest1()10, quest1()10, quest()9, 8, 8, quest()8, quest()7, 6, 6, 6, 5, 4, 4, 4; sn n=48, k >=21: newdquest1()13, newd1()12, 12, 12, newdquest1()11, newdquest1()10, quest1()10, quest1()10, quest()9, 8, 8, quest()8, quest()7, 6, 6, 6, quest()5, 4, 4; sn n=49, k >=21: quest1()14, newdquest1()13, newd1()12, 12, quest1()12, newdquest1()11, newdquest1()10, quest1()10, quest1()10, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()5, 4; sn n=50, k >=21: quest1()14, quest1()14, newdquest1()13, newd1()12, quest1()12, quest1()12, newdquest1()11, newdquest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()5; pstail pshead(80) // k = 40 41 42 43 44 45 46 47 48 49 psnext n=46, k>=40: 3, 2, 2, 2, 2, 2; sn n=47, k>=40: 4, 3, 2, 2, 2, 2, 2; sn n=48, k>=40: 4, 4, 3, 2, 2, 2, 2, 2; sn n=49, k>=40: 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=50, k>=40: 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; pstail \vspace{0.12in} \begin{svb} data_block(There is a unique $[51,8,24]$ code) [51_8_24] type [51,8,24]; [a] := Cyclic(1, 51, 8, 001010111001100111111010011110101111011111011011) :: {y24 = 204, y32 = 51}; alt Act( { (1,2,3,4,5,6,7,8)(1) }, {00011101,00100101,00101111,00111011, 00111111,01010101,01111111} ) + check; CLASSIFICATION_OF([base], x_32|x_16_16|x_6_6_10_2|x15155511, [a]) STATUS_UNIQUE_WE(1 + 204t^24 + 51t^32) data_block(There is no $[55,39,8]$ code) type [55,16,13] {y55=1, mu1=0, mu2=0, mu3=0, mu4=0, mu5=0, mu6=0, mu7=0}; =config 55 : {1}; kill y13, y14, y15, y16, y17 by x_0_18, y18 by x_0_18, y19; kill [current] by x_20; type [55,39,8_2]; via dual nonexistence infer [base] = ; no [55,39,8]; data_block(Table for codes of length $51$ through $55$) type [51,13,20_2]; status: weights = {20,24,28,32,36,40}; type [51,13,20]; status: weights = {20,24,28,32,36,40}; type [52,5,26_2]; status: weights = {26,28,30,32}; type [52,10,22_2]; kill y52 by x_22; status: weights = {22,24,26,28,30,32,34,36,38,40,42,44,46,48}; no [52,11,22]; no [53,9,24]; type [53,11,22_2]; kill y48 by (x_22_0, x_22_2, x_18_4); status: weights = {22,24,26,28,30,32,34,36,38,40,42,44,46}; type [53,14,20_2]; show (joint:0) y52 = 0 ; status: weights = {20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}; no [53,18,18]; no [54,7,26]; type [54,9,24_2]; status: weights = {24,26,28,32,34,36,40,44,48}; type [54,9,24]; status: weights = {24,25,26,28,32,33,34,36,40,44,48}; type [54,12,22_2]; { kill y54, y46 by (x_14_8, x_15_7, x_16_6, x_16_8), y44 by (x_12_10, x_13_9, x_14_10, x_15_7, x_15_9, x_17_7), y42 by (x_11_11, x_12_10, x_13_9, x_13_11, x_14_8, x_14_10), y40 by (x_11_11, x_12_10, x_12_12, x_13_9, x_13_11, x_14_8) }; status: weights = 22_2 - {26,40..54}; kill jy30y36y38, jy30y38y38, jy34y36y36, jy34y36y38, jy36y36y36, jy24y38y38, jy28y36y38, jy28y38y38, jy30y34y38, jy32y32y38, jy32y34y38, jy32y36y38 ; via lp (joint:5) [current] = ; no [54,12,22]; no [54,19,18]; [55_5_28] type [55,5,28]; [a] config 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1 : {1001011001101001011010011001011,0101010101010101101010101010101, 0011001100110011110011001100110,0000111100001111111100001111000, 0000000011111111111111110000000} :: {1 + 28t^28 + 3t^32}; at [base]; show y40 = 0; via building [current] implies [a]; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 28t^28 + 3t^32) type [55,10,24_2]; kill y26, y34, y48; status: weights = {24,28,32,36,40,44}; type [55,10,24]; status: weights = {24,28,32,36,40,44}; no [55,13,22]; type [56,11,24_2]; kill y56 by x_28 ; status: weights = {24,28,32,36,40}; type [56,13,22_2]; status: weights = 22_2 - {56}; psheadx(80) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=51, k >= 2: 34, 28, 26, 25, 24, 24, 24, quest1()22, newdquest1()21, newd1()20, quest1()20, quest1()20, newdquest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, newdquest1()15; sn n=52, k >= 2: 34, 29, 27, 26, 25, 24, 24, 22, quest1()22, newdquest1()21, newd1()20, quest1()20, newdquest1()19, newdquest1()18, quest1()18, quest1()18, newdquest1()16, quest1()16, quest1()16; sn n=53, k >= 2: 35, 30, 28, 26, 26, 24, 24, quest1()23coderef(dodunekov encheva ivanov), 22, quest1()22, newdquest1()20, 20, quest1()20, newdquest1()19, newdquest1()18, quest1()18, newdquest1()17, newdquest1()16, quest1()16; sn n=54, k >= 2: 36, 30, 28, 27, 26, 24, 24, quest1()24, quest1()23, quest1()22, newdquest1()21, newd1()20, 20, quest1()20, newdquest1()19, newdquest1()18, quest1()18, newdquest1()17, newdquest1()16; sn n=55, k >= 2: 36, 31, 28, 28, 27, 25coderef(tilborg 1979), 24, 24, quest1()24, quest1()23, quest1()22, newdquest1()21, newd1()20, 20, quest1()20, newdquest1()19, quest1()18, quest1()18, newdquest1()17; pstail pshead(80) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 psnext n=51, k >=21: newdquest1()14, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, newdquest1()11, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, quest()6; sn n=52, k >=21: newdquest1()15, newdquest1()14, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, quest1()11coderef(brouwer linear programming bound), quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, quest()7, 6, 6; sn n=53, k >=21: quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, quest()7, 6; sn n=54, k >=21: quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, newd()6; sn n=55, k >=21: newdquest1()16, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, newdquest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, newdquest()7; pstail pshead(80) // k = 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 psnext n=51, k >=40: quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=52, k >=40: quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=53, k >=40: 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=54, k >=40: 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=55, k >=40: newd()6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; pstail \vspace{0.12in} \begin{svb} data_comment( ![ \block{Table for codes of length $56$ through $71$}\label{section-56-71} ]! ) no [64,21,22]; no [58,27,16]; no [58,9,26]; no [58,7,28]; no [67,8,32]; no [67,10,30]; type [57,4,30_2]; status: weights = {30,32}; no [57,12,24]; type [58,12,24_2]; kill y58, y54, y50, y46, y42, y38 by (x_5_19, x_6_20, x_7_17, x_8_18, x_9_15), y34 by (x_1_23, x_2_24, x_3_21, x_4_22, x_5_19, x_5_23, x_6_20, x_7_17, x_7_21, x_8_18, x_9_15, x_9_19) ; show (joint) y26 = 0; show (joint:0) y56 = 0; status: weights = 24_4 - {56}; type [57,18,20_2]; kill y56 by x_26_0, y54 by x_17_3, y52 by (x_15_5, x_17_3) ; status: weights = 20_2 - {22,52..57}; type [58,19,20_2]; kill y58 by x_20, y50 by (x_16_8, x_18_8, x_20_0) ; status: weights = 20_2 - {22,50..58}; no [60,36,12] ; type [59,5,30_2]; status: enumerator = 1 + 24t^30 + 7t^32; type [59,9,26_2]; status: weights = 26_2 - {58}; kill y56 by x_26_0 ; status: weights = 26_2 - {56,58}; no [57,12,24]; type [59,13,24]; status: weights = {24,28,32,36,40,44,48}; no [58,9,26]; type [60,10,26_2]; status: weights = {26,28,30,32,34,36,38,40,42,44,46,48,50,52,54}; type [61,8,28_2]; status: weights = 28_2 - {50,56..61}; no [60,18,22]; type [61,18,22_2]; kill y60, y58, y56 by (x_17_5, x_27_5, x_25_5), y54 by (x_15_7, x_16_6, x_17_7, x_18_6), y52 by (x_13_9, x_15_9, x_19_9, x_21_9, x_22_0); status: weights = {22,24,28,30,32,34,36,38,40,42,44,46,48,50}; type [60,21,20_2]; kill y60,y42,y38,y34,y48,y46,y44 ; via lp [current] = ; no [60,21,20]; type [60,32,14_2]; show y60 = 1; status: weights = 14_2 - {48..58}, constraints = {y60 = 1}; type [61,11,26_2]; kill y54 by (x_21_5, x_23_5, x_23_7, x_24_2); status: weights = 26_2 - {54..61}; kill y52 by (x_17_9, x_19_9, x_21_9, x_23_9, x_25_9, x_26_0) ; status: weights = 26_2 - {52..61}; type [62,19,22_2]; kill y62 by x_22, y50 by (x_12_12, x_16_12, x_18_12, x_22_12, x_20_12, x_24_12, x_11_11, x_13_11, x_22_0), y48; status: weights = {22,24,28,30,32,34,36,38,40,42,44,46}; TYPE_WE(62,7,30_2,1 + 63t^30 + 63t^32 + t^62) type [62,7,30]; status: weights = {30,31,32,62}; no [61,9,28]; type [62,9,28_2]; kill y62, y54; status: weights = {28,30,32,34,36,40,42,44,46,48,52}; kill jy28y28y46, jy28y30y46, jy28y30y48, jy28y30y52, jy28y32y46, jy28y34y46, jy28y34y52, jy28y36y46, jy28y40y46, jy28y42y46, jy28y42y48, jy30y30y46; show (joint:5) y46 = 0; kill jy30y30y48, jy30y30y52, jy30y32y48, jy30y34y44, jy32y32y34, jy32y34y34, jy32y34y40, jy32y34y42, jy32y34y48; show (joint:5) y34 = 0; status: weights = {28,30,32,36,40,42,44,48,52}; kill jy30y30y44, jy32y42y44, jy36y42y42; type [62,55,4_2]; status: weights = 4_2 - {62} ; TYPE_WE(63,6,32,1 + 63t^32) type [63,10,28]; status: weights = {28,32,36,40,44,48}; kill jy28y48y48, jy32y44y48, jy28y44y48 ; type [63,20,22_2]; status: weights = 22_2 - {26,48,50,52,54,56,58,60,62}; set auto mu1; type [63,31,16_2]; status: weights = 16_2 - {62}; type [64,11,28_2]; status: weights = {28,32,36,40,44}; kill y44 by x_18_10, y40 by x_16_12 ; no [64,11,28]; psheadx(110) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=56, k >= 2: 37, 32, 29, 28, 28, 26, 24, 24, 24, quest1()24, newdquest1()22, quest1()22, newdquest1()21, newd1()20, 20, quest1()20, quest1()19coderef(brouwer linear programming bound), quest1()18, quest1()18; sn n=57, k >= 2: 38, 32, 30, 28, 28, 26, 25, newd1()24, 24, quest1()24, newdquest1()23, quest1()22, quest1()22, newdquest1()21, 20, quest1()20, quest1()20, quest1()19, quest1()18; sn n=58, k >= 2: 38, 32, 30, 29, 28, 27coderef(tilborg 1981 discrete), 26, newdquest1()25, 24, 24, quest1()24, quest1()23coderef(hill traynor), quest1()22, quest1()22, quest1()21coderef(brouwer linear programming bound), quest1()20, quest1()20, quest1()20, quest1()19; sn n=59, k >= 2: 39, 33, 31, 30, 29, 28, 26, quest1()26, quest1()25, 24, quest1()24, quest1()24, newdquest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20; sn n=60, k >= 2: 40, 34, 32, 30, 30, 28, 27, 26, quest1()26, newd1()24, 24, quest1()24, newdquest1()23, newdquest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20; sn n=61, k >= 2: 40, 34, 32, 31, 30, 29coderef(logacev improvement), 28, quest1()27coderef(dodunekov encheva ivanov), 26, newdquest1()25, newd1()24, 24, quest1()24, newdquest1()23, quest1()22, quest1()22, quest1()22, newdquest1()20, quest1()20; sn n=62, k >= 2: 41, 35, 32, 32, 31, 30, 28, quest1()28, quest1()27, quest1()26, newdquest1()25, newd1()24, 24, quest1()24, quest1()23coderef(brouwer linear programming bound), quest1()22, quest1()22, newdquest1()21, newdquest1()20; sn n=63, k >= 2: 42, 36, 32, 32, 32, 31, 28, 28, quest1()28, newd1()26, quest1()26, newdquest1()25, newd1()24, 24, quest1()24, quest1()23, quest1()22, quest1()22, newdquest1()21; pstailx type [64,32,16_2]; kill y60,y58,y56,y54,y52,y50; show y64 = 1 ; status: weights = 16_2 - {50..62}, constraints = {y64 = 1}; set dual constraint bound = 3; type [66,9,30_2]; { kill y66,y64,y62,y60,y58; show (joint:0) y56 = 0; kill y54 by (x_18_12, x_20_10, x_21_11) }; status: weights = {30,32,34,36,38,40,44,46,48}; kill jy36y38y48, jy36y44y46, jy36y44y48, jy36y48y48, jy38y40y44, jy40y44y44, jy44y44y44, jy34y34y48, jy34y38y44, jy32y38y44, jy32y44y48, jy34y34y38, jy30y34y48, jy30y44y46, jy30y44y48, jy30y48y48, jy32y34y46, jy32y34y48, jy32y36y48, jy32y44y44, jy32y44y46, jy32y46y48, jy32y48y48, jy34y34y44, jy34y34y46, jy34y36y38, jy34y36y44, jy34y36y48, jy34y40y44, jy34y40y46, jy36y36y44, jy36y36y48, jy36y40y44, jy36y40y48, jy36y44y44, jy36y46y46, jy40y40y44, jy40y40y46, jy40y40y48, jy30y30y44, jy30y32y44, jy30y32y48 ; show (joint:5) y44 = 0; kill jy30y34y46, jy30y36y46, jy30y36y48, jy30y40y48, jy32y32y46, jy32y36y38, jy32y36y46, jy32y40y46, jy34y34y34, jy34y34y36, jy34y36y36, jy34y36y40, jy34y36y46, jy34y40y40, jy36y36y36, jy36y36y40, jy36y36y46, jy36y38y40, jy36y40y40, jy36y40y46, jy30y30y34, jy30y30y36, jy30y32y32, jy30y32y34 ; show (joint:5) y34 = 0, y36 = 0; kill jy30y32y40, jy30y40y40 ; status: weights = {30,32,38,40,46,48}, constraints = {243 <= y30 <= 244, 107 <= y32 <= 108, 136 <= y38 <= 138, 18 <= y40 <= 20, 3 <= y46 <= 4, y48 <= 1, div4 = 128, 24 <= mu3 <= 26}; set dual constraint bound = -1; type [66,9,30]; status: weights = {30,32,38,40,46,48}; type [65,4,34_2]; status: weights = {34,36,38,40}; type [65,8,30_2]; kill y64, y60 by x_30_0, y62 by x_27_3, y58; status: weights = {30,32,34,36,38,40,42,44,46,48,50,52,54,56}; type [65,8,30]; kill y57, y53, y45, y37, y49 by (x_22_14, x_16_14, x_23_10, x_20_10); status: weights = {30,31,32,33,34,36,38,39,40,41,42,44,46,47,48,50,52,54,56}; type [65,11,28_2]; status: weights = 28_2 - {58,62}; type [65,14,26_2]; kill y64 by x_26_0 ; status: weights = 26_2 - {64}; type [65,18,24_2]; kill y64, y60 by x_24_0; kill y62 by x_21_3 ; status: weights = 24_2 - {30,60..65}; type [66,9,30_2]; status: weights = 30_2 - {34,36,42,44,50..66}; type [66,12,28_2]; status: weights = {28,32,36,40,44,48,52,56,60}; type [66,19,24_2]; status: weights = 24_2 - {30,60..66}; type [67,13,28_2]; status: weights = {28,32,36,40,44,48,52,56}; kill y56 by (x_18_10, x_22_6) ; status: weights = {28,32,36,40,44,48,52}; type [68,5,34_2]; status: weights = 34_2 - {50..68}; type [68,8,32_2]; status: weights = {32,34,36,40,42,44,48,50,52,64}; kill jy32y48y50, jy32y48y52, jy34y42y48, jy36y36y52, jy40y40y52 ; type [68,8,32]; status: weights = {32,33,34,36,40,41,42,44,48,50,52,64}; type [68,10,30_2]; kill y68, y66 by x_30_0; kill y62 by (x_27_3, x_27_5, x_28_2), y60 by x_30_0 ; status: weights = 30_2 - {60,62,66,68}; no [65,12,28]; type [68,14,28_2]; status: weights = {28,32,36,40,44,48}; type [68,14,28]; status: weights = {28,32,36,40,44,48}; type [68,17,26_2]; kill y64 by x_24_2; status: weights = 26_2 - {64}; type [69,9,32_2]; credit: nonexistence due to Bouyukliev, Guritman, and Vavrec; kill y64, y52, y50, y34, y36 by (x_10_22, x_16_20); STATUS_WE(1 + 351t^32 + 156t^40 + 4t^48) [69_9_32] type [69,9,32]; status: enumerator = 1 + 351t^32 + 156t^40 + 4t^48; classification of [base]: Unresidue( [69_9_32], [base], [21_8_8.{a1..7,b,c}] ) --> ; no [69,9,32]; type [69,11,30_2]; kill y58 by (x_19_11, x_20_10, x_21_9, x_21_11, x_22_8, x_22_10, x_23_9, x_23_11, x_24_6); status: weights = 30_2 - {58,60,62,66,68}; kill y64 by (x_25_5, x_27_3, x_27_5, x_29_1, x_29_3, x_29_5, x_30_0, x_30_2, x_30_4, x_31_1, x_31_3, x_31_5) ; status: weights = 30_2 - {58..69}; type [69,18,26_2]; status: weights = 26_2 - {34,56..69}; set dual constraint bound = 3; type [70,6,34_2]; status: weights = {34,36,38,40,42,44,46,48,50,52,54,56,60,64,70}; status: weights = {34,36,38,40,42,44,46,48,50,52,54,56,60,64}; set dual constraint bound = -1; type [70,12,30_2]; kill y56 by (x_16_14, x_17_13, x_18_12, x_18_14, x_20_10, x_20_12, x_22_10, x_22_12, x_22_14, x_23_7) ; status: weights = {30,32,34,36,38,40,44,46,48,50,52,54,70}; type [70,15,28_2]; kill y70 by x_28, y68 by x_26_2; status: weights = {28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66}; type [70,26,22_2]; kill y70, y68 by x_20_2; status: weights = 22_2 - {68,70}; type [70,30,20_2]; kill y70 by x_20, y68 by x_20_0; status: weights = 20_2 - {68,70}; type [70,45,12_2]; status: weights = 12_2 - {70}; [71_5_36] type [71,5,36]; kill y56, ndiv4; [a] config 2,2,3,3,2,2,3,3,2,2,3,3,2,2,3,3,2,2,2,2,2,2,2,2,3,3,1,1,3,3,1 : {1001011001101001011010011001011,0101010101010101101010101010101, 0011001100110011110011001100110,0000111100001111111100001111000, 0000000011111111111111110000000} :: {1 + 27t^36 + 3t^40 + t^44}; [b] config 2,2,3,3,2,2,3,3,2,2,3,3,2,2,3,3,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1 : {1001011001101001011010011001011,0101010101010101101010101010101, 0011001100110011110011001100110,0000111100001111111100001111000, 0000000011111111111111110000000} :: {1 + 28t^36 + 2t^40 + t^48}; [c] config 2,2,3,3,2,2,3,3,2,2,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,1 : {1001011001101001011010011001011,0101010101010101101010101010101, 0011001100110011110011001100110,0000111100001111111100001111000, 0000000011111111111111110000000} :: {1 + 26t^36 + 5t^40}; at [base]; status: weights = {36,40,44,48}; config from x_40|x_20_16; reduce variable set; config from x_10_10_8_8; via building [current] implies [a], [b], [c]; classification of [base]: [a], [b], [c]; type [71,10,32_2]; status: weights = {32,34,36,40,42,44,48,52,64}; kill y42 by (x_17_19, x_21_15, x_13_19, x_14_20, x_21_19), y34 by x_9_27; status: weights = {32,36,40,44,48,52,64}, constraints = {525 <= y32 <= 595, y36 <= 162, 266 <= y40 <= 448, y44 <= 70, y48 <= 17, y52 <= 6, y64 <= 1}; kill jy32y36y64, jy36y36y64, jy36y40y64 ; type [71,13,30_2]; status: weights = {30,32,34,36,38,40,44,46,48,50,52,54}; no [71,13,30]; no [69,6,34]; type [71,16,28_2]; kill y66 by (x_30_0, x_32_0); status: weights = {28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64}; type [71,23,24_2]; kill y70 by x_24_0; status: weights = 24_2 - {70}; type [71,31,20_2]; status: weights = 20_2 - {22,68,70}; type [72,4,38_2]; status: weights = {38,40}; type [72,11,32]; kill y52 by (x_18_18, x_16_16, x_24_20, x_22_14, x_20_12, x_22_10), y44, y36 by (x_0_36, x_18_31) ; status: weights = {32,40,48,64}; unset auto mu1; psheadx(110) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=64, k >= 2: 42, 36, 33, 32, 32, 32, 29, 28, 28, newdquest1()27, newdquest1()26, quest1()26, newdquest1()25, 24, 24, quest1()24, newdquest1()22, quest1()22, quest1()22; sn n=65, k >= 2: 43, 36, 34, 32, 32, 32, 30, quest1()29coderef(dodunekov encheva ivanov), 28, quest1()28, newdquest1()27, quest1()26, quest1()26, quest1()25, 24, quest1()24, newdquest1()23, newdquest1()22, quest1()22; sn n=66, k >= 2: 44, 37, 34, 32, 32, 32, 30, quest1()30, newd1()28, 28, quest1()28, quest1()27coderef(daskalov 66_13_28), quest1()26, quest1()26, quest1()25, 24, quest1()24, newdquest1()23, newdquest1()22; sn n=67, k >= 2: 44, 38, 35, 33, 32, 32, 31coderef(dodunekov ytrehus 1987), 30, newd1()29, newd1()28, quest1()28, quest1()28, quest1()27, quest1()26, quest1()26, quest1()25, 24, quest1()24, newdquest1()23; sn n=68, k >= 2: 45, 38, 36, 34, 32, 32, 32, 30, 30, newdquest1()29, newdquest1()28, quest1()28, quest1()28, newdquest1()26, quest1()26, quest1()26, newd1()24, quest1()24, quest1()24; sn n=69, k >= 2: 46, 39, 36, 34, 33, 32, 32, 31, 30, quest1()30, newdquest1()29, quest1()28, quest1()28, newdquest1()27, newdquest1()26, quest1()26, newdquest1()25, newdquest1()24, quest1()24; sn n=70, k >= 2: 46, 40, 36, 35, 34, 33, 32, 32, 31coderef(hill traynor), quest1()30, quest1()30, newd1()28, quest1()28, quest1()28, newdquest1()27, newdquest1()26, quest1()26, newdquest1()25, newdquest1()24; sn n=71, k >= 2: 47, 40, 37, 36, 34, 34, 32, 32, 32, quest1()31, quest1()30, newdquest1()29, newdquest1()28, quest1()28, quest1()28, newdquest1()27, quest1()26, quest1()26, newdquest1()25; pstailx no [68,36,16]; no [67,36,15]; no [67,31,18]; psheadx(110) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 psnext n=56, k >=21: newdquest1()17, newdquest1()16, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8; sn n=57, k >=21: quest1()18, newdquest1()17, newdquest1()16, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, newdquest()9, newd()8, 8; sn n=58, k >=21: quest1()18, quest1()18, newdquest1()17, newdquest1()16, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, newdquest()9, 8; sn n=59, k >=21: newdquest1()18, quest1()18, quest1()18, newdquest1()17, quest1()16, quest1()16, quest1()16, newdquest1()15, quest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, newdquest1()10, quest1()10, quest1()10, quest()9; sn n=60, k >=21: newdquest1()19, newdquest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, quest1()14, newdquest1()12, quest1()12, quest1()12, newdquest1()11, newdquest1()10, quest1()10, quest1()10; sn n=61, k >=21: quest1()20, newdquest1()19, newdquest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, newdquest1()11, newdquest1()10, quest1()10; sn n=62, k >=21: quest1()20, quest1()20, newdquest1()19, newdquest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, newdquest1()11, quest1()10; sn n=63, k >=21: newdquest1()20, quest1()20, quest1()20, newdquest1()19, newdquest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, quest1()11coderef(brouwer linear programming bound) ; pstail pshead(110) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 psnext n=64, k >=21: newdquest1()21, newdquest1()20, quest1()20, quest1()20, newdquest1()19, quest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, newdquest1()14, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12; sn n=65, k >=21: quest1()22, newdquest1()21, newdquest1()20, quest1()20, quest1()20, quest1()19coderef(brouwer linear programming bound), quest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12; sn n=66, k >=21: quest1()22, quest1()22, newdquest1()21, newdquest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, quest1()18, newdquest1()16, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, newdquest1()13, newdquest1()12; sn n=67, k >=21: newdquest1()22, quest1()22, quest1()22, newdquest1()21, newdquest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, newdquest1()17, quest1()17, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, newdquest1()13; sn n=68, k >=21: newdquest1()23, newdquest1()22, quest1()22, quest1()22, newdquest1()21, quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, newdquest1()17, newdquest1()16, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14; sn n=69, k >=21: quest1()24, newdquest1()23, newdquest1()22, quest1()22, quest1()22, quest1()21coderef(brouwer linear programming bound), quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, newdquest1()17, newdquest1()16, quest1()16, quest1()16, newdquest1()15, quest1()14, quest1()14; sn n=70, k >=21: quest1()24, quest1()24, newdquest1()23, newdquest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, newdquest1()17, newdquest1()16, quest1()16, quest1()16, quest1()15coderef(brouwer linear programming bound), quest1()14; sn n=71, k >=21: newdquest1()24, quest1()24, quest1()24, newdquest1()23, newdquest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, newdquest1()17, newdquest1()16, quest1()16, quest1()16, quest1()15; pstail pshead(110) // k = 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 psnext n=56, k >=40: newdquest()7, newd()6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=57, k >=40: quest()8, newdquest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=58, k >=40: 8, quest()8, quest()7coderef(brouwer linear programming bound), 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=59, k >=40: 8, 8, quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=60, k >=40: quest()9, 8, 8, quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2; sn n=61, k >=40: quest1()10, quest()9, 8, 8, quest()8, quest()7, 6, 6, 6, quest()6, newd()4, 4, 4, 4, 4, 3, 2, 2, 2; sn n=62, k >=40: quest1()10, quest1()10, quest()9, 8, 8, quest()8, quest()7, 6, 6, 6, newd()5, 4coderef(brouwer linear programming bound), 4, 4, 4, 4, 3, 2, 2; sn n=63, k >=40: quest1()10, quest1()10, quest1()10, quest()9, 8, 8, quest()8, quest()7, 6, 6, 6, 5, 4, 4, 4, 4, 4, 3, 2; pstail pshead(110) // k = 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 psnext n=64, k >=40: quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, 8, quest()8, quest()7, 6, 6, 6, 5, 4, 4, 4, 4, 4, 2; sn n=65, k >=40: quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, quest()7, 6, 6, 6, 5, 4, 4, 4, 4, 3; sn n=66, k >=40: quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, quest()7, 6, 6, 6, quest()5, 4, 4, 4, 4; sn n=67, k >=40: quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()5, 4, 4, 4; sn n=68, k >=40: quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()5, 4, 4; sn n=69, k >=40: quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()5, 4; sn n=70, k >=40: quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, newdquest1()10, quest1()10, quest1()10, newdquest()9, 8coderef(brouwer linear programming bound), quest()8, quest()8, quest()8, newd()6, 6, 6, quest()6, quest()5; sn n=71, k >=40: quest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, newdquest1()11, newdquest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, newdquest()7, 6, 6, 6, quest()6; pstail pshead(180) // k = 59 60 61 62 63 64 65 66 67 68 69 70 psnext n=60, k >=59: 2; sn n=61, k >=59: 2, 2; sn n=62, k >=59: 2, 2, 2; sn n=63, k >=59: 2, 2, 2, 2; sn n=64, k >=59: 2, 2, 2, 2, 2; sn n=65, k >=59: 2, 2, 2, 2, 2, 2; sn n=66, k >=59: 3, 2, 2, 2, 2, 2, 2; sn n=67, k >=59: 4, 3, 2, 2, 2, 2, 2, 2; sn n=68, k >=59: 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=69, k >=59: 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=70, k >=59: 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=71, k >=59: quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; pstail \vspace{0.12in} \begin{svb} data_comment(\block{There is no $[81,12,36]$ code}\label{81-12-36-section}) no [77,9,36]; (* new result *); type [81,12,36_2]; { show y66 = 0, y68 = 0, y70 = 0, y72 = 0, y74 = 0, y76 = 0, y78 = 0, y80=0; kill y64, y60, y58, y56; show y50 = 0; kill y48 by (x_24_24, x_24_20); via lp [base] = }; no [81,12,36]; data_comment(![\block{There is no $[73,12,32]$ code}\label{73-12-32}]!) type [73,12,32_2]; { kill y64; !config 24,24,24,1 : {1100,0110}; !config 18,30,18,7 : {1100,0110}; at [base]; ??show jy48y48y48 = 0, jy48y48y36 = 0; via lp (joint:5) [current] = }; no [73,12,32]; data_comment(![ \block{Table for codes of length $72$ through $85$}\label{section-72-80} ]!) type [73,8,34_2]; kill y72, y68, y66, y70; kill y64 by x_27_9 ; status: weights = 34_2 - {62..73}; type [73,8,34]; kill y61, y55, y57, y47, y49, y53, y41, y45, y37, y39; status: weights = 34_2 - {62..73}; type [73,14,30_2]; kill y72, y70, y68 by x_30_0; status: weights = {30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66}; type [73,18,28_2]; status: weights = {28,30,32,34,36,40,44,48,52,56,60}; no [72,6,36]; type [74,7,36_2]; show y72 = 0, y74 = 0, y36 != 0; kill y36 ; no [74,7,36]; type [74,12,32_2]; kill y70, y66 by (x_28_6, x_29_5, x_30_2), y62 by (x_23_11, x_24_10, x_28_10, x_30_10, x_30_12, x_31_1); status: weights = {32,34,36,38,40,42,44,48,50,52,54,56,58,60,64,68,72,74}; type [74,15,30_2]; status: weights = 30_2 - {68..74}; type [74,26,24_2]; status: weights = 24_2 - {72,74}; type [74,30,22_2]; status: weights = 22_2 - {70..74}; type [75,5,38_2]; status: weights = {38,40,46,48}; type [75,9,34_2]; kill y74, y72 by x_31_3, y70 by (x_31_3, x_31_5, x_32_4, x_33_1, x_33_3, x_33_5, x_34_0); kill y68 by x_34_0 ; status: weights = 34_2 - {68..75}; type [75,13,32_2]; kill y64 by (x_21_11, x_23_9, x_24_10, x_25_9, x_25_11, x_27_5, x_27_7, x_28_6, x_29_3, x_29_5, x_29_7, x_30_4, x_30_8, x_31_1, x_31_3, x_31_5, x_31_7, x_31_9, x_32_2, x_32_6) ; status: weights = {32,34,36,38,40,42,44,48,50,52,54,56,58,60}; type [75,23,26_2]; status: weights = 26_2 - {74}; set auto mu1; type [79,10,36_2]; status: weights = {36,40,44,48,52,56,60}, constraints = {542 <= y36 <= 578, 56 <= y40 <= 164, 210 <= y44 <= 330, 35 <= y48 <= 107, y52 <= 18, y56 <= 6, y60 <= 2}; type [79,19,30_2]; kill y78, y76 by x_30_0; status: weights = 30_2 - {76,78}; type [79,23,28_2]; status: weights = 28_2 - {74..79}; type [79,27,26_2]; status: weights = 26_2 - {66..79}; no [81,9,38]; no [81,7,40]; type [81,14,34_2]; status: weights = 34_2 - {76..81}; unset auto mu1; type [83,8,40_2]; { kill y64; [56bound] config 83 ::: {y56 <= 5}; at [base]; via building [current] implies [56bound]; via lp [56bound] = ; classification of [base]: }; no [83,8,40]; (* Dodunekov et. al., 1987 *); no [84,6,42]; type [86,7,42_2]; { show y84 = 0, y86 = 0; kill y68, y60, y56; show div4 <= 47; infer div4 = 32; kill y42; via lp [current] = }; no [86,7,42]; set auto mu1; no [72,25,24]; type [72,28,22_2]; kill y72 by x_22; status: weights = 22_2 - {68..72}; type [72,32,20_2]; kill y72 by x_20; status: weights = 20_2 - {22,68..72}; type [73,6,36_2]; kill y72, ndiv4; status: weights = {36,40,44,48,52,56}; kill y56 by x_26_10 ; status: weights = {36,40,44,48,52}; type [73,18,28_2]; status: weights = 28_2 - {38,42,46,50,54,58,62..73}; type [74,19,28_2]; kill y74,y34; no [74,19,28]; type [75,19,28_2]; kill y74 by x_28_0; status: weights = 28_2 - {74}; type [76,10,34_2]; kill y76, y66 by (x_27_7, x_27_9, x_28_8, x_28_10, x_29_5, x_29_7, x_29_9, x_30_4); status: weights = {34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64}; type [76,14,32]; status: weights = {32,36,40,44,48,52}; type [76,17,30_2]; kill y76 by x_30; status: weights = {30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66}; type [76,20,28_2]; kill y76 by x_28; status: weights = 28_2 - {74,76}; type [77,6,38_2]; kill y76, y60 by x_28_12; status: weights = {38,40,44,46,48,50,52,54,56,62}; status: weights = {38,40,46,48,54,56,62}; no [74,9,34]; type [77,11,34_2]; status: weights = 34_2 - {66..77}; kill y64 by (x_23_13, x_24_12, x_25_13, x_27_13, x_28_10, x_28_12, x_30_8, x_30_12, x_31_13, x_32_2) ; status: weights = 34_2 - {64..77}; type [77,18,30_2]; status: weights = 30_2 - {42,66..77}; type [78,9,36_2]; status: weights = {36,40,44,48,52,56,60,64}; type [78,12,34_2]; status: weights = {34,36,38,40,42,44,46,48,52,54,56,58,60}; type [78,15,32_2]; status: weights = 32_2 - {74..78}; type [78,26,26_2]; status: weights = 26_2 - {70..78}; unset auto mu1; set dual constraint bound = -1; type [80,4,42_2]; status: weights = {42,44,46,48}; type [80,6,{40,48,56}]; show (joint:5) y40 <= 59, y48 >= 3, y56 <= 1; show (joint:5) 58 <= y40 <= 59, 3 <= y48 <= 5, y56 <= 1; type [80,10,36_2]; kill y80, y78, y76, y74 by (x_30_6, x_31_5, x_33_3, x_34_2); status: weights = {36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72}; type [80,24,28_2]; status: weights = 28_2 - {62,66,70..80}; psheadx(105) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=72, k >= 2: 48, 40, 38, 36, 35, 34, 32, 32, 32, quest1()32, newdquest1()30, quest1()30, newdquest1()29, quest1()28, quest1()28, quest1()28, newdquest1()26coderef(brouwer linear programming bound), quest1()26, quest1()26; sn n=73, k >= 2: 48, 41, 38, 36, 36, 34, 33, newd1()32, 32, quest1()32, newdquest1()31, newdquest1()30, quest1()30, quest1()29coderef(brouwer linear programming bound), quest1()28, quest1()28, newdquest1()27, newdquest1()26, quest1()26; sn n=74, k >= 2: 49, 42, 39, 37, 36, 35coderef(tilborg griesmer 1980), 34, newdquest1()33, 32, 32, quest1()32, newdquest1()31, quest1()30, quest1()30, quest1()29, quest1()28, quest1()28, newdquest1()27, newdquest1()26; sn n=75, k >= 2: 50, 42, 40, 38, 36, 36, 34, quest1()34, quest1()33, 32, quest1()32, quest1()32, quest1()31, quest1()30, quest1()30, quest1()29, quest1()28, quest1()28, newdquest1()27; sn n=76, k >= 2: 50, 43, 40, 38, 37, 36, 35, newdquest1()34, quest1()34, quest1()33, 32, quest1()32, quest1()32, newdquest1()30, quest1()30, quest1()30, newdquest1()28, quest1()28, quest1()28; sn n=77, k >= 2: 51, 44, 40, 39, 38, 36, 36, newdquest1()35, quest1()34, quest1()34, quest1()33, quest1()32, quest1()32, newdquest1()31, quest1()30, quest1()30, newdquest1()29, newdquest1()28, quest1()28; sn n=78, k >= 2: 52, 44, 40, 40, 38, 37, 36, quest1()36, quest1()35, quest1()34, quest1()34, newd1()32, quest1()32, quest1()32, quest1()31coderef(brouwer linear programming bound), quest1()30, quest1()30, newdquest1()29, quest1()28; pstailx no [81,9,38]; no [83,10,38]; type [80,13,34_2]; kill y76 by x_34_0; status: weights = 34_2 - {76}; type [80,17,32_2]; status: weights = 32_2 - {74,76,78}; type [80,20,30_2]; status: weights = 30_2 - {76,78,80}; type [81,11,36_2]; kill y70 by (x_25_11, x_27_9, x_29_11, x_30_10, x_31_9, x_31_11, x_32_8, x_32_10, x_33_3, x_33_5, x_33_7, x_33_9, x_33_11, x_34_2); status: weights = {36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,72}; kill y72 by (x_27_9, x_31_9, x_33_9, x_34_8, x_35_1, x_35_9, x_36_0) ; status: weights = {36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68}; type [81,14,34_2]; kill y74 by (x_34_0, x_36_0); status: weights = {34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72}; kill y72 by (x_26_8, x_27_7) ; status: weights = 34_2 - {72..81}; type [81,18,32_2]; status: weights = 32_2 - {46,66..81}; type [82,9,38_2]; status: weights = {38,40,44,46,48,50,52,54,56,60,62,64,66}; show (joint:0) y66 = 0; status: weights = {38,40,44,46,48,50,52,54,56,60,62,64}; kill jy38y40y64, jy38y44y64, jy38y52y64, jy40y44y64, jy40y46y64, jy40y48y62, jy40y50y62, jy40y52y64, jy40y56y60, jy40y56y62, jy40y56y64, jy44y44y60, jy44y44y62, jy44y44y64, jy44y46y62, jy44y46y64, jy44y48y64, jy44y52y60, jy44y52y62, jy44y52y64, jy44y56y56, jy46y46y64, jy46y48y64, jy46y52y62, jy46y52y64, jy48y48y60, jy48y48y62, jy48y48y64, jy48y52y56, jy48y52y64, jy52y52y52, jy38y44y62, jy40y40y62, jy40y48y60, jy40y52y56, jy44y48y56, jy44y52y52, jy48y48y52 ; type [82,12,36_2]; kill y68 by (x_23_13, x_29_11, x_29_13, x_30_12, x_30_14, x_31_11, x_31_13, x_32_12, x_32_14, x_33_3, x_33_9, x_33_11, x_33_13, x_34_2); status: weights = {36,38,40,42,44,46,48,50,52,56,58,60,62,64,66,82}; kill y82 by x_36; status: weights = {36,38,40,42,44,46,48,50,52,56,58,60,62,64,66}; type [82,15,34_2]; status: weights = 34_2 - {72..82}; type [83,5,42_2]; status: weights = {42,44,46,48}; type [83,13,36_2]; kill y66,y62,y58,y50,y46,y42; status: weights = {36,40,44,48,52,56,60,64}; kill jy36y64y64, jy40y60y64, jy44y56y64, jy44y60y60, jy48y52y64 ; type [83,16,34_2]; status: weights = 34_2 - {70..83}; type [83,19,32_2]; status: weights = 32_2 - {78..83}; type [83,23,30_2]; status: weights = 30_2 - {72..83}; type [83,38,22_2]; status: weights = 22_2 - {76..83}; type [84,8,40_2]; status: weights = {40,42,44,48,50,52,56,58,60,64}; type [84,8,40]; status: weights = {40,41,42,44,48,49,50,52,56,57,58,60,64}; type [84,10,38_2]; kill y84, y82, y80, y78 by x_38_0, y76 by x_38_0, y74 by (x_28_10, x_29_9, x_30_8, x_30_10, x_31_7, x_31_9, x_32_6); status: weights = {38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72}; no [79,13,34]; type [84,14,36_2]; status: weights = {36,40,44,48,52,56,60}; type [84,17,34_2]; status: weights = 34_2 - {68..84}; type [84,20,32_2]; status: weights = 32_2 - {78..84}; type [84,31,26_2]; status: weights = 26_2 - {82,84}; type [84,35,24_2]; status: weights = 24_2 - {82,84}; type [85,6,42_2]; kill y84, y68 by x_32_12; status: weights = {42,44,46,48,52,54,56,58,60,62,64,70}; show (joint:0) y52 = 0; kill y70 ; status: weights = {42,44,46,48,54,56,58,60,62,64}; type [85,9,40]; kill y49, ndiv4, y64, y52 by x_20_20; STATUS_WE(1 + 361t^40 + 135t^48 + 15t^56) type [85,11,38_2]; { kill y72 by (x_25_13, x_27_11, x_27_13, x_28_10, x_28_12, x_29_9, x_29_11, x_30_8), y70 by (x_23_15, x_24_14, x_25_15, x_26_12, x_27_11, x_27_13, x_29_15, x_30_14, x_31_15, x_32_12, x_32_14, x_33_9, x_33_13, x_34_10, x_34_12) }; status: weights = {38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68}; type [85,14,36_2]; kill y84, y82, y80, y78 by x_36_0, y76 by (x_27_9, x_30_8, x_31_7, x_31_9, x_33_7, x_34_8, x_35_1, x_35_3, x_35_5, x_35_7, x_35_9, x_36_2, x_36_6, x_37_1, x_37_3, x_37_5, x_37_7, x_37_9, x_38_0, x_38_4); status: weights = {36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74}; type [85,21,32_2]; status: weights = 32_2 - {74..85}; type [85,28,28_2]; status: weights = 28_2 - {84}; psheadx(105) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 psnext n=79, k >= 2: 52, 44, 41, 40, 39, 38, 36, quest1()36, quest1()36, newdquest1()34, quest1()34, newdquest1()33, newdquest1()32, quest1()32, quest1()32, quest1()31, quest1()30, quest1()30, quest1()29coderef(brouwer linear programming bound) ; sn n=80, k >= 2: 53, 45, 42, 40, 40, 38, 37, 36, quest1()36, newdquest1()35, newdquest1()34, quest1()34, newdquest1()33, quest1()32, quest1()32, quest1()32, newdquest1()30, quest1()30, quest1()30; sn n=81, k >= 2: 54, 46, 42, 40, 40, 39, 38, quest1()37, 36, quest1()36, newdquest1()35, quest1()34, quest1()34, quest1()33, quest1()32, quest1()32, newdquest1()31, newdquest1()30, quest1()30; sn n=82, k >= 2: 54, 46, 43, 41, 40, 40, 38, quest1()38, newd1()36, quest1()36, quest1()36, quest1()35, quest1()34, quest1()34, quest1()33, quest1()32, quest1()32, newdquest1()31, quest1()30; sn n=83, k >= 2: 55, 47, 44, 42, 40, 40, 39coderef(dodunekov ytrehus 1987), 38, newdquest1()37, newdquest1()36, quest1()36, quest1()36, quest1()35, quest1()34, quest1()34, quest1()33, quest1()32, quest1()32, quest1()31coderef(brouwer linear programming bound) ; sn n=84, k >= 2: 56, 48, 44, 42, 41, 40, 40, quest1()39, quest1()38, newdquest1()37, newdquest1()36, quest1()36, quest1()36, newdquest1()34, quest1()34, quest1()34, newdquest1()32, quest1()32, quest1()32; sn n=85, k >= 2: 56, 48, 44, 43, 42, 40, 40, quest1()40, 38, quest1()38, newdquest1()37, quest1()36, quest1()36, newdquest1()35, quest1()34, quest1()34, newdquest1()33, quest1()32, quest1()32; pstail pshead(105) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 psnext n=72, k >=21: newdquest1()25, newdquest1()24, quest1()24, quest1()24, newdquest1()23, quest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, newdquest1()17, quest1()16, quest1()16, quest1()16; sn n=73, k >=21: quest1()26, newdquest1()25, quest1()24, quest1()24, quest1()24, quest1()23coderef(brouwer linear programming bound), quest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20, quest1()18, quest1()18, quest1()18, quest1()17coderef(brouwer linear programming bound), quest1()16, quest1()16; sn n=74, k >=21: quest1()26, quest1()26, quest1()25coderef(brouwer linear programming bound), quest1()24, quest1()24, quest1()24, quest1()23, quest1()22, quest1()22, quest1()22, newdquest1()20, quest1()20, quest1()20, quest1()19coderef(brouwer linear programming bound), quest1()18, quest1()18, quest1()18, quest1()17, quest1()16; sn n=75, k >=21: newdquest1()26, quest1()26, quest1()26, quest1()25, quest1()24, quest1()24, quest1()24, newdquest1()22, quest1()22, quest1()22, newdquest1()21, newdquest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, quest1()18, quest1()17; sn n=76, k >=21: newdquest1()27, quest1()26, quest1()26, quest1()26, quest1()25, quest1()24, quest1()24, newdquest1()23, newdquest1()22, quest1()22, quest1()22, newdquest1()21, quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, quest1()18; sn n=77, k >=21: quest1()28, quest1()27coderef(brouwer linear programming bound), quest1()26, quest1()26, quest1()26, quest1()25, quest1()24, quest1()24, newdquest1()23, newdquest1()22, quest1()22, quest1()22, quest1()21coderef(brouwer linear programming bound), quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18; sn n=78, k >=21: quest1()28, quest1()28, quest1()27, quest1()26, quest1()26, quest1()26, quest1()25, quest1()24, quest1()24, newdquest1()23, quest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20, quest1()19, quest1()18; pstail pshead(105) // k = 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 psnext n=79, k >=21: quest1()28, quest1()28, quest1()28, quest1()27, quest1()26, quest1()26, quest1()26, newdquest1()24, quest1()24, quest1()24, quest1()23coderef(brouwer linear programming bound), quest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20, quest1()19; sn n=80, k >=21: quest1()29, quest1()28, quest1()28, quest1()28, newdquest1()26, quest1()26, quest1()26, newdquest1()25, newdquest1()24, quest1()24, quest1()24, quest1()23, quest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20, quest1()20; sn n=81, k >=21: quest1()30, quest1()29, quest1()28, quest1()28, newdquest1()27, newdquest1()26, quest1()26, quest1()26, newdquest1()25, quest1()24, quest1()24, quest1()24, quest1()23, quest1()22, quest1()22, quest1()22, quest1()21, quest1()20, quest1()20; sn n=82, k >=21: quest1()30, quest1()30, quest1()29, quest1()28, quest1()28, newdquest1()27, quest1()26, quest1()26, quest1()26, quest1()25coderef(brouwer linear programming bound), quest1()24, quest1()24, quest1()24, quest1()23, quest1()22, quest1()22, quest1()22, quest1()21, quest1()20; sn n=83, k >=21: quest1()30, quest1()30, quest1()30, quest1()28, quest1()28, quest1()28, quest1()27coderef(brouwer linear programming bound), quest1()26, quest1()26, quest1()26, quest1()25, quest1()24, quest1()24, quest1()24, quest1()23, quest1()22, quest1()22, quest1()22, newdquest1()20; sn n=84, k >=21: quest1()31, quest1()30, quest1()30, quest1()29coderef(brouwer linear programming bound), quest1()28, quest1()28, quest1()28, quest1()27, quest1()26, quest1()26, quest1()26, quest1()25, quest1()24, quest1()24, quest1()24, quest1()23, quest1()22, quest1()22, newdquest1()21; sn n=85, k >=21: 32, quest1()31, quest1()30, quest1()30, quest1()29, quest1()28, quest1()28, quest1()28, quest1()27, quest1()26, quest1()26, quest1()26, quest1()25, quest1()24, quest1()24, quest1()24, quest1()23, quest1()22, quest1()22; pstailx no [74,46,14]; psheadx(105) // k = 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 psnext n=72, k >=40: quest1()15, quest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, newdquest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, quest()7, 6, 6, 6; sn n=73, k >=40: quest1()16, quest1()15, quest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, quest()7, 6, 6; sn n=74, k >=40: quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, quest1()14, newdquest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, quest()7, 6; sn n=75, k >=40: quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, newdquest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8, quest()7; sn n=76, k >=40: quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8, quest()8; sn n=77, k >=40: quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, quest()8; sn n=78, k >=40: quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, newdquest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8; pstail pshead(45) // k = 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 psnext n=79, k >=40: quest1()18, quest1()18, quest1()18, quest1()16, quest1()16, quest1()16, newdquest1()15, newdquest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, quest1()11, quest1()10, quest1()10, quest1()10, quest()9; sn n=80, k >=40: quest1()19, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, newdquest1()15, quest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, quest1()12, newdquest1()10, quest1()10, quest1()10, quest1()10; sn n=81, k >=40: quest1()20, quest1()19, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, newdquest1()11, newdquest1()10, quest1()10, quest1()10; pstailx set price refinement count = 2; psheadx(60) // k = 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 psnext n=82, k >=40: quest1()20, quest1()20, newdquest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, quest1()14, quest1()13, quest1()12, quest1()12, newdquest1()11, quest1()10, quest1()10; sn n=83, k >=40: quest1()20, quest1()20, newdquest1()19, quest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, quest1()14, newdquest1()12, quest1()12, quest1()12, quest1()11, quest1()10; sn n=84, k >=40: quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, newdquest1()13, newdquest1()12, quest1()12, quest1()12, quest1()11; sn n=85, k >=40: quest1()21coderef(brouwer linear programming bound), quest1()20, quest1()20, quest1()20, quest1()19, quest1()18, quest1()18, quest1()18, quest1()17, quest1()16, quest1()16, quest1()16, quest1()15, quest1()14, quest1()14, newdquest1()13, quest1()13, quest1()12, quest1()12; pstailx psheadx(105) // k = 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 psnext n=72, k >=59: quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=73, k >=59: 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=74, k >=59: 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=75, k >=59: 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=76, k >=59: quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=77, k >=59: quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; sn n=78, k >=59: quest()8, quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2, 2; pstail pshead(105) // k = 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 psnext n=79, k >=59: 8, quest()8, quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2, 2; sn n=80, k >=59: quest()9, 8, quest()8, quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2, 2; sn n=81, k >=59: quest1()10, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2, 2; sn n=82, k >=59: quest1()10, newdquest()9, newd()8, 8, quest()8, quest()8, quest()7, 6, 6, 6, quest()6, quest()5, 4, 4, 4, 4, 3, 2, 2; sn n=83, k >=59: quest1()10, quest1()10, newdquest()9, 8coderef(brouwer linear programming bound), 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()6, quest()5, 4, 4, 4, 4, 3, 2; sn n=84, k >=59: quest1()10, quest1()10, quest1()10, quest()9, 8, 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()6, quest()5, 4, 4, 4, 4, 3; sn n=85, k >=59: quest1()11, quest1()10, quest1()10, quest1()10, quest()9, 8, 8, quest()8, quest()8, quest()7, 6, 6, quest()6, quest()6, quest()5, 4, 4, 4, 4; pstail pshead(105) // k = 78 79 80 81 82 83 84 psnext n=79, k >=78: 2; sn n=80, k >=78: 2, 2; sn n=81, k >=78: 2, 2, 2; sn n=82, k >=78: 2, 2, 2, 2; sn n=83, k >=78: 2, 2, 2, 2, 2; sn n=84, k >=78: 2, 2, 2, 2, 2, 2; sn n=85, k >=78: 3, 2, 2, 2, 2, 2, 2; pstailx data_comment( ![ \block{Partial tables for codes of length between $86$ and $228$} For these tables, we have not given references where credit is due, nor have we attached the question mark tag to results which may not be optimal. ]! ) set price refinement count = 1; type [86,5,44_2]; status: weights = {44,48}; type [86,12,38_2]; kill y86 by x_38; status: weights = {38,40,42,44,46,48,50,52,54,56,60,62,64,66,68}; type [87,4,46_2]; status: weights = {46,48}; type [87,10,40_2]; kill y86,y84,y82,y80,y76,y74,y72,y70; show (joint:5) y66 = 0; kill y58 by (x_22_20, x_24_16); status: weights = {40,42,44,48,50,52,56,60,64,68}; kill jy40y42y64, jy40y44y50, jy40y50y52, jy40y50y64, jy40y64y68, jy42y42y48 ; show (joint:5) y42 = 0, y50 = 0; status: weights = {40,44,48,52,56,60,64,68}; type [87,13,38_2]; status: weights = {38,40,44,46,48,50,52,54,56,60,62,64,66}; kill y66 ; via lp (joint:5) [current] = ; no [87,13,38]; type [88,6,44_2]; status: weights = {44,48,56,60,64}; type [88,11,40_2]; kill y88,y68,y64,y60; status: weights = {40,44,48,52,56}; type [88,11,40]; status: weights = {40,44,48,52,56}; no [88,11,40]; type [89,8,42_2]; kill y88, y84 by x_42_0; kill y82 by x_41_1 ; kill y86 ; status: weights = 42_2 - {82..89}; type [89,8,42]; kill y81, y77, y71, y73, y65, y69, y57; status: weights = {42..50,52..56,58,60..64,66,68,70,72,74,76,78,80}; type [89,11,40_2]; kill y88, y86, y84, y82 by (x_33_7, x_34_6, x_35_5, x_35_7, x_36_4), y80 by (x_31_9, x_32_8, x_33_7, x_33_9, x_34_6, x_34_8), y78, y76 by (x_27_13, x_28_12, x_29_11, x_29_13, x_30_10, x_30_12, x_31_9, x_31_11, x_31_13, x_32_8), y74 by (x_25_15, x_27_13, x_27_15, x_28_12, x_28_14, x_29_11, x_29_13, x_29_15, x_30_12, x_30_14, x_31_11, x_31_13, x_32_12, x_33_9, x_33_11, x_33_15, x_34_6) ; status: weights = {40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72}; type [89,14,38_2]; status: weights = 38_2 - {82,84,86,88}; kill y80 by (x_30_8, x_37_1, x_38_0, x_39_1) ; kill y78 by (x_27_11, x_28_10, x_29_11, x_32_10, x_33_11, x_36_10, x_37_1, x_37_11, x_38_0); status: weights = 38_2 - {78..89}; psheadx(60) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n=86, k >= 2: 57, 48, 45, 44, 42, 41, 40, 40, 39, 38, 38, newd1()36, 36; sn n=87, k >= 2: 58, 49, 46, 44, 43, 42, 40, 40, 40, newd1()38, 38, newd1()37, newd1()36; sn n=88, k >= 2: 58, 50, 46, 44, 44, 42, 41, newd1()40, 40, newd1()39, newd1()38, 38, newd1()37; sn n=89, k >= 2: 59, 50, 47, 45, 44, 43, 42, newd1()41, 40, 40, newd1()39, 38, 38; pstailx type [90,5,46_2]; status: weights = {46,48}; type [90,9,42_2]; status: weights = {42,44,46,48,52,54,56,58,60,62,64,68,70,72}; kill y72 by (x_27_15, x_28_16, x_29_13, x_30_12) ; status: weights = 42_2 - {50,66,72..90}; type [90,12,40_2]; kill y90 by x_40; status: weights = {40,42,44,46,48,50,52,54,56,58,60,64,66,68,70,72}; no [91,10,42]; type [91,13,40_2]; kill y70,y42,y66,y58,y54,y50, y72 by (x_22_18, x_24_16); status: weights = {40,44,48,52,56,60,64,68}; no [91,8,44]; type [92,6,46_2]; kill y92, y76, y68, y60, y52; status: weights = {46,48,62,64}; type [92,8,44_2]; status: weights = {44,46,48,52,56,60,64,68,72,76}; type [92,10,42_2]; status: weights = 42_2 - {86..92}; kill y84 by (x_36_6, x_36_8, x_37_5), y82 by (x_34_8, x_34_10, x_35_7), y80 by (x_32_10, x_33_9, x_33_11, x_34_8) ; status: weights = {42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78}; type [92,14,40_2]; status: weights = {40,44,48,52,56,60,64}; no [91,6,46]; no [91,8,44]; type [93,9,44]; status: weights = {44,48,56,60}; via lp (joint) [current] = ; no [93,9,44]; type [94,9,44_2]; status: weights = 44_2 - {54,70,78..94}; type [93,11,42_2]; kill y78; status: weights = {42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76}; kill y76 by (x_27_17, x_28_14, x_28_16, x_29_15, x_29_17, x_30_16, x_31_15, x_31_17, x_32_14, x_32_16, x_33_13, x_33_15, x_34_14, x_35_13, x_35_17, x_36_16, x_37_15, x_37_17, x_38_12, x_38_14) ; status: weights = {42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74}; no [92,11,42]; no [94,10,44]; type [94,12,42_2]; status: weights = {42,44,46,48,50,52,54,56,58,60,62,64,68,70,72,74}; type [95,4,50_2]; status: weights = {50,52,54,56}; TYPE_WE(95,6,48,1 + 62t^48 + t^64) type [95,10,44_2]; kill y74,y66,y50,y58; status: weights = {44,48,52,56,60,64,68,72,76}; no [94,8,46]; type [95,8,46_2]; kill y94, y92, y76, y68, y46; via lp [base] = ; no [95,8,46]; no [94,6,48]; type [96,8,46_2]; kill y96,y94,y88,y84,y80, y92, y78 by x_35_11; status: weights = {46,48,50,52,54,56,62,64,70,72}; kill jy46y46y50, jy46y48y50, jy46y50y50, jy46y50y52, jy46y50y64, jy48y48y50, jy48y50y50, jy48y52y56, jy48y52y62, jy48y52y64, jy48y52y70, jy48y52y72 ; show (joint:5) y50 = 0, y52 = 0; kill jy54y54y72, jy46y48y48 ; status: weights = {46,48,54,56,62,64,70,72}, constraints = {148 <= y46 <= 157, 57 <= y48 <= 63, 20 <= y54 <= 39, y56 <= 6, 3 <= y62 <= 15, y64 <= 3, y70 <= 1, y72 <= 1, 266 <= mu3 <= 404, div4 = 64, co <= 128}; type [96,13,42_2]; kill y94 by x_42_0, y92 by x_42_0, y90 by x_42_0; status: weights = 42_2 - {90,92,94}; kill y88 by (x_36_6, x_40_2) ; status: weights = 42_2 - {88..94}; type [97,11,44_2]; kill y96, y94, y92, y90, y86, y84, y82, y88 by x_44_0; status: weights = {44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80}; type [97,14,42_2]; status: weights = 42_2 - {88,90,92,94,96}; kill y86 by (x_32_10, x_36_10, x_42_0) ; status: weights = 42_2 - {86..97}; type [98,9,46_2]; status: weights = 46_2 - {58,74,82,84,86,88,90,92,94,96,98}; kill y80 by (x_29_17, x_30_18, x_31_15, x_32_14, x_32_16, x_33_13, x_33_15), y78 by (x_28_18, x_31_15, x_31_17, x_32_14, x_32_16, x_32_18, x_33_15, x_33_17, x_34_18, x_35_11, x_35_17, x_36_10, x_36_12, x_36_14, x_37_9, x_37_11, x_38_8) ; status: weights = {46,48,50,52,54,56,60,62,64,66,68,70,72,76}; type [98,12,44_2]; status: weights = {44,46,48,50,52,54,56,58,60,62,64,66,68,72,74,76,78,80}; kill y80 by (x_26_18, x_28_16, x_30_18, x_31_17, x_32_16, x_32_18, x_33_17, x_34_18, x_35_17, x_36_16, x_38_18, x_39_17, x_40_16, x_40_18), y78 by (x_24_20, x_25_19, x_29_19, x_30_20, x_31_19, x_32_20, x_33_19, x_36_20, x_37_19, x_38_20) ; status: weights = {44,46,48,50,52,54,56,58,60,62,64,66,68,72,74,76}; type [99,5,50_2]; status: weights = 50_2 - {66,68,74..99}; status: weights = {50,52,54,56,58,60,62,64}; type [99,8,48]; status: weights = {48,56,64,72}; type [99,10,46_2]; via lp (joint:0) [current] = ; no [99,10,46]; type [99,13,44_2]; kill ndiv4,y76; status: weights = {44,48,52,56,60,64,68,72}; type [100,10,46_2]; kill y100, y98, y96, y94, y92 by (x_38_8, x_40_8, x_44_8, x_45_7, x_46_0), y90 by (x_36_10, x_38_10); status: weights = 46_2 - {90..100}; kill y88 by (x_34_12, x_35_11, x_36_10, x_36_12, x_37_9), y86 by (x_32_14, x_33_13, x_35_11, x_37_9, x_37_11, x_38_10, x_38_12, x_38_14, x_39_7, x_39_9, x_39_11, x_39_13, x_40_6) ; status: weights = 46_2 - {86..100}; type [101,6,50_2]; kill y100, y84 by x_40_12; status: weights = {50,52,54,56,58,60,62,64}; type [101,9,48_2]; kill y100,y98,y96,y92,y88,y84,y82,y80; show (joint:5) y66 = 0; kill y68 ; status: weights = {48,50,52,54,56,64,72}; no [118,8,58]; no [119,8,58]; no [100,6,50]; type [101,11,46_2]; status: weights = 46_2 - {84..101}; type [101,14,44_2]; status: weights = 44_2 - {92,94,96,98,100}; kill y90 by (x_36_10, x_40_10, x_44_0) ; status: weights = 44_2 - {90..101}; type [102,4,54_2]; STATUS_WE(1 + 12t^54 + 3t^56) type [102,5,52_2]; status: weights = {52,56,60,64}; type [102,12,46_2]; kill y82, y102 by x_46; status: weights = {46,48,50,52,54,56,58,60,62,64,66,68,70,72,76,78,80}; kill y80 by (x_24_22, x_25_21, x_26_22, x_28_20, x_30_22, x_31_21, x_32_20, x_32_22, x_33_21, x_34_22, x_35_21, x_36_20, x_38_22, x_39_21, x_40_20, x_40_22) ; status: weights = {46,48,50,52,54,56,58,60,62,64,66,68,70,72,76,78}; psheadx(195) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n= 90, k >= 2: 60, 51, 48, 46, 44, 44, 42, 42, newd1()40, 40, 40, 39, 38; sn n= 91, k >= 2: 60, 52, 48, 46, 45, 44, 43, 42, newd1()41, newd1()40, 40, 40, 39; sn n= 92, k >= 2: 61, 52, 48, 47, 46, 45, 44, newd1()42, 42, newd1()41, newd1()40, 40, 40; sn n= 93, k >= 2: 62, 52, 48, 48, 46, 46, 44, newd1()43, 42, 42, newd1()41, 40, 40; sn n= 94, k >= 2: 62, 53, 49, 48, 47, 46, 44, 44, 43, 42, 42, newd1()40, 40; sn n= 95, k >= 2: 63, 54, 50, 48, 48, 47, 45, 44, 44, 42, 42, newd1()41, newd1()40; sn n= 96, k >= 2: 64, 54, 50, 48, 48, 48, 46, newd1()44, 44, 43, 42, 42, newd1()41; sn n= 97, k >= 2: 64, 55, 51, 48, 48, 48, 46, newd1()45, 44, 44, 43, 42, 42; sn n= 98, k >= 2: 65, 56, 52, 49, 48, 48, 47, 46, newd1()44, 44, 44, 43, 42; sn n= 99, k >= 2: 66, 56, 52, 50, 48, 48, 48, 46, newd1()45, newd1()44, 44, 44, newd1()42; sn n=100, k >= 2: 66, 56, 52, 50, 49, 48, 48, 47, 46, newd1()45, newd1()44, 44, newd1()43; sn n=101, k >= 2: 67, 57, 53, 51, 50, 49, 48, 48, 46, 46, newd1()45, newd1()44, 44; sn n=102, k >= 2: 68, 58, 54, 52, 50, 50, 48, 48, 47, 46, 46, newd1()44, 44; pstailx type [104,6,52_2]; show (joint:0) y58 = 0, y74 = 0; kill y104,y88; status: weights = {52,56,60,64,72,76,80}; status: weights = {52,56,60,64}; type [104,11,48_2]; kill y104,y102,y100,y98,y96,y94,y92,y90,y88,y84,y82,y80,y76,y74,y72,y66,y58; via lp [current] = ; no [104,11,48]; type [104,13,46_2]; kill y102 by x_46_0, y100 by x_46_0; status: weights = 46_2 - {100,102}; type [103,10,48_2]; status: weights = 48_2 - {54,62,70,78,84..103}; kill y82 ; status: weights = {48,50,52,56,58,60,64,66,68,72,74,76,80}; (* Oops -- this should be combined with the previous type [104,13,46_2]. *); type [104,13,46_2]; kill y98 by x_46_0, y96 by (x_46_0, x_48_0); status: weights = 46_2 - {96,98,100,102}; kill y94 by (x_45_1, x_46_0) ; status: weights = 46_2 - {94..102}; no [103,6,52]; no [103,13,46]; no [104,8,50]; type [105,11,48_2]; status: weights = 48_2 - {86..105}; type [105,14,46_2]; status: weights = 46_2 - {94..105}; kill y92 ; status: weights = 46_2 - {92..105}; type [106,5,54_2]; status: weights = {54,56,60,62,64}; no [106,9,50]; type [106,12,48_2]; status: weights = 48_2 - {78,86..106}; kill y84 by (x_26_22, x_28_20, x_29_21, x_30_20, x_30_22, x_31_21, x_32_20, x_34_22, x_35_21, x_36_20, x_36_22, x_37_21, x_38_22, x_39_21, x_40_20, x_42_22) ; status: weights = {48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,80,82}; type [107,13,48_2]; kill y82,y58,y50,ndiv4; status: weights = {48,52,56,60,64,68,72,76,80}; kill y80 by (x_24_24, x_26_22, x_26_26, x_28_20, x_28_24, x_30_18, x_30_22), y76 by (x_24_24, x_26_26, x_28_20, x_28_24, x_28_28, x_30_18, x_30_22, x_30_26, x_30_30, x_32_16) ; status: weights = {48,52,56,60,64,68,72}; type [108,6,54_2]; status: weights = {54,56,62,64,78,80}; status: weights = {54,56,62,64}; type [108,8,52_2]; status: weights = 52_4 - {108}; kill y104 ; status: weights = 52_4 - {104,108}; type [108,10,50_2]; status: weights = 50_2 - {98,100,102,104,106,108}; kill y96, y94 by (x_38_14, x_39_13) ; status: weights = 50_2 - {94..108}; no [108,14,48]; no [107,6,54]; no [107,8,52]; no [109,9,52]; type [109,11,50_2]; kill y88 ; status: weights = 50_2 - {88..109}; type [109,14,48_2]; status: weights = 48_2 - {100,102,104,108}; kill y106 by x_48_0; kill y98 by (x_37_11, x_39_11, x_40_10, x_41_11, x_44_10, x_45_11, x_47_1, x_48_0) ; status: weights = 48_2 - {98..109}; type [110,4,58_2]; status: weights = {58,60,62,64}; no [107,10,50]; type [110,9,52_2]; status: weights = {52,56,60,64,68,72,76,80,84,88,92} ; no [110,10,52]; no [110,12,50]; no [110,6,56]; type [111,6,56]; kill y80 ; status: weights = {56,64}; type [111,10,52_2]; status: weights = {52,56,60,64,68,72,76,80,84,88}; show (joint:0) y88 = 0; status: weights = {52,56,60,64,68,72,76,80,84}; type [112,8,54_2]; status: weights = {54,56,60,62,64,66,68,70,72,76,78,80,84,86,88,92,94,96,100, 108,110}; kill y108, y100 by x_44_12, y92 by (x_36_20, x_42_14, x_42_18, x_44_12, x_44_16, x_44_20); status: weights = {54,56,60,62,64,66,68,70,72,76,78,80,84,86,88,94,96,110}; kill y110, y84, y76, y68, y66 ; kill jy54y56y60, jy54y60y64, jy56y56y62, jy56y60y62, jy56y60y70, jy56y60y72 ; show (joint:0) y60 = 0; status: weights = {54,56,62,64,70,72,78,80,86,88,94,96}; type [112,11,52_2]; status: weights = {52,56,60,64,68,72}; no [112,11,52]; type [112,13,50_2]; kill y108, y106, y112 by x_50, y110 by x_50_0, y104 by x_50_0; kill y102 by (x_40_10, x_41_9, x_42_8, x_42_10, x_43_9, x_44_8, x_44_10, x_45_7, x_45_9, x_46_8), y100 by (x_38_12, x_42_12, x_44_12, x_46_12, x_48_12, x_50_0), y98 by (x_36_14, x_37_13, x_38_14, x_39_13, x_40_14, x_41_13, x_42_14, x_43_13, x_44_14, x_45_13, x_46_14, x_47_13, x_48_14, x_49_1, x_49_13) ; status: weights = 50_2 - {98..112}; no [111,8,54]; no [113,8,56]; no [113,9,54]; type [113,11,52_2]; kill y112,y110,y108,y106,y104,y102,y100,y98,y96,y94 ; status: weights = 52_2 - {94..113}; type [113,14,50_2]; status: weights = 50_2 - {98..112}; type [114,5,58_2]; status: weights = {58,60,62,64}; type [114,9,54_2]; status: weights = 54_2 - {58,74,90,98..114}; kill y96 by x_38_18, y94 ; status: weights = 54_2 - {58,74,90,94..114}; type [114,12,52_2]; status: weights = 52_2 - {54,86,90..114}; set auto mu1; type [115,8,56_2]; kill y114,ndiv4,y112; show (joint:0) 204 <= y56 <= 220, 2 <= y64 <= 50, y68 <= 35, y72 <= 18, y80 <= 9, y88 <= 3, y96 <= 2; show (joint:0) y56 <= 217, y64 >= 5, y68 <= 32, y72 <= 15, y80 <= 7, y88 <= 2, y96 <= 1; show (joint:0) div8 > 224; infer div8 = 256; status: weights = {56,64,72,80,88,96}; type [115,8,56]; status: weights = {56,64,72,80,88,96}; unset auto mu1; type [115,10,54_2]; status: weights = {54,56,60,62,64,68,70,72,76,78,80,84,86,88}; kill y86 by x_35_19 ; kill y84, y76 ; kill y88 by x_36_18 ; status: weights = {54,56,60,62,64,68,70,72,78,80}; type [115,13,52_2]; kill y82,y78,y74,y66,y58,y88; status: weights = {52,56,60,64,68,72,76,80,84}; kill y84 by (x_26_26, x_28_24, x_28_28, x_30_22, x_30_26, x_30_30, x_32_20, x_32_24, x_32_28, x_34_18, x_34_22), y80 by (x_26_26, x_28_28, x_30_26, x_30_30, x_32_24, x_32_28, x_32_32, x_34_22, x_34_26, x_34_30, x_34_34, x_36_16) ; status: weights = {52,56,60,64,68,72,76}; type [116,6,58]; status: weights = {58,60,62,64}; no [116,14,52]; no [115,6,58]; type [117,4,62_2]; status: weights = {62,64}; type [117,5,60_2]; status: weights = {60,64}; type [117,9,56_2]; status: weights = {56,64,66,68,70,72,80,84,88}; kill y88 ; show (joint:0) y70 = 0, y84 = 0; status: weights = {56,64,66,68,72,80}; type [117,11,54_2]; status: weights = 54_2 - {96..117}; type [117,14,52_2]; status: weights = 52_2 - {100,102,106,108,110,112,114}; kill y116 by (x_54_0, x_57_1) ; kill y104 ; status: weights = 52_2 - {100..117}; psheadx(205) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n=103, k >= 2: 68, 58, 54, 52, 51, 50, 48, 48, 48, newd1()46, 46, newd1()45, newd1()44; sn n=104, k >= 2: 69, 59, 55, 52, 52, 51, 49, 48, 48, newd1()47, newd1()46, 46, newd1()45; sn n=105, k >= 2: 70, 60, 56, 53, 52, 52, 50, newd1()48, 48, 48, newd1()47, 46, 46; sn n=106, k >= 2: 70, 60, 56, 54, 52, 52, 50, newd1()49, newd1()48, 48, 48, 47, 46; sn n=107, k >= 2: 71, 60, 56, 54, 53, 52, 51, 50, newd1()49, 48, 48, 48, newd1()46; sn n=108, k >= 2: 72, 61, 56, 55, 54, 53, 52, newd1()50, 50, 49, 48, 48, newd1()47; sn n=109, k >= 2: 72, 62, 57, 56, 54, 54, 52, newd1()51, newd1()50, 50, newd1()48, 48, 48; sn n=110, k >= 2: 73, 62, 58, 56, 55, 54, 52, 52, newd1()51, 50, newd1()49, newd1()48, 48; sn n=111, k >= 2: 74, 63, 58, 56, 56, 55, 53, 52, 52, newd1()50, 50, newd1()49, newd1()48; sn n=112, k >= 2: 74, 64, 59, 56, 56, 56, 54, newd1()52, 52, newd1()51, 50, 50, newd1()49; sn n=113, k >= 2: 75, 64, 60, 57, 56, 56, 54, newd1()53, 52, 52, 51, 50, 50; sn n=114, k >= 2: 76, 64, 60, 58, 56, 56, 55, 54, 53, 52, 52, 51, 50; sn n=115, k >= 2: 76, 65, 60, 58, 57, 56, 56, 54, 54, newd1()52, 52, 52, newd1()50; sn n=116, k >= 2: 77, 66, 61, 59, 58, 57, 56, 55, 54, newd1()53, 52, 52, newd1()51; sn n=117, k >= 2: 78, 66, 62, 60, 58, 58, 56, 56, 55, 54, 53, 52, 52; pstailx no [116,9,56]; type [118,10,56_2]; kill y118; show (joint:0) 719 <= y56 <= 722; status: weights = {56,64,72,80}; show (joint:5) 719 <= y56 <= 720, 215 <= y64 <= 219; show (joint:5) y64 <= 218, 85 <= y72 <= 88, y80 <= 1; status: weights = {56,64,72,80}, constraints = {719 <= y56 <= 720, 215 <= y64 <= 218, 85 <= y72 <= 88, y80 <= 1}; type [118,12,54_2]; status: weights = 54_2 - {58,90..118}; TYPE_WE(119,6,60,1 + 56t^60 + 7t^64) no [116,11,54]; no [116,9,56]; no [119,13,54]; no [118,6,60]; type [120,8,58_2]; kill y116, y112, y108, y104 by x_44_16, y102 by (x_42_16, x_45_15), y100 by (x_41_17, x_42_18, x_44_14, x_44_20, x_46_14, x_46_18, x_48_10, x_48_20); status: weights = 58_2 - {66,82,90,98,100,102,104,106,108,110,112,114,116}; kill y120, y96, y94 by x_38_20, y88 by (x_34_26, x_36_24, x_36_26, x_38_22), y84 ; kill y92 by (x_36_22, x_37_21, x_38_22, x_40_18, x_40_20, x_40_24, x_41_21, x_42_18, x_42_22, x_42_26, x_44_14, x_44_16, x_44_20, x_44_24, x_44_28, x_45_13) ; status: weights = 58_2 - {66,82,84,88..116,120}; type [120,11,56_2]; status: weights = {56,60,64,68,72,76,80,84}; kill y84 ; kill jy68y80y80, jy72y76y80, jy72y80y80, jy76y76y76, jy80y80y80, jy60y80y80, jy64y76y80, jy64y80y80, jy68y68y80, jy68y72y80, jy56y56y80, jy56y60y80, jy56y64y80, jy56y68y80, jy56y72y80, jy56y76y80, jy56y80y80, jy60y60y80 ; show (joint:0) y80 = 0; kill jy60y76y76, jy64y68y76, jy64y72y76, jy64y76y76, jy68y68y68, jy68y68y72 ; via lp (joint:5) [current] = ; no [120,11,56]; type [120,13,54_2]; kill y118,y116,y114,y112,y106,y104, y120 by x_54, y110 by (x_44_10, x_46_10); status: weights = 54_2 - {104,106,110,112,114,116,118,120}; kill y108 by x_54_0; status: weights = 54_2 - {104..120}; type [121,5,62_2]; status: weights = {62,64}; type [121,14,54_2]; status: weights = 54_2 - {102..121}; type [122,9,58_2]; status: weights = 58_2 - {66,82,98,102..122}; type [122,12,56_2]; status: weights = 56_2 - {62,90,94..122}; TYPE_WE(123,6,62,1 + 48t^62 + 15t^64) no [122,8,60]; no [121,9,58]; type [123,10,58_2]; status: weights = 58_2 - {66,74,82,90,94..123}; kill y88, y84 ; status: weights = {58,60,62,64,68,70,72,76,78,80,86,92}; status: weights = {58,60,62,64,68,70,72,76,78,80}; type [123,13,56_2]; status: weights = {56,60,64,68,72,76,80,84,88,92}; kill y92 by (x_28_28, x_30_30, x_32_28, x_34_30, x_36_28, x_38_30) ; status: weights = {56,60,64,68,72,76,80,84,88}; no [121,12,56]; no [124,14,56]; type [125,4,66_2]; status: weights = {66,68,70,72}; set auto mu1; type [125,9,60_2]; status: weights = {60,64,72,76,80,88,92,96}; kill y96 by x_40_20; show (joint:0) y92 = 0; status: weights = {60,64,72,76,80,88}; unset auto mu1; type [125,11,58_2]; status: weights = 58_2 - {102..125}; type [125,14,56_2]; status: weights = 56_2 - {102..122}; kill y124 ; status: weights = 56_2 - {102..125}; TYPE_WE(126,6,64,1 + 63t^64) type [126,8,62_2]; kill y124,y76; show (joint:5) y62 = 127, y64 = 127, y126 = 1; STATUS_WE(1 + 127t^62 + 127t^64 + t^126) type [126,8,62]; status: weights = {62,63,64,126}; no [124,9,60]; type [126,10,60_2]; set dual constraint bound = -1; kill y126,y88,y72; via lp [current] = ; no [126,10,60]; set dual constraint bound = 3; no [124,9,60]; no [124,11,58]; type [126,12,58_2]; kill y126,y100,y94,y90,y86,y96,y92,y82,y78,y74,y58; via lp [current] = ; no [126,12,58]; TYPE_WE(127,7,64,1 + 127t^64) type [127,10,60_2]; status: weights = 60_2 - {70,78,86,94,98,102..127}; kill y90 ; status: weights = {60,62,64,66,68,72,74,76,80,82,84,88,92,96,100}; type [127,12,58_2]; kill y126, y124, y122, y120, y114, y112, y110, y118 by x_58_0, y116 by x_58_0; status: weights = 58_2 - {110..127}; TYPE_WE(128,8,64,1 + 254t^64 + t^128) type [128,11,60_2]; kill y128,ndiv4,y100,y96; status: weights = {60,64,68,72,76,80,84,88,92}; kill y92 ; set adjoin extra brouwer constraints; kill jy68y88y88, jy72y84y88, jy72y88y88, jy76y80y88, jy76y84y84, jy80y80y84, jy80y80y88, jy80y88y88, jy60y88y88, jy64y84y88, jy64y88y88, jy68y80y88, jy68y84y84, jy68y84y88, jy72y72y88, jy72y76y88, jy72y80y84, jy72y80y88, jy72y84y84, jy76y76y84, jy76y76y88; show (joint:5) y88 = 0; kill jy60y84y84, jy64y80y84, jy64y84y84, jy68y68y84, jy68y72y84, jy68y76y84, jy68y80y80, jy68y80y84, jy72y72y84, jy72y76y80, jy72y76y84, jy72y80y80; show (joint:5) y84 = 0; kill jy76y76y76, jy76y76y80, jy76y80y80, jy80y80y80, jy60y64y80, jy60y72y80, jy60y76y80, jy60y80y80, jy64y64y80, jy64y68y80; show (joint:5) y80 = 0; kill jy64y72y76, jy68y68y76, jy68y76y76, jy72y72y76, jy72y76y76; config 76,52 : {10}; show (iterate) 1309 <= y60 <= 1313, y64 <= 15, 122 <= y68 <= 141, 588 <= y72 <= 600, 1 <= y76 <= 4, 19 <= mu3 <= 20, 115 <= x_36_32 <= 116, 808 <= x_38_22 <= 818, 472 <= x_32_28 <= 484, 4 <= x_34_26 <= 25; show (joint:5) y64 >= 1; kill x_32_32, x_30_30, x_36_32; via lp [current] = ; @[base] infer y76 = 0; kill jy60y60y68, jy60y64y68, jy60y64y72, jy60y68y68, jy60y68y72, jy60y72y72; via lp (joint:0) [current] = ; no [128,11,60]; unset adjoin extra brouwer constraints; type [128,13,58_2]; status: weights = 58_2 - {108..128}; type [129,9,62_2]; status: weights = {62,64,68,76,78,80,82,84,92}; kill y92 ; kill y76 ; status: weights = {62,64,68,78,80,82,84}; type [129,14,58_2]; status: weights = 58_2 - {106..129}; type [130,5,66_2]; status: weights = {66,68,70,72,74,76,78,80}; type [130,12,60_2]; kill y130,y128,y126,y124,y122,y120,y118,y116,y114,y112,y110,y108,y106,y104, y100,y98,y94,y90,y86,y62,y66,y82,y78,y74; status: weights = {60,64,68,72,76,80,84,88,92,96}; type [131,10,62_2]; status: weights = 62_2 - {74,82,90,98,102..131}; kill y100, y92 ; status: weights = {62,64,66,68,70,72,76,78,80,84,86,88,94,96}; type [132,4,70_2]; status: weights = {70,72}; no [131,9,64]; type [132,9,64]; status: weights = {64,80}; via lp (joint) [current] = ; no [132,9,64]; no [129,12,60]; type [132,14,60_2]; { kill y96,y92,y88,y84,y80,y76; show y132 = 1; config from x_132|x_60|x_24_36; via lp [current] = }; no [132,14,60]; type [133,5,68_2]; status: weights = {68,72,76,80}; type [133,6,66_2]; kill y132, y116 by x_56_12; status: weights = 66_2 - {98,114,116,120..133}; kill y100 ; status: weights = 66_2 - {98,100,114,116,120..133}; status: weights = 66_2 - {98..133}; type [133,11,62_2]; status: weights = 62_2 - {108..133}; type [133,14,60_2]; status: weights = 60_2 - {108..130}; type [134,10,64_2]; status: weights = {64,68,72,80,88}; type [134,10,64]; show (joint:5) y65 = 0; status: weights = {64,68,72,80,88}; type [135,7,66_2]; kill y132; status: weights = 66_2 - {114,122,126,130,132}; kill y134 ; kill y124, y116 ; status: weights = 66_2 - {114,116,122..126,130..135}; type [135,12,62_2]; status: weights = 62_2 - {114..122,126..135}; kill y124 by x_62_0 ; status: weights = 62_2 - {114..135}; type [136,6,68_2]; kill y106,ndiv4,y136,y120; status: weights = {68,72,76,80,84,88,92,96,104,108,112}; status: weights = {68,72,76,80,84,88,92,96}; no [134,7,66]; type [136,8,66_2]; status: weights = 66_2 - {82,98,106,114,116,122,124,126,130..136}; kill y120,y118,y112,y110,y108,y104,y102,y100,y96,y94,y92,y90,y88,y86, y84,y80,y78,y76,y74; status: weights = {66,68,70,72,128}; type [136,11,64_2]; status: weights = {64,68,72,76,80,84,88,92,96,100}; kill y100 ; status: weights = {64,68,72,76,80,84,88,92,96}; type [136,13,62_2]; status: weights = 62_2 - {114..136}; type [137,5,70_2]; status: weights = {70,72,76,78,80}; type [137,14,62_2]; status: weights = 62_2 - {110..137}; psheadx(275) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n=118, k >= 2: 78, 67, 62, 60, 59, 58, 56, 56, 56, 54, 54, newd1()52, 52; sn n=119, k >= 2: 79, 68, 63, 60, 60, 59, 57, newd1()56, 56, newd1()54, 54, newd1()53, newd1()52; sn n=120, k >= 2: 80, 68, 64, 61, 60, 60, 58, newd1()56, 56, newd1()55, 54, 54, newd1()53; sn n=121, k >= 2: 80, 68, 64, 62, 60, 60, 58, 57, 56, 56, 55, 54, 54; sn n=122, k >= 2: 81, 69, 64, 62, 61, 60, 58, 58, 57, 56, 56, 55, 54; sn n=123, k >= 2: 82, 70, 64, 63, 62, 61, 59, 58, 58, newd1()56, 56, 56, newd1()54; sn n=124, k >= 2: 82, 70, 65, 64, 62, 62, 60, 59, 58, newd1()57, 56, 56, newd1()55; sn n=125, k >= 2: 83, 71, 66, 64, 63, 62, 61, 60, newd1()58, 58, newd1()56, 56, 56; sn n=126, k >= 2: 84, 72, 66, 64, 64, 63, 62, 60, newd1()59, 58, newd1()57, newd1()56, 56; sn n=127, k >= 2: 84, 72, 67, 64, 64, 64, 63, 60, 60, newd1()58, 58, newd1()57, newd1()56; sn n=128, k >= 2: 85, 72, 68, 64, 64, 64, 64, 61, 60, newd1()59, 58, 58, newd1()57; sn n=129, k >= 2: 86, 73, 68, 65, 64, 64, 64, 62, newd1()60, 60, 59, 58, 58; sn n=130, k >= 2: 86, 74, 68, 66, 64, 64, 64, 62, newd1()61, 60, 60, 59, 58; sn n=131, k >= 2: 87, 74, 69, 66, 64, 64, 64, newd1()62, 62, newd1()60, 60, 60, newd1()58; sn n=132, k >= 2: 88, 75, 70, 67, 65, 64, 64, newd1()63, newd1()62, newd1()61, 60, 60, newd1()59; sn n=133, k >= 2: 88, 76, 70, 68, 66, 64, 64, 64, newd1()63, 62, newd1()60, 60, 60; sn n=134, k >= 2: 89, 76, 71, 68, 66, 65, 64, 64, 64, 62, newd1()61, newd1()60, 60; sn n=135, k >= 2: 90, 76, 72, 68, 67, 66, 65, 64, 64, 63, 62, newd1()61, newd1()60; sn n=136, k >= 2: 90, 77, 72, 69, 68, 66, 66, 64, 64, 64, 62, 62, newd1()61; sn n=137, k >= 2: 91, 78, 72, 70, 68, 67, 66, newd1()64, 64, 64, 63, 62, 62; pstailx type [138,7,68_2]; kill y106,y94,y90,y86,y82,y78,y74,y138; status: weights = {68,72,76,80,84,88,92,96,100,104,108,112,120,136}; show (joint:0) y136 = 0; status: weights = {68,72,76,80,84,88,92,96,100,104,108,112,120}; no [138,9,66]; type [138,12,64_2]; kill y138,y136,y134,y132,y130,y128,y126,y124,y122,y120,y118,y116,y114,y112, y108,y106,y102,y98,y94,y90,y86,y82,y74,ndiv4; status: weights = {64,68,72,76,80,84,88,92,96,100,104}; type [139,8,68_2]; kill y120 by x_56_12, y112, y104 by (x_52_28, x_44_28), y96 by (x_36_36, x_44_36); via lp (joint) [current] = ; no [139,8,68]; type [140,4,74_2]; status: weights = {74,76,78,80}; set auto mu1; type [140,6,70_2]; status: weights = 70_2 - {74,90,98..106,114..140}; show (joint:0) y76 = 0, y92 = 0, y108 = 0; status: weights = {70,72,78,80,82,84,86,88,94,96,110,112}; status: weights = {70,72,78,80,82,84,86,88,94,96}; type [140,8,68_2]; kill y138,y122,y114,y106,y98,y94,y90,y82 ; status: weights = 68_2 - {82,86,90,94,98,102,106,110,114,118,122,126,130,134, 138}; kill y136 ; status: weights = 68_2 - {82,86,90,94,98,102,106,110,114,118,122,126,130,134, 136,138}; type [140,10,66_2]; status: weights = 66_2 - {122..140}; kill y120,y118 ; status: weights = 66_2 - {116..140}; type [139,13,64_2]; status: weights = 64_4 - {104..139}; type [140,14,64_2]; kill y100,y96,y92,y88,y84,y80; kill [current] by (x_140|x_64|x_26_38); no [140,14,64]; type [141,11,66_2]; status: weights = 66_2 - {112..141}; type [141,14,64_2]; kill y138,y136,y134,y132,y130,y128,y124,y122,y120,y118,y116,y114,y112,y126; status: weights = 64_2 - {112..138}; type [142,7,70_2]; status: weights = 70_2 - {74,102,106,114,118..122,126..140}; kill y142,y124,y116,y98,y90,y100,y108,y92,y82,y84,y76; ??kill y112 by (x_48_30, x_56_30), y104 by x_52_20 ; status: weights = {70,72,78,80,86,88,94,96,110}; type [142,9,68_2]; status: weights = {68,72,74,76,78,80,82,84,88,90,92,94,96,100,104,108, 100,104,108,112,116,120,136}; type [143,6,72_2]; status: weights = {72,80,84,88,96,112}; type [143,6,72]; status: weights = {72,80,84,88,96,112}; kill y84 ; status: weights = {72,80,88,96,112}; status: weights = {72,80,88,96}; type [143,10,68_2]; status: weights = 68_4 - {112,116..143}; type [143,12,66_2]; status: weights = 66_2 - {120..143}; type [144,8,70_2]; status: weights = 70_2 - {90,106,114,122,130,134,138,140}; kill y144,y142,y132,y124,y116,y108,y100,y98,y92 ; kill y136 ; status: weights = {70,72,74,76,78,80,82,84,86,88,94,96,102,104,110,112,118,120,126,128}; type [144,11,68_2]; status: weights = 68_4 - {112..144}; kill y108 ; status: weights = {68,72,76,80,84,88,92,96,100}; type [144,13,66_2]; status: weights = 66_2 - {118..144}; type [145,5,74_2]; status: weights = {74,76,78,80}; type [145,7,72_2]; kill y144,ndiv4,y112; show (joint:0) y92 = 0, y100 = 0; show div8 > 112; infer div8 = 128; status: weights = {72,80,88,96}; type [145,7,72]; status: weights = {72,80,88,96}; type [146,9,70_2]; status: weights = 70_2 - {74,90,106,122,126..146}; type [147,10,70_2]; kill y116,y112,y110,y108,y100,y92,y84,y82,y76 ; status: weights = {70,72,78,80,86,88,94,96,102,104}; no [143,8,70]; type [145,14,66_2]; status: weights = 66_2 - {114..145}; type [146,12,68_2]; kill y146,y144,y142,y140,y138,y136,y134,y132,y130,y128,y126,y124,y122,y120, y116,y114,y112,y110,y106,y102,y98,y94,y90,y82,ndiv4; status: weights = 68_4 - {112..146}; type [147,4,78_2]; status: weights = {78,80}; type [147,8,72_2]; kill y146,ndiv4; status: weights = 72_4 - {92,108,116,124,132..140}; show (joint:0) y100 = 0, y144 = 0; kill jy72y72y84, jy72y84y84, jy76y84y120, jy80y80y84, jy80y84y84, jy80y84y96, jy84y84y104, jy84y84y112, jy84y84y88, jy84y84y96 ; show (joint:5) y84 = 0; status: weights = {72,76,80,88,96,104,112,120,128}; type [147,13,68_2]; status: weights = 68_4 - {112..147}; type [148,5,76_2]; status: weights = {76,80}; type [148,6,74_2]; status: weights = 74_2 - {82,98,106..114,122..148}; kill y116, y100 ; status: weights = {74,76,78,80,84,86,88,90,92,94,96,102,104,118,120}; status: weights = {74,76,78,80,84,86,88,90,92,94,96}; no [148,9,72]; type [149,9,72_2]; status: weights = 72_2 - {74,76,78,86,90,92,94,106,108,110,118,120..149}; type [149,11,70_2]; status: weights = 70_2 - {122..149}; type [149,14,68_2]; status: weights = 68_2 - {118..146}; type [150,7,74_2]; kill y148; status: weights = 74_2 - {82,110,114,122,126..130,134..148}; kill y150,y132,y120,y118,y116,y104,y102,y100,y98,y88,y86,y84,y124 ; status: weights = {74,76,78,80,90,92,94,96,106,108,112}; type [150,10,72_2]; status: weights = {72,80,88,96}; type [151,6,76_2]; kill y90,y120,y104; status: weights = {76,80,88,92,96}; type [151,6,76]; status: weights = {76,80,88,92,96}; type [151,12,70_2]; status: weights = 70_2 - {126..151}; type [152,5,78_2]; status: weights = {78,80}; type [152,8,74_2]; kill y148; status: weights = 74_2 - {98,114,122,130,138,142,146,148}; kill y152,y150,y144,y140,y136,y134,y132,y120,y118,y116; status: weights = {74,76,78,80,82,84,86,88,90,92,94,96,100,102,104,106,108,110,112,124,126,128}; type [152,11,72_2]; status: weights = {72,76,80,84,88,92,96,100,104,108,112}; type [152,13,70_2]; status: weights = 70_2 - {122..152}; type [153,7,76]; status: weights = {76,80,92,96,108}; type [153,14,70_2]; status: weights = 70_2 - {118..153}; type [154,9,74_2]; status: weights = 74_2 - {82,98,114,126,130,134..154}; type [154,12,72_2]; kill y154,y152,y150,y148,y146,y144,y142,y140,y138,y136,y134,y132,y130,y128, y124,y122,y120,y118,y116,y114,y110,y106,y102,y98,y90,y86,ndiv4; status: weights = {72,76,80,84,88,92,96,100,104,108,112}; type [155,4,82_2]; status: weights = {82,84,86,88}; type [155,6,78]; status: weights = {78,80,94,96}; type [155,8,76_2]; kill y154,ndiv4; status: weights = {76,80,84,88,92,96,104,108,112,120,128,136,152}; show (joint:0) y120 = 0, y136 = 0, y152 = 0; show (joint:5) y104 = 0; status: weights = {76,80,84,88,92,96,108,112,128}; type [155,10,74_2]; status: weights = 74_2 - {82,98,106,114,122..155}; kill y120,y118,y116; status: weights = 74_2 - {82,98,106,114..155}; type [156,13,72_2]; status: weights = 72_2 - {126..156}; type [157,7,78]; status: weights = {78,80,94,96,110,112,126}; type [157,9,76_2]; status: weights = 76_2 - {78,82,84,86,94,98,100,102,114..118,122,126..157}; kill y124 ; kill y106,y90 ; status: weights = {76,80,88,92,96,104,108,112,120}; type [157,11,74_2]; status: weights = 74_2 - {128..157}; no [155,13,72]; type [157,14,72_2]; status: weights = 72_2 - {122..157} ; unset auto mu1; type [158,10,76]; status: weights = {76,80,92,96}; show (joint) y92 != 0; kill [current] by (x_92|x_44_48) ; psheadx(280) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n =138, k >= 2: 92, 78, 72, 70, 68, 68, 66, newd1()65, newd1()64, 64, 64, 63, 62; sn n =139, k >= 2: 92, 79, 73, 71, 69, 68, 67, 66, newd1()65, 64, 64, 64, newd1()62; sn n =140, k >= 2: 93, 80, 74, 72, 70, 68, 68, newd1()66, 66, 65, 64, 64, newd1()63; sn n =141, k >= 2: 94, 80, 74, 72, 70, 69, 68, newd1()67, newd1()66, 66, newd1()64, 64, 64; sn n =142, k >= 2: 94, 80, 75, 72, 71, 70, 68, 68, newd1()67, 66, newd1()65, newd1()64, 64; sn n =143, k >= 2: 95, 81, 76, 72, 72, 70, 69, 68, 68, 67, 66, newd1()65, newd1()64; sn n =144, k >= 2: 96, 82, 76, 73, 72, 71, 70, newd1()68, 68, 68, 66, 66, newd1()65; sn n =145, k >= 2: 96, 82, 76, 74, 72, 72, 70, newd1()69, newd1()68, 68, 67, 66, 66; sn n =146, k >= 2: 97, 83, 77, 74, 72, 72, 71, 70, newd1()69, 68, 68, 67, 66; sn n =147, k >= 2: 98, 84, 78, 75, 73, 72, 72, newd1()70, 70, newd1()68, 68, 68, newd1()66; sn n =148, k >= 2: 98, 84, 78, 76, 74, 72, 72, newd1()71, newd1()70, newd1()69, 68, 68, newd1()67; sn n =149, k >= 2: 99, 84, 79, 76, 74, 73, 72, 72, newd1()71, 70, newd1()68, 68, 68; sn n =150, k >= 2: 100, 85, 80, 76, 75, 74, 72, 72, 72, 70, newd1()69, newd1()68, 68; sn n =151, k >= 2: 100, 86, 80, 77, 76, 74, 73, 72, 72, 71, 70, newd1()69, newd1()68; sn n =152, k >= 2: 101, 86, 80, 78, 76, 75, 74, newd1()72, 72, 72, 70, 70, newd1()69; sn n =153, k >= 2: 102, 87, 80, 78, 76, 76, 74, newd1()73, 72, 72, 71, 70, 70; sn n =154, k >= 2: 102, 88, 81, 79, 77, 76, 75, 74, 73, 72, 72, 70, 70; sn n =155, k >= 2: 103, 88, 82, 80, 78, 76, 76, newd1()74, 74, newd1()72, 72, 71, 70; sn n =156, k >= 2: 104, 88, 82, 80, 78, 77, 76, newd1()75, 74, newd1()73, 72, 72, 71; sn n =157, k >= 2: 104, 89, 83, 80, 79, 78, 76, 76, newd1()74, 74, newd1()72, 72, 72; pstailx set auto mu1; TYPE_WE(158,6,80,1 + 62t^80 + t^96) type [159,8,78_2]; kill y158, y156; kill y88 ; status: weights = {78,80,84,92,94,96,98,100,108,110,112,116,124,132,140}; show (joint:0) y84 = 0, y92 = 0, y98 = 0, y100 = 0, y108 = 0, y116 = 0, y124 = 0, y132 = 0, y140 = 0; status: weights = {78,80,94,96,110,112}; type [159,8,78]; status: weights = {78,80,94,96,110,112}; type [159,12,74_2]; status: weights = 74_2 - {130..159}; type [160,7,80]; status: weights = {80,96,112,128}; type [160,11,76_2]; status: weights = {76,80,84,88,92,96,100,104,108,112,116}; type [160,13,74_2]; status: weights = 74_2 - {126..160}; type [161,5,82_2]; status: weights = {82,84,86,88,90,92,94,96}; type [161,9,78_2]; status: weights = 78_2 - {82,86,88,90,98,102,104,106,118..161}; kill y116 by (x_40_40, x_44_40), y114; kill y108, y92 ; status: weights = {78,80,84,94,96,100,110,112}; type [161,14,74_2]; status: weights = 74_2 - {122,126..161}; psheadx(55) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n =158, k >= 2: 105, 90, 84, 80, 80, 78, 77, 76, newd1()75, 74, newd1()73, 72, 72; sn n =159, k >= 2: 106, 90, 84, 80, 80, 79, 78, 76, 76, 75, 74, 73, 72; sn n =160, k >= 2: 106, 91, 84, 81, 80, 80, 78, 77, 76, 76, 74, 74, 73; sn n =161, k >= 2: 107, 92, 85, 82, 80, 80, 79, 78, newd1()76, 76, 75, 74, 74; pstailx type [162,4,86_2]; status: weights = {86,88}; type [162,8,80_2]; kill y162,ndiv4,y160,y100; status: weights = {80,96,112}; type [162,8,80]; show (joint:5) 234 <= y80 <= 239, 11 <= y96 <= 21, y112 <= 5; show (joint:5) y80 <= 237, y96 >= 14, y112 <= 3; show (joint:5) y80 <= 236, y96 >= 16, y112 <= 2; show (joint:5) 234 <= y80 <= 235, y96 >= 18, y112 <= 1; show (joint:5) y96 >= 19; status: weights = {80,96,112}, constraints = {234 <= y80 <= 235, 19 <= y96 <= 21, y112 <= 1}; no [162,10,78]; type [162,12,76_2]; kill y162,y160,y158,y156,y154,y152,y150,y148,y146,y144,y142,y140,y138,y136,y132, y130,y128,y126,y124,y122,y120,y118,y114,y110,y106,y98,y94,y90,ndiv4; status: weights = {76,80,84,88,92,96,100,104,108,112,116}; type [163,10,78_2]; status: weights = 78_2 - {90,106,114,122..163}; type [164,5,84_2]; status: weights = {84,88,92,96}; type [164,6,82_2]; status: weights = 82_2 - {98,114,122..130,138..164}; kill y132, y116 ; status: weights = 82_2 - {98,114,116,122..132,138..164}; status: weights = 82_2 - {98..164}; type [164,9,80_2]; kill y164, ndiv4, y160, y144, y128, y116; status: weights = {80,96,112}; type [164,9,80]; status: weights = {80,96,112}; type [164,11,78_2]; status: weights = {78,80,84,88,92,94,96,100,104,108,112,116}; kill y94,y92,y88; via lp [current] = ; no [164,11,78]; type [164,13,76_2]; status: weights = 76_2 - {130..164}; no [165,10,80]; type [165,11,78_2]; status: weights = 78_2 - {134..165}; type [165,14,76_2]; status: weights = 76_2 - {126..165}; type [166,7,82_2]; kill y166,y164,y148,y140,y136,y134,y132,y102,y100 ; status: weights = 82_2 - {98,100,102,126,130..166}; type [166,10,80_2]; status: weights = {80,82,84,88,96,100,104,112}; type [167,6,84_2]; kill y106,ndiv4,y136,y120; status: weights = {84,88,92,96,104,108,112}; type [167,6,84]; status: weights = {84,88,92,96,104,108,112}; type [167,6,84]; status: weights = {84,88,92,96}; type [167,12,78_2]; status: weights = 78_2 - {134..167}; type [168,5,86_2]; status: weights = {86,88,92,94,96}; type [168,8,82_2]; kill y168,y166,y164,y160,y156,y152,y150,y148,y136,y134,y132 ; status: weights = 82_2 - {114,130..138,146..168}; type [168,11,80_2]; status: weights = 80_4 - {128..168}; type [168,13,78_2]; status: weights = 78_2 - {132..168}; type [169,7,84_2]; kill y168,ndiv4; status: weights = {84,88,92,96,104,108,112,116,120,124,136}; show (joint:0) y104 = 0, y136 = 0; status: weights = {84,88,92,96,108,112,116,120,124}; type [169,7,84]; status: weights = {84,88,92,96,108,112,116,120,124}; type [170,4,90_2]; status: weights = {90,92,94,96}; type [170,9,82_2]; status: weights = 82_2 - {98,114,130,146,150..162,166..170}; kill y164 ; status: weights = 82_2 - {98,114,130,142,146,150..170}; no [167,8,82]; no [169,9,82]; type [170,12,80_2]; kill y170,y168,y166,y164,y162,y160,y158,y156,y154,y152,y150,y148,y146,y144, y140,y138,y136,y134,y132,y130,y128,y126,y124,y122,y118,y114,y106,y102, y98,y94,ndiv4,y120; status: weights = {80,84,88,92,96,100,104,108,112,116}; type [171,6,86_2]; status: weights = {86,88,92,94,96,108,110,112}; show (joint:0) y92 = 0, y108 = 0; status: weights = {86,88,94,96,110,112}; type [171,6,86]; status: weights = {86,88,94,96,110,112}; type [171,6,86]; status: weights = {86,88,94,96}; type [171,8,84_2]; status: weights = 84_4 - {116,132,140,148,156..164}; show (joint:0) y136 = 0, y152 = 0, y168 = 0; status: weights = {84,88,92,96,100,104,108,112,120,124,128,144}; kill jy100y108y120, jy104y104y120, jy104y108y108, jy104y112y112, jy108y108y112, jy108y108y120; config 120,51 : {10}; kill x_52_44, x_48_40, x_44_44, x_56_40; at [base]; kill y144 by x_68_20; at [base]; kill jy88y104y128, jy88y112y112, jy88y112y128, jy96y104y128, jy96y112y112; status: weights = {84,88,92,96,100,104,108,112,120,124,128}; type [171,10,82_2]; status: weights = 82_2 - {98,114,122..171}; no [172,9,84]; no [172,11,82]; type [172,13,80_2]; kill y172,y170,y168,y166,y164,y162,y160,y158,y156,y154,y152,y150,y148,y146; kill y144 ; kill y142,y140,y138,y136,y134,y82,y130; kill y126 ; kill y118,y114,y110,y106,y122,y102,y94,ndiv4; status: weights = 80_4 - {136..172}; type [173,7,86_2]; kill y172; show (joint:0) y92 = 0, y100 = 0, y108 = 0, y114 = 0, y116 = 0, y124 = 0, y140 = 0, y142 = 0; status: weights = {86,88,94,96,110,112,118,120,126,128}; type [173,9,84_2]; status: weights = 84_4 - {100,116,132,144..173}; kill y140 ; status: weights = {84,88,92,96,104,108,112,120,124,128,136}; type [173,11,82_2]; status: weights = 82_2 - {140..173}; type [173,14,80_2]; status: weights = 80_4 - {132..173}; type [174,6,88_2]; status: weights = {88,96}; type [174,10,84_2]; status: weights = {84,88,92,96,104,108,112}; show (joint:0) y112 = 0; status: weights = {84,88,92,96,104,108}; type [174,10,84]; status: weights = {84,88,92,104,108}; type [175,8,86_2]; kill y172, y174; status: weights = {86,88,92,94,96,100,104,108,110,112,114,116,124,126,128,132, 140,148,156}; kill y156,y148,y140,y132; kill y124,y116,y114,y108,y104,y100 ; status: weights = {86,88,92,94,96,110,112,126,128}; type [175,12,82_2]; status: weights = 82_2 - {140..175}; type [176,5,90_2]; status: weights = {90,92,94,96}; type [176,7,88_2]; status: weights = {88,96,112,120,128}; type [176,11,84_2]; status: weights = 84_4 - {132..176}; type [176,13,82_2]; kill y176,y138,y136,y134,y102,y98,y96; via lp [current] = ; no [176,13,82]; psheadx(195) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n =162, k >= 2: 108, 92, 86, 82, 80, 80, 80, 78, newd1()77, 76, 76, 74, 74; sn n =163, k >= 2: 108, 92, 86, 83, 81, 80, 80, 79, 78, newd1()76, 76, 75, 74; sn n =164, k >= 2: 109, 93, 87, 84, 82, 80, 80, 80, 78, newd1()77, 76, 76, 75; sn n =165, k >= 2: 110, 94, 88, 84, 82, 81, 80, 80, 79, 78, newd1()76, 76, 76; sn n =166, k >= 2: 110, 94, 88, 84, 83, 82, 80, 80, 80, newd1()78, newd1()77, newd1()76, 76; sn n =167, k >= 2: 111, 95, 88, 85, 84, 82, 81, 80, 80, newd1()79, newd1()78, newd1()77, newd1()76; sn n =168, k >= 2: 112, 96, 88, 86, 84, 83, 82, newd1()80, 80, 80, newd1()78, 78, newd1()76; sn n =169, k >= 2: 112, 96, 89, 86, 84, 84, 82, newd1()81, newd1()80, 80, newd1()79, 78, newd1()77; sn n =170, k >= 2: 113, 96, 90, 87, 85, 84, 83, 82, newd1()81, 80, 80, 78, 78; sn n =171, k >= 2: 114, 97, 90, 88, 86, 84, 84, newd1()82, 82, newd1()80, 80, 79, 78; sn n =172, k >= 2: 114, 98, 91, 88, 86, 85, 84, newd1()83, newd1()82, newd1()81, 80, 80, 79; sn n =173, k >= 2: 115, 98, 92, 88, 87, 86, 84, 84, newd1()83, 82, newd1()80, 80, 80; sn n =174, k >= 2: 116, 99, 92, 88, 88, 86, 85, 84, 84, newd1()82, newd1()81, 80, 80; sn n =175, k >= 2: 116, 100, 92, 89, 88, 87, 86, 84, 84, newd1()83, 82, newd1()80, 80; sn n =176, k >= 2: 117, 100, 93, 90, 88, 88, 86, 85, 84, 84, newd1()82, newd1()81, newd1()80; pstailx type [170,14,78_2]; status: weights = 78_2 - {142..168} ; type [177,4,94_2]; status: weights = {94,96}; type [177,9,86_2]; status: weights = 86_2 - {90,98,102,104,106,114,118,120,122,134..138,142..177}; kill y140,y132,y130,y124,y116,y108,y100 ; status: weights = {86,88,92,94,96,110,112,126}; type [177,13,82_2]; kill y176,y174,y172,y170,y168,y166,y160,y158,y156,y154,y150,y162; status: weights = 82_2 - {150,154..162,166,168,170,172,174,176}; type [178,8,88]; STATUS_WE(1 + 216t^88 + 38t^96 + t^128) no [178,10,86]; type [178,12,84_2]; kill y178,y176,y174,y172,y170,y168,y166,y164,y162,y160,y158,y156,y154,y152, y148,y146,y144,y142,y140,y138,y136,y134,y132,y130,y128,y126,y124,y122, y114,y110,y106,y102,y98,ndiv4,y120; status: weights = {84,88,92,96,100,104,108,112,116}; type [178,14,82_2]; kill y178 by x_82,y164,y152,y148; status: weights = 82_2 - {148..178}; type [179,5,92_2]; status: weights = {92,96}; type [179,6,90_2]; status: weights = {90,92,94,96,100,102,104,116,118,120}; show (joint:0) y100 = 0, y116 = 0; status: weights = {90,92,94,96,102,104,118,120}; type [179,6,90]; status: weights = {90,92,94,96,102,104,118,120}; type [179,6,90]; status: weights = {90,92,94,96}; type [179,10,86_2]; status: weights = 86_2 - {106,122,130,136,138,142..179}; kill y140 ; status: weights = 86_2 - {106,122,130,136..179}; type [180,11,86_2]; status: weights = 86_2 - {90,98,106,114,122,130..178}; kill y180,y128,y126,y124,y116,y108,y100,y92 ; status: weights = {86,88,94,96,102,104,110,112,118,120}; psheadx(40) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n =177, k >= 2: 118, 100, 94, 90, 88, 88, 87, 86, newd1()84, 84, newd1()83, 82, newd1()81; sn n =178, k >= 2: 118, 101, 94, 91, 89, 88, 88, 86, newd1()85, 84, 84, 82, 82; sn n =179, k >= 2: 119, 102, 95, 92, 90, 88, 88, 87, 86, 85, 84, 83, 82; pstailx type [180,9,88_2]; kill y180,ndiv4,y176,y160,y144; kill y132 ; type [180,9,88]; status: weights = {88,96,112}; type [180,13,84_2]; kill y180,y178,y176,y174,y172,y170,y168,y166,y164,y162,y160,y158,y156; kill y154 ; kill y152,y150,y148; kill y146 ; kill y144,y142,y140,y138,y134,y130,y126,y122,y118,y114, y110,y106,y102,y98,ndiv4,y136; status: weights = {84,88,92,96,100,104,108,112,116,120,124,128,132}; type [181,7,90_2]; kill y180,y150,y148,y136,y134,y132,y120,y118,y116,y108,y104,y102,y100 ; status: weights = {90,92,94,96,122,124,126,128}; type [181,14,84_2]; status: weights = 84_4 - {128..181}; TYPE_WE(182,6,92,1 + 56t^92 + 7t^96) no [180,7,90]; no [182,8,90]; type [182,10,88_2]; status: weights = {88,92,96,98,100,104,112,116,120,128}; type [183,5,94_2]; status: weights = {94,96}; type [183,8,90_2]; kill y180,y182,y164,y156,y148,y140,y132,y116,y112,y108 ; status: weights = {90,92,94,96,100,102,104,118,120,122,124,134,136}; type [183,11,88_2]; kill y128,y120 ; kill y104 ; via lp [current] = ; no [183,11,88]; type [183,12,86_2]; status: weights = 86_2 - {146..183}; type [184,7,92]; status: weights = {92,96,124,128}; type [184,11,88_2]; kill y184,y182,y180,y178,y176,y174,y172,y170,y168,y164,y162,y160,y156,y154, y152,y148,y146,y144,y140,y138 ; status: weights = {88,90,92,96,98,100,104,106,108,112,114,116,120,122,124, 128,130,132,136}; type [185,4,98_2]; status: weights = {98,100,102,104}; type [185,9,90_2]; kill y148,y140,y138,y136,y134,y132,y120,y118,y116 ; status: weights = {90,92,94,96,100,102,104,108,124}; type [185,13,86_2]; status: weights = 86_2 - {156..185}; TYPE_WE(186,6,94,1 + 48t^94 + 15t^96) type [186,8,92_2]; show (joint:0) y104 = 0, y122 = 0, y136 = 0, y184 = 0, y186 = 0; status: weights = {92,94,96,120,124}; type [186,12,88_2]; kill y186,y184,y182,y180,y178,y176,y174,y172,y170,y168,y166,y164,y162,y160, y156,y154,y152,y150,y148,y146,y144,y142,y140,y138,y136,y134,y132,y130, y128,y122,y118,y114,y110,y106,y102,ndiv4,y124; status: weights = 88_4 - {124..186}; no [184,13,86]; type [186,14,86_2]; kill y186 by x_86; kill y154 ; status: weights = 86_2 - {154..186}; type [187,10,90_2]; status: weights = 90_2 - {114,130,138,142..187}; kill y140 ; status: weights = 90_2 - {114,130,138..187}; type [188,7,94_2]; status: weights = {94,96,124,126,128}; show (joint:0) y124 = 0; status: weights = {94,96,126,128}; type [188,7,94]; status: weights = {94,96,126,128}; type [188,9,92_2]; kill y188,ndiv4,y184,y168,y152,y140; status: weights = {92,96,104,120,136}; no [188,9,92]; no [188,11,90]; type [188,13,88_2]; kill y188,y186,y184,y182,y180,y178,y176,y174,y172,y170,y168,y166; kill y164 ; kill y160,y158,y156,y152,y150,y148,y146,y144,y142,y140,y138,y136,y134,y130, y126,y122,y118,y114,y110,y106,y102,y98,y94,ndiv4,y132,y128,y124; status: weights = {88,92,96,100,104,108,112,116,120}; TYPE_WE(189,6,96, 1 + 63t^96) TYPE_WE(189,8,94,1 + 189t^94 + 63t^96 + 3t^126) type [189,9,92_2]; status: weights = {92,94,96,98,100,104,106,108,112, 120,122,124,128,136,138,140,142,144,152,156}; type [189,11,90_2]; kill y188,y186,y184,y182,y180,y178,y176,y174,y172,y170,y168,y166,y164,y162, y160,y158,y156,y154,y152 ; status: weights = 90_2 - {152..189}; type [190,10,92_2]; status: weights = {92,96,100,104,108,112,124}; type [190,14,88_2]; kill y190 by x_88,y188,y186,y184,y182,y180,y178,y174,y172,y170,y168,y164, y162,y160,y158,y156; kill y176,y166 ; status: weights = 88_2 - {156..190}; TYPE_WE(191,7,96, 1 + 126t^96 + t^128) type [191,12,90_2]; status: weights = 90_2 - {152..191}; no [190,7,96]; TYPE_WE(192,8,96,1 + 252t^96 + 3t^128) type [192,4,102_2]; status: weights = {102,104}; type [192,5,98_2]; status: weights = {98,100,102,104,106,108,110,112}; type [192,9,94_2]; status: weights = {94,96,100,108,124}; no [192,9,94]; type [192,11,92_2]; status: weights = 92_2 - {94,102,110,114,118,126,130,134,138,142,146..192}; type [193,9,94_2]; kill y192,y190,y188,y184,y180,y176,y174,y172,y164,y160,y158,y156,y140 ; status: weights = 94_2 - {106,114,118,120,122,130,134,136,138,140,148,150..193}; type [193,13,90_2]; status: weights = 90_2 - {160..193}; type [194,10,94_2]; status: weights = 94_2 - {98,102,106,114,118..122,126..194}; type [194,12,92_2]; kill y194,y192,y190,y188,y186,y184,y182,y180,y178,y176,y174,y172,y170,y168, y164,y162,y160,y158,y156,y154,y152,y150,y148,y146,y144,y142,y140,y138, y136,y130,y126,y122,y118,y114,y110,y106,ndiv4; status: weights = 92_4 - {136..194}; type [194,14,90_2]; kill y194 by x_90, y158; status: weights = 90_2 - {158..194}; type [195,5,100_2]; status: weights = {100,104,108,112}; type [195,10,94_2]; kill y194,y192,y190,y188,y186,y184,y182,y180,y178,y176,y174,y172,y168,y166, y164,y160,y158,y156,y152,y150 ; status: weights = 94_2 - {122,138,146,150..195}; type [196,6,98_2]; status: weights = 98_2 - {130,146,154..162,170..196}; kill y164,y148 ; status: weights = 98_2 - {130,146,148,154..164,170..196}; status: weights = 98_2 - {130..196}; type [196,9,96_2]; status: weights = {96,98,100,104,112,128,144,148}; show (joint:0) y148 = 0; status: weights = {96,98,100,104,112,128,144}; type [196,11,94_2]; kill y144,y142,y140,y132,y124 ; status: weights = {94,96,100,102,104,108,110,112,116,118,120,126,128,134,136}; type [197,13,92_2]; kill y196,y194,y192,y190,y188,y186,y184,y182,y180,y178; kill y176 ; kill y174,y172,y170,y168,y166,y164,y162; status: weights = 92_2 - {162..197}; type [198,7,98_2]; kill y196 ; kill y198, y180, y172 by (x_80_20, x_84_20), y168, y164, y166 ; status: weights = 98_2 - {130,158,162..198}; status: weights = 98_2 - {130..198}; set purge joints on type exit; type [198,10,96_2]; status: weights = {96,98,100,104,108,112,114,116,120,128,132,136}; type [198,14,92_2]; kill y198 by x_92; status: weights = 92_2 - {162..198}; type [199,5,102_2]; status: weights = {102,104,108,110,112}; type [199,6,100_2]; kill y138,ndiv4,y168,y152; status: weights = {100,104,108,112,116,120,124,128,136,140,144}; status: weights = {100,104,108,112,116,120,124,128}; no [197,7,98]; type [199,8,98_2]; status: weights = 98_2 - {114,122,126,130..199}; kill y124 ; status: weights = {98,100,102,104,106,108,110,112,116,118,120,128}; type [199,11,96_2]; status: weights = {96,104,112,120,128}; type [199,12,94_2]; status: weights = 94_2 - {158..199}; type [200,4,106_2]; status: weights = {106,108,110,112}; (* No credits have been added for 201,..204. *); type [201,7,100]; status: weights = 100_4 - {129..201}; type [202,8,100]; status: weights = {100,104,108,112,120}; show (joint:0) 196 <= y100 <= 206, 20 <= y104 <= 47, y108 <= 21, 2 <= y112 <= 10, 1 <= y120 <= 3; show (joint:0) 199 <= y100 <= 205, 23 <= y104 <= 39, 7 <= y108 <= 20, 4 <= y112 <= 9, y120 = 2; show (joint:0) 202 <= y100 <= 203, 27 <= y104 <= 30, 14 <= y108 <= 17, 6 <= y112 <= 7; via lp (joint:0) [current] = ; no [202,8,100]; type [201,13,94_2]; status: weights = 94_2 - {165..201}; type [202,9,98_2]; status: weights = 98_2 - {130,146,162,178,190..194,200,202}; type [202,12,96_2]; status: weights = 96_4 - {137..202}; type [202,14,94_2]; status: weights = 94_2 - {161..202}; type [203,6,102_2]; status: weights = 102_2 - {106,122,129..203}; type [203,8,100_2]; status: weights = 100_2 - {118,126,130,134,146,148,150,158,162,164,166,170, 172,174,178,180,182,185..199,201..203}; no [203,10,98]; unset auto mu1; psheadx(300) // k = 2 3 4 5 6 7 8 9 10 11 12 13 14 psnext n =180, k >= 2: 120, 102, 96, 92, 90, 89, 88, 88, newd1()86, 86, 84, 84, 83; sn n =181, k >= 2: 120, 103, 96, 92, 91, 90, 88, 88, newd1()87, 86, newd1()84, 84, 84; sn n =182, k >= 2: 121, 104, 96, 93, 92, 90, 89, 88, 88, newd1()86, newd1()85, 84, 84; sn n =183, k >= 2: 122, 104, 96, 94, 92, 91, 90, 88, 88, newd1()87, 86, newd1()84, 84; sn n =184, k >= 2: 122, 104, 97, 94, 92, 92, 90, 89, 88, 88, 86, newd1()85, newd1()84; sn n =185, k >= 2: 123, 105, 98, 95, 93, 92, 91, 90, newd1()88, 88, 87, 86, newd1()85; sn n =186, k >= 2: 124, 106, 98, 96, 94, 92, 92, 90, newd1()89, 88, 88, 86, 86; sn n =187, k >= 2: 124, 106, 99, 96, 94, 93, 92, newd1()90, 90, newd1()88, 88, 87, 86; sn n =188, k >= 2: 125, 107, 100, 96, 95, 94, 93, newd1()91, newd1()90, newd1()89, 88, 88, newd1()86; sn n =189, k >= 2: 126, 108, 100, 96, 96, 94, 94, 92, newd1()91, 90, newd1()88, 88, newd1()87; sn n =190, k >= 2: 126, 108, 100, 96, 96, 95, 94, 92, 92, newd1()90, newd1()89, 88, 88; sn n =191, k >= 2: 127, 108, 101, 97, 96, 96, 95, newd1()92, 92, newd1()91, 90, newd1()88, 88; sn n =192, k >= 2: 128, 109, 102, 98, 96, 96, 96, newd1()93, 92, 92, 90, newd1()89, newd1()88; sn n =193, k >= 2: 128, 110, 102, 98, 96, 96, 96, 94, newd1()92, 92, 91, 90, newd1()89; sn n =194, k >= 2: 129, 110, 103, 99, 96, 96, 96, 94, newd1()93, 92, 92, 90, 90; sn n =195, k >= 2: 130, 111, 104, 100, 97, 96, 96, 95, 94, 93, 92, newd1()90, 90; sn n =196, k >= 2: 130, 112, 104, 100, 98, 96, 96, 96, newd1()94, 94, 92, newd1()91, newd1()90; sn n =197, k >= 2: 131, 112, 104, 100, 98, 97, 96, 96, newd1()95, 94, newd1()92, 92, newd1()91; sn n =198, k >= 2: 132, 112, 104, 101, 99, 98, 97, 96, 96, 95, newd1()93, 92, 92; sn n =199, k >= 2: 132, 113, 105, 102, 100, 98, 98, 96, 96, 96, 94, newd1()92, 92; sn n =200, k >= 2: 133, 114, 106, 102, 100, 99, 98, 96, 96, 96, 94, newd1()93, 93; sn n =201, k >= 2: 134, 114, 106, 103, 100,100, 98, 97, 96, 96, 95, 94, 93; sn n =202, k >= 2: 134, 115, 107, 104, 101,100, 99, 98, newd1()96, 96, 96, 94, 94; sn n =203, k >= 2: 135, 116, 108, 104, 102,100,100, 98, newd1()97, 96, 96, newd1()94, 94; sn n =204, k >= 2: 136, 116, 108, 104, 102,101,100, 99, 98, 97, 96, newd1()95, 94; sn n =205, k >= 2: 136, 116, 108, 104, 103,102,100,100, 99, 98, newd1()96, 96, 95; sn n =206, k >= 2: 137, 117, 109, 105, 104,102,101,100,100, 98, newd1()97, 96, 96; pstailx data_comment( ![\block{Computer-generated tables for $207 \leq n \leq 300$, $k \leq 14$} In the this section we give computer-generated restrictions on weights and bounds on minimum distance for $207 \leq n \leq 300$, $k \leq 14$, obtained via the command sequence: \begin{verbatim} accept (tables only) inputs/code.data; set dual constraint bound = 3; set repeat loop; set allowed failures = 10; build tables for 207 <= n <= 300, 2 <= k <= 14; \end{verbatim} where {\tt code.data} was the {\it old\/} {\tt code.data}, before inclusion of this section. (There was some minor editing by hand done afterwards.) These bounds are not likely to be particularly sharp. They have not been compared with Brouwer's tables. ]! ) set dual constraint bound = 3; type [207,8,102_2]; status: weights = 102_2 - {122,130..134,138,140,150..156,162..206}; type [207,10,100_2]; status: weights = 100_2 - {102,126,130,134,138,142,146,150,154,158,162,166..206}; type [208,11,100_2]; status: weights = 100_4 - {148..208}; type [207,12,98_2]; status: weights = 98_2 - {166..206}; type [207,14,96_2]; status: weights = 96_2 - {182..190,194..204}; n = 207, k >= 2: 138, 118, 110, 106, 104, 103, 102, 100, 100, 99, 98, 96, 96; type [208,8,102_2]; status: weights = 102_2 - {154,170,172,178,186,188,194..198,202,204}; type [209,9,102_2]; status: weights = 102_2 - {106,122,130,134..138,146..156,162..208}; type [208,10,100_2]; status: weights = 100_2 - {178..208}; type [208,12,98_2]; status: weights = 98_2 - {178..208}; type [209,13,98_2]; status: weights = 98_2 - {170..208}; n = 208, k >= 2: 138, 118, 110, 106, 104, 104, 102, 101, 100, 100, 98, 97, 96; type [210,8,104_2]; status: weights = {104,106,108,112,116,120,128,144,160,208}; type [209,10,100_2]; status: weights = 100_2 - {190..198,202..208}; type [209,11,100_2]; status: weights = 100_2 - {170..208}; type [210,12,100_2]; status: weights = 100_4 - {148..208}; type [210,14,98_2]; status: weights = 98_2 - {168..210}; n = 209, k >= 2: 139, 119, 111, 107, 104, 104, 103, 102, 100, 100, 99, 98, 97; type [210,9,102_2]; status: weights = 102_2 - {138,154,170,186,208,210}; type [211,10,102_2]; status: weights = {102,104,110,112,116,118,120,126,128,134,136,142,144,150,152,158}; type [210,11,100_2]; status: weights = 100_2 - {182..210}; type [210,13,98_2]; status: weights = 98_2 - {190..194,200..210}; n = 210, k >= 2: 140, 120, 112, 108, 105, 104, 104, 102, 101, 100, 100, 98, 98; type [212,9,104_2]; status: weights = {104,112,120,128,144,160}; type [212,11,102_2]; status: weights = {102,104,110,112,118,120,126,128,134,136,142,144}; type [211,12,100_2]; status: weights = 100_2 - {170..210}; type [211,14,98_2]; status: weights = 98_2 - {186..194,198..210}; n = 211, k >= 2: 140, 120, 112, 108, 106, 104, 104, 103, 102, 101, 100, 98, 98; type [212,10,102_2]; status: weights = 102_2 - {178,182..212}; type [212,12,100_2]; status: weights = 100_2 - {182..212}; type [213,13,100_2]; status: weights = 100_2 - {170..212}; n = 212, k >= 2: 141, 120, 112, 108, 106, 105, 104, 104, 102, 102, 100, 99, 98; type [214,8,106_2]; status: weights = {106,108,110,112,122,124}; type [213,9,104_2]; status: weights = 104_2 - {110,126,134,138..142,150,154..158,166,170..174,178, 182,186..190,194..206,210,212}; type [214,10,104_2]; status: weights = {104,112,120,128,136,144,152}; type [213,11,102_2]; status: weights = 102_2 - {174..212}; type [213,12,100_2]; status: weights = 100_2 - {198,202..212}; type [214,14,100_2]; status: weights = 100_2 - {170..214}; n = 213, k >= 2: 142, 121, 112, 109, 107, 106, 105, 104, 103, 102, 100, 100, 99; type [215,11,104_2]; status: weights = {104,112,120,128,136}; type [215,12,102_2]; status: weights = 102_2 - {170..214}; type [214,13,100_2]; status: weights = 100_2 - {190,194..198,202..214}; n = 214, k >= 2: 142,122, 113, 110, 108, 106, 106, 104, 104, 103, 101, 100, 100; type [215,8,106_2]; status: weights = 106_2 - {130,138..142,146,158..164,170..212}; type [215,10,104_2]; status: weights = 104_2 - {110,142,158,166,170..214}; type [215,14,100_2]; status: weights = 100_2 - {186..198,202..214}; n = 215, k >= 2: 143,122, 114, 110, 108, 107, 106, 104, 104, 104, 102, 100, 100; type [217,8,108_2]; status: weights = {108,112,124}; type [217,9,106_2]; status: weights = {106,108,110,112,120,122,124,126,128,136,140,152,156,170}; type [216,10,104_2]; status: weights = 104_2 - {182,186..216}; type [216,11,104_2]; status: weights = 104_2 - {110,118,126,134,142,150,158,162..216}; type [216,12,102_2]; status: weights = 102_2 - {184..216}; type [217,13,102_2]; status: weights = 102_2 - {174..216}; n = 216, k >= 2: 144,123, 114, 111, 108, 108, 107, 105, 104, 104, 102, 101, 100; type [217,10,104_2]; status: weights = 104_2 - {198..206,210..216}; type [217,11,104_2]; status: weights = 104_2 - {174,178..216}; type [218,12,104_2]; status: weights = 104_4 - {156..216}; type [218,14,102_2]; status: weights = 102_2 - {154,158,162,166,170..218}; n = 217, k >= 2: 144,124, 115, 112, 109, 108, 108, 106, 104, 104, 103, 102, 101; type [218,8,108_2]; status: weights = {108,110,112,114,116,120,124,126,128,136,152,156,168,216}; type [219,10,106_2]; status: weights = 106_2 - {114,146,162,166..218}; type [218,11,104_2]; status: weights = 104_2 - {188..218}; type [218,13,102_2]; status: weights = 102_2 - {190,194..202,206..218}; n = 218, k >= 2: 145,124, 116, 112, 110, 108, 108, 106, 105, 104, 104, 102, 102; type [220,11,106_2]; status: weights = 106_2 - {114,116,122,130..134,138,142..220}; type [219,12,104_2]; status: weights = 104_2 - {174..218}; type [219,13,102_2]; status: weights = 102_2 - {216}; type [219,14,102_2]; status: weights = 102_2 - {190..218}; n = 219, k >= 2: 146,124, 116, 112, 110, 109, 108, 106, 106, 105, 104, 102, 102; type [221,8,110_2]; status: weights = {110,112,126,128}; type [221,9,108_2]; status: weights = 108_2 - {118,122,134,138,142,146..150,154,158,162..166,170, 178..182,186,190,194..198,202,206..214,218,220}; type [220,10,106_2]; status: weights = 106_2 - {186,190..220}; type [220,12,104_2]; status: weights = 104_2 - {186..220}; type [221,13,104_2]; status: weights = 104_2 - {174..220}; n = 220, k >= 2: 146,125, 116, 112, 111, 110, 109, 107, 106, 106, 104, 103, 102; type [222,10,108_2]; status: weights = 108_4 - {116,148,160..220}; type [221,11,106_2]; status: weights = 106_2 - {178..220}; type [221,12,104_2]; status: weights = 104_2 - {206..220}; type [222,14,104_2]; status: weights = 104_4 - {176..220}; n = 221, k >= 2: 147,126, 117, 112, 112, 110, 110, 108, 107, 106, 104, 104, 103; type [222,8,110_2]; status: weights = 110_2 - {122,124,134..156,162..220}; type [222,10,108_2]; status: weights = 108_4 - {116,144..220}; type [222,11,106_2]; status: weights = 106_2 - {190..222}; type [223,12,106_2]; status: weights = 106_2 - {178..222}; type [222,13,104_2]; status: weights = 104_2 - {194..222}; n = 222, k >= 2: 148,126, 118, 113, 112, 111, 110, 108, 108, 106, 105, 104, 104; type [223,10,108_2]; status: weights = 108_2 - {118,150,166,170,174,178..222}; type [224,11,108_2]; status: weights = 108_2 - {118,126,134,142,146,150,154,158,162,166,170..224}; type [223,13,104_2]; status: weights = 104_2 - {220,222}; type [223,14,104_2]; status: weights = 104_2 - {190..222}; n = 223, k >= 2: 148,127, 118, 114, 112, 112, 111, 108, 108, 107, 106, 104, 104; type [225,9,110_2]; status: weights = 110_2 - {122,138,146,150..154,162,166..172,182..188,194..204,208..224}; type [224,10,108_2]; status: weights = 108_2 - {190,194..224}; type [224,12,106_2]; status: weights = 106_2 - {190..224}; type [225,13,106_2]; status: weights = 106_2 - {178..224}; type [224,14,104_2]; status: weights = 104_2 - {218..222}; n = 224, k >= 2: 149,128, 119, 114, 112, 112, 112, 109, 108, 108, 106, 105, 104; type [225,8,112_2]; status: weights = {112,114,116,120,128,130,132,160,224}; type [226,10,110_2]; status: weights = {110,112,126,128,132,136,142}; type [225,11,108_2]; status: weights = 108_2 - {182,186..224}; type [226,12,108_2]; status: weights = 108_4 - {160..224}; n = 225, k >= 2: 150,128, 120, 115, 112, 112, 112, 110, 109, 108, 107, 106, 104; type [227,10,110_2]; status: weights = 110_2 - {122,154,170,174..226}; type [226,11,108_2]; status: weights = 108_2 - {194..226}; type [226,13,106_2]; status: weights = 106_2 - {194..226}; n = 226, k >= 2: 150,128, 120, 116, 113, 112, 112, 110, 109, 108, 108, 106, 105; type [228,9,112_2]; status: weights = {112,114,116,120,128,130,132,136,144,160,176,180,192}; type [228,11,110_2]; status: weights = 110_2 - {122,124,130,138,140,146,154,156,162..228}; type [227,12,108_2]; status: weights = 108_2 - {182..226}; type [227,13,106_2]; status: weights = 106_2 - {222..226}; n = 227, k >= 2: 151,129, 120, 116, 114, 112, 112, 111, 110, 109, 108, 106, 106; type [228,10,110_2]; status: weights = 110_2 - {194..228}; type [228,12,108_2]; status: weights = 108_2 - {194..228}; type [229,13,108_2]; status: weights = 108_2 - {180..228}; type [228,14,106_2]; status: weights = 106_2 - {220..226}; n = 228, k >= 2: 152,130, 120, 116, 114, 113, 112, 112, 110, 110, 108, 107, 106; type [230,8,114_2]; status: weights = 114_2 - {130..230}; type [229,9,112_2]; status: weights = 112_2 - {126,142,150,154..158,166,170..174,186..190,198,202..206,214,218,222,228}; type [230,10,112_2]; status: weights = 112_2 - {118,122..126,134,138,142,150,154..158,162,166..230}; type [229,11,110_2]; status: weights = 110_2 - {182..228}; type [229,12,108_2]; status: weights = 108_2 - {210..228}; type [230,14,108_2]; status: weights = 108_4 - {176..228}; n = 229, k >= 2: 152,130, 121, 117, 115, 114, 113, 112, 111, 110, 108, 108, 107; type [231,11,112_2]; status: weights = {112,116,120,128,136,144}; type [231,12,110_2]; status: weights = 110_2 - {186..230}; type [230,13,108_2]; status: weights = 108_2 - {198..230}; n = 230, k >= 2: 153,131, 122, 118, 116, 114, 114, 112, 112, 111, 109, 108, 108; type [231,8,114_2]; status: weights = 114_2 - {146,154..158,162,174..180,186..228}; type [231,10,112_2]; status: weights = 112_2 - {126,158,174,178,182,186..230}; type [231,13,108_2]; status: weights = 108_2 - {226..230}; type [231,14,108_2]; status: weights = 108_2 - {194..230}; n = 231, k >= 2: 154,132, 122, 118, 116, 115, 114, 112, 112, 112, 110, 108, 108; type [233,8,116_2]; status: weights = {116,120,124,128}; type [233,9,114_2]; status: weights = 114_2 - {130,146,154,158..166,170,174..232}; type [232,10,112_2]; status: weights = 112_2 - {198,202..232}; type [232,11,112_2]; status: weights = 112_2 - {126,134,142,150,158,166,170,174..232}; type [232,12,110_2]; status: weights = 110_2 - {198..232}; type [233,13,110_2]; status: weights = 110_2 - {182..232}; type [232,14,108_2]; status: weights = 108_2 - {224..230}; n = 232, k >= 2: 154,132, 123, 119, 116, 116, 115, 113, 112, 112, 110, 109, 108; type [233,10,112_2]; status: weights = 112_2 - {210,214..222,226..232}; type [233,11,112_2]; status: weights = 112_2 - {186,190,194..232}; type [234,12,112_2]; status: weights = 112_4 - {172..232}; n = 233, k >= 2: 155,132, 124, 120, 117, 116, 116, 114, 112, 112, 111, 110, 108; type [234,8,116_2]; status: weights = 116_2 - {134,138,142,146..150,154..166,170,174..182,186..230,234}; type [235,10,114_2]; status: weights = 114_2 - {130,162,174..178,182..234}; type [234,11,112_2]; status: weights = 112_2 - {202..234}; type [234,13,110_2]; status: weights = 110_2 - {200..234}; type [235,14,110_2]; status: weights = 110_2 - {198..234}; n = 234, k >= 2: 156,133, 124, 120, 118, 116, 116, 114, 113, 112, 112, 110, 109; type [236,9,116_2]; status: weights = 116_4 - {132,148,156..236}; type [236,11,114_2]; status: weights = 114_2 - {130,132,138,142..236}; type [235,12,112_2]; status: weights = 112_2 - {186..234}; type [235,13,110_2]; status: weights = 110_2 - {228..234}; n = 235, k >= 2: 156,134, 124, 120, 118, 117, 116, 115, 114, 113, 112, 110, 110; type [237,8,118_2]; status: weights = {118,120,126,128}; type [236,10,114_2]; status: weights = 114_2 - {202..236}; type [236,12,112_2]; status: weights = 112_2 - {200..236}; type [237,13,112_2]; status: weights = 112_2 - {186..236}; type [236,14,110_2]; status: weights = 110_2 - {226..236}; n = 236, k >= 2: 157,134, 125, 120, 119, 118, 117, 116, 114, 114, 112, 111, 110; type [237,9,116_2]; status: weights = 116_2 - {134,150,158,162..166,170,174,178..182,186,190, 194..198,202,206,210..214,218,222,226,230,234}; type [238,10,116_2]; status: weights = 116_4 - {132,164,172..236}; type [237,11,114_2]; status: weights = 114_2 - {190..236}; type [237,12,112_2]; status: weights = 112_2 - {216..236}; n = 237, k >= 2: 158,135, 126, 121, 120, 118, 118, 116, 115, 114, 112, 112, 110; type [238,8,118_2]; status: weights = 118_2 - {138,140,150..172,178..236}; type [239,11,116_2]; status: weights = {116,120,124,136}; type [239,12,114_2]; status: weights = 114_2 - {190..238}; type [238,13,112_2]; status: weights = 112_2 - {202..238}; type [239,14,112_2]; status: weights = 112_2 - {198..238}; n = 238, k >= 2: 158,136, 126, 122, 120, 119, 118, 116, 116, 115, 113, 112, 111; type [239,10,116_2]; status: weights = 116_2 - {134,166,178,182,186,190..238}; type [239,13,112_2]; status: weights = 112_2 - {232..238}; n = 239, k >= 2: 159,136, 127, 122, 120, 120, 119, 116, 116, 116, 114, 112, 112; type [241,9,118_2]; status: weights = 118_2 - {138,154,162,166..170,178,182..188,198..204,210..220,224..230,234,236}; type [240,10,116_2]; status: weights = 116_2 - {202,206..240}; type [240,11,116_2]; status: weights = 116_2 - {134,142,146,150,154,158,162,166,170,174,178..240}; type [240,12,114_2]; status: weights = 114_2 - {204..240}; type [241,13,114_2]; status: weights = 114_2 - {186..240}; type [240,14,112_2]; status: weights = 112_2 - {222,230..238}; n = 240, k >= 2: 160,136, 128, 123, 120, 120, 120, 117, 116, 116, 114, 113, 112; type [241,8,120_2]; status: weights = {120,122,124,128,130,132,136,144,148,176,240}; type [242,10,118_2]; status: weights = {118,120,126,128,142,152}; type [241,11,116_2]; status: weights = 116_2 - {190,194..240}; type [242,12,116_2]; status: weights = 116_4 - {176..240}; n = 241, k >= 2: 160,137, 128, 124, 121, 120, 120, 118, 117, 116, 115, 114, 112; type [242,11,116_2]; status: weights = 116_2 - {206,210..242}; type [242,13,114_2]; status: weights = 114_2 - {206..242}; type [243,14,114_2]; status: weights = 114_2 - {202..242}; n = 242, k >= 2: 161,138, 128, 124, 122, 120, 120, 118, 118, 116, 116, 114, 113; type [244,9,120_2]; status: weights = {120,124,128,132,136,144,148,152,160,176,192,208,224,240}; type [243,10,118_2]; status: weights = 118_2 - {138,170,172,178,186..242}; type [244,11,118_2]; status: weights = 118_2 - {138,140,146,154,156,162,164,168..244}; type [243,12,116_2]; status: weights = 116_2 - {194..242}; type [243,13,114_2]; status: weights = 114_2 - {234..242}; n = 243, k >= 2: 162,138, 128, 124, 122, 121, 120, 119, 118, 117, 116, 114, 114; type [245,8,122_2]; status: weights = {122,124,126,128}; type [244,10,118_2]; status: weights = 118_2 - {206,210..244}; type [244,12,116_2]; status: weights = 116_2 - {206..244}; type [245,13,116_2]; status: weights = 116_2 - {190..244}; type [244,14,114_2]; status: weights = 114_2 - {226,232..244}; n = 244, k >= 2: 162,139, 129, 125, 123, 122, 121, 120, 118, 118, 116, 115, 114; type [246,10,120_2]; status: weights = 120_2 - {126,134,138..142,150,154,158,162,166,170..174,178..246}; type [245,11,118_2]; status: weights = 118_2 - {194..244}; type [246,12,118_2]; status: weights = 118_2 - {170..246}; n = 245, k >= 2: 163,140, 130, 126, 124, 122, 122, 120, 119, 118, 117, 116, 114; type [246,8,122_2]; status: weights = 122_2 - {146,148,158..180,186..244}; type [247,11,120_2]; status: weights = {120,124,128,136,144,152,160}; type [246,13,116_2]; status: weights = 116_2 - {206..246}; type [247,14,116_2]; status: weights = 116_2 - {202..246}; n = 246, k >= 2: 164,140, 130, 126, 124, 123, 122, 120, 120, 119, 118, 116, 115; type [248,8,124_2]; status: weights = {124,128}; type [248,9,122_2]; status: weights = {122,124,128,132,134,136,150,152,156}; type [247,10,120_2]; status: weights = 120_2 - {142,174,182,190,194,198..246}; type [247,12,118_2]; status: weights = 118_2 - {196..246}; type [247,13,116_2]; status: weights = 116_2 - {230,238..246}; n = 247, k >= 2: 164,140, 131, 127, 124, 124, 123, 121, 120, 120, 118, 116, 116; type [248,10,120_2]; status: weights = 120_2 - {210,214..248}; type [248,11,120_2]; status: weights = 120_2 - {142,150,158,166,174,178,182..248}; type [248,12,118_2]; status: weights = 118_2 - {210..248}; type [249,13,118_2]; status: weights = 118_2 - {190,194..248}; type [248,14,116_2]; status: weights = 116_2 - {230,236..246}; n = 248, k >= 2: 165,141, 132, 128, 125, 124, 124, 122, 120, 120, 118, 117, 116; type [249,8,124_2]; status: weights = {124,126,128,130,132,136,140,144,152,156,184,248}; type [249,9,122_2]; status: weights = 122_2 - {146,162,170,174..178,186,190..196,206..212,216..228,232..244}; type [249,10,120_2]; status: weights = 120_2 - {226,230..238,242..248}; type [249,11,120_2]; status: weights = 120_2 - {198,202..248}; type [250,12,120_2]; status: weights = 120_2 - {174,178,182..250}; type [250,10,122_2]; kill y250, y230, y204, y246, y248, y188, y184, y166, y172, y180, y150, y168, y164, y160, y140, y152, y148, y132, y156; via lp [current] = ; no [250,10,122]; n = 249, k >= 2: 166,142, 132, 128, 126, 124, 124, 122, 120, 120, 119, 118, 116; type [251,10,122_2]; status: weights = 122_2 - {146,178,180,190..250}; type [250,11,120_2]; status: weights = 120_2 - {214..250}; type [250,13,118_2]; status: weights = 118_2 - {210..250}; type [251,14,118_2]; status: weights = 118_2 - {206..250}; n = 250, k >= 2: 166,142, 132, 128, 126, 125, 124, 122, 121, 120, 120, 118, 117; type [252,8,126_2]; status: weights = {126,128}; type [252,9,124_2]; status: weights = 124_2 - {130,134,142,146..150,158,162..166,170..182,186..200,206..246}; type [252,11,122_2]; status: weights = 122_2 - {146,148,154,162..170,174..252}; type [251,12,120_2]; status: weights = 120_2 - {198..250}; type [251,13,118_2]; status: weights = 118_2 - {234,240..250}; n = 251, k >= 2: 167,143, 133, 128, 127, 126, 125, 123, 122, 121, 120, 118, 118; type [252,10,122_2]; status: weights = 122_2 - {214,218..252}; type [252,12,120_2]; status: weights = 120_2 - {212..252}; type [253,13,120_2]; status: weights = 120_2 - {194,198..252}; type [252,14,118_2]; status: weights = 118_2 - {230..234,240..252}; n = 252, k >= 2: 168,144, 134, 128, 128, 126, 126, 124, 122, 122, 120, 119, 118; type [253,8,126_2]; status: weights = 126_2 - {138,140,146..156,162..188,192..252}; type [254,10,124_2]; status: weights = 124_2 - {134,142,146..150,154,158,162,166,170,174,178..254}; type [253,11,122_2]; status: weights = 122_2 - {198..252}; type [254,12,122_2]; status: weights = 122_2 - {178..254}; type [254,14,120_2]; kill y254, y196, y192, y190, y188, y186, y184, y182, y180, y178, y176, y174, y172, y170, y168, y166, y164, y162, y160, y158, y154, y150, y146, y138, y142, y134, y122, y126, y130; status: weights = {120,124,128,132,136,140,144,148,152,156}; n = 253, k >= 2: 168,144, 134, 129, 128, 127, 126, 125, 123, 122, 121, 120, 119; type [254,11,122_2]; status: weights = 122_2 - {214,218..254}; type [254,13,120_2]; status: weights = 120_2 - {210..254}; n = 254, k >= 2: 169,144, 135, 130, 128, 128, 127, 126, 124, 122, 122, 120, 120; type [255,10,124_2]; status: weights = 124_2 - {150,182,194,198,202..254}; type [256,11,124_2]; status: weights = 124_2 - {150,158,166,170,174,178,182,186,190..256}; type [255,12,122_2]; status: weights = 122_2 - {202..254}; type [255,13,120_2]; status: weights = 120_2 - {234,238,244..254}; type [255,14,120_2]; status: weights = 120_2 - {206..254}; n = 255, k >= 2: 170,145, 136, 130, 128, 128, 128, 127, 124, 123, 122, 120, 120; type [256,10,124_2]; status: weights = 124_2 - {218,222..256}; type [256,12,122_2]; status: weights = 122_2 - {214..256}; type [257,13,122_2]; status: weights = 122_2 - {194,198..256}; type [256,14,120_2]; status: weights = 120_2 - {230,234..238,242..254}; n = 256, k >= 2: 170,146, 136, 131, 128, 128, 128, 128, 124, 124, 122, 121, 120; type [258,10,126_2]; status: weights = 126_2 - {138,146..156,162..170,176..258}; type [257,11,124_2]; status: weights = 124_2 - {202,206..256}; type [258,12,124_2]; status: weights = 124_2 - {182,186..258}; n = 257, k >= 2: 171,146, 136, 132, 128, 128, 128, 128, 125, 124, 123, 122, 120; type [258,11,124_2]; status: weights = 124_2 - {218,222..258}; type [258,13,122_2]; status: weights = 122_2 - {214..258}; type [259,14,122_2]; status: weights = 122_2 - {210..258}; n = 258, k >= 2: 172,147, 136, 132, 129, 128, 128, 128, 126, 124, 124, 122, 121; type [259,10,126_2]; status: weights = 126_2 - {154,186,188,198..258}; type [260,11,126_2]; status: weights = 126_2 - {154,156,162,170,172,178,182..260}; type [259,12,124_2]; status: weights = 124_2 - {206..258}; type [259,13,122_2]; status: weights = 122_2 - {234,238..242,246..258}; n = 259, k >= 2: 172,148, 137, 132, 130, 128, 128, 128, 126, 125, 124, 122, 122; type [261,10,128_2]; status: weights = {128,132,136,144,160}; type [260,12,124_2]; status: weights = 124_2 - {218..260}; type [261,13,124_2]; status: weights = 124_2 - {198,202..260}; type [260,14,122_2]; status: weights = 122_2 - {230,234,238..242,246..260}; n = 260, k >= 2: 173,148, 138, 133, 130, 128, 128, 128, 127, 126, 124, 123, 122; type [261,11,126_2]; status: weights = 126_2 - {206..260}; type [262,12,126_2]; status: weights = 126_2 - {186..262}; n = 261, k >= 2: 174,148, 138, 134, 131, 129, 128, 128, 128, 126, 125, 124, 122; type [262,10,128_2]; status: weights = 128_2 - {142,150,154..158,166,170,174,182,186..190,194..262}; type [263,11,128_2]; status: weights = {128,130,132,136,140,144,146,148,152,160,168}; type [262,13,124_2]; status: weights = 124_2 - {218..262}; type [263,14,124_2]; status: weights = 124_2 - {210..262}; n = 262, k >= 2: 174,149, 139, 134, 132, 130, 128, 128, 128, 127, 126, 124, 123; type [263,10,128_2]; status: weights = 128_2 - {158,190,202,206,210..262}; type [263,12,126_2]; status: weights = 126_2 - {206..262}; type [263,13,124_2]; status: weights = 124_2 - {238,242..246,250..262}; n = 263, k >= 2: 175,150, 140, 135, 132, 130, 129, 128, 128, 128, 126, 124, 124; type [265,9,130_2]; status: weights = 130_2 - {142..254,258..264}; type [264,10,128_2]; status: weights = 128_2 - {230..254,258..264}; type [264,11,128_2]; status: weights = 128_2 - {158,166,174,182,186,190,194..264}; type [264,12,126_2]; status: weights = 126_2 - {222..264}; type [265,13,126_2]; status: weights = 126_2 - {198..264}; type [264,14,124_2]; status: weights = 124_2 - {230,234,238,242..246,250..262}; n = 264, k >= 2: 176,150, 140, 136, 132, 131, 130, 129, 128, 128, 126, 125, 124; type [265,10,128_2]; status: weights = 128_2 - {242,246..254,260..264}; type [265,11,128_2]; status: weights = 128_2 - {206,210..264}; type [266,12,128_2]; status: weights = 128_2 - {190,194..266}; type [265,14,124_2]; status: weights = 124_2 - {262}; n = 265, k >= 2: 176,151, 140, 136, 133, 132, 130, 130, 128, 128, 127, 126, 124; type [266,10,128_2]; status: weights = 128_2 - {254,262..266}; type [266,11,128_2]; status: weights = 128_2 - {226..266}; type [266,13,126_2]; status: weights = 126_2 - {218..266}; type [267,14,126_2]; status: weights = 126_2 - {214..266}; n = 266, k >= 2: 177,152, 141, 136, 134, 132, 131, 130, 128, 128, 128, 126, 125; type [268,10,130_2]; status: weights = 130_2 - {230..268}; type [267,11,128_2]; status: weights = 128_2 - {242..266}; type [267,12,128_2]; status: weights = 128_2 - {210..266}; type [267,13,126_2]; status: weights = 126_2 - {238,242..266}; n = 267, k >= 2: 178,152, 142, 136, 134, 132, 132, 130, 129, 128, 128, 126, 126; type [269,9,132_2]; status: weights = 132_2 - {158,162,166,174,178,182,186,190,194..198,202,206, 210..214,218,222,226..230,234,238,242..246,250,254,258,262,266}; type [269,11,130_2]; status: weights = 130_2 - {192..268}; type [268,12,128_2]; status: weights = 128_2 - {224..268}; type [269,13,128_2]; status: weights = 128_2 - {198,202,206..268}; type [268,14,126_2]; status: weights = 126_2 - {234..268}; n = 268, k >= 2: 178,152, 142, 137, 135, 133, 132, 131, 130, 129, 128, 127, 126; type [269,10,130_2]; status: weights = 130_2 - {246,250..258,264..268}; type [270,12,130_2]; status: weights = 130_2 - {174,178..270}; type [269,14,126_2]; status: weights = 126_2 - {262..266}; n = 269, k >= 2: 179,153, 143, 138, 136, 134, 132, 132, 130, 130, 129, 128, 126; type [271,10,132_2]; status: weights = 132_2 - {134,166,190,194,198,206,210,214,218..270}; type [270,11,130_2]; status: weights = 130_2 - {226,230..270}; type [270,13,128_2]; status: weights = 128_2 - {222..270}; type [271,14,128_2]; status: weights = 128_2 - {214..270}; n = 270, k >= 2: 180,154, 144, 138, 136, 134, 133, 132, 131, 130, 130, 128, 127; type [272,11,132_2]; status: weights = {132,136,140,142,144,148,152,156,160,164,168,172,176,180,184}; type [271,12,130_2]; status: weights = 130_2 - {214..270}; type [271,13,128_2]; status: weights = 128_2 - {242..254,258..270}; n = 271, k >= 2: 180,154, 144, 139, 136, 135, 134, 132, 132, 131, 130, 128, 128; type [273,9,134_2]; status: weights = 134_2 - {162,170,178,186,194..204,210..220,226..236,242..252,258..272}; type [272,10,132_2]; status: weights = 132_2 - {234,238..262,266..272}; type [272,12,130_2]; status: weights = 130_2 - {226..272}; type [273,13,130_2]; status: weights = 130_2 - {202..272}; type [272,14,128_2]; status: weights = 128_2 - {234..254,258..272}; n = 272, k >= 2: 181,155, 144, 140, 136, 136, 134, 133, 132, 132, 130, 129, 128; type [273,10,132_2]; status: weights = 132_2 - {250,254..262,268..272}; type [273,11,132_2]; status: weights = 132_2 - {210,214,218..272}; type [274,12,132_2]; status: weights = 132_2 - {194,198..274}; type [273,14,128_2]; status: weights = 128_2 - {266..270}; n = 273, k >= 2: 182,156, 144, 140, 137, 136, 135, 134, 132, 132, 131, 130, 128; type [275,10,134_2]; status: weights = 134_2 - {138,170,194,196,202,204,210..274}; type [274,11,132_2]; status: weights = 132_2 - {230,234..274}; type [274,13,130_2]; status: weights = 130_2 - {224..274}; type [275,14,130_2]; status: weights = 130_2 - {214,218..274}; n = 274, k >= 2: 182,156, 145, 140, 138, 136, 136, 134, 133, 132, 132, 130, 129; type [276,9,136_2]; status: weights = {136,140,144,148,152,156,160,168,176,184,192,208,224,240,256}; type [276,11,134_2]; status: weights = {134,136,142,144,150,152,158,160,166,168,174,176,182}; type [275,12,132_2]; status: weights = 132_2 - {214,218..274}; type [275,13,130_2]; status: weights = 130_2 - {242,246..274}; n = 275, k >= 2: 183,156, 146, 141, 138, 136, 136, 135, 134, 133, 132, 130, 130; type [276,10,134_2]; status: weights = 134_2 - {238..276}; type [276,12,132_2]; status: weights = 132_2 - {230..276}; type [277,13,132_2]; status: weights = 132_2 - {202,206,210..276}; type [276,14,130_2]; status: weights = 130_2 - {238..276}; n = 276, k >= 2: 184,157, 146, 142, 139, 137, 136, 136, 134, 134, 132, 131, 130; type [277,9,136_2]; status: weights = 136_2 - {174,190,198,202..206,214,218..222,234..238,246,250..254,262,266,270,274}; type [278,10,136_2]; status: weights = 136_4 - {140,172,196,204..276}; type [277,11,134_2]; status: weights = 134_2 - {214..276}; type [278,12,134_2]; status: weights = 134_2 - {198..278}; type [277,14,130_2]; status: weights = 130_2 - {268..276}; n = 277, k >= 2: 184,158, 147, 142, 140, 138, 136, 136, 135, 134, 133, 132, 130; type [279,11,136_2]; status: weights = {136,144,152,160,168}; type [278,13,132_2]; status: weights = 132_2 - {226..278}; type [279,14,132_2]; status: weights = 132_2 - {210,214,218..278}; n = 278, k >= 2: 185,158, 148, 143, 140, 138, 137, 136, 136, 135, 134, 132, 131; type [279,10,136_2]; status: weights = 136_2 - {142,174,198,206,214,218,222,226..278}; type [279,12,134_2]; status: weights = 134_2 - {218..278}; type [279,13,132_2]; status: weights = 132_2 - {246..278}; n = 279, k >= 2: 186,159, 148, 144, 140, 139, 138, 136, 136, 136, 134, 132, 132; type [281,9,138_2]; status: weights = 138_2 - {178..182,194..198,202,206..218,222..232,238..250,254..280}; type [280,10,136_2]; status: weights = 136_2 - {242,246..270,274..280}; type [280,11,136_2]; status: weights = 136_2 - {142,174,182,190,194,198,202..280}; type [281,12,136_2]; status: weights = 136_4 - {176..280}; type [281,13,134_2]; status: weights = 134_2 - {206..280}; type [280,14,132_2]; status: weights = 132_2 - {238..280}; n = 280, k >= 2: 186,160, 148, 144, 141, 140, 138, 137, 136, 136, 135, 133, 132; type [281,10,136_2]; status: weights = 136_2 - {258,262..270,276..280}; type [281,11,136_2]; status: weights = 136_2 - {218,222..280}; type [281,14,132_2]; status: weights = 132_2 - {272..280}; n = 281, k >= 2: 187,160, 149, 144, 142, 140, 139, 138, 136, 136, 136, 134, 132; type [283,10,138_2]; status: weights = 138_2 - {146,178,210,212,222..282}; type [282,11,136_2]; status: weights = 136_2 - {238,242..282}; type [282,12,136_2]; status: weights = 136_2 - {202,206..282}; type [282,13,134_2]; status: weights = 134_2 - {230..282}; type [283,14,134_2]; status: weights = 134_2 - {206,210,214..282}; n = 282, k >= 2: 188,160, 150, 144, 142, 140, 140, 138, 137, 136, 136, 134, 133; type [284,9,140_2]; status: weights = 140_4 - {148,180,184,196..232,240..284}; type [284,11,138_2]; status: weights = 138_2 - {146..152,162..168,178..284}; type [283,12,136_2]; status: weights = 136_2 - {222..282}; type [283,13,134_2]; status: weights = 134_2 - {250..282}; n = 283, k >= 2: 188,161, 150, 144, 143, 141, 140, 139, 138, 137, 136, 134, 134; type [284,10,138_2]; status: weights = 138_2 - {246..284}; type [284,12,136_2]; status: weights = 136_2 - {238..284}; type [285,13,136_2]; status: weights = 136_2 - {206,210,214..284}; type [284,14,134_2]; status: weights = 134_2 - {242..284}; n = 284, k >= 2: 189,162, 151, 145, 144, 142, 140, 140, 138, 138, 136, 135, 134; type [285,9,140_2]; status: weights = 140_2 - {182,198,202,206,210..214,218,222,226..230,234, 242..246,250,254,258..262,266,270,274,278,282}; type [286,10,140_2]; status: weights = 140_4 - {148,180,208..284}; type [285,11,138_2]; status: weights = 138_2 - {218,222..284}; type [286,12,138_2]; status: weights = 138_2 - {206..286}; type [285,14,134_2]; status: weights = 134_2 - {274..284}; n = 285, k >= 2: 190,162, 152, 146, 144, 142, 141, 140, 139, 138, 137, 136, 134; type [287,11,140_2]; status: weights = {140,144,156,160,172}; type [286,13,136_2]; status: weights = 136_2 - {234..286}; type [287,14,136_2]; status: weights = 136_4 - {224..284}; n = 286, k >= 2: 190,163, 152, 146, 144, 143, 142, 140, 140, 139, 138, 136, 135; type [288,9,142_2]; status: weights = {142,144,158,160,174,176,190,192,238,240}; type [287,10,140_2]; status: weights = 140_2 - {150,182,214,226,230..286}; type [287,12,138_2]; status: weights = 138_2 - {226..286}; type [287,13,136_2]; status: weights = 136_2 - {250..286}; n = 287, k >= 2: 191,164, 152, 147, 144, 144, 142, 141, 140, 140, 138, 136, 136; type [288,10,140_2]; status: weights = 140_2 - {250,254..278,282..288}; type [288,11,140_2]; status: weights = 140_2 - {150,154,166,170,182,186,190,198,202,206,210..288}; type [289,12,140_2]; status: weights = 140_4 - {188..288}; type [289,13,138_2]; status: weights = 138_2 - {206,210..288}; type [288,14,136_2]; status: weights = 136_2 - {242..288}; n = 288, k >= 2: 192,164, 152, 148, 144, 144, 143, 142, 140, 140, 139, 137, 136; type [289,9,142_2]; status: weights = 142_2 - {186,202,210,214..218,226,230..236,246..252,258,262..268,274..284}; type [290,10,142_2]; status: weights = {142,144,158,160,162,164,166,168,174,176,190,192,200,204}; type [289,11,140_2]; status: weights = 140_2 - {222,226,230..288}; type [289,14,136_2]; status: weights = 136_2 - {278..288}; n = 289, k >= 2: 192,164, 153, 148, 145, 144, 144, 142, 141, 140, 140, 138, 136; type [291,9,144_2]; status: weights = {144,160,176,192,240}; type [290,11,140_2]; status: weights = 140_2 - {242,246..290}; type [290,12,140_2]; status: weights = 140_2 - {206,210..290}; type [290,13,138_2]; status: weights = 138_2 - {236..290}; n = 290, k >= 2: 193,165, 154, 148, 146, 144, 144, 143, 142, 140, 140, 138, 136; type [291,10,142_2]; status: weights = 142_2 - {154,186,218,220,230..290}; type [292,11,142_2]; status: weights = 142_2 - {154,186,188,194,200..292}; type [291,12,140_2]; status: weights = 140_2 - {226,230..290}; type [291,13,138_2]; status: weights = 138_2 - {254..290}; type [292,14,138_2]; status: weights = 138_2 - {244..292}; n = 291, k >= 2: 194,166, 154, 149, 146, 144, 144, 144, 142, 141, 140, 138, 137; type [292,9,144_2]; status: weights = 144_2 - {150,154,158,170,174,182,186..190,198,202..206, 210..222,226..238,246..254,258..270,274..286,290,292}; type [293,10,144_2]; status: weights = {144,160,164,168,176,192}; type [292,12,140_2]; status: weights = 140_2 - {242..292}; type [293,13,140_2]; status: weights = 140_2 - {210,214,218,222..292}; n = 292, k >= 2: 194,166, 155, 150, 147, 145, 144, 144, 143, 142, 140, 139, 138; type [293,11,142_2]; status: weights = 142_2 - {226..292}; type [294,12,142_2]; status: weights = 142_2 - {210..294}; type [293,14,138_2]; status: weights = 138_2 - {282..292}; n = 293, k >= 2: 195,167, 156, 150, 148, 146, 144, 144, 144, 142, 141, 140, 138; type [294,10,144_2]; status: weights = 144_2 - {150,154..158,174,182,186..190,198,202,206,210,214,218..294}; type [295,11,144_2]; status: weights = 144_2 - {150,154..158,166,170,174,182,186..190,194..294}; type [294,13,140_2]; status: weights = 140_2 - {238..294}; type [295,14,140_2]; status: weights = 140_4 - {208..292}; n = 294, k >= 2: 196,168, 156, 151, 148, 146, 145, 144, 144, 143, 142, 140, 139; type [295,10,144_2]; status: weights = 144_2 - {158,190,222,234,238..294}; type [295,12,142_2]; status: weights = 142_2 - {230..294}; type [295,13,140_2]; status: weights = 140_2 - {254,258..294}; n = 295, k >= 2: 196,168, 156, 152, 148, 147, 146, 144, 144, 144, 142, 140, 140; type [297,9,146_2]; status: weights = 146_2 - {194,210,218,222..226,230..242,254..296}; type [296,10,144_2]; status: weights = 144_2 - {258,262..286,290..296}; type [296,11,144_2]; status: weights = 144_2 - {158,190,198,206,210,214..296}; type [297,12,144_2]; status: weights = 144_4 - {200..296}; type [297,13,142_2]; status: weights = 142_2 - {210,214..296}; type [296,14,140_2]; status: weights = 140_2 - {246..296}; n = 296, k >= 2: 197,168, 157, 152, 149, 148, 146, 145, 144, 144, 143, 141, 140; type [297,10,144_2]; status: weights = 144_2 - {274,278..286,292..296}; type [297,11,144_2]; status: weights = 144_2 - {226,230,234..296}; type [297,14,140_2]; status: weights = 140_2 - {284..296}; n = 297, k >= 2: 198,169, 158, 152, 150, 148, 147, 146, 144, 144, 144, 142, 140; type [299,10,146_2]; status: weights = 146_2 - {162,194,226..230,234,238..298}; type [298,11,144_2]; status: weights = 144_2 - {246,250,254..298}; type [298,12,144_2]; status: weights = 144_2 - {214,218..298}; type [298,13,142_2]; status: weights = 142_2 - {242..298}; n = 298, k >= 2: 198,170, 158, 152, 150, 148, 148, 146, 145, 144, 144, 142, 140; type [300,9,148_2]; status: weights = 148_4 - {196,212,220..244,256..300}; type [300,11,146_2]; status: weights = 146_2 - {162,194..300}; type [299,12,144_2]; status: weights = 144_2 - {234,238..298}; type [299,13,142_2]; status: weights = 142_2 - {258..298}; type [300,14,142_2]; status: weights = 142_2 - {248..300}; n = 299, k >= 2: 199,170, 159, 153, 151, 149, 148, 147, 146, 145, 144, 142, 141; type [300,10,146_2]; status: weights = 146_2 - {262..300}; type [300,12,144_2]; status: weights = 144_2 - {250..300}; type [301,13,144_2]; status: weights = 144_2 - {214,218,222,226..300}; n = 300, k >= 2: 200,171, 160, 154, 152, 150, 148, 148, 146, 146, 144, 143, 142; data_comment( ![ One gets a few improvements if the procedure is repeated. Perhaps some of the improvements are due to modifications to {\tt Split} in the interim. ]! ) type [209,9,102_2]; status: weights = {102,104,110,112,118,120,126,128,142,144,158,160}; type [210,8,104_2]; status: weights = {104,106,108,112,116,120,128,144,160}; type [225,10,108_2]; status: weights = 108_2 - {202,206..214,218..224}; n = 225, k >= 2: 150,128, 120, 115, 112, 112, 112, 110, 108, 108, 107, 106, 104; type [228,11,110_2]; status: weights = 110_2 - {122,124,130,138,140,146,154..158,162..228}; type [233,11,112_2]; status: weights = 112_2 - {186,190..232}; type [247,11,120_2]; status: weights = {120,124,128,136,144,152}; type [252,11,122_2]; status: weights = 122_2 - {146,148,154,162..252}; data_comment( ![ The following segment was created with \begin{verbatim} set repeat loop; set allowed failures = 6; build tables for 86 <= n <= 177, 15 <= k <= 25; \end{verbatim} except that on $n = 138$, I got some error messages from the simplex method, and when I restarted with $n = 138$, they went away. ]! ) set dual constraint bound = -1; set allowed failures = 6; set repeat loop; type [86,15,36_2]; status: weights = 36_2 - {76..86}; type [87,16,36_2]; status: weights = 36_2 - {64..86}; type [87,19,34_2]; status: weights = 34_2 - {80..86}; type [86,22,32_2]; status: weights = 32_2 - {66,70..84}; n = 86, k >= 15: 36, 35, 34, 34, 33, 32, 32, 32, 30, 30, 30; type [88,20,34_2]; status: weights = 34_2 - {78..88}; n = 87, k >= 15: 36, 36, 35, 34, 34, 33, 32, 32, 31, 30, 30; type [89,24,32_2]; status: weights = 32_2 - {86,88}; n = 88, k >= 15: 36, 36, 36, 34, 34, 34, 32, 32, 32, 31, 30; type [90,15,38_2]; status: weights = 38_2 - {78..90}; type [90,25,32_2]; status: weights = 32_2 - {86..90}; n = 89, k >= 15: 37, 36, 36, 35, 34, 34, 33, 32, 32, 32, 31; type [91,16,38_2]; status: weights = 38_2 - {64..90}; type [91,19,36_2]; status: weights = 36_2 - {80..90}; n = 90, k >= 15: 38, 37, 36, 36, 35, 34, 34, 33, 32, 32, 32; type [91,15,38_2]; status: weights = 38_2 - {90}; type [92,20,36_2]; status: weights = 36_2 - {74..92}; n = 91, k >= 15: 38, 38, 36, 36, 36, 35, 34, 34, 33, 32, 32; type [92,16,38_2]; status: weights = 38_2 - {90,92}; type [93,24,34_2]; status: weights = 34_2 - {86..92}; n = 92, k >= 15: 38, 38, 37, 36, 36, 36, 34, 34, 34, 33, 32; type [94,15,40_2]; status: weights = 40_2 - {82..94}; type [93,20,36_2]; status: weights = 36_2 - {92}; type [94,21,36_2]; status: weights = 36_2 - {92,94}; n = 93, k >= 15: 39, 38, 38, 37, 36, 36, 35, 34, 34, 34, 32; type [95,16,40_2]; status: weights = 40_2 - {66..94}; type [95,19,38_2]; status: weights = 38_2 - {80..94}; n = 94, k >= 15: 40, 39, 38, 38, 37, 36, 36, 35, 34, 34, 33; type [95,15,40_2]; status: weights = 40_2 - {94}; type [96,23,36_2]; status: weights = 36_2 - {90..94}; n = 95, k >= 15: 40, 40, 38, 38, 38, 36, 36, 36, 35, 34, 34; type [96,16,40_2]; status: weights = 40_2 - {94,96}; type [97,17,40_2]; status: weights = 40_2 - {92..96}; type [97,20,38_2]; status: weights = 38_2 - {94,96}; type [97,24,36_2]; status: weights = 36_2 - {84..96}; n = 96, k >= 15: 40, 40, 39, 38, 38, 37, 36, 36, 36, 35, 34; type [98,15,42_2]; status: weights = 42_2 - {82..98}; type [98,18,40_2]; status: weights = 40_2 - {90..96}; type [98,21,38_2]; status: weights = 38_2 - {94..98}; n = 97, k >= 15: 41, 40, 40, 39, 38, 38, 37, 36, 36, 36, 34; type [99,19,40_2]; status: weights = 40_2 - {80..98}; type [99,22,38_2]; status: weights = 38_2 - {92..98}; type [99,25,36_2]; status: weights = 36_2 - {98}; n = 98, k >= 15: 42, 40, 40, 40, 39, 38, 38, 37, 36, 36, 35; type [99,15,42_2]; status: weights = 42_2 - {96,98}; type [100,16,42_2]; status: weights = 42_2 - {94..100}; type [100,23,38_2]; status: weights = 38_2 - {82,86..98}; n = 99, k >= 15: 42, 41, 40, 40, 40, 38, 38, 38, 37, 36, 36; type [101,17,42_2]; status: weights = 42_2 - {90..100}; type [101,20,40_2]; status: weights = 40_2 - {94..100}; type [101,24,38_2]; status: weights = 38_2 - {78..100}; n = 100, k >= 15: 42, 42, 41, 40, 40, 39, 38, 38, 38, 37, 36; type [102,15,44_2]; status: weights = 44_2 - {86..102}; type [102,18,42_2]; status: weights = 42_2 - {86..100}; type [102,21,40_2]; status: weights = 40_2 - {92..102}; n = 101, k >= 15: 43, 42, 42, 41, 40, 40, 39, 38, 38, 38, 36; type [103,19,42_2]; status: weights = 42_2 - {78..102}; type [103,22,40_2]; status: weights = 40_2 - {78..102}; type [103,25,38_2]; status: weights = 38_2 - {98..102}; n = 102, k >= 15: 44, 42, 42, 42, 41, 40, 40, 39, 38, 38, 37; type [103,15,44_2]; status: weights = 44_2 - {98..102}; type [104,16,44_2]; status: weights = 44_2 - {96..104}; n = 103, k >= 15: 44, 43, 42, 42, 42, 40, 40, 40, 38, 38, 38; type [105,17,44_2]; status: weights = 44_2 - {86,90..104}; type [105,20,42_2]; status: weights = 42_2 - {96..104}; n = 104, k >= 15: 44, 44, 43, 42, 42, 41, 40, 40, 39, 38, 38; type [106,15,46_2]; status: weights = 46_2 - {84..106}; type [106,21,42_2]; status: weights = 42_2 - {88..106}; n = 105, k >= 15: 45, 44, 44, 43, 42, 42, 41, 40, 40, 39, 38; type [107,25,40_2]; status: weights = 40_2 - {98..106}; n = 106, k >= 15: 46, 44, 44, 44, 42, 42, 42, 40, 40, 40, 39; type [107,15,46_2]; status: weights = 46_2 - {100..106}; type [108,16,46_2]; status: weights = 46_2 - {98..108}; n = 107, k >= 15: 46, 45, 44, 44, 43, 42, 42, 41, 40, 40, 40; type [109,17,46_2]; status: weights = 46_2 - {86..108}; type [109,20,44_2]; status: weights = 44_2 - {96..108}; n = 108, k >= 15: 46, 46, 45, 44, 44, 43, 42, 42, 41, 40, 40; type [110,15,48_2]; status: weights = 48_2 - {86..110}; type [110,18,46_2]; status: weights = 46_2 - {84..110}; type [110,21,44_2]; status: weights = 44_2 - {82..110}; n = 109, k >= 15: 47, 46, 46, 45, 44, 44, 43, 42, 42, 41, 40; type [111,25,42_2]; status: weights = 42_2 - {98..110}; n = 110, k >= 15: 48, 46, 46, 46, 44, 44, 44, 42, 42, 42, 41; type [111,15,48_2]; status: weights = 48_2 - {102..110}; type [112,16,48_2]; status: weights = 48_2 - {100..112}; type [111,21,44_2]; status: weights = 44_2 - {110}; n = 111, k >= 15: 48, 47, 46, 46, 45, 44, 44, 43, 42, 42, 42; type [113,17,48_2]; status: weights = 48_2 - {82..112}; type [113,20,46_2]; status: weights = 46_2 - {96..112}; n = 112, k >= 15: 48, 48, 47, 46, 46, 45, 44, 44, 43, 42, 42; type [114,15,50_2]; status: weights = 50_2 - {88..114}; type [113,16,48_2]; status: weights = 48_2 - {112}; type [114,18,48_2]; status: weights = 48_2 - {82..114}; type [114,21,46_2]; status: weights = 46_2 - {78..114}; type [114,24,44_2]; status: weights = 44_2 - {98..110}; n = 113, k >= 15: 49, 48, 48, 47, 46, 46, 45, 44, 44, 43, 42; type [114,17,48_2]; status: weights = 48_2 - {112,114}; type [115,25,44_2]; status: weights = 44_2 - {92..114}; n = 114, k >= 15: 50, 48, 48, 48, 46, 46, 46, 44, 44, 44, 43; type [115,15,50_2]; status: weights = 50_2 - {104..114}; type [116,16,50_2]; status: weights = 50_2 - {102..116}; type [115,18,48_2]; status: weights = 48_2 - {110..114}; type [115,21,46_2]; status: weights = 46_2 - {110..114}; type [116,22,46_2]; status: weights = 46_2 - {106..116}; n = 115, k >= 15: 50, 49, 48, 48, 47, 46, 46, 45, 44, 44, 44; type [116,15,50_2]; status: weights = 50_2 - {116}; type [117,20,48_2]; status: weights = 48_2 - {94..116}; type [116,25,44_2]; status: weights = 44_2 - {114,116}; n = 116, k >= 15: 50, 50, 48, 48, 48, 47, 46, 46, 45, 44, 44; type [118,15,52_2]; status: weights = 52_2 - {90..118}; type [117,16,50_2]; status: weights = 50_2 - {114,116}; type [118,17,50_2]; status: weights = 50_2 - {114..118}; type [118,24,46_2]; status: weights = 46_2 - {90..116}; n = 117, k >= 15: 51, 50, 49, 48, 48, 48, 46, 46, 46, 45, 44; type [119,18,50_2]; status: weights = 50_2 - {112..118}; type [118,20,48_2]; status: weights = 48_2 - {118}; type [119,21,48_2]; status: weights = 48_2 - {110..118}; n = 118, k >= 15: 52, 50, 50, 49, 48, 48, 47, 46, 46, 46, 44; type [119,15,52_2]; status: weights = 52_2 - {106..118}; type [120,16,52_2]; status: weights = 52_2 - {104..120}; type [120,19,50_2]; status: weights = 50_2 - {106,110..118}; type [120,22,48_2]; status: weights = 48_2 - {102,106..120}; type [120,25,46_2]; status: weights = 46_2 - {116..120}; n = 119, k >= 15: 52, 51, 50, 50, 49, 48, 48, 47, 46, 46, 45; type [121,20,50_2]; status: weights = 50_2 - {94..120}; type [121,23,48_2]; status: weights = 48_2 - {94,98..120}; n = 120, k >= 15: 52, 52, 50, 50, 50, 49, 48, 48, 47, 46, 46; type [122,15,54_2]; status: weights = 54_2 - {92..122}; type [121,16,52_2]; status: weights = 52_2 - {116..120}; type [122,17,52_2]; status: weights = 52_2 - {112..122}; n = 121, k >= 15: 53, 52, 51, 50, 50, 50, 48, 48, 48, 46, 46; type [123,18,52_2]; status: weights = 52_2 - {110..122}; type [123,21,50_2]; status: weights = 50_2 - {110..122}; n = 122, k >= 15: 54, 52, 52, 51, 50, 50, 49, 48, 48, 47, 46; type [123,15,54_2]; status: weights = 54_2 - {106..122}; type [124,16,54_2]; status: weights = 54_2 - {104..124}; type [124,19,52_2]; status: weights = 52_2 - {102..122}; type [124,22,50_2]; status: weights = 50_2 - {90,94,98..124}; type [124,25,48_2]; status: weights = 48_2 - {116..124}; n = 123, k >= 15: 54, 53, 52, 52, 51, 50, 50, 49, 48, 48, 47; type [124,15,54_2]; status: weights = 54_2 - {124}; type [125,20,52_2]; status: weights = 52_2 - {92..124}; type [124,21,50_2]; status: weights = 50_2 - {124}; n = 124, k >= 15: 54, 54, 52, 52, 52, 51, 50, 50, 48, 48, 48; type [126,15,56_2]; status: weights = 56_2 - {94..126}; type [125,16,54_2]; status: weights = 54_2 - {118..124}; type [126,17,54_2]; status: weights = 54_2 - {114..126}; n = 125, k >= 15: 55, 54, 53, 52, 52, 52, 50, 50, 49, 48, 48; type [127,18,54_2]; status: weights = 54_2 - {106,110..126}; type [127,21,52_2]; status: weights = 52_2 - {110..126}; n = 126, k >= 15: 56, 54, 54, 53, 52, 52, 51, 50, 50, 49, 48; type [127,15,56_2]; status: weights = 56_2 - {108..126}; type [128,16,56_2]; status: weights = 56_2 - {106..128}; type [128,19,54_2]; status: weights = 54_2 - {102..126}; type [128,22,52_2]; status: weights = 52_2 - {86..128}; type [128,25,50_2]; status: weights = 50_2 - {112..128}; n = 127, k >= 15: 56, 55, 54, 54, 53, 52, 52, 51, 50, 50, 49; type [128,21,52_2]; status: weights = 52_2 - {126,128}; n = 128, k >= 15: 56, 56, 54, 54, 54, 52, 52, 52, 50, 50, 50; type [130,15,58_2]; status: weights = 58_2 - {94..130}; type [129,16,56_2]; status: weights = 56_2 - {118..128}; type [130,17,56_2]; status: weights = 56_2 - {114..130}; type [130,23,52_2]; status: weights = 52_2 - {122..130}; n = 129, k >= 15: 57, 56, 55, 54, 54, 53, 52, 52, 51, 50, 50; type [130,16,56_2]; status: weights = 56_2 - {130}; type [131,18,56_2]; status: weights = 56_2 - {102..130}; type [131,21,54_2]; status: weights = 54_2 - {110..130}; n = 130, k >= 15: 58, 56, 56, 55, 54, 54, 53, 52, 52, 51, 50; type [131,15,58_2]; status: weights = 58_2 - {110..130}; type [132,16,58_2]; status: weights = 58_2 - {108..132}; type [132,25,52_2]; status: weights = 52_2 - {106..132}; n = 131, k >= 15: 58, 57, 56, 56, 55, 54, 54, 52, 52, 52, 51; type [132,15,58_2]; status: weights = 58_2 - {132}; type [132,21,54_2]; status: weights = 54_2 - {126..132}; n = 132, k >= 15: 58, 58, 56, 56, 56, 54, 54, 53, 52, 52, 52; type [134,15,60_2]; status: weights = 60_2 - {98..134}; type [133,16,58_2]; status: weights = 58_2 - {122..132}; type [134,17,58_2]; status: weights = 58_2 - {116..134}; type [134,23,54_2]; status: weights = 54_2 - {118..134}; n = 133, k >= 15: 59, 58, 57, 56, 56, 55, 54, 54, 53, 52, 52; type [134,16,58_2]; status: weights = 58_2 - {134}; type [135,18,58_2]; status: weights = 58_2 - {100..134}; type [135,21,56_2]; status: weights = 56_2 - {110..134}; type [135,24,54_2]; status: weights = 54_2 - {116..134}; n = 134, k >= 15: 60, 58, 58, 57, 56, 56, 55, 54, 54, 53, 52; type [135,15,60_2]; status: weights = 60_2 - {114..134}; type [136,16,60_2]; status: weights = 60_2 - {110..136}; type [136,19,58_2]; status: weights = 58_2 - {98..134}; n = 135, k >= 15: 60, 59, 58, 58, 57, 56, 56, 54, 54, 54, 52; type [136,21,56_2]; status: weights = 56_2 - {128..136}; type [137,22,56_2]; status: weights = 56_2 - {126..136}; n = 136, k >= 15: 60, 60, 58, 58, 58, 56, 56, 55, 54, 54, 53; type [138,15,62_2]; status: weights = 62_2 - {96..138}; type [137,16,60_2]; status: weights = 60_2 - {122..136}; type [138,17,60_2]; status: weights = 60_2 - {116..138}; type [137,19,58_2]; status: weights = 58_2 - {130,134}; type [138,23,56_2]; status: weights = 56_2 - {106..138}; n = 137, k >= 15: 61, 60, 59, 58, 58, 57, 56, 56, 55, 54, 54; type [138,16,60_2]; status: weights = 60_2 - {136,138}; type [139,21,58_2]; status: weights = 58_2 - {108..138}; type [138,22,56_2]; status: weights = 56_2 - {138}; type [139,24,56_2]; status: weights = 56_2 - {100..138}; n = 138, k >= 15: 62, 60, 60, 58, 58, 58, 57, 56, 56, 55, 54; type [139,15,62_2]; status: weights = 62_2 - {114..138}; type [140,16,62_2]; status: weights = 62_2 - {110..140}; type [139,17,60_2]; status: weights = 60_2 - {134..138}; n = 139, k >= 15: 62, 61, 60, 59, 58, 58, 58, 56, 56, 56, 54; type [140,15,62_2]; status: weights = 62_2 - {140}; type [141,19,60_2]; status: weights = 60_2 - {126..138}; type [140,21,58_2]; status: weights = 58_2 - {128..140}; type [141,22,58_2]; status: weights = 58_2 - {126..140}; n = 140, k >= 15: 62, 62, 60, 60, 59, 58, 58, 57, 56, 56, 55; type [142,15,64_2]; status: weights = 64_2 - {98,102..142}; type [141,16,62_2]; status: weights = 62_2 - {126..140}; type [142,17,62_2]; status: weights = 62_2 - {118..142}; type [142,20,60_2]; status: weights = 60_2 - {114..118,122..138}; type [142,23,58_2]; status: weights = 58_2 - {96..142}; n = 141, k >= 15: 63, 62, 61, 60, 60, 59, 58, 58, 57, 56, 56; type [142,16,62_2]; status: weights = 62_2 - {138..142}; type [143,21,60_2]; status: weights = 60_2 - {108..142}; type [142,22,58_2]; status: weights = 58_2 - {140,142}; n = 142, k >= 15: 64, 62, 62, 60, 60, 60, 59, 58, 58, 56, 56; type [143,15,64_2]; status: weights = 64_2 - {118..142}; type [144,16,64_2]; status: weights = 64_2 - {110..144}; type [144,18,62_2]; status: weights = 62_2 - {130..134,138..144}; type [143,23,58_2]; status: weights = 58_2 - {138..142}; n = 143, k >= 15: 64, 63, 62, 61, 60, 60, 60, 58, 58, 57, 56; type [145,19,62_2]; status: weights = 62_2 - {130..144}; type [144,21,60_2]; status: weights = 60_2 - {128..144}; type [145,22,60_2]; status: weights = 60_2 - {126..144}; type [145,25,58_2]; status: weights = 58_2 - {136..142}; n = 144, k >= 15: 64, 64, 62, 62, 61, 60, 60, 59, 58, 58, 57; type [145,16,64_2]; status: weights = 64_2 - {126..144}; type [146,17,64_2]; status: weights = 64_2 - {118..146}; type [146,20,62_2]; status: weights = 62_2 - {112..144}; n = 145, k >= 15: 64, 64, 63, 62, 62, 61, 60, 60, 58, 58, 58; type [147,15,66_2]; status: weights = 66_2 - {120..146}; type [146,16,64_2]; status: weights = 64_2 - {142..146}; type [147,21,62_2]; status: weights = 62_2 - {108..146}; type [146,22,60_2]; status: weights = 60_2 - {140..146}; type [147,23,60_2]; status: weights = 60_2 - {138..146}; n = 146, k >= 15: 65, 64, 64, 62, 62, 62, 61, 60, 59, 58, 58; type [148,16,66_2]; status: weights = 66_2 - {112..148}; type [147,17,64_2]; status: weights = 64_2 - {138..146}; type [148,18,64_2]; status: weights = 64_2 - {132..148}; type [148,24,60_2]; status: weights = 60_2 - {136..148}; n = 147, k >= 15: 66, 65, 64, 63, 62, 62, 62, 60, 60, 59, 58; type [149,19,64_2]; status: weights = 64_2 - {130..148}; type [148,21,62_2]; status: weights = 62_2 - {128..148}; type [149,22,62_2]; status: weights = 62_2 - {126..148}; type [149,25,60_2]; status: weights = 60_2 - {128..148}; n = 148, k >= 15: 66, 66, 64, 64, 63, 62, 62, 61, 60, 60, 59; type [150,15,68_2]; status: weights = 68_2 - {102,106..150}; type [149,16,66_2]; status: weights = 66_2 - {126..148}; type [150,17,66_2]; status: weights = 66_2 - {122..150}; type [150,20,64_2]; status: weights = 64_2 - {114..148}; n = 149, k >= 15: 67, 66, 65, 64, 64, 63, 62, 62, 60, 60, 60; type [150,16,66_2]; status: weights = 66_2 - {142,146..150}; type [150,22,62_2]; status: weights = 62_2 - {140..150}; type [151,23,62_2]; status: weights = 62_2 - {138..150}; n = 150, k >= 15: 68, 66, 66, 64, 64, 64, 62, 62, 61, 60, 60; type [151,15,68_2]; status: weights = 68_2 - {122..150}; type [152,16,68_2]; status: weights = 68_2 - {114..152}; type [151,17,66_2]; status: weights = 66_2 - {140..150}; type [152,18,66_2]; status: weights = 66_2 - {130..152}; type [152,21,64_2]; status: weights = 64_2 - {130..152}; type [152,24,62_2]; status: weights = 62_2 - {126..152}; n = 151, k >= 15: 68, 67, 66, 65, 64, 64, 63, 62, 62, 61, 60; type [152,17,66_2]; status: weights = 66_2 - {152}; type [153,19,66_2]; status: weights = 66_2 - {122..152}; type [153,22,64_2]; status: weights = 64_2 - {124..152}; type [153,25,62_2]; status: weights = 62_2 - {114..152}; n = 152, k >= 15: 68, 68, 66, 66, 65, 64, 64, 63, 62, 62, 61; type [153,16,68_2]; status: weights = 68_2 - {128..152}; type [154,17,68_2]; status: weights = 68_2 - {124..154}; type [154,20,66_2]; status: weights = 66_2 - {110..152}; n = 153, k >= 15: 68, 68, 67, 66, 66, 65, 64, 64, 62, 62, 62; type [155,15,70_2]; status: weights = 70_2 - {126..154}; type [154,16,68_2]; status: weights = 68_2 - {146..154}; type [154,22,64_2]; status: weights = 64_2 - {142..154}; type [155,23,64_2]; status: weights = 64_2 - {136..154}; n = 154, k >= 15: 69, 68, 68, 66, 66, 66, 64, 64, 63, 62, 62; type [156,16,70_2]; status: weights = 70_2 - {114..156}; type [155,17,68_2]; status: weights = 68_2 - {142..154}; type [156,18,68_2]; status: weights = 68_2 - {126..156}; type [156,21,66_2]; status: weights = 66_2 - {128..156}; type [156,24,64_2]; status: weights = 64_2 - {112..156}; n = 155, k >= 15: 70, 69, 68, 67, 66, 66, 65, 64, 64, 63, 62; type [156,17,68_2]; status: weights = 68_2 - {154,156}; type [157,19,68_2]; status: weights = 68_2 - {118..156}; type [157,22,66_2]; status: weights = 66_2 - {122..156}; type [156,23,64_2]; status: weights = 64_2 - {156}; n = 156, k >= 15: 70, 70, 68, 68, 67, 66, 66, 65, 64, 64, 62; type [158,15,72_2]; status: weights = 72_4 - {108..156}; type [157,16,70_2]; status: weights = 70_2 - {130..156}; type [158,17,70_2]; status: weights = 70_2 - {126..158}; n = 157, k >= 15: 71, 70, 69, 68, 68, 66, 66, 66, 64, 64, 63; type [158,16,70_2]; status: weights = 70_2 - {146..158}; type [158,19,68_2]; status: weights = 68_2 - {152..156}; type [159,20,68_2]; status: weights = 68_2 - {150..156}; type [158,22,66_2]; status: weights = 66_2 - {142..158}; type [159,23,66_2]; status: weights = 66_2 - {134..158}; n = 158, k >= 15: 72, 70, 70, 68, 68, 67, 66, 66, 65, 64, 64; type [159,15,72_2]; status: weights = 72_2 - {130..158}; type [160,16,72_2]; status: weights = 72_2 - {118..160}; type [159,17,70_2]; status: weights = 70_2 - {142..158}; type [160,18,70_2]; status: weights = 70_2 - {126..160}; type [160,21,68_2]; status: weights = 68_2 - {126..160}; type [159,22,66_2]; status: weights = 66_2 - {158}; type [160,24,66_2]; status: weights = 66_2 - {104..160}; n = 159, k >= 15: 72, 71, 70, 69, 68, 68, 67, 66, 66, 65, 64; type [160,17,70_2]; status: weights = 70_2 - {156..160}; type [161,19,70_2]; status: weights = 70_2 - {114,118..160}; type [161,22,68_2]; status: weights = 68_2 - {122..160}; type [160,23,66_2]; status: weights = 66_2 - {156..160}; n = 160, k >= 15: 72, 72, 70, 70, 69, 68, 68, 67, 66, 66, 64; type [161,16,72_2]; status: weights = 72_2 - {130..150,154..160}; type [162,17,72_2]; status: weights = 72_2 - {130..162}; type [162,25,66_2]; status: weights = 66_2 - {152..160}; n = 161, k >= 15: 72, 72, 71, 70, 70, 68, 68, 68, 66, 66, 65; type [163,15,74_2]; status: weights = 74_2 - {132..162}; type [162,16,72_2]; status: weights = 72_2 - {150..162}; type [162,19,70_2]; status: weights = 70_2 - {154..160}; type [163,20,70_2]; status: weights = 70_2 - {146..160}; type [162,22,68_2]; status: weights = 68_2 - {142..162}; type [163,23,68_2]; status: weights = 68_2 - {130..162}; n = 162, k >= 15: 73, 72, 72, 70, 70, 69, 68, 68, 67, 66, 66; type [164,16,74_2]; status: weights = 74_2 - {118..164}; type [163,17,72_2]; status: weights = 72_2 - {146..162}; type [164,18,72_2]; status: weights = 72_2 - {126..164}; type [164,21,70_2]; status: weights = 70_2 - {126..164}; type [163,22,68_2]; status: weights = 68_2 - {160,162}; n = 163, k >= 15: 74, 73, 72, 71, 70, 70, 69, 68, 68, 66, 66; type [164,17,72_2]; status: weights = 72_2 - {158..164}; type [165,22,70_2]; status: weights = 70_2 - {122..164}; type [164,23,68_2]; status: weights = 68_2 - {156..164}; type [165,24,68_2]; status: weights = 68_2 - {152..164}; n = 164, k >= 15: 74, 74, 72, 72, 70, 70, 70, 69, 68, 67, 66; type [165,16,74_2]; status: weights = 74_2 - {132..164}; type [166,17,74_2]; status: weights = 74_2 - {130..166}; type [165,18,72_2]; status: weights = 72_2 - {154..164}; type [166,19,72_2]; status: weights = 72_2 - {150..166}; type [166,25,68_2]; status: weights = 68_2 - {150..164}; n = 165, k >= 15: 74, 74, 73, 72, 71, 70, 70, 70, 68, 68, 67; type [167,15,76_2]; status: weights = 76_2 - {136..162}; type [166,16,74_2]; status: weights = 74_2 - {152..166}; type [167,20,72_2]; status: weights = 72_2 - {142,146..166}; type [166,22,70_2]; status: weights = 70_2 - {144..166}; type [167,23,70_2]; status: weights = 70_2 - {124..166}; n = 166, k >= 15: 75, 74, 74, 72, 72, 71, 70, 70, 69, 68, 68; type [168,16,76_2]; status: weights = 76_2 - {118..168}; type [167,17,74_2]; status: weights = 74_2 - {146..166}; type [168,18,74_2]; status: weights = 74_2 - {126..168}; type [168,21,72_2]; status: weights = 72_2 - {126..168}; type [167,22,70_2]; status: weights = 70_2 - {160..166}; n = 167, k >= 15: 76, 75, 74, 73, 72, 72, 71, 70, 70, 68, 68; type [168,17,74_2]; status: weights = 74_2 - {160..168}; type [169,22,72_2]; status: weights = 72_2 - {118..168}; type [168,23,70_2]; status: weights = 70_2 - {158..168}; type [169,24,70_2]; status: weights = 70_2 - {146..168}; n = 168, k >= 15: 76, 76, 74, 74, 72, 72, 72, 71, 70, 69, 68; type [169,16,76_2]; status: weights = 76_2 - {134..168}; type [170,17,76_2]; status: weights = 76_2 - {132..170}; type [169,18,74_2]; status: weights = 74_2 - {156..168}; type [170,19,74_2]; status: weights = 74_2 - {150..170}; type [170,25,70_2]; status: weights = 70_2 - {140..170}; n = 169, k >= 15: 76, 76, 75, 74, 73, 72, 72, 72, 70, 70, 69; type [171,15,78_2]; status: weights = 78_2 - {136..168}; type [170,16,76_2]; status: weights = 76_2 - {154..170}; type [171,20,74_2]; status: weights = 74_2 - {142..170}; type [170,22,72_2]; status: weights = 72_2 - {142..170}; type [171,23,72_2]; status: weights = 72_2 - {122..170}; n = 170, k >= 15: 77, 76, 76, 74, 74, 73, 72, 72, 71, 70, 70; type [172,16,78_2]; status: weights = 78_2 - {120..172}; type [171,17,76_2]; status: weights = 76_2 - {146..170}; type [172,18,76_2]; status: weights = 76_2 - {130..172}; type [172,21,74_2]; status: weights = 74_2 - {126..172}; type [171,22,72_2]; status: weights = 72_2 - {162..170}; n = 171, k >= 15: 78, 77, 76, 75, 74, 74, 73, 72, 72, 70, 70; type [172,17,76_2]; status: weights = 76_2 - {162..172}; type [172,23,72_2]; status: weights = 72_2 - {158..172}; type [173,24,72_2]; status: weights = 72_2 - {142..172}; n = 172, k >= 15: 78, 78, 76, 76, 74, 74, 74, 72, 72, 71, 70; type [173,16,78_2]; status: weights = 78_2 - {136..172}; type [174,17,78_2]; status: weights = 78_2 - {134..174}; type [173,18,76_2]; status: weights = 76_2 - {158..172}; type [174,19,76_2]; status: weights = 76_2 - {146,150..174}; type [174,22,74_2]; status: weights = 74_2 - {142..174}; type [173,23,72_2]; status: weights = 72_2 - {172}; type [174,25,72_2]; status: weights = 72_2 - {126..174}; n = 173, k >= 15: 78, 78, 77, 76, 75, 74, 74, 73, 72, 72, 71; type [175,15,80_2]; status: weights = 80_2 - {142..172}; type [174,16,78_2]; status: weights = 78_2 - {154..174}; type [174,18,76_2]; status: weights = 76_2 - {174}; type [175,20,76_2]; status: weights = 76_2 - {142..174}; n = 174, k >= 15: 79, 78, 78, 76, 76, 75, 74, 74, 72, 72, 72; type [176,16,80_2]; status: weights = 80_2 - {122..176}; type [175,17,78_2]; status: weights = 78_2 - {150..174}; type [176,18,78_2]; status: weights = 78_2 - {126,130..176}; type [175,22,74_2]; status: weights = 74_2 - {164..174}; type [176,23,74_2]; status: weights = 74_2 - {160..176}; n = 175, k >= 15: 80, 79, 78, 77, 76, 76, 74, 74, 73, 72, 72; type [176,17,78_2]; status: weights = 78_2 - {164..176}; type [177,21,76_2]; status: weights = 76_2 - {170,174}; type [177,24,74_2]; status: weights = 74_2 - {132..176}; n = 176, k >= 15: 80, 80, 78, 78, 76, 76, 75, 74, 74, 73, 72; type [177,16,80_2]; status: weights = 80_2 - {138..176}; type [178,17,80_2]; status: weights = 80_2 - {136..178}; type [177,18,78_2]; status: weights = 78_2 - {158..176}; type [178,19,78_2]; status: weights = 78_2 - {142,146..178}; type [178,22,76_2]; status: weights = 76_2 - {142..178}; type [177,23,74_2]; status: weights = 74_2 - {172..176}; n = 177, k >= 15: 80, 80, 79, 78, 77, 76, 76, 75, 74, 74, 72; data_comment( ![ \block{A menagerie of codes}\label{menagerie-section} This section contains a huge list of codes, including a few with previously unknown parameters. The whole list is in transition, as I try to find simpler (or better) descriptions of the codes. Because many of the codes are derived from other codes in the list, the list has gotten to be a bit of a tangle. It will in due course be cleaned up! In particular, I barely started the project of replacing many of the codes by codes described with the {\tt cyclic} command. Some codes have been replaced by generator matrices, which has the advantage of reducing interdependency, but the disadvantage that pages and pages are now filled with matrices. Hopefully better descriptions of these codes will be found. Note also that there is a certain amount of nonsense in this section resulting from uniqueness statements that should be proved by the methods of van Tilborg [.tilborg griesmer 1980.]. These have not yet been formalized in the {\tt Split} language. ]! ) DHIDE( ![ "done" notations for the following. Always look for all isomorphism types H: auto group residual transform, with nzv length and group size max specified K: auto group residual transform alt, with nzv length and group size max specified C: LAST column deleted E: each column deleted suffix P: done with "double column pairs" option suffix G: done with "double column groups" option Versions: suffix S: done after code shortening added suffix *: semifinal version suffix #: "final" version suffix !: done with "delete pairs = 5" added *); ]! ) unset auto joint list; [2_1_1] type [2,1,1]; [a] := {10}; DHIDE( ![ Some good seed codes: D1# run on everything in DATA_F2_1 except [31,13,9] D2#: [31,13,9] and [28_10_10.c-g2] skipped D3#: the above, [16,11,4], the [21,8,8]'s, the [24,14,6], and all the [28,10,10]'s skipped, [28,14,8], [29,8,12] --> end O(28)# done for the [28,14,8] (* DC1P#, D2PG#, O(30)#, DC1.7# done for *); ]! ) [18_9_6x] type [18,9,6]; [a] := Cyclic(2, 18, 9, 000101010000001101); (* isomorphic to [18_9_6.a] *); DHIDE( ![ (* DC2#, O(26)#, DC1.7# done for [20_8_8.a] *); (* DC1#, D3#, O(30)# done for [21_9_8.a] *); (* D3#, DC2P#, D1G, O(24)#, DC1.7# done for [21_8_8.b] *); (* DC4S(26/5,12), D4S(38/5,11)(stopped after 560 minutes), DC1# done for [24,12,8] *); ]! ) DHIDE( ![ DC1#, OE(26)#, DC1.7# done for [a] ]! ) DHIDE( ![ PertTwo tried on [a] -- [k] ]! ) [45_8_20] type [45,8,20]; (* to be continued later *); CREDIT(existence due to Blokh and Zyablov, blokh zyablov) DUAL_TRANSFORM([a], [48_8_22.a], ![30_{1,-17},30_{17}]!) (* [a] := [48_8_22.a] - dual word of weight 3 *); (* this code is generalized-cyclic *); [b] := Cyclic(5, 45, 8, 000111100000111111011010010101100100001011111); DHIDE( ![ (* DC2#, D3#, O(26)#, DC1.7# *); ]! ) [178_8_88] type [178,8,88]; DUAL_TRANSFORM_CH([a], [20_8_8.a-1], ![7,11,12,15,16]!) alt P( [51_8_24.a] ~ column 1 ); status: realizable; DHIDE( ![ (* DE1.7# done for [12,7,4] *); ]! ) (* ****************** SOME SIX-DIMENSIONAL CODES ************************** *); type [53,6,{26,28,30,32}]; config from x_26; show y32 != 0; (* This implies that [a], [b] is a complete list. *); (* **************** JUNK TO AVOID RE-ENTERING A CODE TYPE. **************** *); [75_7_36x] type [75,7,36]; DUAL_TRANSFORM([a], [178_8_88.a-1], ![88_{41},96]!) (* the above iso. to [75_7_36.a], but not equal *); DUAL_TRANSFORM([b], [178_8_88.a-1], ![88_{49},96]!) (* the above iso. to [75_7_36.b], but not equal *); [82_7_40x] type [82,7,40]; [a] := P( [18_6_8.a] ); [87_7_42x] type [87,7,42]; DUAL_TRANSFORM_PLUS([d], [75_7_36x.a-2], ![35_{10},36_{10},37,38_{10},39,40,41_{-10},42_{10},63_{10}]!, ![+ column 65]!) [105_8_50x] type [105,8,50]; DUAL_ORBIT_PLUS([b], [21_9_8.a], ![$2,$3,$4]!, ![000000110,000010001,001111101,010001011,010101111]!, ![- column 3 - column 40]!) [140_8_68y] type [140,8,68]; [d] := [21_8_8.b]^T using {$1,$2,$3 : 00001001,00010001,00011101,00100000, 00100011,00110000,00110100,01101000,01101010,01111000,01111110,10110101}; [42_8_18y] type [42,8,18]; DUAL_ORBIT([d], [140_8_68y.d], ![$2,$5]!, ![00000111,00001100,00101010,01101011]!) [147_8_72y] type [147,8,72]; DUAL_ORBIT([b], [21_8_8.b], ![$1, $2, $3]!, ![00000101,00001001,00001101,00010001,00011101,00100011,00110100,01101000, 01101010]!) (* ************** PUTATIVELY OPTIMAL SEVEN-DIMENSIONAL CODES *************** *); [40_7_18] type [40,7,18]; (* to be continued later *); % Delete if possible, redundant: DUAL_TRANSFORM_PLUS([ax], [87_7_42x.d-1], ![42_{85},43_{-85},45_{-85},47_{-85},48_{-85},49_{85},63_{85}]!, ![+ column 38]!) % Delete if possible, redundant: DUAL_ORBIT([cx], [24_7_10.f], ![$1,$3]!, ![0000001,0001001,0001111,0010011,1001001,1001010]!) at type [56_7_26]; [kk] := {10001000111010011011011101010010010100110011011001010000,0100101100101110010001 1110010001101100101100111001001110,001010011100010101011011000001111001101000010 01010011011,00011010100001001001110101001001101010110110001101010110,00000111111 000000111111111000000011111111000000001111111,0000000000011111111111111100000000 0000000111111111111111,00000000000000000000000000111111111111111111111111111111} ; [nn] := {10000111000111111000001111010100011010100010001001011010,0100011100011100011100 1100001111110000011111000001111111,001001000110011011000010001101101111000101100 10010110011,00010101010101100010010101101100100110010011101010011001,00001110001 100110001011110100101101010000101000111010101,0000000011111111111100000000000000 1111111111111111111111,00000000000000000000111111111111111111111111111111111111} ; [oo1..17] := PertTwo( Act( { (1,2)(3,5)(6,8), (3,8)(4,5)(6,7) }, {00000001, 00001101,00010101,00010111,11000000,11000001,11000111,11001111,11011110, 11011111,11111111} ) + check ); [r] := Act( { (2,4)(5,6), (1,8)(2,6,4,5), (2,5)(3,6) }, {00000101,00000111, 00001110,00011111,00111110,10000001,10111101,10111111} ); [x] := Act( { (1,8)(2,3)(4,7), (1,9,2)(3,5,4)(6,8,7) }, {000101111,000111101,001011111,011101111,111111111} ) + check; DUAL_ORBIT_CH([58], [40_7_18.cx], ![$1,$2]!, ![0000001,0000101,0000110,0001011,0001101,0001110,0100000,0100001,0100010, 0100011,0100101,0100111,0110010,0110110,0110111,0111011,1100000,1100100, 1100101,1101000]!) DUAL_ORBIT_CH([59], [40_7_18.cx], ![$1,$2]!, ![0000001,0000010,0001011,0010100,0100000,0100111,0101000,0101101,0101110, 0110010,0110110,0110111,0111010,0111011,1100001,1100011,1100100,1100101, 1101000,1101100]!) DUAL_ORBIT_PLUS([z], [40_7_18.ax], ![$3,$4]!, ![0000101,0001000,0010100,0011000, 0011001,0011010,0100011,0100100,0111101,1011111]!, ![+ column 42]!) [XX2_1..12] := PertTwo( [40_7_18.ax]^T using {$4:0000001,0000010,0000100, 0000111,0001001,0001011,0001101,0010001,0010010,0010111,0011010,0011110, 0101000,0110001,0110101,0110111,0111111,1010011,1011111} + check ); [XX10_1..8] := PertTwo( [40_7_18.ax]^T using {$4:0000001,0000011,0000101, 0010000,0010010,0010111,0011000,0011001,0011010,0011110,0100011,0100100, 0101000,0110101,1010001,1010011,1010101,1010111,1011101,1011111,1111100} + column 12 ); [XX13_1..8] := PertTwo( [40_7_18.ax]^T using {$4:0000010,0000100,0001001, 0001111,0010000,0010001,0010100,0100000,0100100,0101000,0101011,0101100, 0110001,0110101,0111011,0111101,1010001,1010011,1010111,1011111,1111100} + check ); [XX19_1..20] := PertTwo( [40_7_18.ax]^T using {$4:0000001,0000010,0000110, 0001000,0001001,0010001,0010100,0011111,0100000,0100011,0100100,0101000, 0101011,0101100,0110101,0110111,0111011,0111101,1010011,1010111,1011101} + column 42 ); DUAL_ORBIT_CH([XX22], [40_7_18.ax], ![$4]!, ![0000001,0000011,0000100,0000101,0000111,0001000,0001001,0010111,0011000, 0011010,0011110,0100011,0100100,0101000,0101100,0110001,0110101,1010001, 1010111,1011101,1110100]!) DUAL_ORBIT([XX26], [40_7_18.ax], ![$4]!, ![0000010,0000100,0000111,0001000,0001001,0001011,0010000,0010001,0010111, 0011010,0011110,0011111,0100011,0101000,0101011,0101100,0111101,0111111, 1010011,1010101,1010111,1111100]!) [XX27_1..8] := PertTwo( [40_7_18.ax]^T using {$4:0000010,0000011,0000110, 0000111,0001000,0001001,0001011,0001101,0001111,0010100,0011110,0011111, 0100011,0101000,0101100,0111101,0111111,1010011,1010101,1011101} ); DUAL_ORBIT_PLUS([XX40], [40_7_18.ax], ![$4]!, ![0000001,0000110,0001000,0001001,0001011,0001111,0010001,0010010,0010111, 0011001,0011100,0011110,0011111,0100000,0101011,0101100,1010011,1010101, 1010111,1011101,1110100]!, ![+ column 51]!) [XXX1..5] := PertTwo( [40_7_18.ax]^T using {$4: 0000001,0000100,0000101,0000110,0000111,0001000,0001011,0010000,0010001, 0010010,0010100,0011001,0011111,0100100,0101011,0110001,0110111,1010001, 1010011,1011111,1111100} + check ); DUAL_TRANSFORM_PLUS([k], [40_7_18.ax-2], ![17,19_{-33},20_{33},21_{33},28_{-33},32_{33}]!, ![+ column 13 + column 54]!) [f1..9] := PertTwo( [24_7_10.f-2]^T using {9,11,13_{-21},14_{21},16_{21}, 18_{-21}} - column 55 ); DUAL_ORBIT([rr], [75_7_36x.b], ![$6]!, ![0001110,0100000,0100001,0100100, 0100101,0100111,0101000,0101111,0110100,0110101,0110110]!) [Q1..5] := PertTwo( {10001010000110001011111110011110010010010010011001111010, 01000110000111100101101001010110100111110010110110001010,0010100000100111 1111000000011111110010100111101101001001,00010100001100011111111100111100 100100100100110011100101,000000010001001000100001100110011011101110111010 10110111,00000000100010010001010011001100110111011101110101010111,0000000 0010001001000111001100110011011101110101010110111} ); [Q6..21] := PertTwo({10000000010010010001110011001100110111011101010101101111, 01000101001111000011000111111000101101111100010011111001,0010000101010111 1100011010011010010000101111000011001101,00010101011010001010000110000110 100111100011100111100101,000010010011011101111010011010010000101111010011 00110000,00000010001001000000011001100110111011101110101010101111,0000000 0100101101010100110011001101110111011101010101110} ); [Q22..77] := PertTwo( {1000100001110101110110010101101001111100101001100110110 1,01000000011111100011001011001011110100001011000110010101,00101001010110 110100100110100110001011110100110000101100,000100010111000111110111111000 01100111010010001101110011,0000010001000100000001100110011111101100111010 1010101111,00000010001000100110001100110011011101110111010101100110,00000 000100010010001110011001101110111111101010101000110} ); [Q78..107] := PertTwo( {100001000011111100001001011001011110100001011000111101 00,01000100101101111000010110101001001111011000010110111010,0010010011100 1001110101110110001011100101001101000111111,00010000110000110001110011110 011110010010010001111111011,000010000111011010110110000001111000010101100 10011010111,00000010101010101000111111111111101010101010100000000010,0000 0001010101010101011111111111110111010101000000000000} ); [Q108] := {10001000001110100100110010101101001111110101011001001110,0100010010 0101011100111010011010000100111111000110110101,00101000100011110110011101 100000001100011101011010011001,000101000001001010011100000011111110010100 11101101111000,00000010101010101101011101111111101010101010100000001000,0 0000001101110111011011011100110000100000001010101100111,00000000010001000 000111001100110011011111110110101100111}; [Q109] := {10000010000110000110111111011110010010010010011011010001,0100010001 1110110000101110010011100001101011001011001010,00100010000001111001001110 011100101111010000111000011110,000101000111010011100000101110101111110010 10011010100011,00001010001000100111001110000011011101110111010110000110,0 0000001010101010101110111111111110101010101000000000010,00000000100010001 100001001101100110111011101110110110101}; [Q110] := {10001000111111011000011000000111100011010110010110001010,0100000001 0001111100100000101111000101001111111100001101,00101000101010101000010011 010011000101111010011000111101,000100000100100010101110011101100110111011 10101101101010,00000100001100011111111100101100100100100100110111010010,0 0000010101001010001011111111111101010101010100000000110,00000001010110100 010111111101111110101110101000000000100}; [Q111..121] := PertTwo( {10001000011101000010110010101100011111000000011001011 111,01000100011111100000100101100101110100000011000110110111,001010000100 10111111000000111111000101000111011010000011,0001010001100001001111110011 1101001001001011100111001110,00000010011001101010001010100010100110111011 111111001011,00000001000110010100010011001101001110111011101010001111,000 00000100010000101111001100110010111011111010101100110} ); [Q122..138] := PertTwo( {10001000001110100011010010101101001110100101001101011 001,01000100011110101101011100000011100001101011001011001001,001010000010 01011111101000011111110011110111101110000001,0001010001110101011110010101 1010111110001010011010101000,00000010001000100101000100110011011101100111 010110111110,00000001010101000011011111111111110100010101000000110100,00 000000100010011001010011001100110111011101110110011010} ); [Q139] := {10100010101110101000010111011110010111001010010010110100,0110011011 0100101110110011010100100010000101000101100110,00010110100110110011010011 001000111001101001110011000111,000011100111100100001100001110000001111001 11110000111111,00000001111110001111110000000111111111100000001111111111,0 0000000000001111111110000000000000000011111111111111111,00000000000000000 000001111111111111111111111111111111111}; [Q140..144] := PertTwo( {10010100100011101100110010111001010110101001000011101 000,01010010110001100010101010010100010101110100101101001101,001101100010 00100110011001110000110000110011111011100100,0000111000011110011110000111 1100001100001111100011000111,00000001111111100000011111111100000011111111 100000111111,00000000000000011111111111111100000000000000011111111111,000 00000000000000000000000000011111111111111111111111111} ); disjoint [x], [r], [oo1..17], [nn], [kk], [a1..19549], [58..59], [z], [XX2_1..12], [XX10_1..8], [XX13_1..8], [XX19_1..20], [XX22], [XX26], [XX27_1..8], [XX40], [XXX1..5], [k], [f1..9], [rr], [Q1..144]; (* ********************* DIMENSION EIGHT AND HIGHER ********************* *); DHIDE( ![ "PertTwo" tried on [a], [b] ]! ) [63_11_26] type [63,11,26]; CREDIT(existence due to Kasami and Tokura, kasami tokura) [a] := Act( { (3,9)(4,6)(7,8)(10,11), (1,9,8)(2,4,3)(5,7,6) }, {00000001110,00001011011,00010010111,00010111110,00101100111,01011101101, 11111111101} ) - column 64 - column 64; [b] := Act( { (3,9)(4,6)(7,8)(10,11), (1,9,8)(2,4,3)(5,7,6) }, {00000000001,00000011101,00001001100,00001110010,00010010100,00011001101, 01111111111} ) - column 1 - column 1; disjoint [a], [b]; status: realizable; DHIDE( ![ PertTwo tried on [a], [b], [c], [d] ]! ) [112_10_52] type [112,10,52]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel some low codes) [a] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0000011101,0010000011,0010011111,0110011011,0110111011, 1110000001,1110111111} ); [b] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0000011101,0010010011,0010101011,0110010101,0110111111, 1110000001,1110111111} ); [c] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0010001010,0010011011,0010101111,0110111011,1110000001, 1110010111,1110111111} ); [d] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001110,0000111111,0010000101,0010101111,0110000011,0110000111, 1110000001,1110111111} ); disjoint [a], [b], [c], [d]; status: realizable; [116_10_54] type [116,10,54]; [a] := [112_10_52.a] + dual word of weight 4; [b] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0000011101,0010010011,0010101011,0110010101,0110111111, 1110000001,1110111111} ) + dual word of weight 4; [c] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001110,0000111111,0010000101,0010101111,0110000011,0110000111, 1110000001,1110111111} ) + dual word of weight 4; disjoint [a], [b], [c]; status: realizable; [153_10_72] type [153,10,72]; CREDIT(existence due to Blokh and Zyablov, blokh zyablov) [a] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000000,0000001110,0010000000,0010000011,0010000111,0010011011, 0110010101,0110111011,0110111111,0111111111,1110000001,1110011101} ) - column 1; status: realizable; [146_10_68] type [146,10,68]; credit: existence due to Jaffe; [a1..11] := Pert( Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0010000000,0010000101,0010010101,0010111111,0110010011, 0110011111,0110101011,0111111111,1110011101} ) ); disjoint [a1..11]; status: realizable; [143_10_66] type [143,10,66]; CREDIT(existence due to Groneick and Grosse, groneicke grosse) note: More [143,10,66] codes are obtainable by deleting dual words of weight three from various [146,10,68] codes.; flags: find no more; [e1..159] := [146_10_68.a5] - dual word of weight 3; disjoint [e1..159]; status: realizable; [150_10_70] type [150,10,70]; CREDIT(existence due to Blokh and Zyablov, blokh zyablov) [a1..53] := Pert( [146_10_68.a1] + dual word of weight 4 ); disjoint [a1..53]; status: realizable; type [162,9,78]; credit: existence due to Jaffe; [a] := Act( { (1,4)(2,3)(5,9), (1,9,2)(3,4,5)(6,8,7), (1,2,9)(3,7,4,6,5,8) }, {000000001,000001011,000001101,000010011,000011101,000101011,000101101, 000111110,001011101,001011111,010110111,011111111,111111111} ) - column 1 - column 161 + column 161; status: realizable; DHIDE( ![ tried PertTwo on [a] ]! ) type [165,9,80]; credit: existence due to Jaffe; [a] := Act( { (1,4)(2,3)(5,9), (1,9,2)(3,4,5)(6,8,7), (1,2,9)(3,7,4,6,5,8) }, {000000001,000001011,000001101,000010011,000011101,000101011,000101101, 000111110,001011101,001011111,010110111,011111111,111111111} ) + column 163 + column 163; status: realizable; [136_10_64] type [136,10,64]; CREDIT(existence due to Groneick and Grosse, groneicke grosse) DUAL_ORBIT([a], [22_10_8.a], ![$5,$7,$8,$9]!, ![0011001100,0011001101,0011011111,0011100100,0111000101,0111000110, 0111001011,0111100000,1111000011]!) status: realizable; [133_10_62] type [133,10,62]; CREDIT(existence due to Groneick and Grosse, groneicke grosse) [a] := [136_10_64.a] - dual word of weight 3; status: realizable; [91_12_40] type [91,12,40]; credit: existence due to Aaron Gulliver; [a] := Cyclic(7, 91, 12, 000100100000010000100110110011100100011010010011001101 1011001100000110011111010111110001); credit: existence due to Aaron Gulliver; status: realizable; [169_11_78] type [169,11,78]; credit: existence due to Aaron Gulliver; [a] := Cyclic(12, 168, 11, 0001001000001011010110101110100101100011100001101010 00010110100101110101000001110011100111110001000000100111000011011010001111 10011010101111100100111001011011111110111) + check; credit: existence due to Aaron Gulliver; status: realizable; [172_11_80] type [172,11,80]; credit: existence due to Jaffe; [a] := [169_11_78.a] + dual word of weight 3; status: realizable; DHIDE( ![ tried PertTwo on [a] ]! ) [120_8_58] type [120,8,58]; credit: existence due to I. Boukliev; [a] := {0110001111001100111101010101001010001100110001011110100010100110000011001101110 11011100101111010100110111010101011111000, 01001111100000000101111011111011110001010111100110011000110011000011110100101010 0001101100111101010001010010100000011000, 11101010011011111110000110110001100001010000000110010010000011110001010010100110 0110010100011110101011110011000101001111, 11011000001111001010001101010010100001011001000110110001110100000001101100011011 1111001111110000111111000100100100100110, 10100100010101010001111101110111101101000100111000111011111010100001010101000110 1100001111001101101111000111101100001001, 00011111010110010001100100101001010101110000000101111010000010001101111011100101 0101011110110000111110001010100111111000, 01100110001010010111010100000000000111010111101001010100110001010101111000100101 1110101111101110010111000101001000110001, 01001000000101000110111010110001100000111000111101101111010000000111011011101001 0101000101101110010110111100011100011101}; credit: existence due to I. Boukliev; status: realizable; [132_11_60] type [132,11,60]; credit: existence due to Aaron Gulliver; [a] := Cyclic(12, 132, 11, 0000001000010001001011000011011010110010101111110011 01110111101010010010101011110100010001100011000001100010101000111100010110 101); credit: existence due to Aaron Gulliver; status: realizable; [154_11_70] type [154,11,70]; credit: existence due to Aaron Gulliver; [a] := Cyclic(14, 154, 11, 0001001000011101101110101111101111001010011010101111 11001001010110001101111011111110011100001011011000110011111101010101101000 1101010010110011001001111); credit: existence due to Aaron Gulliver; status: realizable; [159_8_78] type [159,8,78]; credit: existence due to I. Boukliev; [a1..9] := PertTwo( {0000000000000000000000000000000000000000000000000000000000000000000000000000111 11111111111111111111111111111111111111111111111111111111111111111111111100000111 , 00000000000000000000000000000000000000111111111111111111111111111111111111110000 0000000000000000000000000000000000111111111111111111111111111111111111100011001, 00000000000000000000111111111111111111000000000000000000011111111111111111110000 0000000000000011111111111111111111000000000000000000011111111111111111101101000, 00000000000111111111000000000111111111000000000111111111100000000011111111110000 0000011111111100000000001111111111000000000111111111100000000001111111110100010, 00000011111000011111000011111000011111000001111000001111100001111100000111110000 0111100000111100000111110000011111000011111000001111100000111110000011100010110, 00111100111001100111001100011000100011001110111001110001100110011100011000010000 1001100111001100011001110111100111000100001000110011100111000110011101101010001, 11001101011010000001011101101001100100000111011000110110101000101101100001110011 1010101011010101101010011001101001001000110011011101100001001010101110111001000, 01010100001010101010010100111010101001011011001010011011000011110100101010110101 1100011101010000111010100010110011011001011101100100101010010110000111110100100} ); status: realizable; [165_11_76] type [165,11,76]; credit: existence due to Aaron Gulliver; [a] := Cyclic(15, 165, 11, 0000000000100101100001010101101101100011110010001100 00100001011001110100101110111110000011110110100111100000100100110100000100 0101001111010100101111001101101101011); credit: existence due to Aaron Gulliver; status: realizable; type [156,11,72]; credit: existence due to Jaffe; [a] := Cyclic( {11,11,11,11,11,11,11,11,11,11,11,11,11,11}, 156, 11, 0110000000 01111001010000100111111001110101001111000111111000011001100010111000010010 010010101101000000101100100101010010111101110001111100000101001100000011 ); status: realizable; [129_11_58] type [129,11,58]; credit: existence due to Jaffe; [1..3] := [132_11_60.a] - dual word of weight 3; disjoint [1..3]; status: realizable; [162_11_74] type [162,11,74]; credit: existence due to Jaffe; [1..10] := [165_11_76.a] - dual word of weight 3; disjoint [1..10]; status: realizable; type [45,14,16]; credit: existence due to I. Boukliev; [a] := Cyclic(3, 45, 14, 0000000100000100111011001001010111011001); credit: existence due to I. Boukliev; status: realizable; [12_7_4x] type [12,7,4]; [a] := {100000001110,010000001101,001001001001,000101001010,000011001100, 000000101011,000000010111}; [b] := Dual( Even(3) # Even(4) ); DHIDE( ![ Tried PertTwo on [a], [d], [e], [f], [g], [h], [j], [k] ]! ) [140_8_68] type [140,8,68]; (* to be continued later *); [a],[c] := P( [12_7_4x.{b,a}] ); DUAL_TRANSFORM([b], [178_8_88.a], ![88_{172},96_{1,-172},96_{-1,172}]!) [d] := [21_8_8.b]^T using {$1,$2,$3 : 00001001,00010001,00011101,00100000, 00100011,00110000,00110100,01101000,01101010,01111000,01111110,10110101}; alt Cyclic( {15,15,15,15,15,15,15,15,15,5}, 140, 8, 001111100101111010111110110 10101111111100001100101100000001001110101000110101001000011111101110011011 011101010110110011001001111000111001111 ); [203_8_100] type [203,8,100]; (* to be continued later *); DUAL_ORBIT([l], [140_8_68.c], ![$2,$4,$5,$6]!, ![00000001,00000010,00000101,00001000,00001010,00010011,00011101,00101001, 00101011,00111111,01100101,11101001]!) DHIDE( ![ tried PertTwo on [a] ]! ) [105_8_50] type [105,8,50]; (* to be continued later *); CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_ORBIT([a], [48_8_22.a], ![$5]!, ![00000101,00000111,00001000,00001110,00010100,00111000,00111001]!) DUAL_ORBIT_PLUS([b], [21_9_8.a], ![$2,$3,$4]!, ![000000110,000010001,001111101,010001011,010101111]!, ![- column 3 - column 40]!) DUAL_ORBIT_PLUS([c], [140_8_68.d], ![$1,$2,$3,$4]!, ![00000010, 00000011,00000100,00000101,00001011,00010101,01101001]!, ![+ column 1]!) alt Act( { (1,2)(3,5)(6,8), (3,8)(4,5)(6,7) }, {00000001,00010111,01000001, 01000110,01001111,01010011,01010111,01111111,11000001,11000011,11001100, 11001101,11001111,11010101,11010111,11111111} ) + check; DUAL_ORBIT([d], [120_8_58.a], ![$6,$7]!, ![00000001,00000010,00010000,00010001,00100000,00100101]!) alt Cyclic( {10,10,10,10,10,10,10,5,10,10,10}, 105, 8, 000000010100010101010111 01110001110110010011011000001100110001110010000101001000010110111111110011 1111011 ); DUAL_ORBIT([e], [120_8_58.a], ![$6]!, ![00010000,00010011,00011010,00011011,00011100,00011101,00011111,00100010, 00100011,00100101,00100110,00100111,00101110,00101111,01110100,01110101, 01110110,01110111,01111000,01111011,01111110]!) DHIDE( ![ {D3.7#, OE(32).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ OE(28).7!(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [64_10_28] type [64,10,28]; [a] := BCH(6, 63, 1..23) + check; DUAL_ORBIT_CH([b], [64_10_28.a], ![$3,$4]!, ![0010001010,0010011111,0110100111,0110110110,1110001101,1110010110]!) alt Act( { (3,9)(4,6)(7,8)(10,11), (1,9,8)(2,4,3)(5,7,6) }, {00001011011, 00001110111,00010010100,00111100100,01011101111,01011111111} ) + check; [c] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0000001011,0010010011,0110011111,1110001110} ) + check; [d] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0010000000,0010001010,0010010011,0011111111,1110001110,1110111111, 1111111111} ) + check; [e] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0001111111,0010000000,0010001010,0010010011,0111111111,1110000000, 1110001011,1110111111} ); [f] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0010000000,0010010011,0011111111,0110011111,1110001110, 1111111111} ) + check; disjoint [a], [b], [c], [d], [e], [f]; status: realizable; [56_10_24] type [56,10,24]; CREDIT(existence due to Blokh and Zyablov, blokh zyablov) [a] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0010101011,0110111011,1110011101} ); [b] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0010001010,0010010011,0011111111,0111111111,1110111111} ) + check; [c] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0010000000,0010000011,0010000111,0011111111,1110111111} ) + check; [d] := [64_10_28.b] - columns {45..48,50,52,62,64}; [e] := [64_10_28.c] - columns {1,17,26,31,39,43,56,63}; [f] := [64_10_28.d] - columns {13,14,21,25,34,41,55,59}; disjoint [a], [b], [c], [d], [e], [f]; status: realizable; [61_10_26] type [61,10,26]; CREDIT(existence due to Cheng, cheng new linear codes) [a] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001110,0001111111,0010000101,0011111111,0110010011,1110111111} ) + check; [b] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001110,0010000011,0110010101,0111111111,1110000000,1110111111} ) + check; [c] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001011,0001111111,0010000000,0010000011,0110010101,1110111111, 1111111111} ); [d] := [64_10_28.b] - columns {46,64} - column 45 - column 45 + check; [e] := [64_10_28.b] - columns {46,64} - column 45 - column 48 + check; [f] := [64_10_28.b] - columns {46,64} - column 45 - column 50 + check; [g] := [64_10_28.c] - columns {1,63} - column 16 - column 24 + check; [h] := [64_10_28.c] - columns {1,63} - column 16 - column 29 + check; [i] := [64_10_28.c] - columns {5,14} - column 6 - column 7 + check; [j] := [64_10_28.d] - columns {13,55} - column 13 - column 19 + check; [k] := [64_10_28.d] - columns {1,63} - column 15 - column 15 + check; disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k]; status: realizable; [53_10_22] type [53,10,22]; CREDIT(existence due to van Pul, van Pul thesis) [a1..4] := PertTwo( Sub( { L(%1) := AllSubIso( %1, Col(1,2) | Col(1,3) ) }, Cycle({1,2,3,4,5,6,7}) # {1,0,0} | Cycle({1,3,5,7,2,4,6}) # {0,1,0} | Cycle({1,4,7,3,6,2,5}) # {0,0,1} | L( Cycle({1,2,3,4,5,6,7}) ) # {1,0,1} | L( Cycle({1,3,5,7,2,4,6}) ) # {1,1,0} | L( Cycle({1,4,7,3,6,2,5}) ) # {0,1,1} | Choose( 7, {0,6} ) # Choose(3,3) | Choose( 7,7 ) # Choose(3,1) ) ); note: The definition of [a1] involves a partition of K_7 into three Hamiltonian cycles.; disjoint [a1..4]; status: realizable; [71_10_32] type [71,10,32]; DUAL_ORBIT_CH([a], [64_10_28.a], ![$3,$4]!, ![0000000111,0000001010,0010000010,0010000111,0010001100,0011010111, 1110000000,1110000011,1111111111]!) [b] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001110,0010000000,0010101111,0110000000,0110010011,1110000000, 1110000001,1110001011} ) + check; [c] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000000001,0000010111,0001111111,0010000000,0010101011,0110111011, 0111111111,1110000000,1110011101} ); disjoint [a], [b], [c]; status: realizable; [119_10_56] type [119,10,56]; DUAL_ORBIT_CH([a], [64_10_28.a], ![$3,$4]!, ![0000001000,0000001101,0000011011,0010001000,0010001010,0010110110, 0011011010,0110001111,0110010011,1110000001,1110001101]!) [b] := Act( { (1,2)(3,4)(6,7), (1,7,3,2,6,4)(8,10,9), (1,6)(2,3)(4,5) }, {0000001000,0000001111,0000111001,0000111101,0001111100,0011101000, 0111111011,0111111111} ); disjoint [a], [b]; status: realizable; [64_16_24] type [64,16,24]; [a] := BCH(6, 63, 1..21) + check; status: realizable; type [128,15,56]; (* Don't try to compute the automorphism group of this configuration: *); [a] := BCH(7, 127, 1..50) + check; status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) DHIDE( ![ tried PertTwo on [a] ]! ) [45_10_18] type [45,10,18]; credit: existence due to Aaron Gulliver; [a] := Cyclic(3, 45, 10, 000000101011000111000010010111111000101001); credit: existence due to Aaron Gulliver; status: realizable; DHIDE( ![ OE(32).7#(allowing length up to 495) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) type [48,10,20]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) [a] := Cyclic(4, 48, 10, 00000000111100101010001011101000001100111010011); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) [b] := Act( { (3,9)(4,6)(7,8)(10,11), (1,9,8)(2,4,3)(5,7,6) }, {00001111110,00101000101,00111101111,01011101111} ); disjoint [a], [b]; status: realizable; DHIDE( ![ OE(32).7#(allowing length up to 495) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [81_10_36] type [81,10,36]; CREDIT(existence due to Gulliver and Bhargava, two new rate 1994) (* I think that the following code should have a cyclic description, but it does not respond to the cyclic command. *); [a] := {1000100000000110000011110010011110110100010011101101100011110111111000010101101 10,01001000001001000000100011110100011111101110100110010101100011000101000111100 1100,001010000001010000000011010111011001101110111110000100100011000111001011101 110000,0001100000001100000011101100101101101001100101011111000111101111010001101 00101110,00000100000111100101011111100101101100000111100100110110010011010011101 0001110110,000000100010111011011011100011101100100010111111010001011101100100011 111000000101,0000000100110110100111011011100101100100110110000111110000011011010 01101100111100,00000000101110101011111011100010101000101110101111100000111110100 1100100110100001,000000000111110010101111010011110100000111110010001011101000101 011110000011101110,0000000000000001111100000111110000000000000001111111111111111 11110000000000111111}; CREDIT(existence due to Gulliver and Bhargava, two new rate 1994) [b] := Act( { (1,5,4,3,2)(6,10,9,8,7), (1,10,3,6)(2,8)(4,9,5,7) }, {0000000001,0000100101,0000111111,0011100111,0101101110,0101111011, 0111110111} ) + check; disjoint [a], [b]; status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [78_10_34] type [78,10,34]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) [a] := [81_10_36.a] - dual word of weight 3; [b] := Act( { (1,5,4,3,2)(6,10,9,8,7), (1,10,3,6)(2,8)(4,9,5,7) }, {0000000111,0000011111,0000110000,0000110010,0001101011,0011101110} ) + check; disjoint [a], [b]; status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [96_10_44] type [96,10,44]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) [a] := Cyclic(8, 96, 10, 000000000101010001001111011000001100100011011111010010 000011001100110101011011100111110001011001); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [68_10_30] type [68,10,30]; [a] := [64_10_28.a] + dual word of weight 4; [c1..3] := [64_10_28.c] + dual word of weight 4; [d] := [64_10_28.d] + dual word of weight 4; disjoint [a], [c1..3], [d]; status: realizable; DHIDE( ![ K(24,25000) done for [1..3] ]! ) [100_10_46] type [100,10,46]; [1..3] := [96_10_44.a] + dual word of weight 4; disjoint [1..3]; status: realizable; DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a] ]! ) [103_10_48] type [103,10,48]; [a] := [100_10_46.1] + dual word of weight 3; (* this code is generalized-cyclic *); status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [93_10_42] type [93,10,42]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) [a] := [96_10_44.a] - dual word of weight 3; status: realizable; DHIDE( ![ OE(32).7#(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) type [100,11,44]; CREDIT(existence due to Gulliver and Bhargava, some best rate 1991) [a] := Cyclic(9, 99, 11, 00000000001000010110100000110111000001110010000110010 100011010101001001011110011110101100111110101) + check; CREDIT(existence due to Gulliver and Bhargava, some best rate 1991) status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [108_12_46] type [108,12,46]; CREDIT(existence due to Gulliver and Bhargava, some best rate 1991) [a] := Cyclic(9, 108, 12, 00000000000100111100111000010011111000100100101000000 000011000101110111000101111101000111011001000110101101); CREDIT(existence due to Gulliver and Bhargava, some best rate 1991) status: realizable; DHIDE( ![ K(24,25000) done for [a] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a] ]! ) [111_12_48] type [111,12,48]; credit: existence due to B. Groneick and S. Grosse; [a] := [108_12_46.a] + dual word of weight 3; status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) DHIDE( ![ tried PertTwo on [a] ]! ) [140_9_66] type [140,9,66]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) [a] := Cyclic(14, 140, 9, 00010010000000001010000101110000010011010101011101001 11111000011101101100011001011110000001100110011100111010111101100011010110 000001101111); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) [b] := Cyclic( {10,10,10,10,5,10,10,10,10,10,10,10,10,10,5}, 140, 9, 0011000000 00000100100011001010001101000100010000101001101110110100111000001011101001 10111001011010101100001111110000111111011010111001101110 ); disjoint [a], [b]; status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) [141_11_64] type [141,11,64]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) [a] := Cyclic(10, 140, 11, 0100011000010001111001111001110000101110011000000101 01100101100001011000110010101000000110110111100111010111111110001101110111 110111000011) + check; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) status: realizable; DHIDE( ![ OE(28).7!, DC1# done for [b] ]! ) DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) DHIDE( ![ tried PertTwo on [a] ]! ) type [144,9,68]; credit: existence due to Aaron Gulliver; flags: find no more; note: "[147_9_70.{1..68}] - dual word of weight 3" is at least 765 [144,9,68] codes.; [a] := Cyclic(16, 144, 9, 00000000100100110011010000011111100110110101000010100 10110000001110110001001011000011011110101011101001110100011100000010110101 1110110101011101); credit: existence due to Aaron Gulliver; [b] := Cyclic(12, 144, 9, 00011001011101110100110000010010110000011011010101010 11011000001001111010101111001000001101001000000101001010101111010110110111 101100000101101); status: realizable; [147_11_66] type [147,11,66]; (* to be continued later *); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) [a] := Cyclic(7, 147, 11, 00000101001000001100101110011001011100100010001000100 01011110111001100100011110001010100001101000001000101111101110010011100000 00111100111011011100); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [b] ]! ) [150_11_68] type [150,11,68]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) [a] := Cyclic(10, 150, 11, 0000000000111111001010000000101001001100000011001110 11111011001001110100110011111101101011001100001011011101001001000110011100 010010101100010111); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) [b] := [147_11_66.a] + dual word of weight 3; disjoint [a], [b]; status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [1..5] ]! ) [147_11_66] type [147,11,66]; (* continued from earlier *); [1..5] := [150_11_68.a] - dual word of weight 3; disjoint [a], [1..5]; status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) [160_10_74] type [160,10,74]; credit: existence due to Aaron Gulliver; [a] := Cyclic(16, 160, 10, 0000000101111110000111100101010001011011100101010101 00001010010100100110011011111001110010011101100001000001110010011001111101 01101101101101100000011010101); credit: existence due to Aaron Gulliver; status: realizable; DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a],[b],[c],[d],[e] ]! ) [40_10_16] type [40,10,16]; [a] := Cyclic(4, 40, 10, 000000000101101101100111011100011111101); [b] := Cyclic(4, 40, 10, 0100000000010101101000001111011101101); [c] := Cyclic(4, 40, 10, 010100000001100011110000111101001101); [d] := Cyclic(4, 40, 10, 0000000101011110001101011110001111100101); [e] := Cyclic(4, 40, 10, 0000000101010000101001000001111101101101); DUAL_ORBIT([f], [22_10_8.a], ![$3,$6,$9]!, ![0100110011,0110000010,1100000110,1100101101,1100111110,1110100111]!) DUAL_ORBIT([g], [22_10_8.a], ![$2,$3,$4,$5,$9]!, ![0100000010,0110000000,1100000100,1100111110,1110000000]!) DUAL_ORBIT([h], [40_10_16.f], ![$4,$7]!, ![0001000000,0011011100,0111011101]!) DUAL_ORBIT_CH([i], [40_10_16.f], ![$4,$7]!, ![0000000100,0000111001,0000111010,0001011110,0111000000]!) DUAL_ORBIT([j], [40_10_16.f], ![$4,$7]!, ![0000000110,0000000111,0000111010,0001000010,0111011110,1111000110]!) DUAL_ORBIT([k], [40_10_16.g], ![$5,$7]!, ![0000111010,0001000001,0001010010]!) DUAL_ORBIT([l], [40_10_16.g], ![$5,$7]!, ![0001010010,0001111000,0101110010]!) [m] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001110,0001111111,0010010101,0011111111,1110000000,1110011101} ); disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [l], [m]; status: realizable; [165_10_78] type [165,10,78]; (* to be continued later *); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) flags: find no more; note: "[162,10.{1..34}] + dual word of weight 3" is 34 [165,10,78] codes.; [a] := Cyclic(11, 165, 10, 0000011001110010000010100101001111110000011110110100 11101010101001010100001110110110010111100100001110001000010000100000110111 011001101101110011110000101010110111); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) [156_9_74] type [156,9,74]; (* to be continued later *); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) flags: find no more; [a] := Cyclic(13, 156, 9, 00000001000110011001111110101100100101000011100000001 10111010001110011011111010110100101101000001111101101001010101011111011011 1001101011110010011111111); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) DHIDE( ![ OE(32).7#(allowing length up to 256) done for [a] ]! ) [168_10_80] type [168,10,80]; credit: existence due to me; [a] := [165_10_78.a] + dual word of weight 3; (* this code is generalized-cyclic *); status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [a], [b] ]! ) DHIDE( ![ D1.7#(allowing length up to 256) done for [a] ]! ) [165_10_78] type [165,10,78]; (* continued from earlier *); [b] := [168_10_80.a] - columns {155,160,165}; disjoint [a], [b]; status: realizable; [162_10_76] type [162,10,76]; credit: existence due to me; [1..34] := [165_10_78.a] - dual word of weight 3; disjoint [1..34]; status: realizable; (* Eliminate: there is a [165,11,76]. *); [166_11_76] type [166,11,76]; [a] := Cyclic(15, 165, 11, 0100000000010111110110011000100000100100010000011100 01111111100101010101100001001110011000000111011111010101011111100010100011 011011110011101010011101101101111101) + check; [228_9_112] type [228,9,112]; (* to be continued later *); CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) DUAL_ORBIT_PLUS([a], [64_10_28.a], ![$2,$4]!, ![0000000011,1100000000,1100100001,1111111111]!, ![+ column 225 + column 225 + column 225]!) DUAL_ORBIT([b], [64_10_28.a], ![$1,$2]!, ![0000000011,1000000001,1000000111,1000001001,1000010111]! ) (* All the [166,9,80]'s should be deleted. *); [166_9_80] type [166,9,80]; (* to be continued later *); DUAL_ORBIT_PLUS([b], [228_9_112.a], ![$8]!, ![000000001,000000010,000000100,000000110,000001001,000001101,000001110, 000011011,000100100,000100101,000101100,000111100,001110001,001111111, 111111110]!, ![+ column 164]!) (* The following should be deleted: *); [163_9_78] type [163,9,78]; [a] := Cyclic(18, 162, 9, 00000000110100000101100100100101110111011110101110101 00011001001111101100101110111100100111001010110110001000010001010101000010 10011000101010110011110000111011) + check; [1..67] := [166_9_80.b] - dual word of weight 3; DHIDE( ![ OE(32).7#(allowing length up to 256) done for [a] ]! ) [159_9_76] type [159,9,76]; credit: existence due to me; [a] := [156_9_74.a] + dual word of weight 3; (* this code is generalized-cyclic *); DUAL_ORBIT_PLUS([b], [21_9_8.a], ![$2,$3,$5]!, ![001000111,001010000,001111101,011000011,011000110,011000111,011011110, 100000010,100010110,101000111,101001100,101001110,111000010,111000110, 111100001]!, ![+ column 148]!) [c] := Sub( { Triangles(%1) := AllSubIso( %1, Choose(3,2) ), M1 := Cycle({1,2,3,4,5,6}), M2 := Cycle({1,2,5,6,3,4}), M3 := DelDup(M1|M2), M0 := Off(M1|M2), G(%1) := Un(%1) | Triangles(%1) - Triangles(M0) }, {1,0,0} # Un(M1) | {0,1,0} # Un(M2) | {0,0,1} # Un(M3) | {0,0,0} # ( Un(M0) | Triangles(M0) ) | {1,1,0} # G( DelDup(M0|M1|M2) ) | {0,1,1} # G( DelDup(M0|M2|M3) ) | {1,0,1} # G( DelDup(M0|M1|M3) ) | Choose( 3, {1,2} ) # Choose( 6, {5,6} ) | Choose( 3, 3 ) # Choose( 6, {3,4,6,6} ) ); DUAL_ORBIT_PLUS([d], [21_9_8.a], ![$1,$2,$3,$6]!, ![000000110,001000001,001001100,001011100,010000001,010001011,010101111, 011000000,011000110,011010010,110001100,110001101,110011111,111001101, 111100001]!, ![+ column 153]!) DUAL_ORBIT([e], [163_9_78.a], ![$1]!, ![000000111,000001111,000010001,000011101,000100011,000101001,000101011, 000101111,000111001,001001001,001011101,001101011,001101101,010110111, 010111011,010111111,011011011,011011111,011111111]!) (* this code is generalized-cyclic *); [f] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000101,000000111,000001101,000001111,000011101,000111101,001000111, 001010111,001101011,001111011,010111111,011111111} ) - column 27 - column 141 - column 32 - column 137 + check; [g] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000101,000000111,000001101,000001111,000011101,000111101,001000111, 001010111,001101011,001111011,010111111,011111111} ) - column 27 - column 141 - column 39 - column 132 + check; [h] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000101,000000111,000001101,000001111,000011101,000111101,001000111, 001010111,001101011,001111011,010111111,011111111} ) - column 27 - column 141 - column 53 - column 114 + check; [i] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000101,000001011,000001110,000001111,000010011,000011011,000011111, 000110111,001000111,001001111,011010111,011011111,011111111} ); disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i]; status: realizable; DHIDE( ![ tried PertTwo on [a] ]! ) [189_9_92] type [189,9,92]; (* to be continued later *); credit: existence due to Aaron Gulliver; [a] := Cyclic(9, 189, 9, 011010100011110000000000000100010110101101001000100000 00101111111011100110011011010001111111110110011110100100001100001110110010 0010111000111001111011101011001010101011010011100100100101000); credit: existence due to Aaron Gulliver; [196_9_96] type [196,9,96]; (* to be continued later *); DUAL_ORBIT_PLUS([a], [64_10_28.a], ![$2,$4]!, ![0000000011,1100000000,1100000100,1111111111]!, ![+ column 193 + column 193 + column 193]!) DUAL_ORBIT([b], [64_10_28.a], ![$2,$3]!, ![0000000011]!) DUAL_ORBIT([c], [228_9_112.b], ![$2,$3]!, ![000000110,000000111,000001110,000001111,000010011,000011010,000011101, 000110000,000110100,001111000]!) DUAL_ORBIT([d], [228_9_112.b], ![$2,$3]!, ![000000110,000000111,000001110,000001111,000010010,000011010,000011101, 000110001,000110100,001111000]!) DUAL_ORBIT([e], [189_9_92.a], ![$1]!, ![000001111,000010011,000011011,000101011,000101110,000110100,000111111, 001010011,001110100,001111010]!) (* this code is generalized-cyclic *); DHIDE( ![ [a] is not "cyclic". ]! ) [79_9_36] type [79,9,36]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_ORBIT_CH([a], [196_9_96.b], ![$2,$4]!, ![000000010,000000011,000001100,000011010,000110111,001110011,010111100]!) alt Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000111,000010101, 000011001,000011101,001010111,010111111,011111111} ) + check; status: realizable; DHIDE( ![ [a] is not "cyclic". ]! ) [123_9_58] type [123,9,58]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_ORBIT([a], [196_9_96.b], ![$2,$4]!, ![000000001,000000010,000000100,000000111,000001100,000001110,000011010, 000110111,000111100,001000101,011110101]!) alt Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000101,000001101, 000001110,000001111,000010101,000011001,001001011,001101011,001111011, 001111101,001111111,011010111} ) - column 4 - column 46 - column 85; status: realizable; [126_9_60] type [126,9,60]; credit: existence due to Jaffe; [a] := [123_9_58.a] + dual word of weight 3; status: realizable; DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) [156_9_74] type [156,9,74]; (* continued from earlier *); [b1..30] := [159_9_76.b] - dual word of weight 3; [c1..28] := [159_9_76.c] - dual word of weight 3; [d1..35] := [159_9_76.d] - dual word of weight 3; [e1..101] := [159_9_76.e] - dual word of weight 3; disjoint [a], [b1..30], [c1..28], [d1..35], [e1..101]; status: realizable; DHIDE( ![ [a] is not "cyclic". ]! ) [130_9_62] type [130,9,62]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_ORBIT_CH([a], [196_9_96.b], ![$2,$4]!, ![000000001,000000010,000011010,000100001,000110111,000111100,001000101, 001010010,001110011,010011011,010111100,011110101,110010010]!) alt Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000001,000000111, 000001101,000001110,000011001,000011101,001000111,001101111,001110111, 001111101,010101111,010111111,011010111} ) + check; [a1..3] := [126_9_60.a] + dual word of weight 4; disjoint [a], [a1..3]; status: realizable; [133_9_64] type [133,9,64]; credit: existence due to Jaffe; [a] := [130_9_62.a] + dual word of weight 3; status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [b1..2] ]! ) [193_9_94] type [193,9,94]; flags: find no more; note: "[196_9_96.c] - dual word of weight 3" is a large number of [193,9,94] codes.; [a1..10] := [196_9_96.a] - dual word of weight 3; [b1..2] := [196_9_96.b] - dual word of weight 3; disjoint [a1..10], [b1..2]; status: realizable; [228_9_112] type [228,9,112]; (* continued from earlier and to be continued *); CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) DUAL_ORBIT([c], [193_9_94.b2], ![$2,$3]!, ![000000011,000000111,000001010,000010111,000011001,000011100,000101000, 000101011,000101101,001111000]!) DUAL_ORBIT_PLUS([d], [196_9_96.c], ![$1,$2]!, ![000001110,000011100,000101001,000101011,010000011,010000100,010001011, 010001100,010001111,010010010,010011001,010011101,011110011]!, ![+ check]!) DUAL_ORBIT_PLUS([e], [196_9_96.c], ![$1,$2]!, ![000001110,000011100,000101001,000101011,010000011,010000100,010000110, 010001100,010001101,010001111,010011001,010011101,011110011]!, ![+ check]!) DHIDE( ![ {D1.7#, O(28).7#}(allowing length up to 256) done for [b] ]! ) DHIDE( ![ OE(30).7#(allowing length up to 256) done for [c] ]! ) DHIDE( ![ OE(28).7!(allowing length up to 256) done for [f],[g] ]! ) [196_9_96] type [196,9,96]; (* continued from earlier *); DUAL_ORBIT([f], [228_9_112.c-2], ![$2,$3]!, ![000000100,000000110,000000111,000010000,001000001,001000100,001000110, 001001100,001001101,100001111]!) DUAL_ORBIT_PLUS([g], [68_10_30.a], ![$3,$4]!, ![0000000111,0001100011,1111111111]!, ![+ column 193 + column 193 + column 193]!) disjoint [a], [b], [c], [d], [e], [f], [g]; status: realizable; [264_10_128] type [264,10,128]; flags: find no more, no automorphism group computation; DUAL_ORBIT_PLUS([a], [68_10_30.a], ![$3,$4]!, ![0000000100,0000010010,0000010011,1111111111]!, ![+ column 256 + column 256 + column 256 + column 256 + column 256 + column 256 + column 256 + check]!) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a], [b] ]! ) [203_9_98] type [203,9,98]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) DUAL_ORBIT([a], [228_9_112.c], ![$2,$4]!, ![000000011,000010000,000010011,000010100,000010110,000011000,000011100, 000011110,000101110,000101111,000111111]!) DUAL_ORBIT([b], [228_9_112.c-2], ![$2,$3]!, ![000000100,000000110,000000111,000001100,000010000,001000001,001000100, 001000110,001001100,001001101,100001111]!) disjoint [a], [b]; status: realizable; DHIDE( ![ DC1P#, D2#, O(29/5,10)# done for [a] DE2(26).7(only 4 orbits checked)# for [a] OE(28).7#(allowing length up to 495) for [a] {DE2(28).7#, OE(30).7#}(allowing length up to 256) for [b] OE(28).7#(allowing length up to 256) done for [b] ]! ) [35_9_14] type [35,9,14]; (* continued from earlier *); DUAL_ORBIT([b], [228_9_112.c-2], ![$2,$3]!, ![000001100,001001011,100001111]!) alt Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000111111,0010011111,1110001110} ); [c] := Act( { (1,2,3,4,5,6,7,8)(9) }, {000100111,001111010,001111110,010101011,011011111} ) + check; disjoint [a], [b], [c]; status: realizable; [225_9_110] type [225,9,110]; (* to be continued later *); credit: existence due to Aaron Gulliver; flags: find no more; note: "[228_9_112.b] - dual word of weight 3" is at least 24 [225,9,110] codes. Also "PertTwo( [225_9_110.a] ) is at least 360 (and probably far more) [225,9,110] codes.; [a] := Cyclic(25, 225, 9, 01100000001001001110110111011000011101010000011111011 00110011100111100000000010111101001010111011111111001111000100100100011001 11001000100101111001101011110001010000001000000101001010101101100111110100 1000011110101000110111); credit: existence due to Aaron Gulliver; DUAL_ORBIT([b], [193_9_94.b2], ![$2,$3]!, ![000000011,000000111,000001010,000010111,000011001,000011100,000101000, 000101011,000101101]!) DUAL_ORBIT_PLUS([c], [228_9_112.e], ![$1,$2]!, ![000000001,000000010,000000110,000001001,000001111,000010101,000011010, 000011101,000011110,000011111,000101010,001001100,001111000]!, ![- column 1 - column 1]!) DUAL_ORBIT_PLUS([d], [228_9_112.e], ![$1,$2]!, ![000000001,000000010,000000110,000001001,000001111,000010101,000011010, 000011101,000011110,000011111,000101010,001001100,001111000]!, ![- column 15 - column 15]!) DUAL_ORBIT_PLUS([e], [228_9_112.e-228], ![$1,$2]!, ![000000001,000000110,000001001,000001010,000011010,000011011,000011101, 000011111,000101010,000110010,001001100,001001111,001111000]!, ![- column 4 - column 4]!) DUAL_ORBIT_PLUS([f], [228_9_112.e-228], ![$1,$2]!, ![000000001,000000110,000001001,000001010,000011010,000011011,000011101, 000011111,000101010,000110010,001001100,001001111,001111000]!, ![- column 27 - column 28]!) DUAL_ORBIT_PLUS([g], [203_9_98.a], ![$2,$3]!, ![000000010,000000101,000001000,000010111,000011110,000100101,000110110, 000110111,001000111,001101011,011100100]!, ![- column 2 - column 74]!) DUAL_ORBIT_PLUS([h], [203_9_98.a], ![$2,$3]!, ![000000010,000000101,000001000,000010111,000011110,000100101,000110110, 000110111,001000111,001101011,011100100]!, ![- column 7 - column 63]!) DUAL_ORBIT_PLUS([i], [196_9_96.c], ![$1,$2]!, ![000000001,000001110,000101001,000101011,010000000,010000001,010000011, 010000100,010000110,010001100,010001101,010001111,010011001,011110011]!, ![- columns {1,9,10}]!) DUAL_ORBIT_PLUS([j], [196_9_96.c], ![$1,$2]!, ![000000001,000001110,000101001,000101011,010000000,010000001,010000011, 010000100,010000110,010001100,010001101,010001111,010011001,011110011]!, ![- columns {1,27,28}]!) DUAL_ORBIT_PLUS([k], [196_9_96.c], ![$1,$2]!, ![000000001,000001110,000101001,000101011,010000000,010000001,010000011, 010000100,010000110,010001100,010001101,010001111,010011001,011110011]!, ![- columns {1,30,31}]!) DUAL_ORBIT_PLUS([l], [196_9_96.c], ![$1,$2]!, ![000000001,000001110,000101001,000101011,010000000,010000001,010000011, 010000100,010000110,010001100,010001101,010001111,010011001,011110011]!, ![- columns {1,40,41}]!) DHIDE( ![ OE(28).7!(allowing length up to 256) done for [a] ]! ) DHIDE( ![ O(28).7#(allowing length up to 256) done for [b] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [d],[e],[f] ]! ) DHIDE( ![ OE(30).7#(allowing length up to 256) done for [c] ]! ) [228_9_112] type [228,9,112]; (* continued from earlier for second time *); DUAL_ORBIT_CH([f], [35_9_14.b], ![$1,$2]!, ![000000100,000000111,000001001,000010100,000010110,000011010,000011111, 000101110,000111001,000111110,001101100,010110011,011111010]!) [g] := [225_9_110.a] + dual word of weight 3; disjoint [a], [b], [c], [d], [e], [f], [g]; status: realizable; [221_9_108] type [221,9,108]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) [1] := [228_9_112.f] - columns {71,98,191,196,228} - column 128 - column 144; [2] := [228_9_112.f] - columns {61,113,182,209,228} - column 126 - column 149; [3] := [228_9_112.f] - columns {69,103,182,209,228} - column 131 - column 140; [4] := [228_9_112.f] - columns {5,99,115,165,174} - column 154 - column 174; [5] := [228_9_112.f] - columns {6,98,115,165,174} - column 155 - column 173; [6] := [228_9_112.f] - columns {47,73,115,163,175} - column 114 - column 213; [7] := [228_9_112.f] - columns {42,75,115,161,176} - column 130 - column 195; disjoint [1], [2], [3], [4], [5], [6], [7]; status: realizable; [214_9_104] type [214,9,104]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) [1] := [221_9_108.1] - columns {5,97,113,161,170} - column 150 - column 170; [2] := [221_9_108.1] - columns {11,91,113,161,170} - column 140 - column 175; [3] := [221_9_108.1] - columns {47,72,113,159,171} - column 112 - column 207; [4] := [221_9_108.1] - columns {42,74,113,157,172} - column 127 - column 189; [5] := [221_9_108.1] - columns {15,88,113,156,173} - column 135 - column 182; [6] := [221_9_108.1] - columns {23,84,113,156,173} - column 139 - column 176; [7] := [221_9_108.1] - columns {15,88,113,155,174} - column 136 - column 181; [8] := [221_9_108.1] - columns {23,84,113,155,174} - column 140 - column 175; [9] := [221_9_108.1] - columns {31,80,113,154,175} - column 123 - column 195; [10] := [221_9_108.1] - columns {4,99,113,146,180} - column 137 - column 178; [11] := [221_9_108.1] - columns {35,77,113,138,188} - column 115 - column 204; DUAL_ORBIT_PLUS([a], [79_9_36.a-79], ![$1,$2]!, ![000000100,000000101,000000111,000001000,000010111,001001000,001001011, 001001101,001010011,001010110,001011010,001100101,001101100,001111101, 100000101,100011110]!, ![+ check + dual word of weight 3]!) [b] := Act( { (1,3)(6,8)(7,9)(10), (4,5)(6,7)(8,9)(10), (1,5)(3,4)(7,8)(10), (1,6,5,2)(3,7,8,4)(10), (1,3,7,6,4,9,2,5)(10) }, {0000011110,0000110101, 0000111111,0010101111,0010111110,1111111111} ) + column 211 + column 211 + column 211; [c] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000001,000001011, 000001110,000010011,000011001,000011101,000011111,000101111,000110111, 000111011,001000011,001001111,001011011,001101011,001111111,010111111, 011010111,011011111,011111111} ) + check; disjoint [1..11], [a], [b], [c]; status: realizable; [172_9_82] type [172,9,82]; (* to be continued later *); flags: find no more; note: "PertTwo( [172_9_82.a] )" is at least 154 (and possibly more) [172,9,82] codes.; credit: existence due to Aaron Gulliver; [a] := Cyclic(19, 171, 9, 00000101011100001010100110100111100010011111110000011 01110010011111100001001001100001010101100000101100100001101110111001001010 01101010111100010011010111100110111110111000) + check; credit: existence due to Aaron Gulliver; DUAL_ORBIT_CH([b], [196_9_96.c], ![$1,$2]!, ![000001110,000011100,000101001,000101011,010000000,010000011,010001100, 010010010,011110011]!) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a] ]! ) [38_9_16] type [38,9,16]; CREDIT(existence due to Farkas and Bruhl, farkas bruhl) [a] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000001011,0000111111,0110000000,0110101111} ); [b] := Act( { (1,2,3,4,5,6,7,8)(9) }, {001010111,001101110,001111011,001111110,010101010,011101111} ); disjoint [a], [b]; status: realizable; type [218,9,106]; credit: existence due to Jaffe and Simonis; flags: find no more; note: Over 100 [218,9,106] codes may be obtained by adding a dual word of weight 4 to a [214,9,104] code.; [a] := [225_9_110.a] - columns {36,120,141,198,215,216} - column 28 - column 117 + check; status: realizable; (* Eliminate: *); DHIDE( ![ [a..e] checked for "cyclic". ]! ) [134_9_64] type [134,9,64]; DUAL_ORBIT_PLUS([a], [21_9_8.a], ![$4,$5,$6]!, ![000000011,000100010,000100100,000111010,001100001,001100011,001101001, 011100010,011101011,011110111,011111011,111100001,111100011,111111111]!, ![+ column 133]!) [b] := Act( { (1,4)(2,3)(5,9), (1,9,2)(3,4,5)(6,8,7), (1,2,9)(3,7,4,6,5,8) }, {000000111,000001110,000001111,000010101,000011001,000011101,000101011, 000111011,010111111,011011111,011111111,111111111} ) + column 133; DUAL_ORBIT_PLUS([c], [196_9_96.e], ![$2]!, ![000001000,000010101,000010111,000011111,000100000,000100100,000100110, 000110010,000111000,001000000,001001010,001001011,001001101,001011001, 001100011,010001101,101010011]!, ![+ column 88]!) alt Cyclic( {9,9,9,9,9,9,9,3,9,9,9,9,9,9,9,3}, 134, 9, 011000100010010111000100 01001110011001100101100001011001010001100100011100001111000101000000001111 110101001010100111111101111001001111 ); DUAL_ORBIT_PLUS([d], [156_9_74.a], ![$1]!, ![000000001,000000010,000000110,000001111,000010111,000100101,000110100, 001001111,001010011,001011011,001111000,001111001,001111101]!, ![+ column 1]!) alt Cyclic( {12,12,12,12,12,12,12,12,12,6,6,12}, 134, 9, 0000000100011111110011 00111110001000000010111011000100100011111001010100110110001010110101100100 00101101111111000000111111000001001011 ); DUAL_ORBIT_PLUS([e], [225_9_110.b], ![$1,$3]!, ![000000110,000001000,000001001,000001011,000001111,000011010,000011011, 000100011,000100111,000101100,110110111]!, ![+ column 117]!) alt Act( { (1,4)(2,3)(5,9), (1,9,2)(3,4,5)(6,8,7), (1,2,9)(3,7,4,6,5,8) }, {000000111,000001011,000001111,000010111,000011001,000101001,000101011, 000111011,001111111,011111111,111111111} ) + column 133; disjoint [a], [b], [c], [d], [e]; status: realizable; DHIDE( ![ (D1.7#, O(28).7#}(allowing length up to 256) done for [a] ]! ) DHIDE( ![ K(24,25000) done for [a] ]! ) DHIDE( ![ PertTwo tried on [o], [p] ]! ) [150_9_72] type [150,9,72]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) [a] := Cyclic(15, 150, 9, 00000000110100110001011001101110110111110000010111001 11111001100101000100101101101111111011010001010011010100010000100111100011 01101000000101001101); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) DUAL_ORBIT([b], [189_9_92.a], ![$2]!, ![000000110,000001011,000010001,000010010,000011111,000100111,000110010, 001001001,001001010,001001110,001001111,001110011,001110100,010000010, 010000011,010010010,010010101,010011101]!) (* this code is generalized-cyclic *); [c] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000101,000000111, 000001111,000010011,000111111,001001111,001101011,001110111,001111011, 001111101,001111111,011011111} ); [d] := Act( { (1,8)(2,3)(4,7), (1,9,2)(3,5,4)(6,8,7) }, {000000011,000000111, 000010101,000011011,000011111,000100111,000101101,000111101,001011111, 001101101,001111110,011101111} ); DUAL_ORBIT([e], [196_9_96.e], ![$2]!, ![000000011,000000111,000001001,000010000,000010001,000010011,000010110, 000100100,000100101,000110010,000111001,000111101,001000000,001001010, 001001011,001010000,001111010,010001101]!) (* this code is generalized-cyclic *); [f] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000001,000000110, 000001011,000010011,000011111,000101111,000111101,001000011,001010111, 001011011,001101111,011010111} ); DUAL_ORBIT([g], [140_9_66.a], ![$1]!, ![000001101,000001110,000010000,000010011,000011001,000011010,000011100, 000110010,000110111,001001001,001001010,001011011,001101110,010101101, 010110101,010111111]!) (* this code is generalized-cyclic *); DUAL_ORBIT([h], [140_9_66.a], ![$1]!, ![000000010,000001011,000001110,000010000,000010101,000011100,000100011, 000110010,000111101,000111110,001001010,001001111,001011011,001110011, 001110110,010111111]!) (* this code is generalized-cyclic *); DUAL_ORBIT([i], [140_9_66.a], ![$1]!, ![000000100,000001011,000001101,000010000,000010101,000011010,000100011, 000110010,000110111,001001010,001010111,001101011,001101101,001110011, 010101011,010111111]!) (* this code is generalized-cyclic *); DUAL_ORBIT([j], [134_9_64.e], ![$1,$2,$3]!, ![000000001,000000101,000001100,000010110,000011010,000011111,000110100, 000111100,001000100,001000101,001011001,001100101,010000110,010010010]!) alt Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000111,000001101, 000010011,000010101,000011001,000011101,000111101,001000111,001010111, 001101011,001111011,001111101,011010111,011111111} ); [k] := Cyclic( {10,5,10,10,10,10,10,10,10,10,10,10,10,10,5,10}, 150, 9, 0000010 01000010000101001101110100000111000010011101101001110000010101011000010100 001100111000100111110001011110001101010111010111011100011100111011111 ); [l] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000110,000011101,000011111,000111101,001001011,001010111,001101011, 001101111,001110111,001111101,001111111,011111111} ); [m] := Cyclic( {10,10,10,10,10,5,10,10,10,10,10,10,10,10,5,10}, 150, 9, 0010010 00000000100010011010001000111100000111000010000100001010110010101010001111 101000111010110001111011001110110100110111100011101110010110111110111 ); [n] := Cyclic( {10,10,10,10,10,10,5,10,10,10,10,10,10,10,10,5}, 150, 9, 0100110 01000001100000100010110000001010001001011000100111110010000110011000011010 111001101111000110110110001111011001110110100111101010001110111001110 ); [o] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000001,000001110, 000011011,000011101,000011111,000111011,001000011,001000111,001001111, 001011011,001101011,001111111,011111111} ); [p] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000001,000000101, 000001011,000001111,000010101,000111111,001010111,001011011,001110111, 001111011,001111101,010111111} ); disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [l], [m], [n], [o], [p]; status: realizable; [147_9_70] type [147,9,70]; credit: existence due to me; flags: find no more; [1..67] := [150_9_72.a] - dual word of weight 3; disjoint [1..67]; status: realizable; [166_9_80] type [166,9,80]; (* continued from earlier *); [a] := [163_9_78.a] + dual word of weight 3; DUAL_ORBIT_CH([f], [196_9_96.b], ![$2,$4]!, ![000000010,000000011,000001100,000010011,000010101,000011101,000100000, 000111010,000111011,000111100,001010010,001110110,010011101,011110101, 110010010]!) DUAL_ORBIT_CH([g], [196_9_96.b], ![$2,$4]!, ![000000011,000000100,000000101,000000110,000001100,000001110,000011010, 000011101,000110111,000111010,001011100,001110110,010111100,110010010]!) DUAL_ORBIT_CH([i], [196_9_96.e], ![$2]!, ![000000011,000001001,000001010,000010000,000010001,000010011,000010100, 000010101,000011100,000011110,000011111,000101000,000101100,000110010, 000111101,001001011,001011001,001101010,001111010]!) DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) [252_11_120] type [252,11,120]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) [a] := Cyclic(12, 252, 11, 0010100110010000000101010100010101100011011110101111 01010000000101100110000111010001111111101100101110100100010110111000011001 11011110111010010011101001001001101001101100010000101010111111001011110000 00010111011101110100010111000001101001011101111111); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) status: realizable; DHIDE( ![ OE(32).7#(allowing length up to 495) done for [a] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [b],[c],[d],[e] ]! ) [84_11_36] type [84,11,36]; CREDIT(existence due to Gulliver and Bhargava, nine good rate codes) [a] := Cyclic(7, 84, 11, 001000010000001010000011011111101111011011101011001000 10001101100000010101111); CREDIT(existence due to Gulliver and Bhargava, nine good rate codes) [b] := [252_11_120.a] - columns {1..84,106..168,190..210}; (* this code is generalized-cyclic *); [c] := [252_11_120.a] - columns {1..84,127..147,190..252}; (* this code is generalized-cyclic *); [d] := [252_11_120.a] - columns {22..147,190..210,232..252}; (* this code is generalized-cyclic *); [e] := [252_11_120.a] - columns {22..42,64..147,190..252}; (* this code is generalized-cyclic *); disjoint [a], [b], [c], [d], [e]; status: realizable; [249_11_118] type [249,11,118]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel some low codes) [1..34] := [252_11_120.a] - dual word of weight 3; disjoint [1..34]; status: realizable; DHIDE( ![ OE(26)#, DC1# done for [a] ]! ) DHIDE( ![ Neither [a] nor [b] is "cyclic". ]! ) DHIDE( ![ PertTwo( [a] ) tested ]! ) [92_8_44] type [92,8,44]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_ORBIT([a], [21_8_8.b], ![$1,$2,$3]!, ![00011101, 00100000,00110000,00110100,01101010,01111000,01111110,10110101]!) alt Sub( { F(%1) := %1 | Un( Off( %1 ) ) }, Choose(3,1) # Choose(6,5) | Choose(3,2) # Choose(6,6) | Choose(3,3) # Choose( 6, {3,5} ) | {1,1,0} # F( {100,010,001,100,010,001} ) | {1,0,1} # F( {100,010,001,001,100,010} ) | {0,1,1} # F( {100,010,001,010,001,100} ) ); DUAL_ORBIT([b], [105_8_50.c], ![$2,$4,$5]!, ![00000100,00011111,00100000,00100111,01100101,10000010,10001000,10001001, 10011000,10100001,10100110,10110111]!) disjoint [a], [b]; status: realizable; DHIDE( ![ OE(28).7#(length <= 255) done for [a] ]! ) [99_8_48] type [99,8,48]; CREDIT(![existence due to Dodunekov, Helleseth, Manev, and Ytrehus]!, dodunekov ytrehus 1987) DUAL_ORBIT([a], [21_9_8.a], ![$1,$3,$5,$6]!, ![000000001,000000110,011000110,011001010,011001100,011011110]!) alt Cyclic( {8,2,8,8,8,8,8,8,8,8,8,8,8}, 99, 8, 0000010101010001110101001101010 10000010110010101110101001000000111011000110111011001110011010111101 ); status: realizable; DHIDE( ![ OE(26).7#(allowing length up to 495) done for [a] ]!) [96_8_46] type [96,8,46]; CREDIT(existence due to van Tilborg, tilborg quasi-cyclic) [a] := [99_8_48.a] - columns {1,2,3}; [b] := [99_8_48.a] - columns {1,45,46}; alt Cyclic(12, 96, 8, 0000110101011110010101110101111100011111010110110100111011 11110011101101111111101011001111100110); [c] := [99_8_48.a] - columns {4,23,27}; [d] := [99_8_48.a] - columns {1,12,13}; [e] := [99_8_48.a] - columns {1,21,22}; [f] := [99_8_48.a] - columns {1,36,37}; [g] := [99_8_48.a] - columns {1,62,63}; [h] := [99_8_48.a] - columns {4,37,38}; disjoint [a], [b], [c], [d], [e], [f], [g], [h]; status: realizable; DHIDE( ![ DE1# done for [a] O(32)#, OE(28).7#(allowing length up to 495) done for [a], [b] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [c] ]! ) [238_9_116] type [238,9,116]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) DUAL_TRANSFORM([a], [35_9_14.a], ![14_{35},16_{35},20_{35},22_{35}]!) alt Cyclic(14, 238, 9, 000000001001110010000001111010111100001000011011011000010 1100100110100001110111110111000100010111111010001001000110101100010100101 0001110001100110001111100100101110011101001010111010100110010110100111111 10011011101100111101010101101111011); DUAL_ORBIT([b], [35_9_14.a], ![$1,$2]!, ![000001010,000010000,000010110, 000011101,000100010,000101101,000110111,001001011,001011010]!) alt Cyclic(14, 238, 9, 000001100110000010101011010100010001011100000000111010011 1011110111001110110100001011011111000010010000110010001110001000101110011 1010000011010010110011101111110101101101000101111101000110101010111100111 10111111101100001101110100111111001); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava 1997) DUAL_ORBIT_PLUS([c], [228_9_112.c-2], ![$2,$3]!, ![000001100,001000000,001000010,001000100,001000101,001000110,001000111, 001001000,001001010,001001011,001001100,001001101,001011001,011000000, 100001111]!, ![+ check]!) disjoint [a], [b], [c]; status: realizable; [235_9_114] type [235,9,114]; flags: find no more; [1..47] := [238_9_116.b] - dual word of weight 3; disjoint [1..47]; status: realizable; (* The following should be eliminated because there exists a [81,10,36]. *); [80_9_36] type [80,9,36]; DUAL_ORBIT([a], [238_9_116.a-1], ![$1,$2]!, ![000010011,000011001,000101001,001000001,001000100]!) DHIDE( ![ DC1P#, DC2#, DC1.7#, OE(28.7)#(length <= 255) done for [a] ]! ) [115_8_56] type [115,8,56]; CREDIT(![existence due to Dodunekov, Helleseth, Manev, and Ytrehus]!, dodunekov ytrehus 1987) DUAL_TRANSFORM([a], [48_8_22.a], ![22_{2},24_{2},30_{-2},32_{-1,-2}]!) alt Cyclic( {8,8,2,8,8,8,8,8,8,8,8,8,8,8,8}, 115, 8, 00101110011111100100010000 00111110010011000101001000001110011110100101010001100100011010000111011001 011110010101111 ); DUAL_ORBIT([b], [120_8_58.a], ![$6,$7]!, ![00000001,00000010,00010001,00010100,00010101,00100100,00100101, 00100110]!) (* this code is generalized-cyclic *); disjoint [a], [b]; status: realizable; [42_8_18] type [42,8,18]; (* to be continued later *); % All codes shown here are redundant, and included only because they are % ingredients in the construction of other codes. CREDIT(existence due to Blokh and Zyablov, blokh zyablov) DUAL_TRANSFORM([a], [45_8_20.a-45], ![27,28_{10}]!) (* [a] := [45_8_20.a] - dual word of weight 3 *); alt Cyclic( {12,12,6,12}, 42, 8, 001010100000001110110001011110000001101011 ); [e] := {100000011110011110110011010110110001010101,010000010011000110110011100000011100 001111,001000010111001111110101111010001111100000,000100001111000001111001111111 110000000000,000010011011001010011001001100001001111100,000001001110010011101010 000011011011000110,000000100101011000001101001111011101000101,000000000000111111 111111111111111111111111}; alt Act( { (1,8)(2,3)(4,7), (1,9,2)(3,5,4)(6,8,7) }, {000111111,001101111,001111110,011111111} ); [f] := {100000011101011110110011010111010001001011,010000000111000110110011100000111100 000111,001000010111001111110101111010001111100000,000100001111000001111001111111 110000000000,000010001001001010011001001101001001111110,000001001011010011101010 000011011011010010,000000110010011000001101001110011101010011,000000000000111111 111111111111111111111111}; [g] := {100000010110101100110100001010101010101010,010000001100111001010110100110111011 011000,001000000101010101100001010011010001111101,000100011001110000000111100001 110000111110,000010010111100000101111101100011011100100,000001011101000001101110 000111010110001010,000000100010111101101110000000101001110101,000000000000000011 111111111111111111111111}; [168_8_82] type [168,8,82]; % Delete the following if possible. Redundant. DUAL_ORBIT([b], [20_8_8.a], ![$1,$4,$5]!, ![00001100,00100000,00100011,00100101,00100111,00101000,01100011,01100100, 01111101,11100000,11100011,11100100,11110111]!) [a] := Cyclic( {30,15,30,30,30,15,15,2}, 168, 8, 010000100101011101111011010100 00010101001011001100010100110010011101011001100111100101111111000011010000 0011100111110100100011000001011001100011011111000100010111000011 ); [P1..246] := PertTwo( P( [40_7_18.x1..172] ) ); disjoint [a], [P1..246]; status: realizable; [58_8_26] type [58,8,26]; (* to be continued later *); CREDIT(![existence due to Dodunekov, Helleseth, Manev, and Ytrehus]!, dodunekov ytrehus 1987) note: As you can see, there are over 300,000 [58,8,26] codes, and probably far more.; DUAL_TRANSFORM_PLUS([a], [42_8_18.a-42], ![22_{-1,2},23_{-1,2},24_{1,2},25,26,27_{1,-2},27_{2},28_{1,-2},28_{2}]!, ![- column 38]!) (* [a] is redundant *); [42_8_18] type [42,8,18]; (* continued from earlier and to be continued *); % All codes shown here are redundant, and included only because they are % ingredients in the construction of other codes. DUAL_TRANSFORM_PLUS([b], [58_8_26.a], ![32_{2},34_{-2},34_{1,2},36,38_{1,-2},38_{-1,2}]!, ![- column 38]!) alt Cyclic( {8,8,8,8,8,2}, 42, 8, 001111100111010100110100011101000000001101 ); DUAL_ORBIT([d], [140_8_68.d], ![$2,$5]!, ![00000111,00001100,00101010,01101011]!) alt Act( { (3,9)(4,6)(7,8)(10,11), (1,9,8)(2,4,3)(5,7,6) }, {00000010100,01001111111,01011101100,01011111001} ); [140_8_68] type [140,8,68]; (* continued from earlier and to be continued *); [e] := [178_8_88.a]^T using {$5,$6,$7 : 00001010,00001011,00100001,00100011, 00110011,01100000,01100001,01100010,01100011,11101000}; alt Act( {(3,4)(6,7), (1,4)(5,6), (2,6,3)(4,5,7), (8,9)(1) }, {000011101,000110101,000111111,001111101} ); [f] := [178_8_88.a]^T using {$5,$6,$7 : 00000111,00001010,00001011,00100011, 00110011,01100000,01100001,01100010,01100011,11101001,11101010}; DUAL_TRANSFORM_PLUS([g], [168_8_82.b-168], ![81_{54},82_{54},83_{54},84_{54},85,86_{54},87_{-54},88_{54},91,92]!, ![+ column 48 + column 57]!) DUAL_ORBIT_PLUS([h], [92_8_44.a], ![$3,$4]!, ![00000001,00000010,00000100,00000111,00001001,00001010,00001100,00001101, 00001111,00011011,00011101,00100011,00100111,00101101,00110011,00110101, 00111110,01011111,01110111,01111111]!, ![+ column 5 + column 71]!) [j] := Act( { (4,5)(6,7)(8,9), (4,9)(5,6)(7,8), (2,3)(4,8)(7,9), (1,3)(4,5)(6,9)(7,8) }, {000000011,000010111,001000000,001000101, 001001100,001010111,001011110,011000110,011001111,011010111,011111111, 111000011,111111111} ) + column 139; DUAL_ORBIT_PLUS([k], [140_8_68.a], ![$13,$14,$16]!, ![00000001,00000111,00001010,00001110,01000001,01000010,01000111,01001001, 01001010,01001111,01010010,01010100,01111111,10000000,10000001,10001111, 10010010,10010100,11000001,11001010,11001011,11001110,11001111,11010010, 11010100,11111111]!, ![+ column 71]!) DHIDE( ![ O(26)# done for [a] ]! ) DHIDE( ![ tried PertTwo( [b] ) ]! ) [84_8_40] type [84,8,40]; (* to be continued later *); CREDIT(existence due to Blokh and Zyablov, blokh zyablov) DUAL_ORBIT([a], [140_8_68.f], ![$2,$4]!, ![00000111,00001100,00001110,00100111,00101010,00101110,10101000,10101001, 10111000,10111001]!) alt Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0000011111, 0000111111,1110000001,1110000011,1110001011,1110001110,1110010111, 1110011101} ); [b] := {1000001111100000000111111100000000011111110000111110000011111000000111111100000 11100,01000011100110000111000001100001111110011100011100110011110001000011000011 1001110110,001000101001001100110010101010101010010101110101001011001101100110001 101110100110010,0001000101110100010001010011101101011011010000100110111100011010 10111010110001000011,00001011001001100010000111110011100011001101011001010110011 1010001101100010100011011,000001001101100100100001111111000111001100100110010110 011000101101101100010111100100,0000000000000000111111111111111111111111111100000 00000000000000011111111111111111111,00000000000000000000000000000000000000000000 1111111111111111111111111111111111111111}; DUAL_ORBIT([c], [64_10_28.a], ![$2,$4]!, ![0000000011]! ) DUAL_ORBIT([d], [193_9_94.b2], ![$2,$3]!, ![000001010,000011100,000101000,001111000]!) alt Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0110001010,0110001111,0110101011,0110111111} ); DHIDE( ![ O(26)# done for [a] ]! ) DHIDE( ![ [a] is not "cyclic". ]! ) DHIDE( ![ PertTwo tried on [a] ]! ) [108_8_52] type [108,8,52]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_ORBIT_PLUS([a], [84_8_40.a], ![$2,$4]!, ![00000001,00000011,00000110,00001010,00011111]!, ![+ column 4]!) alt Act( { (1,2)(3,4)(6,7), (1,7,3,2,6,4)(8,10,9), (1,6)(2,3)(4,5) }, {0000000111,0000001111,0000011111,0000111000,0001011000,0011101111, 0011111000,0111111111,1111111111} ) + check; status: realizable; DHIDE( ![ DC1# done for both [a] and [b], D2# done for [a], [b], [c] O(26)# done for [c], [d], [e], [f] OE(26).7#(allowing length up to 511) done for [g] ]! ) [140_8_68] type [140,8,68]; (* continued from earlier for second time *); DUAL_ORBIT_CH([l], [108_8_52.a], ![$5]!, ![00000100,00000101,00001001,00001010,00010011,00010100,00010110,00100011, 00100100,00100101,00100110,00101010,00101100,00101101,00101110,00110111, 00111000,01000000,01011100,01100111,01110101,10000010,10001110,10100101, 10100111,10101001,11111111]!) disjoint [a], [b], [c], [d], [e], [f], [g], [h], [j], [k], [l]; status: realizable; DHIDE( ![ D2#, O(30)# done for [a] OE(28).7#(length <= 255) done for [a], [b] [a..f] checked for cyclic ]! ) [105_8_50] type [105,8,50]; (* continued from earlier *); DUAL_ORBIT_PLUS([f], [108_8_52.a], ![$5]!, ![00000100,00000101,00001001,00010011,00010100,00100011,00100100,00100101, 00100110,00101001,00101100,00101101,00101110,00110111,01000000,10000010, 10001110,10010011,10100101,11010110,11111111]!, ![+ column 104]!) [a1..2] := [108_8_52.a] - dual word of weight 3; disjoint [a], [b], [c], [d], [e], [f], [a1..2]; status: realizable; [45_8_20] type [45,8,20]; (* continued from earlier and to be continued *); [c] := [42_8_18.e] + dual word of weight 3; alt Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {001101111,001110111,001111101,010101111,011111111} ); [d] := [42_8_18.f] + dual word of weight 3; [e] := [42_8_18.g] + dual word of weight 3; DUAL_ORBIT([f], [120_8_58.a], ![$6]!, ![00011011,00100101,00101010,00101111,01110101,01111000,01111001,01111010, 01111101]!) DHIDE( ![ OE(30).7#(allowing length up to 495) done for [12] ]! ) DHIDE( ![ O(28).7#(allowing length up to 256) done for [a1..12] ]! ) [89_8_42] type [89,8,42]; credit: existence due to B. Groneick and S. Grosse; DUAL_ORBIT([b], [45_8_20.c], ![$1,$2]!, ![00001010,00010110,00100001,00100100,00100101,00100111,00101000, 00101001,00101010,00111000,00111001,01000101,01000110,01001011,01001111, 01101011,01110111]!) DUAL_ORBIT_CH([c], [99_8_48.a], ![$2,$3]!, ![00001000,00001011,00001110,00010010,00010101,00010110,00011000,00011001, 01001011,10000000,10000010,10000011,10000100,10000101,10001100,10011110]!) [a1..12] := [92_8_44.a] - dual word of weight 3; [b1..19] := [92_8_44.b] - dual word of weight 3; disjoint [b], [c], [a1..12], [b1..19]; status: realizable; DHIDE( ![ PertTwo tried for [a] -- [h] ]! ) [77_8_36] type [77,8,36]; (* to be continued later *); DUAL_ORBIT([a], [105_8_50.a], ![$3]!, ![00000100,00001001,00010011,00010100,00010101,00010110,00011001,00011110, 00101111,00110011,00111000,01010000,01010001,01010110,01110100,10010111, 11111111]!) DUAL_ORBIT_CH([b], [105_8_50.a], ![$3]!, ![00000100,00001010,00001011,00001101,00010000,00010001,00010011,00011100, 00011101,00101101,00101111,00111000,00111001,00111111,01010001,01101000]!) DUAL_ORBIT_CH([c], [105_8_50.a], ![$3]!, ![00000111,00001010,00001101,00010100,00010101,00010110,00011101,00011110, 00101101,00111001,00111010,00111110,01010001,01011101,01110100,10010111]!) DUAL_ORBIT([d], [105_8_50.b], ![$3]!, ![00000010,00000100,00000111,00001001,00010100,00010101,00011111,00100110, 00101100,00101101,00111010,00111011,00111111,01001000,01011000,01011001, 11110101]!) DUAL_ORBIT_PLUS([e], [105_8_50.b], ![$3]!, ![00000101,00001001,00001101,00001110,00010000,00010001,00010010,00010101, 00100111,00111010,00111011,00111100,01001011,01010000,01110010,11001110, 11110101]!, ![+ column 74]!) DUAL_ORBIT([f], [45_8_20.c], ![$1,$2]!, ![00001001,00001010,00001101,00010001,00010100,00011101,00100001,00100100, 00101001,00101111,00110111,00111000,00111001,00111111,01101011]!) DUAL_ORBIT([g], [45_8_20.c-43], ![$1,$2]!, ![00000001,00001000,00001011,00010001,00100001,00100101,00101000, 00101011,00101111,00110000,00110011,00111001,01000110,01111101,10111111]!) DUAL_ORBIT_CH([h], [105_8_50.a], ![$3]!, ![00000011,00001011,00010010,00010100,00011010,00100000,00101110,00101111, 00110110,00111110,00111111,01010000,01010001,01110100,10010001,11111111]!) DHIDE( ![ PertTwo tried on [a] -- [n] ]! ) [61_8_28] type [61,8,28]; (* to be continued later *); credit: existence due to Amir Said; DUAL_ORBIT_CH([a], [42_8_18.b], ![$1]!, ![00000010,00001011,00001111,00010010,00011000,00011111,00101010, 01001011]!) alt Act( { (1,2,3,4,5,6,7,8)(1) }, {00011101,00100101,00101111,00111011, 00111111,01011111,01110111,01111111} ) + check; (* this code is generalized-cyclic *); DUAL_ORBIT_CH([b], [42_8_18.b], ![$1]!, ![00000001,00000011,00000100,00000111,00001011,00010111,00101010, 01001011]!) alt Act( { (1,2,3,4,5,6,7,8)(1) }, {00001101,00011111,00110101,00110111, 01011111,01101111,01110111,01111111} ) + check; (* this code is generalized-cyclic *); DUAL_ORBIT([c], [45_8_20.c], ![$1,$2]!, ![00000010,00001101,00010001,00100100,00100111,00110000,00110100,00111001, 00111100,01001011,01011001,10101001]!) DUAL_ORBIT_CH([d], [45_8_20.c], ![$1,$2]!, ![00100011,00100100,00100101,00101011,00111001,00111011,01000110,01001011, 01011001,01101011,01110111]!) DUAL_ORBIT_CH([e], [45_8_20.c], ![$1,$2]!, ![00000001,00001001,00001101,00001111,00011101,00100000,00100011,00101001, 00101100,00111001,01111101]!) DUAL_ORBIT_CH([f], [45_8_20.c-43], ![$1,$2]!, ![00000001,00000010,00000110,00001000,00001101,00100101,00110000, 00110011,00110111,01011001,01110111]!) DUAL_ORBIT_CH([g], [89_8_42.b], ![$1,$2]!, ![00000101,00000110,00001100,00001101,00010110,00011001,00011110,00110001, 00110100,00111111,01000010,01010001,01010110,01111110]!) [45_8_20] type [45,8,20]; (* continued from earlier for second time *); DUAL_ORBIT_CH([g], [77_8_36.g], ![$2]!, ![00000001,00000010,00001010,00100001,00100010,00101101,01001000,01010111, 10000110]!) DUAL_ORBIT([h], [77_8_36.g], ![$2]!, ![00000001,00000010,00001010,00100001,00100010,00101101,01010111,01100111, 10000110,11001101]!) DUAL_ORBIT([i], [61_8_28.c], ![$1,$2]!, ![00001000,00001011,00010000,00110000,01010100,01111001,01111100,10000000, 10001111,10111000]!) DUAL_ORBIT_CH([j], [61_8_28.f], ![$2]!, ![00000011,00001101,00001111,00011111,00101001,00101100,00111000,00111101, 01110111]!) [k] := Act( { (1,2,3,4,5,6,7,8,9)(1) }, {001010101,001101111,001111011,010101111,010111011} ); [de] config 45 ::: {y22 = 0, y30 = 0}; [x1..200] := Unresidue( [45_8_20], [de], [13_7_4.a6], 200 ); disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [x1..200]; status: realizable; DHIDE( ![ DC1#, D2# done for [a] OE(26).7# (allowing length up to 320) done for [a], [b] ]! ) [112_8_54] type [112,8,54]; [a] := Cyclic(14, 112, 8, 00001011000101010100000001001010000111110100111100011 01001011011011101100010001101100010101110100100110101101111); DUAL_TRANSFORM_PLUS([b], [42_8_18.a], ![18_{5},20_{5},22_{5},24_{1,5},26_{-5},28_{1,-5}]!, ![- column 30]!) [c] := [115_8_56.a] - columns {1,8,9}; [d] := [115_8_56.a] - columns {1,20,21}; [e] := [115_8_56.a] - columns {7,8,58}; [b1..24] := [115_8_56.b] - dual word of weight 3; disjoint [a], [b], [c], [d], [e], [b1..24]; status: realizable; DHIDE( ![ D2S, DC1#, OE(26)# done for [a] ]! ) DHIDE( ![ OE(26).7#(allowing length up to 495) done for [a] ]!) [245_9_120] type [245,9,120]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_TRANSFORM([a], [21_9_8.a-21], ![7,11,16]!) alt Cyclic( {15,15,5,15,15,15,15,15,15,15,15,15,15,15,5,15,15,5,5}, 245, 9, 0000100111100000011110110100000000100010010011000100111011001010000010101 01001000011101010001010011000010110000010101100110010001111101110010011011 00011100000110011111101001011011011101001101111001101001110001011110101110 011010101111100110101111 ); status: realizable; [32_11_12x] type [32,11,12_4]; [a] := Cyclic( {31}, 32, 11, 00000001011011100000100100101011 ); (* The following should be eliminated because there is a [186,11,88]. *); [186_10_88] type [186,10,88]; DUAL_TRANSFORM([a], [32_11_12x.a], ![20_{-1}]!) (* this code is generalized-cyclic *); DHIDE( ![ D2#, OE(26)#, D3(28).7#(only 4 orbits checked) done for [a] ]! ) DHIDE( ![ OE(26).7#(allowing length up to 495) done for [a] ]!) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [1..2] ]! ) [242_9_118] type [242,9,118]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_TRANSFORM_PLUS([a], [186_10_88.a-186], ![87_{3},95_{3}]!, ![- column 237 + column 113]!) alt Cyclic( {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15}, 242, 9, 001001000101010010101011000011001110010111101011001001100000 000010000011110011110011110111010011011100001001000010011111 010100001110110001111111000110011000100011011001110101110011 01001011001101000001011101000000010110100011110101001010111111 ); [a1..2] := [245_9_120.a] - dual word of weight 3; disjoint [a], [a1..2]; status: realizable; [147_8_72] type [147,8,72]; (* to be continued later *); DUAL_TRANSFORM([a], [178_8_88.a], ![88_{2},96,128_{1,2}]!) alt P([19_7_8.a]); DUAL_ORBIT([b], [21_8_8.b], ![$1, $2, $3]!, ![00000101,00001001,00001101,00010001,00011101,00100011,00110100,01101000, 01101010]!) alt Act( { (1,2)(3,5)(6,8), (3,8)(4,5)(6,7) }, {00000001,00000111,00001101, 00001111,00010111,00011110,01000001,01000011,01000111,01001100,01001101, 01010011,01011011,01011110,11000011,11000111,11001101,11001111,11011111} ); (* this code is generalized-cyclic *); DUAL_ORBIT([c], [242_9_118.a], ![$4,$5]!, ![000001010,000001011,000010000,000010110,000011010,000011011,000100000]!) DUAL_ORBIT([d], [147_8_72.c], ![$6]!, ![00000111,00001001,00001101,00010000,00010001,00010100,00010101,00011000, 00101010,00101011,00110011,01101000,01101001]!) (* this code is generalized-cyclic *); [77_8_36] type [77,8,36]; (* continued from earlier *); DUAL_ORBIT_CH([i], [147_8_72.c], ![$4]!, ![00000001,00000010,00000101,00001000,00010100,00011000,00100110,00101110, 01100111,10000001,10000101,10001000,10001011,10010010,10101110]!) DUAL_ORBIT_PLUS([j], [108_8_52.a], ![$5]!, ![00000001,00000101,00001001,00100010,00101100,00110001,00111000,01011011, 01100111,10001101,10001110,10010011,10100100,10100111,10101000,10110111, 11010110]!, ![+ column 21]!) DUAL_ORBIT_PLUS([k], [105_8_50.a], ![$3]!, ![00000001,00000100,00000111,00010010,00010100,00010110,00011001,00011101, 00100001,00111010,00111011,01010001,01011101,01101000,10010001]!, ![+ check + dual word of weight 3]!) DUAL_ORBIT_PLUS([l], [112_8_54.a], ![$4]!, ![00000010,00000110,00010001,00010010,00010100,00010101,00010110,00011100, 00110111,01000001,01010010,01010101,01011000,10100010,11010010,11111111]!, ![+ dual word of weight 3]!) disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [l]; status: realizable; DHIDE( ![ DC1#, D2# done for [a] OE(28).7#(allowing length up to 255) done for [a] O(28).7#(allowing length up to 255) done for [b] ]! ) DHIDE( ![ PertTwo for [a], [b], [c] ]! ) [175_8_86] type [175,8,86]; credit: existence due to Bierbrauer and Edel; DUAL_TRANSFORM_CH([a], [147_8_72.a], ![72_{12},76]!) DUAL_ORBIT_PLUS([b], [105_8_50.a], ![$2,$3]!, ![00000001, 00000011,00000111,00001011,00001101,00010010,00010011,01101000,11111111]!, ![+ column 174]!) alt P( [47_7_22.a] ); DUAL_ORBIT_PLUS([c], [147_8_72.a], ![$2,$4,$5]!, ![00000011,00000111,00001010,00001110,00010100,00010110,00011001,00011010, 00011011,00110101,00110111,01000111,11111000,11111010]!, ![+ column 167]!) (* [a], [b], [c] := [178_8_88.a] - dual word of weight 3 *); disjoint [a], [b], [c]; status: realizable; DHIDE( ![ D2P#, DC1# done for [a] OE(26).7#(allowing length up to 495) done for [a] H(28,8000).7# ]! ) [155_8_76] type [155,8,76]; DUAL_TRANSFORM_CH([a], [48_8_22.a], ![22_{2,-3},22_{-2,3}, 24_{2,-3},24_{-2,3},30,32_{1,2,3}]!) alt P( [27_7_12.a] ); status: realizable; DHIDE( ![ DC1#, O(26)# done for [a] ]! ) [171_8_84] type [171,8,84]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel reed solomon) [a] := Act( { (2,4)(5,6), (1,8)(2,6,4,5), (2,5)(3,6) }, {00000100,00000101, 00000111,00001101,00001110,00001111,00011011,00011100,00011101,00011110, 00011111,00101101,00111110,00111111,01111100,01111101,10000101,10001111, 10011101,10111101,10111111,11111101,11111111} ) + check; [P1..7] := P( [43_7_20.x1..7] ); disjoint [a], [P1..7]; status: realizable; DHIDE( ![ D2P#, DC1#, H(28,8000).7# ]! ) [136_8_66] type [136,8,66]; (* unique -- Tilborg type III *); DUAL_TRANSFORM_CH([a], [155_8_76.a], ![76_{3,-29},76_{-3,29},80_{3,-29}, 80_{-3,29},84_{3,29},128_{3,29}]!) alt P( Even(8) ); status: realizable; (* I would like to REMOVE the following code, as it is superceded by the [92,8,44]. *); [93_8_44] type [93,8,44]; DUAL_TRANSFORM_CH([a], [136_8_66.a], ![68_{1,28},70,72_{-1,28}]!) [68_8_32] type [68,8,32]; (* to be continued later *); DUAL_TRANSFORM_PLUS([a], [93_8_44.a], ![48_{1},64_{-2},64_{1,2}]!, ![+ column 1 + column 1 + column 1]!) alt Act( { (1,2)(1), (2,3)(1), (4,5)(1), (5,6)(1), (7,8)(1), (6,8,9)(1) }, {000111111,001000011,001111111,111001111} ) + column 1 + column 1 + column 1 + check; DUAL_TRANSFORM([b], [35_9_14.a], ![16_{-35}]!) alt Act( { (1,2,3,4,5,6,7,8)(1) }, {00011011,00011101,00100101,00100111, 00101111,00110011,00111011,00111111,01111111} ); DUAL_TRANSFORM([c], [68_8_32.b], ![32_{2,14,27},40_{-27},40_{-14,27},40_{-2,14,27}]!) (* this code is generalized-cyclic *); alt Act( { (1,2,3,4,5,6,7,8)(1) }, {00001101,00011011,00011111,00100111, 00110011,00110101,00110111,01101111,01111111} ); [d] := Act( { (1,2,3,4,5,6,7,8)(1) }, {00011101,00011111,00101011,00101111, 00110101,00110111,01010101,01010111,01101111} ) + column 12 + column 38; (* this code is generalized-cyclic *); DUAL_ORBIT_PLUS([e], [64_10_28.a], ![$1,$2]!, ![0100100011,1000000000,1000010111,1111111111]!, ![+ column 65 + column 65 + column 65]!) DUAL_ORBIT_PLUS([f], [105_8_50.a], ![$3]!, ![00000100,00001010,00010001,00010100,00010101,00010110,00010111,00011011, 00100001,00101101,00111000,01010110,01011101,01110011,10010111]!, ![+ column 42]!) DUAL_ORBIT([g], [105_8_50.a], ![$3]!, ![00000110,00000111,00001010,00010100,00010101,00010110,00011001,00011101, 00011110,00110011,00111110,01010001,01101000,01110100,10010111,10110010]!) DUAL_ORBIT_CH([h], [105_8_50.a], ![$3]!, ![00000011,00001101,00010100,00010101,00011011,00011100,00011101,00100001, 00100011,00110011,00111010,00111011,01000000,01010001,10010111]!) DUAL_ORBIT([i], [21_9_8.a], ![$1,$3,$4]!, ![000000110,000001001,001100001,100000010,100001001,100110011,100110111]!) [j] := Act( { (1,2,3,4,5,6,7,8)(1) }, {00011011,00011101,00100101,00110011, 00110101,01010111,01011011,01011111,01111111} ); (* this code is generalized-cyclic *); DUAL_ORBIT([k], [42_8_18.d], ![$2,$3]!, ![00000010,00000111,00001000,00001110,00010110,00010111,00011101, 00011110,00110000,01001110,01011011]!) DUAL_ORBIT([l], [45_8_20.c], ![$1,$2]!, ![00000010,00000011,00000101,00010001,00010110,00100001,00110011, 00111000,00111011,00111100,01000101,01001111,01101011,10111111]!) DUAL_ORBIT([m], [45_8_20.c-43], ![$1,$2]!, ![00000011,00001111,00010110,00011101,00100000,00100001,00100100, 00101010,00101011,00101100,00110011,00111011,01000110,10111111]!) DUAL_ORBIT_PLUS([n], [140_8_68.a], ![$13,$14,$16]!, ![00000001,00001110,01000010,01111111,10000000,10001010,10001011,10010010, 10111111,11000010,11000111,11001011,11010010,11010111]!, ![+ column 19 + column 43 + check]!) [61_8_28] type [61,8,28]; (* continued from earlier *); DUAL_ORBIT_CH([h], [68_8_32.b], ![$1,$4]!, ![00000011,00000100,00001010,00001011,00001101,00011000,00011110,00100001, 10000001,10000111,10001000,10001001,10110110]!) DUAL_ORBIT([i], [68_8_32.b], ![$1,$4]!, ![00000001,00000010,00000100,00001000,00001101,00011010,00011110,00100001, 00101010,10000111,10001001,10001110,10011101,10101000]!) DUAL_ORBIT_CH([j], [68_8_32.b], ![$1,$4]!, ![00000011,00000100,00001111,00010111,00011010,00011110,00100001,00101000, 10000011,10000101,10001010,10001111,10101010]!) DUAL_ORBIT_PLUS([k], [140_8_68.e], ![$3,$6]!, ![00010010,00101001,01000010,01001001,01101010,01110000,10100000,10111111, 11111001]!, ![+ check + dual word of weight 3]!) DUAL_ORBIT_PLUS([l], [147_8_72.c], ![$4]!, ![00010100,00011000,00101110,01101111,10010001,10010010,10010011,10011010, 10101110,10110110,10111110]!, ![+ check + dual word of weight 3]!) DUAL_ORBIT_PLUS([m], [147_8_72.c], ![$4]!, ![00000010,00000011,00001100,00011000,00100110,01101111,10000000,10000010, 10001000,10001100,10010011]!, ![+ check + dual word of weight 3]!) [n] := [130_9_62.a] - columns {12..21,36..69,84..108,130} + column 41; disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [l], [m], [n]; status: realizable; [65_8_30] type [65,8,30]; (* to be continued later *); CREDIT(![existence due to Dodunekov, Helleseth, Manev, and Ytrehus]!, dodunekov ytrehus 1987) [a] := [68_8_32.b] - dual word of weight 3; (* this code is generalized-cyclic *); DUAL_ORBIT_CH([d], [105_8_50.b], ![$3]!, ![00000001,00000010,00000101,00001111,00010001,00010010,00010101,00011100, 00011110,00100111,00111101,01010001,01011001,11110100]!) alt Act( { (4,5)(6,7)(8,9), (4,9)(5,6)(7,8), (2,3)(4,8)(7,9), (1,3)(4,5)(6,9)(7,8) }, {000010111,000111111,001001111,001010111, 011000011,011111111,111000011} ) + check; (* this code is generalized-cyclic *); DUAL_ORBIT([g], [45_8_20.c], ![$1,$2]!, ![00000011,00000110,00000111,00001001,00100001,00100101,00101100,00110011, 00110111,00111011,01000110,01001011,01011001]!) DUAL_ORBIT_PLUS([l], [140_8_68.a], ![$13,$14,$16]!, ![00000111,00010111,01000000,01001001,01010100,10000001,10000010,10001011, 10001110,10010010,11000000,11001010,11001111]!, ![- column 20 - column 63 + column 9 + column 46 + check]!) [c1..3] := [68_8_32.c] - dual word of weight 3; [d1..13] := [68_8_32.d] - dual word of weight 3; [f1..25] := [68_8_32.f] - dual word of weight 3; [g1..5] := [68_8_32.g] - dual word of weight 3; [h1..3] := [68_8_32.h] - dual word of weight 3; [l1..26] := [68_8_32.l] - dual word of weight 3; [m1..3] := [68_8_32.m] - dual word of weight 3; DHIDE( ![ D6 (only 1 orbit) for [a], DC5 (only one orbit) for [a], DC2 done for [a] DC1# done for [a], [b], [c] D3#, DC2# done for [b] D2# done for [c] O(26)# done for [b], [c] H(28,8000).7# for [a], [b], [c], [d] ]! ) [68_8_32] type [68,8,32]; (* continued from earlier *); DUAL_ORBIT_CH([o], [65_8_30.a], ![$4]!, ![00000101,00001001,00001010,00001110,00100110,01100111,01101101, 01110111]!) (* this code is generalized-cyclic *); DUAL_ORBIT_PLUS([p], [77_8_36.e], ![$2,$3]!, ![00000001,00000111,00011001,00011111,00100001,00100101,00100111,00110000, 00110001,00110100,00111101,01001100,01010110,01011110]!, ![+ check + dual word of weight 3]!) DUAL_ORBIT_PLUS([q], [147_8_72.d], ![$1,$2]!, ![00000100,00001100,00010001,00101100,00101110,00110011,01110000,10000010, 10001001,10001100,10010000,10011000,10011011]!, ![+ check + dual word of weight 3]!) DUAL_ORBIT_PLUS([r], [65_8_30.d], ![$5]!, ![00000001,00000010,00000011,00000111,00001000,00010101,00010111,01000110, 01011001,10000000,10111001]!, ![+ check + dual word of weight 3]!) [s] := Act( { (3,4)(6,7), (1,4)(5,6), (2,6,3)(4,5,7), (8,9)(1) }, {000001111,000011111,001101111,011111111,111111100} ) + column 64 + column 64 + column 64 + check; disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [l], [m], [n], [o], [p], [q], [r], [s]; status: realizable; DHIDE( ![ D2#, O(26)# done for [a] ]! ) [65_8_30] type [65,8,30]; (* continued from earlier *); [m] := [68_8_32.i] - columns {47,55} - column 15 - column 37 + check; [n] := [68_8_32.k] - columns {7,12} - column 4 - column 9 + check; [o] := [68_8_32.k] - columns {7,12} - column 24 - column 29 + check; [p] := [65_8_30.m3] - columns {5,50} + column 7 + check; [o1..14] := [68_8_32.o] - dual word of weight 3; [p1..19] := [68_8_32.p] - dual word of weight 3; [q1..27] := [68_8_32.q] - dual word of weight 3; [r1..10] := [68_8_32.r] - dual word of weight 3; disjoint [a], [d], [g], [l], [m], [n], [o], [p], [c1..3], [d1..13], [f1..25], [g1..5], [h1..3], [l1..26], [m1..3], [o1..14], [p1..19], [q1..27], [r1..10]; status: realizable; [144_8_70] type [144,8,70]; (* to be continued later *); flags: find no more; DUAL_TRANSFORM([c], [175_8_86.a], ![86_{1},88_{1},94,126_{1}]!) (* [c] is isomorphic to [2] *); [e] := Cyclic( {12,12,6,6,6,12,12,12,12,12,12,12,12,6}, 144, 8, 011000110010010 00000010111101011001000110110001011011100010111101001110100100001100000110 1100111110010110110100011001001011100101011010100111100 ); DUAL_ORBIT([f], [147_8_72.b], ![$1,$2,$4]!, ![00000111,00001101,00010001,00011001,00100001,00101011,00111111]!) [h] := P( [16_7_6.a2] ); [i] := P( [16_7_6.a1] ); [j] := {1000011111000001100001111100000111100001110000001111110000111110000111111000001 11111000000011110000111110000011110000001111100000011110000111110,01000100011100 01101100011000110011000111100011010000111100100111100100011110011000111100110110 00010111000011001100111001110000110100111011100010,00100010100101010001101110101 00010101101101010100110101010001010110001110101100101010101100010101101101010100 10100011011101010101110100110010100,00010001110110011101110100011001101101110001 10111010011001011100100010101100110001100110010000110101011001100010010100110110 01101010010001000111,00001111111111000000111111111100000000111111110000000000001 11111110000000000111111111111000000000011111111110000000011111111111100000000111 11111,00000000000000111111111111111100000000000000001111111111111111111100000000 0000000000000011111111111111111111000000000000000000001111111111111111,000000000 00000000000000000000011111111111111111111111111111111111100000000000000000000000 0000000000000000000111111111111111111111111111111111111,000000000000000000000000 00000000000000000000000000000000000000000011111111111111111111111111111111111111 1111111111111111111111111111111111111111}; [k] := {1000011010100010111001010100010110101100010011010101101011010101010001110101010 10010101110100100100101101110101010010011101000011011010010101010,01000011100011 00101101101000111000110001011001110011011100110011000110100001100110111001100100 01101100110011100110001000111001010011100100111100,00100011001010011101110001001 10010011010101010011001110110011010010100101100111101100010110010010001101111001 10011011010110001111000101001100110,00010011010001011001101100100011010110110010 11101001010010100110100010110010111010100111010001110010011101110100101000100101 00110101001110100101,00001111111000000000111111100000000011111110000000000001111 11111110000000000011111111100000000000111111110000000000011111111000000011111111 11111,00000000000111111111111111100000000000000001111111111111111111111100000000 0000000000001111111111111111111000000000000000000011111111111111111111,000000000 00000000000000000011111111111111111111111111111111111111100000000000000000000000 0000000000000000111111111111111111111111111111111111111,000000000000000000000000 00000000000000000000000000000000000000000011111111111111111111111111111111111111 1111111111111111111111111111111111111111}; (* [k] is isomorphic to [e1] *); [l] := [147_8_72.b] - columns {1,10,12}; [m] := [147_8_72.b] - columns {1,11,15}; [n] := [147_8_72.b] - columns {1,16,17}; [o] := [147_8_72.b] - columns {1,32,34}; [p] := [147_8_72.b] - columns {1,52,57}; [q] := [147_8_72.b] - columns {2,9,14}; [r] := [147_8_72.b] - columns {2,17,21}; [s] := [147_8_72.b] - columns {2,23,29}; [t] := [147_8_72.b] - columns {2,24,28}; [u] := [147_8_72.b] - columns {2,25,30}; [v] := [147_8_72.b] - columns {2,33,37}; [w] := [147_8_72.b] - columns {2,34,39}; [x] := [147_8_72.b] - columns {2,48,52}; [y] := [147_8_72.b] - columns {2,50,59}; [z] := [147_8_72.b] - columns {2,83,90}; [aa] := [147_8_72.b] - columns {2,103,110}; [bb] := [147_8_72.b] - columns {6,17,25}; [cc] := [147_8_72.b] - columns {64,111,113}; [dd] := [147_8_72.b] - columns {61,92,123}; [1..3] := [147_8_72.a] - dual word of weight 3; [4..11] := [147_8_72.c] - dual word of weight 3; [12..27] := [147_8_72.d] - dual word of weight 3; DHIDE( ![ D2#, DC1#, O(28).7#(length <= 255) done for [a] OE(28).7#(allowing length up to 255) for [b], [c], [d] ]! ) [147_8_72] type [147,8,72]; (* continued from earlier *); [e] := [144_8_70.k] + dual word of weight 3; (* this code is generalized-cyclic *); DUAL_ORBIT([f], [45_8_20.c], ![$1,$2]!, ![00000001,00000011,00000110,00000111,00001101,00001111,00010001, 00010011,00010100,00010110,00100101,00100111,00101011,00101100,00110011, 00110100,00110111,00111001,00111011,00111100,00111111,01000101,01000110, 01001011,01001111,01011001,01101011]!) DUAL_ORBIT([g], [89_8_42.a11], ![$1]!, ![00000001,00000011,00000101,00000110,00000111,00001001,00001100, 00001101,00001111,00010001,00010010,00010100,00010110,00011010,00011101, 00011111,00100001,00100011,00101011,00101101,00111011,00111101,00111111, 01000100,01100111,01110010,01111110]!) DUAL_ORBIT_CH([h], [96_8_46.b], ![$1,$2]!, ![00000010,00000101,00001000,00001001,00001011,00001100,00001110,00001111, 00010001,00010110,00011010,01000000,01000001,01000010,01000100,01000101, 01010000,01010010,01010011,01010100,01011100,01011110,01100101,11001010, 11001111]!) disjoint [a], [b], [c], [d], [e], [f], [g], [h]; status: realizable; DHIDE( ![ D2#, DC1# done for [a], [b], [c]; OE(28).7#(allowing length up to 495) done for [b] -- [g] ]! ) [144_8_70] type [144,8,70]; (* continued from earlier *); [e1..41] := [147_8_72.e] - dual word of weight 3; [f1..179] := [147_8_72.f] - dual word of weight 3; [g1..182] := [147_8_72.g] - dual word of weight 3; [h1..138] := [147_8_72.h] - dual word of weight 3; disjoint [e],[f],[h],[i],[j],[l],[m],[n],[o],[p],[q],[r],[s],[t],[u],[v], [w],[x],[y],[z],[aa],[bb],[cc],[dd],[1..27], [e1..41], [f1..179], [g1..182], [h1..138]; status: realizable; DHIDE( ![ D2P#, DC1# done for ]! ) [199_8_98] type [199,8,98]; [a] := P( [71_7_34.a] ); status: realizable; DHIDE( ![ DC2, DC1# done for ]! ) [189_8_94] type [189,8,94]; (* unique -- Tilborg type II *); credit: existence due to Belov; DUAL_TRANSFORM([a], [155_8_76.a], ![76_{3,-14},76_{14},80_{3,-14},80_{14}, 84_{3,14}]!) alt Even(3) # Simp(6); status: realizable; (* The following three types are extra -- to avoid reentering a code type. *); [245_8_122x] type [245,8,122]; DUAL_TRANSFORM([a], [189_8_94.a-189], ![93,94,95,96_{1,-2},96_{2}]!) [207_8_102x] type [207,8,102]; DUAL_TRANSFORM_CH([a], [136_8_66.a], ![66_{1,-17},66_{17},68_{1,-17},68_{17},70,72_{-1,17},128_{1,17}]!) DUAL_ORBIT([n], [147_8_72.b], ![$1,$3,$4]!, ![00000111,00001011,00001101,00001111,00010001,00011000,00011101,00101001, 00101101,00110000,00110010,00111000,00111111,01110000]!) [183_8_90x] type [183,8,90]; DUAL_TRANSFORM([b], [207_8_102x.a-207], ![101,102_{1},103,104_{1},107,108_{1},127,128_{1}]!) [210_8_104] type [210,8,104]; [b] := Act( { (1,2)(1), (6,9)(1), (5,6)(1), (5,7)(1), (7,8)(1), (2,3)(1), (4,8)(1), (3,4)(1) }, {000001111,000111111} ); [d] := Act( { (1,2)(1), (2,3)(1), (4,5)(1), (5,6)(1), (7,8)(1), (6,8,9)(1) }, {001000011,001001111,011000011,011001111,111000011,111001111} ); [z1..11] := P( [82_7_40.z1..11] ); DUAL_ORBIT([g], [242_9_118.a], ![$4,$5]!, ![000000001,000000110,000001011,000010110,000011010,000011011,000110111, 001000010]!) DUAL_ORBIT([h], [20_8_8.a], ![$2,$3,$5]!, ![00000011,00000110,00001101,01000000,01000010,01000111,01001110,01010000, 01010100,01111101,11000000,11000011,11000111,11001000,11011110]!) DUAL_ORBIT_PLUS([i], [207_8_102x.n], ![$1,$6]!, ![00000011,00000100,00000110,00001000,00010000,00010001,00010010,00010011, 00010111,00011110,00011111,01110011,10010001,10111011]!, ![+ column 122]!) [a1..2] := [203_8_100.l] + dual word of weight 4 + dual word of weight 3; disjoint [b], [d], [g], [h], [i], [z1..11], [a1..2]; status: realizable; (* Try to eliminate: *); [210_8_104] type [210,8,104]; DUAL_TRANSFORM_PLUS([c], [68_8_32.a-68], ![31_{-6},31_{-5,6},32_{5,-6},32_{6},39,40,63_{5,6}]!, ![+ column 97]!) (* Eliminate: There exists a [120,8,58], found by Boukliev. *); [121_8_58] type [121,8,58]; DUAL_TRANSFORM([a], [20_8_8.a-20], ![7_{-1,2},8_{2},11_{2},12_{2},15_{1}]!) status: realizable; [207_8_102] type [207,8,102]; CREDIT(existence due to Blokh and Zyablov, blokh zyablov) [L1..20] := PertTwo( [203_8_100.l] + dual word of weight 4, ex triples ); [a1..293] := PertTwo( P( [79_7_38.x1..216] ) ); [b1..11] := [210_8_104.{b,d,g,h}] - dual word of weight 3; [i1..10] := PertTwo( [210_8_104.i] - dual word of weight 3 ); disjoint [L1..20], [a1..293], [b1..11], [i1..10]; status: realizable; (* type [245,8,122] show y148 = 0, y150 = 0, y152 = 0, y180 = 0, y182 = 0, y244 = 0 kill y134, y140, y136, y132 type [245,8,122] show y128 != 0 so the following is a complete classification [a] := P( [117_7_58.a] ) [b] := P( [117_7_58.b] ) disjoint [a], [b] *); DHIDE( ![ DC1#, D2# done for [a] ]! ) [245_8_122] type [245,8,122]; credit: existence due to Belov; [a] := P( [117_7_58.a] ); [b] := P( [117_7_58.b] ); disjoint [a], [b]; ??classification of [base]: [a], [b]; status: classified, realizable; DHIDE( ![ DC1# done for [a], [b1]; D2# done for [a]; D3# done for [b1]; ]! ) [183_8_90] type [183,8,90]; CREDIT(existence due to Blokh and Zyablov, blokh zyablov) [a] := Act( { (1,2)(1), (2,3)(1), (4,5)(1), (5,6)(1), (7,8)(1), (6,8,9)(1) }, {001000011,001001111,011000011,011001111,011111111} ); [b1..19] := PertTwo( Act( { (1,2)(1), (2,3)(1), (4,5)(1), (5,6)(1), (7,8)(1), (6,8,9)(1) }, {001000011,001001111,011000000,011000011,011001111} ) ); [d] := Act( { (2,4)(5,6), (1,8)(2,6,4,5), (2,5)(3,6) }, {00000100,00000101, 00000111,00001101,00001110,00001111,00011001,00011011,00011100,00011101, 00011111,00101101,00101111,00111101,00111110,00111111,01111100,01111101, 01111111,10000101,10001111,10011101,10111111} ) - column 2 - column 180; disjoint [a], [b1..19], [d]; status: realizable; DHIDE( ![ DC1#, DC2S (but on column deletion, only 1 column checked, and for it, only 9 orbits checked) D2# ]! ) [221_8_110] type [221,8,110]; credit: existence due to Belov; DUAL_TRANSFORM([a], [189_8_94.a], ![94,96_{2}]!) alt P( Simp(5) # Simp(2) ); status: realizable; DHIDE( ![ DC1#, D2# done for ]! ) credit: existence due to Belov; [217_8_108] type [217,8,108]; (* unique -- Tilborg type II *); [a] := Simp(5) # Simp(3); status: realizable; DHIDE( ![ DC1#, D2# done for ]! ) [233_8_116] type [233,8,116]; credit: existence due to Belov; [a] := P( Simp(3) # Simp(4) ); status: realizable; DHIDE( ![ DC1# for [a], D1# for [b]; O(26)# done for [a], [b], [c], [pa], [pb] ]! ) DHIDE( ![ PertTwo tried on pa, pe, pf, 1, 2 ]! ) [152_8_74] type [152,8,74]; [pd1..5] := PertTwo( P( [24_7_10.b3] ) ); [p{a,e,f}] := P( [24_7_10.{a,e,f}] ); [1] := [159_8_78.a1] - columns {39,76,78,114,115,116} - column 39 - column 74 + check; [2] := [159_8_78.a1] - columns {37,76,78,112,113,117} - column 37 - column 74 + check; [3] := [159_8_78.a1] - columns {54,76,78,98,129,130} - column 54 - column 74 + check; [4] := [159_8_78.a1] - columns {60,76,78,92,136,137} - column 60 - column 74 + check; [5] := [159_8_78.a1] - columns {14,76,77,78,88,151} - column 14 - column 135 + check; [6] := [159_8_78.a1] - columns {48,76,77,78,124,151} - column 48 - column 99 + check; [7] := [159_8_78.a1] - columns {37,43,74,75,110,117} - column 37 - column 40 + check; [8] := [159_8_78.a1] - columns {10,71,74,75,83,144} - column 10 - column 68 + check; [9] := [159_8_78.a1] - columns {29,52,72,73,100,124} - column 50 - column 76 + check; [10] := [159_8_78.a1] - columns {21,73,99,132,133,151} - column 71 - column 78 + check; [11] := [159_8_78.a1] - columns {56,73,96,97,129,151} - column 71 - column 78 + check; [12] := [159_8_78.a1] - columns {15,64,72,73,87,141} - column 14 - column 76 + check; [13] := [159_8_78.a1] - columns {18,61,72,73,81,151} - column 59 - column 86 + check; [14] := [159_8_78.a1] - columns {33,71,83,112,113,120} - column 69 - column 113 + check; [15] := [159_8_78.a1] - columns {44,71,83,107,115,116} - column 69 - column 102 + check; [16] := [159_8_78.a1] - columns {14,58,70,71,83,151} - column 14 - column 135 + check; [17] := [159_8_78.a1] - columns {29,55,70,71,83,151} - column 53 - column 92 + check; [18] := [159_8_78.a1] - columns {70,71,79,83,147,151} - column 7 - column 142 + check; [19] := [159_8_78.a1] - columns {28,67,97,125,126,151} - column 55 - column 93 + check; [20] := [159_8_78.a1] - columns {21,63,107,132,133,151} - column 43 - column 103 + check; [21] := [159_8_78.a1] - columns {18,43,54,55,98,151} - column 41 - column 104 + check; disjoint [pd1..5], [pa], [pe], [pf], [1..21]; status: realizable; DHIDE( ![ DC1G# done for ]! ) [186_8_92] type [186,8,92]; DUAL_TRANSFORM([a], [221_8_110.a], ![110]!) (* [a] = [6_3_3.a] # Simp(5) =(presumably) [93_7_46.a] # Proj(1) *); [b] := Act( { (2,4)(5,6), (1,8)(2,6,4,5), (2,5)(3,6) }, {00000100,00000101, 00000111,00001101,00001110,00001111,00011001,00011011,00011100,00011101, 00011111,00101101,00101111,00111101,00111110,00111111,01111100,01111101, 01111111,10000101,10001111,10011101,10111111} ) + column 91; [c] := [189_8_94.a] - dual word of weight 3; DUAL_ORBIT_PLUS([d], [140_8_68.a], ![$14,$15,$16]!, ![01000001,01000111,01001001,01001010,01001110,01001111,10000000,10000001, 10001001,10001010,10001110,10001111,10111111,11000001,11001001,11001010, 11001110,11001111,11111111]!, ![- column 1 - column 63 + column 61 + column 122 + column 185]!) disjoint [a], [b], [c], [d]; status: realizable; DHIDE( ![ DC1# done for ]! ) [237_8_118] type [237,8,118]; credit: existence due to Belov; DUAL_TRANSFORM([a], [186_8_92.a-186], ![91,92,93,95]!) alt P( [109_7_54.a] ); status: realizable; DHIDE( ![ D2# done for [a] ]! ) [214_8_106] type [214,8,106]; credit: existence due to Belov; DUAL_TRANSFORM([a], [237_8_118.a-237], ![117,118,119_{60},120_{60},126_{60},127_{60}]!) alt Act( { (2,4)(5,6), (1,8)(2,6,4,5), (2,5)(3,6), (6)(8,7,9) }, {000001001,000001111,000011011,000111001,000111111,001111011,011111111}); [b] := [217_8_108.a] - dual word of weight 3; disjoint [a], [b]; status: realizable; DHIDE( ![ D2, DC1# done for [a] ]! ) [230_8_114] type [230,8,114]; credit: existence due to Belov; [a1..3] := P( [102_7_50.a1..3] ); DUAL_TRANSFORM([b], [237_8_118.a-237], ![117,118,119,120_{60},126_{60},127]!) DUAL_ORBIT([d], [214_8_106.a], ![$9,$10,$12]!, ![00000100,00000101,00000110,00000111,00001000,00001001,00001101,00010000, 00010001,00110000,00110001,01000010,01000011,01000100,01000110]!) disjoint [a1..3], [b], [d]; status: realizable; DHIDE( ![ DC1G# ]! ) [162_8_80] type [162,8,80]; CREDIT(![existence due to Boukliev, Dodunekov, Helleseth, and Ytrehus]!, boukliev dodunekov helleseth ytrehus) DUAL_TRANSFORM_PLUS([a], [21_8_8.b], ![12_{-1},12_{1},16_{-1},16_{1},16_{1}]!, ![+ column 64]!) status: realizable; DHIDE( ![ D1# done for [a], O(26)# done for [a], [b] ]! ) [58_8_26] type [58,8,26]; (* continued from earlier *); [b] := Cyclic( {6,12,4,12,12,6,6}, 58, 8, 000101011110110100100010000001111100110101100000110111101 ); (* [b] is redundant *); [E1..4] := PertTwo( {1000001000000010011111010011100101110101000110001010011101,01000010110010111110 11001110001001101110100011110010101100,00100000110101010100101110001010001010110 11010010101100101,0001001101011010110010100111010001011010101010010101011001,000 0101110011101001110100110101101000010010101010001000110,000001111100000000001111 1111111100000111111111000011111111,000000000011111111111111111111110000000000000 0111111111111,0000000000000000000000000000000011111111111111111111111111} ); [f] := {1000001011010010000011011011111000100110101011001010111100,01000100110011000010 10101111000100011100110101100110101011,00100100100101100111001101101000100010001 11010011010011001,0001001001001110010000111000110011110000111011100011100001,000 0111011000001001111111000001111110000000111100000011111,000000011100011100000000 0111111111110000000000011111111111,000000000011111100000000000000000000111111111 1111111111111,0000000000000000111111111111111111111111111111111111111111}; [g] := Act( { (1,7)(2,4)(5,6), (2,7)(3,5)(4,6), (8,9)(1) }, {000000011, 000000111,000010111,000100111,000111011,001101100,001111100,011011100, 111111100} ); (* this code is generalized-cyclic *); DUAL_ORBIT([i], [105_8_50.a], ![$3]!, ![00001010,00011001,00011101,00101110,00110110,00111010,01000001,01010000, 01010110,01011111,01101000,01110100,10110010]!) DUAL_ORBIT_CH([j], [105_8_50.a], ![$3]!, ![00010101,00011010,00011100,00101110,00101111,00111000,00111001,00111010, 00111111,01000000,01010110,10110010]!) (* [j] is redundant *); DUAL_ORBIT([k], [105_8_50.a], ![$3]!, ![00000011,00010010,00010100,00010101,00011010,00011100,00011101,00110011, 00111001,01010110,01011101,01101000,01110011]!) DUAL_ORBIT_CH([l], [105_8_50.a], ![$3]!, ![00010101,00010111,00011100,00100000,00100001,00100011,00101110,00110011, 00111111,01011101,01110011,01110100]!) DUAL_ORBIT([n], [105_8_50.b], ![$3]!, ![00000010,00000011,00000111,00001100,00010000,00010001,00011110,00111010, 00111100,01010011,01100000,01110010,11001110,11110101]!) DUAL_ORBIT_PLUS([y], [140_8_68.a], ![$13,$14,$16]!, ![00000111,01000000,01000010,01001001,01001010,10000000,10010111,10111111, 11000000,11000001,11001110,11001111,11010100]!, ![+ column 33]!) DUAL_ORBIT([A], [105_8_50.a], ![$3]!, ![00000001,00000111,00001101,00010001,00010100,00101101,00101110,00110011, 00110110,01010000,01010001,01110011,10010111]!) DUAL_ORBIT([B], [105_8_50.a], ![$3]!, ![00010001,00010100,00011110,00100001,00100011,00110110,00111001,00111010, 00111110,01000000,01000001,11111111]!) DUAL_ORBIT_PLUS([F], [42_8_18.a], ![$1,$2]!, ![00000001,00000010,00000100,00001010,00010001,00011111,00100100,00111011, 01011001,01011010,01110111,11100000]!, ![+ column 50]!) DUAL_ORBIT_CH([H], [89_8_42.b], ![$1,$2]!, ![00000110,00001011,00001100,00011011,00011111,00100010,00100100,00110001, 00110111,01001100,01110001,01111110,10001010]!) DUAL_ORBIT([J], [112_8_54.a], ![$4]!, ![00000010,00000110,00001101,00010001,00010110,00011001,00100011,00101001, 00110111,01010101,01011111,10000111,10010000]!) DUAL_ORBIT([K], [147_8_72.c], ![$4]!, ![00000010,00000111,00001000,00011010,00101000,10000101,10010001,10010010, 10011011,10110000,10110110]!) DUAL_ORBIT([N], [147_8_72.c], ![$4]!, ![00000011,00001000,00001110,00011010,00101000,10000010,10001100,10001110, 10011010,10100000,10110110]!) DUAL_ORBIT([P], [147_8_72.c], ![$4]!, ![00000011,00011010,00100110,00101000,01101111,10000001,10000010,10011010, 10100000,10100110,10110110]!) DUAL_ORBIT([Q], [147_8_72.c], ![$4]!, ![00000001,00000010,00000100,00000101,00001100,10000011,10001000,10101110, 10110000,10110110,10111000]!) (* [Q] is isomorphic to [m14] *); DUAL_ORBIT([T], [68_8_32.b], ![$1,$4]!, ![00000001,00000100,00001010,00001100,00011000,00011010,00011110,00100001, 10000101,10001000,10001011,10011111,10110100]!) DUAL_ORBIT_PLUS([W], [108_8_52.a], ![$5]!, ![00000001,00000100,00000111,00001001,00001100,00100001,00100011,00100100, 01011011,01011100,01110010,10010011,10100101]!, ![+ column 24]!) DUAL_ORBIT([X], [65_8_30.c2], ![$1,$2]!, ![00000010,00000100,00001000,00001111,00010011,00100010,00100111,00101110, 00110101,01000001,01011100,01110100,01111010]!) DUAL_ORBIT([AA], [65_8_30.c3], ![$2,$3]!, ![00000001,00000010,00000100,00001010,00010001,00101110,01000101,01110111, 10001010]!) (* [AA] is redundant *); [a1..12] := [61_8_28.a] - dual word of weight 3; [b1..12] := [61_8_28.b] - dual word of weight 3; [c1..16] := [61_8_28.c] - dual word of weight 3; [d1..15] := [61_8_28.d] - dual word of weight 3; [e1..17] := [61_8_28.e] - dual word of weight 3; [f1..14] := [61_8_28.f] - dual word of weight 3; [g1..18] := [61_8_28.g] - dual word of weight 3; [h1..12] := [61_8_28.h] - dual word of weight 3; [i1..16] := [61_8_28.i] - dual word of weight 3; [j1..16] := [61_8_28.j] - dual word of weight 3; [k1..4] := [61_8_28.k] - dual word of weight 3; [l1..17] := [61_8_28.l] - dual word of weight 3; [m1..15] := [61_8_28.m] - dual word of weight 3; [n1..21] := [61_8_28.n] - dual word of weight 3; [B1..300000] := PertTwo( [58_8_26.b], ex triples, stop after 300000 codes ); note: This calculation takes about 70 days of CPU time. A total of 180721 codes were processed (and #180722 was partially processed) before finding #300000.; [J1..1000] := PertTwo( [58_8_26.j], ex triples, stop after 1000 codes ); [M1..7] := PertTwo( [105_8_50.b]^T using {$3 : 00000010,00000011,00000110,00001001,00010000,00010100,00010101,00100111, 00111011,00111111,01010000,01011000,11001110} + check ); [S1..46] := PertTwo( [45_8_20.c]^T using {$1,$2 : 00001000,00001010,00010001,00100000,00100011,00100100,00100101, 01000101,01000110,01011001,10111111} + check ); [U1..6] := PertTwo( [45_8_20.c]^T using {$1,$2 : 00000101,00000111,00001000,00001010,00101010,00110100,01000101, 01000110,01011001,01111101,10111111} + check ); [C1..2000] := PertTwo( [105_8_50.a]^T using {$3 : 00000001,00001101,00010011,00011001,00100001,00101111,00110011,00111001, 00111111,01010000,01110011,10010111,10110010}, ex triples, stop after 2000 codes ); [D1..500] := PertTwo( [105_8_50.c]^T using {$2,$4 : 00000100,00000101,00000111,00001000,00001001,00010011,00111101,10000111, 10001000,10001001,10001011,10100001,10101111,10110111,10111001,11000011}, ex triples, stop after 500 codes ); disjoint [E1..4], [f], [g], [i], [k], [l], [n], [y], [A], [B], [F], [H], [J], [K], [N], [P], [T], [W], [X], [a1..12], [b1..12], [c1..16], [d1..15], [e1..17], [f1..14], [g1..18], [h1..12], [i1..16], [j1..16], [k1..4], [l1..17], [m1..15], [n1..21], [B1..300000], [J1..1000], [M1..7], [S1..46], [U1..6], [C1..2000], [D1..500]; status: realizable; (* The following code is superceded by the [165,9,80]. *); [167_9_80] type [167,9,80]; DUAL_ORBIT_PLUS([b], [242_9_118.a], ![$4,$5]!, ![000000010,000000101,000001010,000001111,000100000,000100011,000101001, 001000000,001110000,111111111]!, ![+ column 166]!) DHIDE( ![ OE(26)#, D1# done for [a]; D3(28).7#(but only 1 orbit checked) for [a] ]! ) DHIDE( ![ tried PertTwo( [a], [b], [c], [e], [g], [h], [i], [j], [k], [l], [m], [n], [a1..2] ) ]! ) [76_9_34] type [76,9,34]; credit: existence due to Boukliev; [a] := Cyclic( {15,15,15,15,15}, 76, 9, 000010000011110001001110111001000001101 1110110101010001001000111101110111101 ); [b] := Cyclic( {9,9,9,9,9,9,9,9,3}, 76, 9, 010000000000100101000001111010101110 0110001110111010110111011110011111010111 ); [c] := Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000001,000001111,000110111,001000111,001111111,011010111} ) + check; [d1..37] := PertTwo( Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000001110,000001111,000010011,000011001,001000011,001000111,001001011, 001111111} ) + check ); [e] := Cyclic( {9,9,9,9,9,9,9,9,3}, 76, 9, 010101101000000101001000100011011100 0110100110101000100000110010110111010111 ); [f1..20] := PertTwo( [79_9_36.a] - columns {20,47,64,79} + check ); [g] := Cyclic( {10,10,10,10,10,10,5,10}, 76, 9, 0100110100010001011000101101000 110000101011011010101001011110110100101011111 ); [h] := Cyclic( {10,10,10,10,10,5,10,10}, 76, 9, 0100100000011111010001010100100 111110010010111101001110010101111001111111101 ); [i] := Cyclic( {10,10,10,10,10,10,5,10}, 76, 9, 0110000000010001000001111110000 100101100010101001001011101100111001111111011 ); [j] := Cyclic( {9,9,9,9,9,3,9,9,9}, 76, 9, 010000000010100000011100000011010100 0111011000100111110100101101100101111101 ); [k] := Cyclic( {9,9,9,9,9,9,9,3,9}, 76, 9, 010001010000001110000101100000001111 0011011010111011010001011110110111111111 ); [l] := Cyclic( {9,9,9,9,9,9,9,9,3}, 76, 9, 010010100010100000010001100011100101 0011111010011011010111011010111101110111 ); [m] := Cyclic( {9,9,9,9,9,9,9,3,9}, 76, 9, 010110001011111011011001110000111100 0010100100011111100111110100100111111011 ); [n] := Act( { (1,2)(3,5)(7,9), (1,3)(2,5)(6,8), (1,2)(3,9)(4,6)(5,7) }, {000010101,000011110,000111011,000111110,001010111,010010110,010011110, 010011111,011010111,011011100} ) + check; [o] := Act( { (1,2)(3,4)(6,8)(9), (1,4,3,2)(5,8,7,6), (1,8)(2,7)(3,6)(4,5) }, {000000011,000100110,000101001,000111001,000111010,000111111,001101110, 010101011,011111110} ); [p] := Act( { (1,2)(3,4)(6,8)(9), (1,4,3,2)(5,8,7,6), (1,8)(2,7)(3,6)(4,5) }, {000001110,000100111,000111111,001110101,001110111,001111010,010111111, 011110111,011111110} ); [a1..2] := [79_9_36.a] - dual word of weight 3; disjoint [a], [b], [c], [d1..37], [e], [f1..20], [g], [h], [i], [j], [k], [l], [m], [n], [o], [p], [a1..2]; status: realizable; [74_8_34] type [74,8,34]; credit: existence due to Amir Said; note: PertTwo( [74_8_34.H1] ) consists of over 64,000 codes, but only 100 are shown here.; [a] := Cyclic( {2,8,8,8,8,8,8,8,8,8}, 74, 8, 01010110011111000101000110011100001111110110101000010000010000101110011101 ); [b] := Cyclic( {8,8,8,8,8,8,8,8,8}, 74, 8, 01001000010001111100101010001111001101110111100100001000010011110011000111 ); [c] := Cyclic( {8,8,8,8,2,8,8,8,8,8}, 74, 8, 11111100011010100111000100111010100011110111001000111000110111111111011010 ); [d] := Cyclic( {8,8,8,8,2,8,8,8,8,8}, 74, 8, 01111110010100111110001001000111101000100110101000000011011110001100111000 ); [e] := Act( { (1,2,3,4,5,6,7,8)(9) }, {000101110,000110111,000111010,001011011, 001100111,001101010,001111110,010101010,010111111,011011111,011101111} ); [f] := {10000010110010101001010101100100100000011110110010101011010110110101000011,0100 0100110001110000101011010101111000010100111001100010001100011001101011,001001001 01010111000110011100110110101001100010001110100110011001000011001,00010010011001 111000111100000111000110001111100001111000111100001111100001,0000111011100010010 0000011111111000001111111100000000111111100000000011111,000000011110000111000000 00000000111111111111100000000000000011111111111111,00000000000111111100000000000 000000000000000011111111111111111111111111111,0000000000000000001111111111111111 1111111111111111111111111111111111111111}; [g] := {10100001111000001111001011001000011100010100011010101001001101100110011001,0110 0100001110010101100000101111010101000011111100000111010110011000111010,000101001 10010010001011001001100111011000100110011001011010110101001001011,00001000101101 001110100010110011001000110101010011010011000111101011000011,0000001111111100001 1111000011110001111110001111110011111100001111100001111,000000000000001111111110 00000001111111110000000001111111100000000011111111,00000000000000000000000111111 111111111110000000000000000011111111111111111,0000000000000000000000000000000000 0000001111111111111111111111111111111111}; [H1..100] := PertTwo( [84_8_40.a] - columns {4,19,27,40,48,50,52,55,59,62,79} + check, stop after 100 codes); DUAL_ORBIT([k], [105_8_50.a], ![$3]!, ![00000001,00000011,00000111,00001011,00010000,00010111,00011001,00011010, 00100011,00101101,00110110,00111110,01000001,01010000,01101000,10110010, 11111111]!) DUAL_ORBIT_PLUS([l], [105_8_50.a], ![$3]!, ![00000100,00000101,00001101,00010111,00011001,00011011,00100000,00100011, 00101111,00110110,00111111,01010110,01011101,01110011,01110100,11111111]!, ![+ column 73]!) [N1..10] := PertTwo( [105_8_50.a]^T using {$3 : 00000001,00010001,00010110,00011110,00100000,00100001,00100011,00110001, 00110110,00111000,00111001,00111111,01010000,01010110,10010001,11111111} + column 73, stop after 10 codes ); DUAL_ORBIT([o], [105_8_50.a], ![$3]!, ![00000110,00000111,00001011,00010000,00010101,00011100,00100000,00110001, 00110110,00111010,01000000,01010001,01011101,01101000,01110100,10010111, 10110010]!) [P1..2] := PertTwo( [105_8_50.a]^T using {$3 : 00010001,00010010,00010100,00010101,00100000,00100001,00100011,00101101, 00111010,00111011,00111110,01010001,01011101,10010111,10110010} + check ); DUAL_ORBIT_CH([s], [105_8_50.a], ![$3]!, ![00000011,00001001,00001010,00010000,00010011,00010100,00010101,00010111, 00100011,00111000,00111001,00111111,01000000,01010110,01101000,10110010]!) DUAL_ORBIT_CH([t], [105_8_50.a], ![$3]!, ![00000001,00000110,00001010,00001101,00010000,00010101,00010110,00011011, 00011110,00110001,00111001,00111011,01010001,01010110,01011111,01101000]!) DUAL_ORBIT_CH([u], [105_8_50.a], ![$3]!, ![00010100,00010101,00010110,00011010,00011100,00101111,00111011,01000000, 01000001,01010000,01011111,01110011,01110100,10010001,10110010,11111111]!) DUAL_ORBIT_CH([w], [105_8_50.a], ![$1,$2]!, ![00000111,00001100,00010000,00010110,00011100,00011101,00011110,00100100, 01100011,01111000,11100100,11101111]!) DUAL_ORBIT_CH([x], [105_8_50.a], ![$1,$2]!, ![00000001,00000011,00000111,00001011,00010011,00100101,00101111,00110100, 01100011,01101000,01111000]!) DUAL_ORBIT_CH([bb], [105_8_50.b], ![$3]!, ![00000001,00000101,00001001,00001010,00001101,00010000,00011110,00100111, 00111100,00111110,01011000,01011001,01100001,11001100,11001111]!) DUAL_ORBIT([dd], [105_8_50.b], ![$3]!, ![00000001,00000010,00000011,00000101,00001001,00001111,00010010,00011100, 00011111,00101101,00111101,01010000,01010001,01011000,01110010,11001101, 11001111]!) DUAL_ORBIT_CH([ee], [105_8_50.b], ![$3]!, ![00000001,00000011,00000100,00001010,00001101,00001111,00010101,00011110, 00100110,00100111,00111011,00111101,00111110,00111111,01010001,11001100, 11110100]!) [gg] := Act( { (1,2,3,4,5,6,7,8)(1) }, {00011001,00100101,00101111,00110111, 00111101,00111111,01010101,01010111,01011111,01111111} ); (* this code is generalized-cyclic *); [hh1..10] := PertTwo( [45_8_20.c]^T using {$1,$2 : 00000101,00000111,00001010,00010110,00011101,00100000,00100001,00100111, 00101000,00110000,00111011,01000101,01001111,01101011,10111111}, stop after 10 codes ); DUAL_ORBIT([ii], [45_8_20.c], ![$1,$2]!, ![00000011,00000101,00001101,00010110,00011101,00100000,00100001,00100011, 00101001,00101011,01000101,01001011,01011001,01111101,10111111]!) [jj1..10] := PertTwo( [45_8_20.c]^T using {$1,$2 : 00000010,00000111,00001000,00001001,00001101,00010011,00100001, 00100100,00101011,00110000,00110011,00110111,01000110,01011001,01111101}, stop after 10 codes ); DUAL_ORBIT([kk], [45_8_20.c], ![$1,$2]!, ![00000001,00000010,00000101,00001000,00001001,00001111,00010011,00100001, 00110000,00110011,00110100,00110111,01000110,01001011,01001111]!) DUAL_ORBIT([ll], [45_8_20.c], ![$1,$2]!, ![00000011,00000110,00001000,00010001,00010110,00011101,00100001,00101000, 00101100,00101111,00110100,01000110,01001111,01110111,01111101]!) DUAL_ORBIT([mm], [45_8_20.c], ![$1,$2]!, ![00000010,00001010,00001111,00010011,00010110,00100001,00100111,00101011, 00101111,00110000,00111000,00111011,00111111,01000101]!) DUAL_ORBIT([nn], [45_8_20.c], ![$1,$2]!, ![00000110,00001001,00001010,00001101,00010001,00011101,00100001,00100101, 00101001,00110111,00111001,00111111,01001111,01011001,01111101]!) DUAL_ORBIT([oo], [45_8_20.c], ![$1,$2]!, ![00001000,00001001,00001101,00010011,00010110,00011101,00100000,00100001, 00100011,00101111,00110011,01000101,01001011,01011001,01101000]!) DUAL_ORBIT([pp], [45_8_20.c], ![$1,$2]!, ![00000101,00000110,00000111,00001101,00010110,00100000,00100001,00101000, 00101011,00111011,01000101,01000110,01101011,01110111]!) DUAL_ORBIT([qq], [45_8_20.c], ![$1,$2]!, ![00000001,00000011,00000111,00001000,00010110,00100000,00100001,00100111, 00101111,00110100,00111011,00111100,01001111,01011001,10111111]!) DUAL_ORBIT([rr], [45_8_20.c], ![$1,$2]!, ![00000010,00001001,00100000,00100001,00100100,00101011,00101100,00101111, 00110011,00111011,00111100,01011001,01101011,01111101,10111111]!) DUAL_ORBIT([ss], [45_8_20.c], ![$1,$2]!, ![00000111,00001000,00001010,00010001,00010110,00100001,00100011,00100101, 00101000,00101100,00110011,01000110,01001011,01111101]!) DUAL_ORBIT([tt], [45_8_20.c], ![$1,$2]!, ![00000010,00000101,00001000,00010011,00100001,00110000,00110011,00110111, 00111000,00111011,00111100,00111111,01011001,01111101]!) DUAL_ORBIT([uu], [45_8_20.c], ![$1,$2]!, ![00000010,00000101,00000110,00001000,00001001,00001010,00001111, 00010011,00100001,00111000,00111100,00111111,01001111,01111101,10111111]!) DUAL_ORBIT([vv], [45_8_20.c-43], ![$1,$2]!, ![00000010,00001001,00001010,00100001,00100100,00101011,00101111, 00110000,00110011,00110111,00111000,00111111,01000101,01000110,01011001]!) DUAL_ORBIT([ww], [45_8_20.c-43], ![$1,$2]!, ![00000001,00000101,00001001,00011101,00100001,00100011,00101100, 00110011,00110100,00110111,00111011,01001011,01110111,01111101]!) DUAL_ORBIT([yy], [45_8_20.c-43], ![$1,$2]!, ![00000010,00000011,00001001,00011101,00100000,00100001,00100100, 00101001,00101111,00110111,00111111,01000110,01101000,01101011,01111101]!) DUAL_ORBIT_PLUS([1], [140_8_68.a], ![$13,$14,$16]!, ![00001111,00010111,01001011,01001110,01111111,10000010,10000111,10001010, 10010100,11001110,11010010,11010100,11010111,11111111]!, ![+ column 25]!) DUAL_ORBIT_CH([2], [140_8_68.a], ![$13,$14,$16]!, ![00001111,00010111,01000001,01000010,01001001,01001110,01010010,10000000, 10000111,10001011,10111111,11000000,11000010,11000111,11001010,11001011]!) DUAL_ORBIT_CH([3], [140_8_68.a], ![$13,$14,$16]!, ![00001110,00001111,01000111,01001010,01010010,01010100,01111111,10000000, 10001001,10001111,10010111,11000010,11000111,11010100,11010111,11111111]!) [4] := Act( { (2,4)(5,6), (1,8)(2,6,4,5), (2,5)(3,6) }, {00000001,00000010,00000110,00011001,00011011,00011101,00111101,01111100, 01111111,10000001,10000011,10000101,10011111,10111111} ) + column 28; DUAL_ORBIT_CH([6], [140_8_68.f], ![$3,$4]!, ![00000111,00001000,00001001,00001011,00001100,00010011,00100111,00101000, 00101101,00110000,00110001,10001000,10101001,10111011,10111110,11011111]!) DUAL_ORBIT_PLUS([7], [105_8_50.a], ![$3]!, ![00000101,00000110,00000111,00010001,00010101,00010111,00011010,00101110, 00101111,00110110,00111010,00111111,01000000,01010000,10010111]!, ![+ column 43]!) DUAL_ORBIT_PLUS([8], [105_8_50.a], ![$3]!, ![00000100,00000110,00000111,00001001,00001011,00010101,00011100,00011110, 00100000,00101110,00101111,00111001,00111111,01010110,10010111]!, ![+ column 48]!) DUAL_ORBIT([9], [105_8_50.a], ![$3]!, ![00000011,00000111,00010000,00010010,00010100,00011001,00011011,00011100, 00100000,00100001,00100011,00101111,00111110,01010001,01101000,10010111]!) DUAL_ORBIT([10], [105_8_50.c], ![$2,$5]!, ![00000101,00001110,00011110,00011111,00100101,00101000,00101100,10000000, 10001000,10001001,10001100,10010100,10011001,10100010,10100110,10101010, 10111001]!) DUAL_ORBIT([11], [99_8_48.a], ![$3,$4]!, ![00000001,00001010,00001101,00011101,00111100,00111111,01001010,01001011, 01011010,01011110,01101000,01101110,11001100,11001101]!) DUAL_ORBIT([12], [99_8_48.a], ![$3,$4]!, ![00000111,00001000,00001001,00001101,00011000,00011001,00111100,00111101, 00111111,01001101,01001110,01001111,01101000,11001000]!) DUAL_ORBIT_CH([13], [77_8_36.e], ![$2,$3]!, ![00000101,00000111,00001101,00010010,00010110,00011111,00100011,00101001, 00110010,00110100,01000111,01001111,01010101,01011100,01011110,01100110, 11110111]!) DUAL_ORBIT([14], [61_8_28.f], ![$1,$2]!, ![00001000,00010100,00010111,00011011,00100001,00100011,00101000,00101100, 00111001,00111101,01000001,01000011,01010000,01110111]!) DUAL_ORBIT([16], [112_8_54.b24], ![$1,$2]!, ![00000001,00000010,00000101,00000110,00001001,00001010,00001101,00001110, 01000001,01011011]!) DUAL_ORBIT([17], [112_8_54.b24], ![$1,$2]!, ![00000101,00000110,00000111,00001001,00001010,00001110,00010011,00011011, 00110000,01011011]!) DUAL_ORBIT([18], [112_8_54.b24], ![$1,$2]!, ![00000010,00000101,00000110,00001001,00001010,00010011,00011011,00111010, 01000001,01011011]!) [19] := Act( { (2,4)(6,8)(9), (1,4)(5,8), (1,4,3)(5,8,7), (1,8,3,6)(2,5,4,7) }, {000001110,000011110,000101110,000111100,000111110,001101110} ); DUAL_ORBIT([20], [112_8_54.b24], ![$1,$2]!, ![00000001,00000010,00000111,00001010,00001011,00010010,00011011,00111010, 01011110,01101001]!) DUAL_ORBIT_CH([21], [147_8_72.c], ![$4]!, ![00000011,00000101,00001000,00001110,00010100,00011000,00100110,01101111, 10000001,10000010,10001110,10011010,10011011,10101110,10110000]!) DUAL_ORBIT_CH([22], [147_8_72.c], ![$4]!, ![00010100,00010101,00100110,00101110,01101111,10000000,10001000,10001100, 10001110,10010001,10010011,10011010,10101000,10110110]!) DUAL_ORBIT_CH([23], [147_8_72.c], ![$4]!, ![00000010,00000011,00001011,00001100,00001110,01100111,10000000,10000010, 10001000,10001010,10010010,10100110,10101110]!) DUAL_ORBIT_CH([24], [147_8_72.c], ![$1,$3]!, ![00000001,00000110,00001010,00011011,01000001,01000011,01001010,01100000, 01101111,10000101,10010001,11000010,11001000,11001001,11001101,11100000]!) DUAL_ORBIT_CH([25], [147_8_72.c], ![$1,$3]!, ![00001000,00010011,00011101,00011111,01001000,01001100,01001110,01101111, 10010011,10011001,10011101,11000010,11001000,11100000,11100010]!) DUAL_ORBIT_CH([26], [147_8_72.c], ![$1,$3]!, ![00000010,00000101,00001000,00011001,01001000,01001110,01100000,01101111, 10000001,10000101,10010010,11000000,11001001,11100000,11100010]!) DUAL_ORBIT([27], [175_8_86.a], ![$4]!, ![00000011,00000100,00100000,00100010,00100101,00101011,00110001,00111111, 01011010,01011111,01100000,01100001,11111111]!) DUAL_ORBIT_CH([28], [175_8_86.a], ![$4]!, ![00000001,00000100,00000111,00100010,00100101,00101000,00101011,01011010, 01011111,01100000,01100001,11111111]!) [29] := Act( { (1,2,3,4,5,6,7,8)(9) }, {000101111,000111011,001011011,001100111, 001111110,001111111,010101010,010111110,010111111,011011110,011101111} ); DUAL_ORBIT([30], [68_8_32.b], ![$1,$3,$4]!, ![00000001,00000110,00001111,00010101,00011000,00011101,00101000,00101010, 00111001,01000000,10000000,10000010,10001000,10001001,10001011,10110100]!) DUAL_ORBIT_PLUS([32], [108_8_52.a], ![$5]!, ![00001000,00001010,00001011,00001100,00010011,00100000,00100100,00101001, 00101101,00101110,00110001,01011100,01110010,10000001,10001110,10110111, 11111111]!, ![+ column 13]!) [U1..8] := PertTwo( [150_9_72.j] - columns {20..42,64..93,115..137} ); [34] := [150_9_72.j] - columns {11..19,29..42,55..63,73..78,84..93,102..114, 128..137,146..150}; [35] := [150_9_72.j] - columns {6..10,15..19,26..28,36..42,51..54,60..63, 66..72,76..81,84..87,94..97,102..110,115..120,128..134,138..141,146}; [36] := [150_9_72.j] - columns {6..14,26..35,51..59,66..75,82..87,98..110, 121..134,142..146}; [37] := [150_9_72.j] - columns {5,8,9,12,14,16,19,20,23,25..27,30,33,34,36,38, 39,42,44,45,47,48,50,51,55,57,59,60,63,65..67,69,71,75,76,78,79,83,84,86, 88,90,92..94,96,97,99,102,103,105,107,108,112,114..116,119,122,125..128, 131,133,136..138,140,141,143,146,148,149}; [V1..8] := PertTwo( [150_9_72.j] - columns {5,8,9,11,13,15,17,18,20,23,25..27, 29,31,32,35,37,40,41,44,45,47,48,50,51,56,58,61,62,65..67,69,71,73,74,77, 80..82,84,86,88,90,92,93,95,98,100..103,105,107,108,112,114,117,118,120, 121,123,124,128,131,133,136,137,139,142,144..146,148,149} ); [W1..8] := PertTwo( [150_9_72.j] - columns {5,8,9,11,13,15,17,18,20,23,25..27, 29,31,32,35,37,40,41,43,46,49,52..55,57,59,60,63,64,68,70,72,75,76,78, 80..82,84,86,88,90,92,93,95,98,100..103,105,107,108,112,114..116,119,122, 125..127,129,130,132,134,135,138,140,141,143,147,150} ); [X1..8] := PertTwo( [150_9_72.j] - columns {3,4,7,10,12,13,16,18,21..23,25,27, 29,31,32,37,40,42,44,45,47..49,51,55,57,58,60,62,64,65,68,69,71,75,76,78, 80,82,83,85,86,89,92..94,99..103,105,109,110,112,113,117,119,121,123, 125..127,129..131,133,135,137,138,143..145,148,150} ); [a1..32] := [77_8_36.a] - dual word of weight 3; [b1..32] := [77_8_36.b] - dual word of weight 3; [c1..36] := [77_8_36.c] - dual word of weight 3; [d1..31] := [77_8_36.d] - dual word of weight 3; [e1..19] := [77_8_36.e] - dual word of weight 3; [f1..36] := [77_8_36.f] - dual word of weight 3; [g1..22] := [77_8_36.g] - dual word of weight 3; [h1..36] := [77_8_36.h] - dual word of weight 3; [i1..33] := [77_8_36.i] - dual word of weight 3; [j1..32] := [77_8_36.j] - dual word of weight 3; [k1..32] := [77_8_36.k] - dual word of weight 3; [l1..32] := [77_8_36.l] - dual word of weight 3; disjoint [a], [b], [c], [d], [e], [f], [g], [H1..100], [k], [l], [N1..10], [o], [P1..2], [s], [t], [u], [w], [x], [bb], [dd], [ee], [gg], [hh1..10], [ii], [jj1..10], [kk], [ll], [mm], [nn], [oo], [pp], [qq], [rr], [ss], [tt], [uu], [vv], [ww], [yy], [1..4], [6..14], [16..30], [32], [34..37], [a1..32], [b1..32], [c1..36], [d1..31], [e1..19], [f1..36], [g1..22], [h1..36], [i1..33], [j1..32], [k1..32], [l1..32], [U1..8], [V1..8], [W1..8], [X1..8]; status: realizable; [42_8_18] type [42,8,18]; (* continued from earlier *); note: There are large numbers of these codes. Many more can be found easily. The following weights are known to occur: 18,20,22,24,26,28,30,32,34. The following weights may or may not occur: 19,21,23,25,27,29,31,33,36,38,40.; [c1..3] := PertTwo( Cyclic( {12,12,12,6}, 42, 8, 011000110010010011101100000110101100110000 ) ); [Y1..10000] := PertTwo( [45_8_20.x1..200] - dual word of weight 3, stop after 10000 codes ); [f1..4] := [45_8_20.f] - dual word of weight 3; [h1..6] := [45_8_20.h] - dual word of weight 3; [h] := {100000101011111001010001100100101100001010,010000100001110011001011011110011011 001010,001000101010100101001000110011011101000110,000100100101000101010111010011 010010100110,000010100110110100000100011001100111110010,000001100011001110010010 110101010101101011,000000011111111111000000000000011111111111,000000000000000000 111111111111111111111111}; [i] := {100100010000110101011000110101001001001101,010000011010110001010101101011100100 101101,001100011000011011010100011100110111000011,000010011011101011001011101100 110100110011,000001011001010010010010001010011011110101,000000111010100110011001 011001010111011001,000000000111111111000000000000000111111111,000000000000000000 111111111111111111111111}; [j] := {100000101000100111000110110001110101100100,010000000011000111001110000111111000 111000,001000100011101010000101001100110110011100,000100101010010001001001011010 110010110110,000010000110011011010011010110001011001010,000001100110100100010000 101001101011110101,000000011111111111000000000000011111111111,000000000000000000 111111111111111111111111}; [l] := {100001001011001011010101101010001101001000,010001001100110011011010010110001110 110100,001001001101111101001011010000111000000001,000101001011110100011010101010 011011000110,000011000001111110011110001001100000110100,000000101011010010010111 100100110000101110,000000010100101101010111100100001111010001,000000000000000000 111111111111111111111111}; [m] := Act( { (1,3,2)(4,10,6)(7,9,8), (1,3,2)(5,8,6)(7,10,9) }, {0110011011,0110111111} ); [o] := Act( { (1,7)(2,4)(5,6), (2,7)(3,5)(4,6), (8,9)(1) }, {000000111,000010111,000101100,001110111,001111111,011011100} ); [v] := {100000010001101111001100110010101010101000,010000010010101011110010011100110101 101001,001000010101010000111111100000111001101000,000100010110000111010001110011 111100001110,000010010011011001011011000110101110110010,000001010011011010100100 111001011110110010,000000110000000011111100000000001111111111,000000001111111111 111111111111111111111111}; [y] := {100000110010000111000101011110000000111011,010000010000010111101010010001101110 101010,001000101001101011110101011100010001001101,000100101000101010011010010110 101010101001,000010001010110001010011001110100001111100,000001011010011000110110 011011110011001010,000000000111111111111111000000000111111111,000000000000000000 000000111111111111111111}; [z] := {100000101110110110100001111010110000110111,010000101011011000000010010100110111 101010,001000101011000110110100100111111100000011,000100101111000011000011100011 111001101100,000010101000100001110101010111001010011010,000001100111101101000110 001011010010001001,000000011111111111110000000000011111111111,000000000000000000 001111111111111111111111}; [bb] := {100001001000111001011100100010111000011001,010000000101010111010100110110001001 010101,001000000111011010011010110011011010001110,000100001011011001000110111010 100001111110,000011000110101100010111000111110101000101,000000100110100011010111 011000010101011010,000000011111111111000000000000011111111111,000000000000000000 111111111111111111111111}; [cc] := {100001001011001011100111011001110110100101,010001100010100110010001001000101110 110101,001001000111101100101010001010011100111100,000100100100101001100011000101 101110001110,000011100110001100000111010100111011111000,000000011111100000111111 001111100000011111,000000000000011111111111000000011111111111,000000000000000000 000000111111111111111111}; [dd] := {101000001010101100100101110111000100000110,011001001001100111101001001001001010 001100,000100011001001110100000110101001011011001,000011010001001010010101100111 100010110010,000000110001100011110000101011010001111100,000000000111100000111100 000111111000001111,000000000000011111111100000000000111111111,000000000000000000 000011111111111111111111}; [M1..38] := [45_8_20.{a,b,c,d,e,g,i,j}] - dual word of weight 3; [11x1..200] := PertTwo( [84_8_40.c] - columns {1,7,8,13,16..18,20,23,25,26,28, 29,32,39,40,42,43,45,46,50,51,56,57,60,61,63..68,70,72,73,75..77,80..82, 84}, stop after 200 codes ); DUAL_ORBIT([13], [105_8_50.b], ![$3]!, ![00000011,00000101,00001100,00010001,00100110,00100111,00111101,01010011, 11001100,11001110,11110101]!) [18x1..3] := PertTwo( [105_8_50.a]^T using {$3:00000110,00011001,00011101, 00011110,00110110,01000000,01011101,01011111,01110100} ); DUAL_ORBIT([20], [105_8_50.a], ![$3]!, ![00010001,00010111,00100000,00100001,00111010,01010000,01011101,01110011, 10010001]!) DUAL_ORBIT([22], [77_8_36.a], ![$1,$2]!, ![00001011,00010000,00010011,00101111,00110000,00111010,01010001,01011001, 01101100]!) [23x1..200] := PertTwo( [77_8_36.b]^T using {$2:00000010,00000011,00001010, 00001110,00010000,00010101,00011001,00101110,01010110}, stop after 200 codes ); [24x1..200] := PertTwo( [77_8_36.b]^T using {$1,$2:00010100,00011001,00011111, 00100001,00111011,01000101,01001110,01010010,01011011}, stop after 200 codes ); [26x1..4] := PertTwo( [77_8_36.b]^T using {$1,$2:00000010,00001011,00001101, 00010000,00010100,00101100,01010110,01110010,11001110,11011011} + column 3 ); DUAL_ORBIT([27], [77_8_36.c], ![$1,$2]!, ![00000010,00000101,00001001,00001100,00010010,00010110,00111101,01100010, 01101111]!) DUAL_ORBIT([29], [61_8_28.d], ![$1,$2]!, ![00000101,00001000,00001111,00011000,00011101,00011110,00100011, 00110000]!) DUAL_ORBIT([30], [61_8_28.f], ![$1,$2]!, ![00000010,00001000,00001111,00010010,00010100,00101001,01000011, 01101111]!) DUAL_ORBIT([34], [147_8_72.c], ![$2,$5]!, ![00001100,00001101,00010100,01000101,10000100,10001011,10111011]!) [39] := [58_8_26.n] - columns {3,5,7,8,13,19,22,29,30,38,40..42,46,52} - column 2; [40] := [58_8_26.C1] - columns {4,6..9,12,18,22..24,27,28,31,42,49,55}; [43] := [74_8_34.N1] - columns {5,6,8,10,15,17,20,21,25,28,30,32,33,35..37, 41..43,46..49,54,59,60,62,67,68,71,73,74}; [44x1..3] := PertTwo( [74_8_34.22] - columns {2,3,5,8,11..13,15,16,24..29, 32..36,39..43,45,48,53,55,59,62,68,73} + check ); disjoint [c1..3], [h], [i], [j], [l], [m], [o], [M1..38], [v], [y], [z], [bb], [cc], [dd], [11x1..200], [13], [20], [22], [27], [29..30], [34], [39..40], [43], [f1..4], [h1..6], [18x1..3], [23x1..200], [24x1..200], [26x1..4], [44x1..3], [Y1..10000]; status: realizable; data_comment( ![ More {\bf nine-dimensional codes} are given below. ]! ) [307_9_152] type [307,9,152]; DUAL_ORBIT([a], [18_9_6x.a], ![$1,$2]!, ![000001000,000011011,100000000, 100000010,100001011,100001111,100101011,111111111]!) status: realizable; (* The following codes should be removed because there exists a [96,10,44] code. *); [96_9_44] type [96,9,44]; DUAL_ORBIT([a], [307_9_152.a], ![$6,$7]!, 000000100) DUAL_ORBIT([b], [96_9_44.a], ![$10,$12]!, ![000011100,001010111,010000110, 010010010,010011100,010110110]!) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a], [b] ]! ) DHIDE( ![ D1.7#(allowing length up to 256) done for [a] ]! ) [189_9_92] type [189,9,92]; (* continued from earlier *); DUAL_ORBIT([b], [193_9_94.b2], ![$2,$3]!, ![000000011,000001010,000001011,000001101,000010010,000010110,000010111]!) alt Act( { (2,7)(4,6)(8,9), (1,9,5,4,3,2)(6,8,7) }, {000000110,000000111, 000001111,000010101,000011011,000011111,000101111,000111011,001000111, 001001011,001001111,001011011,001011111,001101011} ); (* this code is generalized-cyclic *); disjoint [a], [b]; status: realizable; DHIDE( ![ OE(32).7#(allowing length up to 256) for [a] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [b..h] ]! ) DHIDE( ![ OE(28).7!(allowing length up to 256) done for [i..l] ]! ) DHIDE( ![ OE(25).7!(allowing length up to 256) with crazy code search for [m], [n] ]! ) DHIDE( ![ [a], [h..q] checked for "cyclic". ]! ) [175_9_84] type [175,9,84]; CREDIT(existence due to Jaffe and Simonis, jaffe simonis dual transform) DUAL_ORBIT([a], [189_9_92.a], ![$1]!, ![000100101,000101011,000110100,000111111,001010011,001010101,001100110, 001110100,001111010]!) alt Cyclic( {21,21,21,21,21,21,21,7,21}, 175, 9, 011011011101110100100010111101 00111101010001111011011010010110001101010010101111110001110101100111100101 0011010111011010101010011101100101101100110010111001101111111110101111 ); [b] := [172_9_82.a] + dual word of weight 3; (* this code is generalized-cyclic *); [c] := [189_9_92.b] - columns {1,3,9,10,52,58,130..132,135,141,143,180,182}; [d] := [189_9_92.b] - columns {2,11,13,14,53,57,59,62..64,134,142,181,189}; (* this code is generalized-cyclic *); [e] := [189_9_92.b] - columns {4,17,24,42,66,78,98,103,109,113,119,128,154,184}; [f] := [189_9_92.b] - columns {6,18,75,80,85,96,100,111,124,129,150,157,174,185}; [g] := [189_9_92.b] - columns {8,23,41,50,86,93,99,110,160,165,167,175,176,188}; DUAL_ORBIT([h], [35_9_14.b], ![$1,$2]!, ![000010100,000011010,000011111,000101110,000111001,000111110,010000010, 010110011,011111010]!) DUAL_ORBIT([i], [35_9_14.b], ![$1,$2]!, ![000001001,000010100,000011111,000101110,000111001,000111110,010000010, 010110011,011111010]!) DUAL_ORBIT([j], [35_9_14.b], ![$1,$2]!, ![000001001,000010100,000010110,000011010,000011111,000101110,000111001, 000111110,011111010]!) DUAL_ORBIT_CH([k], [35_9_14.b], ![$1,$2]!, ![000000111,000001010,000010100,000010110,000011010,000011111,000101110, 000110110,000111110,010110011]!) DUAL_ORBIT([l], [35_9_14.b], ![$1,$2]!, ![000000100,000000101,000001111,000010000,000011010,000101110,000111001, 001101100,010000010]!) DUAL_ORBIT([m], [35_9_14.b], ![$1,$2]!, ![000000100,000000101,000001010,000001111,000011010,000101110,000111001, 001101100,010110011]!) DUAL_ORBIT([n], [35_9_14.b], ![$1,$2]!, ![000000100,000000101,000001001,000001111,000011010,000101110,000111001, 001101100,010110011]!) DUAL_ORBIT_CH([o], [172_9_82.b], ![$1,$2]!, ![000000010,000001000,000010100,000011001,000011010,000101000]!) DUAL_ORBIT([p], [228_9_112.b], ![$2,$3]!, ![000000001,000000010,000000111,000001000,000001001,000001101,000001110, 000010000,000010010,000011101,000110001]!) DUAL_ORBIT_CH([q], [166_9_80.b], ![$3]!, ![000001011,000001101,000010000,000010011,000011010,000100000,000101001, 000101011,000101110,000110001,010100011,010110010,100100100,100110000, 101111010,111000101]!) DUAL_ORBIT_CH([r], [156_9_74.a], ![$1]!, ![000000110,000001111,000010011,000010110,000011111,000100100,000101101, 000111000,000111101,001001011,001010010,001011010,001111101,010110100, 011011010,011011011]!) alt Cyclic( {12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3}, 175, 9, 0000111100 00010011100101001011010000100011011010110011001111000010100101010010110000 01101001000011001001101010111011000001111000111111000110010101100011101011 01110011101000111 ); DUAL_ORBIT([s], [156_9_74.a], ![$1]!, ![000000001,000000010,000000110,000001010,000011011,000011111,000100101, 000101101,000110100,000111100,001001011,001010011,001011011,001011111, 010110100,011011010,011011011]!) alt Cyclic( {12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3}, 175, 9, 0000000100 01111111001100111110101010000011011101111100000000000100100011111010011000 11100101010000011110111100100101011111010110010000101101111111010000001010 10010100001000111 ); DUAL_ORBIT([t], [175_9_84.r], ![$3,$4]!, ![000001011,000010000,000010110,000010111,000011001,000011010,000100001, 001110111,010011001,111111111]!) (* this code is generalized-cyclic *); DUAL_ORBIT_CH([u], [175_9_84.s], ![$1,$2]!, ![000010011,000101111,001101011,100000001,100000011,100000101,100000111, 100001001,100001101,100001111,100011101,100011111,100100101,100101011, 101011011,101101011]!) (* this code is generalized-cyclic *); disjoint [a],[b],[c],[d],[e],[f],[g],[h],[i],[j],[k],[l],[m],[n],[o],[p],[q], [r], [s], [t], [u]; status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) DHIDE( ![ OE(30).7#(allowing length up to 256) done for [b] ]! ) [225_9_110] type [225,9,110]; (* to be continued later *); DUAL_ORBIT_PLUS([m], [175_9_84.l], ![$1,$2]!, ![000000100,000000101,000000111,000001001,000001110,000010110,000010111, 000011100,000100100,000101110,001000011,010101011,101111111]!, ![- column 5 - column 131]!) DUAL_ORBIT_PLUS([n], [175_9_84.l], ![$1,$2]!, ![000000100,000000101,000000111,000001001,000001110,000010110,000010111, 000011100,000100100,000101110,001000011,010101011,101111111]!, ![- column 13 - column 139]!) disjoint [a], [b], [c], [d], [e], [f], [g], [h], [i], [j], [k], [l], [m], [n]; status: realizable; DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a], [b] ]! ) [172_9_82] type [172,9,82]; (* continued from earlier *); [h1..63] := [175_9_84.h] - dual word of weight 3; [i1..64] := [175_9_84.i] - dual word of weight 3; disjoint [a], [b], [h1..63], [i1..64]; status: realizable; [186_9_90] type [186,9,90]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) [1..28] := [189_9_92.a] - dual word of weight 3; disjoint [1..28]; status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) DHIDE( ![ OE(28).7#(allowing length up to 256) done for [a],[b],[c] ]! ) DHIDE( ![ OE(28).7!(allowing length up to 256) done for [e] ]! ) DHIDE( ![ D1.7#(allowing length up to 256) done for [a] ]! ) [207_9_100] type [207,9,100]; credit: existence due to Aaron Gulliver; [a] := Cyclic(23, 207, 9, 00001000011110100001010000100110011111011010001010000 00001110111000001001011110011010110000110111000110111011011100100111111010 01001110110010100111001001100101110000110000101011000000011010110111111111 100000); credit: existence due to Aaron Gulliver; DUAL_ORBIT_CH([b], [228_9_112.c], ![$2,$4]!, ![000000110,000001010,000001110,000010100,000010110,000011000,000011100, 000011110,000100001,000111111,010001000]!) DUAL_ORBIT_CH([c], [228_9_112.c], ![$2,$4]!, ![000000100,000001001,000010000,000010011,000011000,000011110,000100001, 000101100,000101111,001000000]!) DUAL_ORBIT_CH([d], [228_9_112.c-2], ![$2,$3]!, ![000001100,001000000,001000010,001000100,001000101,001000110,001000111, 001001000,001001011,001001100,001001101,100001111]!) DUAL_ORBIT_CH([e], [228_9_112.c-2], ![$2,$3]!, ![000000101,000000111,000010000,001000010,001000100,001000101,001000110, 001001000,001001011,001001101,001011001,100001111]!) DUAL_ORBIT_CH([f], [228_9_112.c-2], ![$2,$3]!, ![000000101,000000111,000010000,001000001,001000010,001000100,001000101, 001000110,001001000,001001101,001011001,100001111]!) DUAL_ORBIT_CH([g], [228_9_112.c-2], ![$2,$3]!, ![000000101,000000111,000010000,001000000,001000110,001000111,001001000, 001001010,001001011,001001100,001101110,100001111]!) DUAL_ORBIT_CH([h], [228_9_112.c-2], ![$2,$3]!, ![000000101,000000111,000010000,001000000,001000001,001000110,001000111, 001001000,001001010,001001100,001101110,100001111]!) DUAL_ORBIT_CH([i], [228_9_112.c-2], ![$2,$3]!, ![000000100,000000110,000000111,001000010,001000101,001000110,001000111, 001001000,001001010,001001011,001011001,100001111]!) DUAL_ORBIT_CH([j], [228_9_112.c-2], ![$2,$3]!, ![000000100,000000110,000000111,001000000,001000001,001000100,001000110, 001001000,001001100,001001101,001101110,100001111]!) DUAL_ORBIT_CH([k], [228_9_112.c-2], ![$2,$3]!, ![000000100,000000110,000000111,000010000,001000000,001000001,001000111, 001001011,001001100,001011001,011000000,100001111]!) DUAL_ORBIT_CH([l], [228_9_112.c-2], ![$2,$3]!, ![000000100,000000110,000000111,000001100,000010000,001000010,001000110, 001000111,001001000,001001010,001001011,001011001]!) DUAL_ORBIT_CH([p], [172_9_82.b], ![$1,$2]!, ![000000110,000001011,000001110,000010111,000011001,000101000,001110100]!) DUAL_ORBIT_PLUS([q], [175_9_84.p], ![$1,$2]!, ![000000010,000001110,000011100,000110010,000110100,100000000,100000010, 100000100,100000101,100001100,100010011,100010111,101011011]!) [a1..7] := [203_9_98.a] + dual word of weight 4; [b1..14] := [203_9_98.b] + dual word of weight 4; disjoint [a],[b],[c],[d],[e],[f],[g],[h],[i],[j],[k],[l],[p],[q], [a1..7],[b1..14]; status: realizable; DHIDE( ![ OE(28).7!(allowing length up to 256) done for [a] ]! ) [211_9_102] type [211,9,102]; CREDIT(existence due to Bierbrauer and Edel, bierbrauer edel twisted 1997) flags: find no more; DUAL_ORBIT_PLUS2([a], [207_9_100.e], ![$1,$2]!, ![000000011,000000100,000001000,000001010,000010001,000010100,000010110, 000011010,000011101,000110001,000110111,000111010,001101100]!, ![- column 10 - column 88 - column 16 - column 106 - column 37 - column 77 - column 94 + check]!) [a1..164] := [214_9_104.a] - dual word of weight 3; disjoint [a], [a1..164]; status: realizable; [265_9_130] type [265,9,130]; flags: find no more; DUAL_TRANSFORM_PLUS([a], [80_9_36.a], ![36_{1,-19},36_{-1,19},40_{1,-19},40_{-1,19},44_{1,-19},44_{-1,19}, 48,52_{-1},52_{1,-19}]!, ![- column 88 - column 262]!) status: realizable; [269_9_132] type [269,9,132]; flags: find no more; DUAL_TRANSFORM_PLUS([a], [80_9_36.a], ![36_{2,-20},36_{-2,20},40_{2,-20},40_{-2,20},44_{2,-20},44_{-2,20}, 48_{-2},48_{2,-20},52]!, ![- column 38]!) status: realizable; DHIDE( ![ O(26).7#(allowing length up to 511) ]! ) [273_9_134] type [273,9,134]; flags: find no more; DUAL_ORBIT([a], [18_9_6x.a], ![$1,$2]!, ![000001000,100000000,100000010,100001011,100001111,100101011,111111111]!) status: realizable; DHIDE( ![ The following is not "is cyclic". ]! ) type [297,9,146]; [a] := {1000011001111000011110011001001100111100110010011110000110010111010001111001100 00101110000101010111110011001001100101110100101111100110100100110011110011000011 11000010100011101001100001010101111100001011101011000100111100001010010111010100 1101100110100100110001110100011000100111101001001100101010,010010101011010010110 10101010101010110101010101011010010101001101100101101010100100110100100100101100 10101010101010011011000101100101011000110101011010101001011010010010110111010101 00100100101100100100110110101000110110100100101001101101010101010101100011010110 111010010100011011011000110101110110,0010101010101010101010101010010101010101010 10010101010101010110101101010101010101011010101011011010100101010010101011010110 11010100101011011001010101010101010101010101101001011010101010110110101001010110 10110101011001010101011010110101100101001010101101100101001011010010101100101011 01100101011011,00011110000111100001111000011111000011110000111110000111100000111 11000011110000111110000111110000011111000011111000001111100000111110000011111100 00111100001111000011111000001111100001111100000111110000011111000011111100001111 100000111110000011111000001111110000011111000001111110000011111100111111,0000000 11111111000000001111111110000000011111111100000000111111111100000000111111111000 00000011111111110000000001111111111000000000011111111111000000001111111100000000 01111111111000000000111111111100000000001111111111000000000111111111100000000001 11111111110000000000111111111110000000000011111111,00000000000000011111111111111 11100000000000000000111111111111111111000000000000000001111111111111111111000000 00000000000001111111111111111111110000000000000000111111111111111111100000000000 00000000111111111111111111110000000000000000000111111111111111111111000000000000 0000000001111111111111111111,000000000000000000000000000000001111111111111111111 11111111111111110000000000000000000000000000000000001111111111111111111111111111 11111111111100000000000000000000000000000000000111111111111111111111111111111111 11111100000000000000000000000000000000000000001111111111111111111111111111111111 111111,0000000000000000000000000000000000000000000000000000000000000000000111111 11111111111111111111111111111111111111111111111111111111111111111111110000000000 00000000000000000000000000000000000000000000000000000000000000001111111111111111 1111111111111111111111111111111111111111111111111111111111111111,000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000011111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111111}; status: realizable; [300_9_148] type [300,9,148]; flags: find no more; DUAL_ORBIT([a], [307_9_152.a], ![$4,$6]!, ![000000100,000000101,000000111,000001001,000010101]!) status: realizable; [304_9_150] type [304,9,150]; flags: find no more; DUAL_ORBIT([a], [307_9_152.a], ![$4,$6]!, ![000000100,000000101,000000111,000001001,000010101,111110100,111110101]!) DUAL_ORBIT([b], [307_9_152.a], ![$4,$6]!, ![000000001,000000011,000000100, 000000101,000000111,000001001,000010101,111110101]!) disjoint [a], [b]; status: realizable; [321_9_158] type [321,9,158]; flags: find no more; DUAL_ORBIT_PLUS([a], [245_9_120.a-123], ![$3,$4]!, ![000000011,000000111,000001011,000001111,000010110,000010111,000011111, 000101100,000101101,000101110,000110110,001000000,011111001,111111111]!, ![+ column 319 + column 319]!) DUAL_ORBIT_PLUS([b], [245_9_120.a-123], ![$2,$4]!, ![000000001,000000011,000000110,000000111,000001011,000001111,000010110, 000010111,000101101,000110110,001011101,011111001,111111111]!, ![+ column 319 + column 319]!) disjoint [a], [b]; status: realizable; DHIDE( ![ O(26).7#(allowing length up to 511) ]! ) [324_9_160] type [324,9,160]; flags: find no more; DUAL_ORBIT([a], [18_9_6x.a], ![$1,$2]!, ![000000101,100000000,100000010,100001011,100001111,100101011,111111111]!) status: realizable; [372_9_184] type [372,9,184]; flags: find no more; DUAL_ORBIT([a], [96_9_44.a], ![$10,$12]!, ![000000100,000000101,000001101, 000010010,000110110,001001100,001010111,010000100,010000101,010000110, 010001101,010010010,010110110,011001100,011010111]!) DUAL_ORBIT([b], [372_9_184.a], ![$16,$17]!, ![000000001,000001000,000001001, 000010000,000010001,000010101,000100001]!) DUAL_ORBIT([c], [238_9_116.a-1], ![$1,$2]!, ![000000010,000000011,000000110,000001001,000001110,000010010,000010011, 000011001,000101010,001000001,001000010,001000100,001000111,001001011, 001001100,001010011,001010111,001011100,001101010]!) disjoint [a], [b], [c]; status: realizable; type [375,9,186]; flags: find no more; DUAL_ORBIT([a], [372_9_184.a], ![$16,$17]!, ![000000001,000001000,000001001, 000010000,000010001,000010101,000100001,000111010]!) DUAL_ORBIT([b], [372_9_184.a], ![$16,$17]!, ![000000001,000001000,000001001, 000010000,000010001,000010101,000100001,000111001]!) disjoint [a], [b]; status: realizable; type [378,9,188]; flags: find no more; DUAL_ORBIT([a], [372_9_184.a], ![$16,$17]!, ![000000001,000001000,000001001, 000010000,000010001,000010101,000100001,010011001]!) status: realizable; type [381,9,190]; flags: find no more; DUAL_ORBIT([a], [372_9_184.a], ![$16,$17]!, ![000000001,000001000,000001001, 000010000,000010001,000010101,000100001,000111010,010011001]!) status: realizable; type [384,9,192]; flags: find no more; DUAL_ORBIT([a], [307_9_152.a], ![$6,$7]!, ![000000100,000000110,000001000]!) status: realizable; [396_9_196] type [396,9,196]; flags: find no more; DUAL_ORBIT([a], [96_9_44.a], ![$10,$12]!, ![000000001,000000100,000001101, 000010010,000011100,000011101,001001100,001010111,010000001,010000100, 010001101,010010010,010011100,010011101,010110110,011001100,011010111]!) DUAL_TRANSFORM_PLUS([b], [80_9_36.a], ![36_{1},36_{-1,22},40_{1},40_{-1,22},44,48_{1},48_{-1,22},52_{1}, 52_{-1,22}]!, ![- column 57 - column 87 - column 97 - column 108]!) DUAL_ORBIT([c], [242_9_118.a], ![$4,$5]!, ![000000010,000000011,000000101,000001001,000001011,000001110,000001111, 000010000,000010110,000011010,000011011,000100000,000100011,000100100, 000101001,001000000,001110000]!) disjoint [a], [b], [c]; status: realizable; type [400,9,198]; flags: find no more; DUAL_ORBIT([a], [242_9_118.a], ![$4,$5]!, ![000000010,000000011,000000101,000001001,000001011,000001110,000001111, 000010000,000010110,000011010,000011011,000100000,000100011,000100100, 000101001,001000000,001110000,101000000,111111111]!) status: realizable; type [403,9,200]; flags: find no more; DUAL_ORBIT([a], [242_9_118.a], ![$4,$5]!, ![000000010,000000011,000000101,000001001,000001010,000001011,000001110, 000001111,000010000,000010110,000011010,000011011,000100000,000100011, 000100100,000101001,001000000,001110000,101000000,111111111]!) status: realizable; type [431,9,214]; flags: find no more; DUAL_ORBIT([a], [245_9_120.a-123], ![$2,$4]!, ![000000001,000000010,000000011,000000110,000000111,000001010,000001101, 000001110,000001111,000010110,000010111,000101101,000110110,001011101, 011111001,111111111]!) status: realizable; type [434,9,216]; flags: find no more; DUAL_ORBIT_PLUS([a], [245_9_120.a-123], ![$2,$4]!, ![000000001,000000010,000000011,000000110,000000111,000001010,000001101, 000001110,000001111,000010110,000010111,000101101,000110110,001011101, 010001111,011111001,111111111]!, ![+ column 433]!) status: realizable; type [448,9,224]; flags: find no more; DUAL_ORBIT([a], [324_9_160.a], ![$3,$4]!, ![000000001,000000010,000000011, 000000101,000000110,000000111,000001010,000001011,000010010,000010011, 000011011,001000011,011011011]!) status: realizable; type [459,9,228]; flags: find no more; DUAL_ORBIT([a], [324_9_160.a], ![$2,$3,$6]!, ![000000010,000000011,000000100, 000000101,000000110,000000111,000001011,000001100,000001101,000001111, 000010011,000010100,000010101,001000000,001000010,001000100,001001010, 001001100,001010000,001011110,001100000]!) status: realizable; [463_9_230] type [463,9,230]; flags: find no more; DUAL_ORBIT([a], [96_9_44.a], ![$10,$11,$12]!, ![000000100,000000101,000000110, 000001101,000010010,000011100,000110110,001001100,001010111,001110111, 010000000,010000001,111001101]!) status: realizable; [466_9_232] type [466,9,232]; flags: find no more; DUAL_ORBIT([a], [242_9_118.a], ![$4,$5]!, ![000000001,000000010,000000011,000000101,000001001,000001011,000001110, 000001111,000010000,000010110,000011010,000011011,000100000,000100011, 000100100,000101001,000110111,001000000,001000010,001110000,101000000, 111111111]!) DUAL_ORBIT([b], [242_9_118.a], ![$4,$5]!, ![000000001,000000010,000000011,000000101,000000110,000001001,000001011, 000001110,000001111,000010110,000011010,000011011,000100011,000100100, 000101001,000110111,001000000,001000010,001110000,101000000,111111111]!) DUAL_ORBIT([c], [242_9_118.a], ![$4,$5]!, ![000000001,000000010,000000011,000000101,000000110,000001001,000001011, 000001110,000001111,000010000,000010110,000011010,000011011,000100000, 000101001,000110111,001000000,001000010,001110000,101000000,111111111]!) DUAL_ORBIT([d], [242_9_118.a], ![$1,$2,$3,$4]!, ![000000010,000000011,000000100,000000101,000000110,000001001,000010000, 000010010,000010110,000011000,000011010,000100001,000101001,001000010, 001001010,111111111]!) disjoint [a], [b], [c], [d]; status: realizable; [480_9_240] type [480,9,240]; flags: find no more; DUAL_ORBIT([a], [96_9_44.a], ![$10,$12]!, ![000000001,000000100,000000101, 000000110,000001101,000010010,000011100,000011101,000110110,001001100, 001010111,010000001,010000100,010000101,010000110,010001101,010010010, 010011100,010011101,010110110,011001100,011010111]!) status: realizable; [486_9_242] type [486,9,242]; flags: find no more; DUAL_ORBIT([a], [96_9_44.b], ![$3,$4]!, ![000000001,000000010,000000101, 000000110,000001000,000001011,000100000,000100001,000100010,000100011, 000100100,000100101,000100110,000100111,000101000,000101011,000110001, 000110010,001101000,010101001,010101010,010101101,010101110,111101001, 111101010]!) status: realizable; [504_9_252] type [504,9,252]; flags: find no more; DUAL_ORBIT([a], [307_9_152.a], ![$6,$7]!, ![000000100,000000110,000001000,000010100]!) status: realizable; [508_9_254] type [508,9,254]; flags: find no more; DUAL_ORBIT([a], [307_9_152.a], ![$6,$7]!, ![000000100,000000110,000001000,000010100,111110100]!) status: realizable; data_comment( ![ Now we give some {\bf codes of lengths 10, 11, and 12} ]! ) DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) [66_11_28] type [66,11,28]; credit: existence due to Aaron Gulliver; [a] := Cyclic(6, 66, 11, 000001000000000010001100011100111001011010100111110001 001011101110); credit: existence due to Aaron Gulliver; [b] := Act( { (3,9)(4,6)(7,8)(10,11), (1,9,8)(2,4,3)(5,7,6) }, {00000001110,00001011011,00010010111,00010111110,00101100111,01011101101, 11111111101} ) + check; [c] := Act( { (3,9)(4,6)(7,8)(10,11), (1,9,8)(2,4,3)(5,7,6) }, {00000000001,00000011101,00001001100,00001110010,00010010100,00011001101, 01111111111} ) + check; disjoint [a], [b], [c]; status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [1..4] ]! ) [138_11_62] type [138,11,62]; credit: existence due to B. Groneick and S. Grosse; [1..4] := [141_11_64.a] - dual word of weight 3; disjoint [1..4]; status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [a] ]! ) DHIDE( ![ D1.7#(allowing length up to 256) done for [a] ]! ) [168_12_76] type [168,12,76]; CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) [a] := Cyclic(8, 168, 12, 00000001001000001000001011110100111000001111001000010 00101001100010111010011011111110111010100100111001010001110110000111001001 01110001101001010010110110001011100001100); CREDIT(existence due to Gulliver and Bhargava, gulliver bhargava improvements 1996) status: realizable; DHIDE( ![ O(28).7#(allowing length up to 256) done for [1..3] ]! ) [165_12_74] type [165,12,74]; credit: existence due to me; [1..3] := [168_12_76.a] - dual word of weight 3; disjoint [1..3]; status: realizable; type [480,11,232]; [a] := {1000000010010101111000000100101100111001110101110010000011001100010100110101011 10110001110000100100100011100110110111010001111110000100000100010001101110001010 01111001111110110011101100000101111000000011001101001100110011111010010011011011 11110110011110010100111110101001110010001011100011001000001000001100011110110110 10110111001101001110111110110011001001110010001000011101111100110011100111010000 01100111000110000010001110110101000011110000111011100000111100110011100011100011 1,010000000110011001111011100010111100011010011010110100001100001101001110011110 00111001000111110110010000001101011010000111111011000001011110000111110100110010 00111111001111011110000000001101000100010111100000101011100001111000111010100110 00111100001111110011100000011100111000111100001110011100000010111110010000011100 10011111100111001000100111011000011100000110111100001111000001100001101111101011 00001100011111000111000000111001011111111000000001110011100000011110001110000001 11,00100000110011101001001000111110000011010011100110110100010010010111010110101 10010011001001011101111011001010000000110000101111000011010001011000101011001101 11111001110001100101100000011100010011101110100111010110101101110001001011001110 10010001101100010100111111000001110001010000100011101111100111011100010001100101 01101100111011001001100110110110000100101110111000110011110011000101101110010001 10101100111100001110001101110110100011001111000111110011000011101100100001100110 001,0001000010111011010010011011001011001101001011101010101110000101011001100001 10110110010101001010011110000111110111011101011000010110111011110001100110010111 01001100001000110100101100101001010110111110110101111010110111011000110111100010 00110110011010100111000110010101111001000110110010001110110001010011100100111011 10100001011100001101001011010101011011011001010010100101010110011011010100001110 11011010011001001001010100110010001001111001100100100110011001101111110000101111 0110,000010000000110001011000011110001111111010001110001100001111000001011110001 10000000110001110011011100001111110000110001100111011100011010011110000111011111 01100000011110000111000000010101111000111110001111110010010011000000001110010111 10000111001000001000110000111000111000001111001111110000111111001001000011111000 11100111011100001101111000110011110000111000001111000011101111110000111111100001 10011000011111100000110001000011100111110000000000011110011111110000111110000001 11111,00000100001111011100000101010110100110010100000110011010101000110100100110 00101001001011011100000011101011010011010010001110111110100011100001001101010111 11010110100101010100100110011101111100100110010110101101010101010010101011101000 10010110101010010101010100101110111010100000100001010111010101001110110000101000 00100111000101110111111010000100110010110011001001110101010001010011101110101001 00100100110100110101010100001011001001010101001010100010111011010111010101100001 011101,0000001000000011001100110100100001101100101101011101100100011010010111101 10010011001010110100110001100101001100010110100100011011011011110010111010000000 10001100110101110011110101001100101000101100111101000111101100010001101010100001 00000010011101111101111010010101001010010110101110100101011011010100100110010010 01111011010110101011000100101001000010110101011111010110100100000101101110101010 01101001010110010010010001000010111001011010011001110110010110011010101000110110 1010011,000000011100000100001010000111101111001000001011101111000100011000010111 01000011001000010010100111110111101010111111110001100010000101111110110001101010 01001100001100010011001100110001001011011111000100110111011100100011100111101010 10100100100100011000010111111110110100011100100000111000100111001001111111000011 00110100011101110111100011001010010010001001100010001001100110010110001100111111 01111101100110000100011010011100010001000111100001101100011010000111011110111100 11110001,00000000000000000000011111111111111111111111111111111111111111110000000 00000000000000000000000000000000000011111111111111111111111111111111111111111111 11111111111111111111111111111000000000000000000000000000000000000000000011111111 11111111111111111111111111111111111111111111111111111111111111111000000000000000 00000000000000000000000000000000000000000000000000000000001111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 111111111,0000000000000000000000000000000000000000000000000000000000000000111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111100000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000011111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 1111111111,000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000001111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111}; [496_11_240] type [496,11,240]; flags: find no more; DUAL_ORBIT([a], [32_11_12x.a], ![$2,$3]!, 00000010011) (* Don't try to compute the automorphism group of the following: *); DUAL_ORBIT([b], [32_11_12x.a], ![$1,$2]!, ![10000000110,10000001000,10000001001,10000001010]!) disjoint [a], [b]; status: realizable; [341_11_162] type [341,11,162]; flags: find no more; DUAL_ORBIT([a], [32_11_12x.a], ![$1,$2]!, ![00000001101,10000000110,10000001000]!) status: realizable; [307_10_146] type [307,10,146]; [a] := Act( { (1,3,2)(4,6,5)(8,10,9), (1,3,2)(4,10,5,8,6,9), (4,9)(5,6)(7,8) }, {0000000001,0001111111,0010000001,0010000011,0010000110,0010000111, 0010010111,0010111111,0110000111,0110001011,0110011101,0110111111, 1110000001,1110000111,1110010111,1110111111} ) - column 9 - column 56; status: realizable; [310_10_148] type [310,10,148]; [a] := Act( { (1,3,2)(4,6,5)(8,10,9), (1,3,2)(4,10,5,8,6,9), (4,9)(5,6)(7,8) }, {0000000001,0001111111,0010000001,0010000011,0010000110,0010000111, 0010010111,0010111111,0110000111,0110001011,0110011101,0110111111, 1110000001,1110000111,1110010111,1110111111} ) + column 8; status: realizable; DHIDE( ![ OE(26).7#(allowing length up to 495) ]! ) [341_10_164] type [341,10,164]; flags: find no more; DUAL_ORBIT([a], [341_11_162.a], ![$1,$2]!, ![00000000011,00000000110,00000001010]!) status: realizable; [343_11_164] type [343,11,164]; flags: find no more; DUAL_ORBIT_PLUS([a], [32_11_12x.a], ![$1,$2]!, ![00000001101,10000000110,10000001000,11111111111]!, ![+ column 342]!) status: realizable; DHIDE( ![ O(28).7#(allowing length up to 495) for [a] -- [e] ]! ) [371_11_176] type [371,11,176]; flags: find no more; DUAL_ORBIT_PLUS([a], [341_11_162.a], ![$1,$2]!, ![00000000010,00000000111,00000001010,00001100010]!, ![- column 19]!) DUAL_ORBIT_PLUS([b], [341_11_162.a], ![$1,$2]!, ![00000000010,00000000111,00000001010,00000111010]! ,![- column 13]!) DUAL_ORBIT_PLUS([c], [341_11_162.a], ![$1,$2]!, ![00000000001,00000000010,00000000111,00000001010,00001100010]!, ![- column 20 - column 29]!) DUAL_ORBIT_PLUS([d], [341_11_162.a], ![$1,$2]!, ![00000000001,00000000010,00000000111,00000001010,00001100010]!, ![- column 20 - column 34]!) DUAL_ORBIT_PLUS([e], [341_11_162.a], ![$1,$2]!, ![00000000001,00000000010,00000000111,00000001010,00001100010]!, ![- column 20 - column 59]!) DUAL_ORBIT_PLUS([f], [343_11_164.a], ![$2,$3]!, ![00000000001,00000000010,00000000111,00000001010,00000111010]!, ![- column 14 - column 33]!) DUAL_ORBIT_PLUS([g], [343_11_164.a], ![$2,$3]!, ![00000000001,00000000010,00000000111,00000001010,00000111010]!, ![- column 14 - column 42]!) DUAL_ORBIT_PLUS([h], [343_11_164.a], ![$2,$3]!, ![00000000001,00000000010,00000000111,00000001010,00000111010]!, ![- column 14 - column 60]!) disjoint [a], [b], [c], [d], [e], [f], [g], [h]; status: realizable; [24_12_8x] type [24,12,8]; [a] := QuadraticResidue(23) + check; DHIDE( ![ OE(26).7# (allowing length up to 320) done for [a], [b] ]! ) [324_12_144] type [324,12,144]; flags: find no more; DUAL_ORBIT([a], [24_12_8x.a], ![$6,$7,$9,$10]!, ![001001000101,001011000011,011001000110]!) DUAL_ORBIT([b], [24_12_8x.a], ![$6,$7,$9,$10]!, ![001001000000,001011000000,011001000010]!) disjoint [a], [b]; status: realizable; [324_10_156] type [324,10,156]; flags: find no more; DUAL_ORBIT([a], [324_12_144.b], ![$1,$2,$3,$4,$5]!, ![000000101001,000001100101,000001101011,000010001001,000010110001]!) status: realizable; DHIDE( ![ OE(26).7#(allowing length up to 495) ]! ) [270_12_120] type [270,12,120]; flags: find no more; DUAL_ORBIT([a], [324_12_144.a], ![$1,$2,$5,$6]!, ![000000100001,000000101100]!) [261_10_126] type [261,10,126]; flags: find no more; DUAL_ORBIT_PLUS2([a], [270_12_120.a], ![$2,$5,$6]!, ![000000001010,000011001101,000111001011,000111101001,001111000000, 011111000111,111111001111]!, ![- column 7 - column 14 + column 1 + column 3 + column 5 + column 8 + column 10]!) status: realizable; [490_10_240] type [490,10,240]; flags: find no more; DUAL_ORBIT([a], [24_12_8x.a], ![$4,$6,$9,$10]!, ![111000000001,111000001101,111100000001,111100000110,111100101101]!) status: realizable; data_comment( ![ More seven and eight-dimensional codes. ]! ) [84_8_40] type [84,8,40]; (* continued from earlier *); [e] := [196_9_96.a] - columns {37..84,133..196}; [f] := [196_9_96.d] - columns {13..28,41..64,77..92,109..124,137..160,173..188}; [g] := [196_9_96.d] - columns {13..40,65..92,109..136,161..188}; [h] := [196_9_96.c] - columns {13..40,65..92,109..136,161..188}; [i] := [196_9_96.e] - columns {85..196}; [j] := [196_9_96.a] - columns {3,4,6,7,9..12,14,16,18,20,21,23,25,27,29,31,34,36,38,40,42,44..46,48,51, 53,54,57..60,62,64,66,67,69,71,73,74,76..78,81,83..86,88,89,91,92,94,96, 98,99,101..104,107,109,110,112,115,117..119,122,124,125,127,129,132,133, 136,138,140,143,144,146,148,149,152,153,155,157,159,161,163..165,167,168, 171,172,174,177..178,180,181,183,186..188,190,193..196}; [k] := [196_9_96.c] - columns {5,6,9..14,16,17,20,21,24,25,27,28,30..32,35,39..41,44,45,49,50,52,53,56, 59..62,65,66,70,72..74,77,79,81..83,86..88,91..97,100,101,104..109, 112..115,118..120,122,124,127..129,131..133,137,138,143..145,148,151..153, 156,157,160..162,166,169..171,173,174,176,177,180,181,184,185,187..192, 195,196}; [l] := [196_9_96.c] - columns {3..10,16..25,32..37,43..50,53,54,61..69,74..79,88..92,99,100,103..108, 110..121,128..135,141..146,149..154,159..163,170..175,186..190,195,196}; (* this code is generalized-cyclic *); [m] := [196_9_96.c] - columns {2,4,6..8,10,12,13,15,16,18,20..24,27,28,30,31,34,35,39,43,45,47,49,51, 54..57,60,61,63,66,68,69,71,73,74,76,77,80..82,84,86,88,89,91,94,96,97, 99..102,104,105,107,111,113,115..117,119,121,123..125,127,128,130,132,134, 136,138,142..145,147,148,150,152..159,161..164,167..170,172,173,177,178, 180,183,185,188,190,191,195}; [n] := [196_9_96.d] - columns {5,6,9..14,16,17,20,21,24,25,27,28,30..32,35,39..41,44,45,49,50,52,53,56, 59..62,65,66,70,72..74,77,79,81..83,86..88,91..97,100,101,104..109, 112..115,118..120,122,124,127..129,131..133,137,138,143..145,148,151..153, 156,157,160..162,166,169..171,173,174,176,177,180,181,184,185,187..192, 195,196}; [o] := [196_9_96.d] - columns {3..10,16..25,32..37,43..50,53,54,61..69,74..79,88..92,99,100,103..108, 110..121,128..135,141..146,149..154,159..163,170..175,186..190,195,196}; (* this code is generalized-cyclic *); [p] := [196_9_96.d] - columns {2,4,6..9,11,14,17,19,20,23,24,26..28,30..35,38..42,45..47,49,51,53..56, 58..60,62,63,65,67,70,71,73,74,76..78,80..82,84,85,87,88,90,92,93,96..99, 103,106,107,109,111,113,115..118,120,123,126,129,131,132,134,138,140, 142..144,146,148,149,151,153,157,160,162..164,166,168,171,172,175,176,179, 183,185,186,188..191,194,196}; DUAL_ORBIT([q], [105_8_50.b], ![$3]!, ![00000001,00000010,00000100,00001001,00001100,00001101,00001110,00010001, 00010010,00011100,00100111,00101101,00111100,01001010,01011001,01110010, 11001100,11001101,11001110,11110101]!) [r] := Act( { (1,2,3,4,5,6,7,8)(9) }, {000010111,000101011,000111111,001001011, 001010110,001100110,001110111,010101111,010110111,011011110,011111111} ); (* this code is generalized-cyclic *); DUAL_ORBIT([s], [42_8_18.b], ![$1]!, ![00000010,00000111,00001001,00001101,00010010,00010100,00010111, 00100111,00101011,00101100,01101111]!) (* this code is generalized-cyclic *); DUAL_ORBIT([t], [42_8_18.b], ![$1]!, ![00000100,00000101,00000110,00000111,00001000,00010100,00010101, 00011000,00101010,00101011,01001011]!) (* this code is generalized-cyclic *); DUAL_ORBIT([u], [45_8_20.c], ![$1,$2]!, ![00000001,00000011,00000101,00000111,00001010,00100101,00100111,00101000, 00101010,00101111,00111000,01000101,01101011,01110111]!) DUAL_ORBIT([v], [45_8_20.c], ![$1,$2]!, ![00000010,00000011,00000101,00001001,00001010,00010001,00010011,00100101, 00101010,00110000,00111100,01000110,01001011,01101011,01111101,10111111]!) DUAL_ORBIT([w], [45_8_20.c], ![$1,$2]!, ![00000010,00001001,00001010,00001111,00010011,00100011,00100101,00101011, 00101111,00111001,00111011,00111100,00111111,01000110,01101011,10111111]!) DUAL_ORBIT([x], [45_8_20.c], ![$1,$2]!, ![00000001,00000010,00000011,00000101,00000110,00001111,00010110,00100011, 00101010,00101111,00110011,00111000,00111001,01000110,01011001,01110111]!) DUAL_ORBIT([y], [45_8_20.c], ![$1,$2]!, ![00000001,00000111,00001001,00001010,00001101,00001111,00010001,00010110, 00100011,00100101,00101010,00111011,01000110,01001111,01101000,01101011]!) DUAL_ORBIT([z], [45_8_20.c], ![$1,$2]!, ![00000001,00000111,00001000,00001101,00100000,00101001,00101010,00101011, 00101111,00111100,01000101,01000110,01001111,01011001,01111101,10111111]!) [aa] := [175_9_84.p] - columns {1,5,6,8,11,12,18,20,24,26,27,30,32,34,36,38,39, 41,42,45,48,50,51,54..56,58,59,63,64,66,72,73,75,77..79,81..84,86,88..93, 96,99,101,103,104,110,112,114,116,118..121,124,125,127,131,132,134,135, 139,144,146..150,153,155,158,159,162,163,165,166,168,170,172,173,175} - column 3 - column 84 - column 85; [bb] := [175_9_84.q] - columns {5..7,9,12,13,15,17,18,20,22,23,27,29,32,36, 38..41,45..47,49,50,52,55,57,58,60,62..64,68,69,71,76,79,82..84,89..91, 96,98,100,102,104..107,109,112..114,116,117,119,122,124,127..129,134,135, 139,140,143,145,146,148,149,154,156..159,161,163,165,167,169..173,175} - column 2 - column 59 - column 60; [cc] := [175_9_84.q] - columns {5..8,10,11,14,16,19,21..23,27,28,30,31,33..35, 37..41,45..48,51,53,54,56,59,61,63,64,68,70,72..75,77,78,80,81,85,86, 89..91,95,97,99,101,103,105..107,110,111,115,118,120,121,123,127..129,133, 136..138,141,142,144,147,150,154,156..159,162,164,166,168,174} - column 2 - column 24 - column 85; disjoint [a],[b],[c],[d],[e],[f],[g],[h],[i],[j],[k],[l],[m],[n],[o],[p],[q], [r],[s],[t],[u],[v],[w],[x],[y],[z],[aa],[bb],[cc]; status: realizable; DHIDE( ![ D2#, OE(26)# done for [a] ]! ) [81_8_38] type [81,8,38]; CREDIT(existence due to Blokh and Zyablov, blokh zyablov) DUAL_ORBIT([a], [21_8_8.b], ![$2,$3,$4]!, ![00011101,01010011,01111110]!) (* this code is generalized-cyclic *); [a1..2] := [84_8_40.a] - dual word of weight 3; [b1..6] := [84_8_40.b] - dual word of weight 3; [j1..2] := PertTwo( [225_9_110.a] - columns {28..36,46..63,73..126,145..153,163..189,199..225} ); (* [j1] is generalized-cyclic *); [k1..140] := PertTwo( [189_9_92.a] - columns {5,8..10,13,16,19,21..25,27,28,31..34,36,38..42,45,47,48,50,51,53..56,60, 61,63..65,68,70,73..76,79,80,82,84,88..90,93..97,101,103..105,107, 110..116,121,122,124,125,127,128,130,132,135,137,139,140,144..147, 149..152,155,157..160,162,166,168,171..175,177..181,183,186} ); [l1..3] := PertTwo( [193_9_94.b1] - columns {4,5,7,8,10,11,13,15,17,18,20,22,23,25,26,29,31..33,35,38..41,44,45,47,49, 51,53,55..58,61..63,65,67,69,70,72,75..78,80,82,84,85,87,90,92..94,96,97, 99,100,102,106,107,109,110,113..115,117,119,120,122,124,126,128..130, 132..134,136,138,139,141,143,144,146,147,150,153..156,158,159,162, 164..166,169,171,172,175,176,178,180,181,183,185,186,188,189,192} ); [p1..13] := PertTwo( [105_8_50.a]^T using {$3 : 00000100,00000110,00001101,00010000,00010001,00011001,00011010,00100000, 00100001,00100011,00110110,00111010,01000000,01000001,01010000,01011111, 10110010} ); [r1..54] := PertTwo( [105_8_50.a]^T using {$3 : 00000100,00000101,00000110,00001011,00010000,00010001,00010100,00010111, 00011001,00011010,00011011,00100001,00111001,00111111,01000000,01010000, 01011101} ); [t1..54] := PertTwo( [105_8_50.a]^T using {$3 : 00000001,00000100,00000110,00001101,00010000,00010011,00010100,00011100, 00011110,00101101,00111010,01000000,01000001,01010000,01010110,01011101, 01011111} ); [U1..28] := PertTwo( [105_8_50.a]^T using {$3 : 00000101,00001011,00010100,00010110,00010111,00011100,00011110,00100001, 00100011,00101101,00111001,00111010,00111110,01000000,01010000,01011101, 01110100} ); [W1..13] := PertTwo( [105_8_50.b]^T using {$3 : 00000011,00000101,00000111,00001010,00001011,00001110,00010000,00010100, 00010101,00100110,00100111,00101101,00111011,01001000,01001011,01011001, 11001100,11001101,11001110} - column 1 - column 66 ); [hh1..50] := PertTwo( [45_8_20.c]^T using {$1,$2 : 00000001,00000010,00000011,00001001,00010001,00010110,00100000,00100100, 00101000,00110000,00110111,00111001,00111111,01101011,01110111} ); [oo1..13] := PertTwo( [105_8_50.b]^T using {$3 : 00000001,00000010,00000100,00000110,00000111,00001010,00001101,00010101, 00011100,00100111,00111101,01001010,01010000,01010001,01011000,01110010, 11001100,11001101,11110101} - column 2 - column 60 ); [u1..48] := [84_8_40.u] - dual word of weight 3; [v1..48] := [84_8_40.v] - dual word of weight 3; [w1..28] := [84_8_40.w] - dual word of weight 3; [x1..50] := [84_8_40.x] - dual word of weight 3; [y1..50] := [84_8_40.y] - dual word of weight 3; [z1..50] := [84_8_40.z] - dual word of weight 3; disjoint [a], [a1..2], [b1..6], [j1..2], [k1..140], [l1..3], [p1..13], [r1..54], [t1..54], [U1..28], [W1..13], [hh1..50], [oo1..13], [u1..48], [v1..48], [w1..28], [x1..50], [y1..50], [z1..50]; status: realizable; [203_8_100] type [203,8,100]; (* continued from earlier *); [p1..3606] := P( [75_7_36.a1..3606] ); DUAL_TRANSFORM([c], [210_8_104.c-210], ![103,104_{17},107,108,112_{-17}]!) DUAL_ORBIT_PLUS([f], [121_8_58.a], ![$4,$7]!, ![00000010,00000100,00000101,00000110,00000111,00001000,00001001,00001010, 00001011,00001101,00011101,01010111,11111110]!, ![+ column 201]!) DUAL_ORBIT([g], [147_8_72.b], ![$1,$2,$4]!, ![00000111,00001011,00001101,00010001,00011001,00011101,00100001,00101011, 00110000,00110010,00111000,00111111]!) DUAL_ORBIT([i], [147_8_72.c], ![$1,$5]!, ![00000001,00000010,00000101,00000111,00001000,00001010,00001100,00010001, 00011000,01100010,01110001,01110111,10000001,10001010,10010011,11110011]!) DUAL_ORBIT([j], [175_8_86.b], ![$2,$3,$6]!, ![00000100,00000111,00001000,00001001,00001011,00001100,00001101,00010010, 00011000,00011001,00011010,01011101,10001000,10001001,10001010,10001011, 10001110,10011011,10101000,10111011]!) DUAL_ORBIT([k], [140_8_68.c], ![$2,$4,$5,$6]!, ![00000001,00000101,00001000,00001010,00010011,00011101,00101001,00101011, 00111111,01100101,11101001,11111101]!) DUAL_ORBIT([l], [140_8_68.c], ![$2,$4,$5,$6]!, ![00000001,00000010,00000101,00001000,00001010,00010011,00011101,00101001, 00101011,00111111,01100101,11101001]!) [n] := Cyclic( {7,21,21,21,21,21,21,21,7,7,7,7,21}, 203, 8, 0011000001010010011 11111100100110111000000111011001000101111001100111101011011110110100000000 01100101011111000011110001010101000111001001000001001101001011000100110101 010100111111101111101010011000100001 ); DUAL_ORBIT([o], [140_8_68.e], ![$4,$6]!, ![00000111,00001000,00001001,00001100,00011001,01000001,01000010,01001000, 01001001,01001100,01011001]!) DUAL_ORBIT([r], [105_8_50.b-64], ![$1,$2,$3]!, ![00000010,00000011,00000101,00000110,00000111,00001010,00001011,00010000, 00010001,00010010,00010011,00011101,00011110,00011111,00100111,00111010, 00111011,11001110,11001111]!) DUAL_ORBIT([s], [144_8_70.c-11], ![$2,$5]!, ![00000100,00000111,00001010,00001100,00001110,00010010,00011000,00011001, 00011110,00011111,00100000,00100001,00101110,00101111,00110001,00110010, 01111000,01111100,01111101]!) DUAL_ORBIT([1], [228_9_112.b], ![$2,$3]!, ![000000110,000001100,000001110,000010001,000010011,000011011,000011101, 000110001,000110101,001000110,001111001]!) DUAL_ORBIT([2], [228_9_112.b], ![$2,$3]!, ![000000010,000000110,000001110,000010001,000010011,000011101,000011111, 000110001,000110101,001000110,001111001]!) DUAL_ORBIT_PLUS2([3], [228_9_112.a], ![$7,$8]!, ![000000011]!, ![- columns {1,2,3} - columns {1,4,9} - columns {1,3,8} - column 1 - column 1 - column 4 - column 15 - columns {1,5,12} - column 1 - column 2 - column 1 - column 1 - column 5 - column 7 + check]!) disjoint [p1..3606], [c], [f], [g], [i], [j], [k], [l], [n], [o], [r], [s], [1..3]; status: realizable; (* ********* The following codes may be optimal but are not needed: ******** *); DHIDE( ![ DC2S, DC1# done for ]! ) [128_8_64] type [128,8,64]; DUAL_TRANSFORM([a], [20_8_8.a], ![8_{2},12_{2},16_{2}]!) set auto joint list; DHIDE( ![ DC2S, DC1# done for ]! ) [192_8_96] type [192,8,96]; [a] := P( ReedMuller(1,6) ); DHIDE( ![ DC2S, DC1# done for ]! ) [224_8_112] type [224,8,112]; DUAL_TRANSFORM([a], [20_8_8.a-20], ![7,8_{1,-2},8_{2},11,12_{1,-2},12_{2}, 15_{1,-2},15_{2},16_{1,2}]!) DHIDE( ![ DC2S (but only one column deleted, and only 4 orbits checked for it) for DC1# done for ]! ) [240_8_120] type [240,8,120]; DUAL_TRANSFORM_CH([a], [189_8_94.a], ![94,96_{1,-2},96_{2},126_{1,2}]!) DHIDE( ![ DC1# done for ]! ) [248_8_124] type [248,8,124]; DUAL_TRANSFORM([a], [155_8_76.a], ![76,80_{1,-73},80_{73},84_{1,-73},84_{73}]!) DHIDE( ![ DC1# done for ]! ) [252_8_126] type [252,8,126]; DUAL_TRANSFORM([a], [155_8_76.a], ![76,80,84_{1,-2},84_{2}]!) DHIDE( ![ DC1# done for ]! ) type [255,8,128]; DUAL_TRANSFORM([a], [20_8_8.a], ![8,12,16_{1,-2},16_{2}]!) unset auto joint list; DHIDE( ![ (* The following lines are temporary. *); type [128,8,64]; ??status: unique; type [192,8,96]; ??status: unique; type [224,8,112]; ??status: unique; type [240,8,120]; ??status: unique; type [127,8,63]; ??status: unique; type [191,8,95]; ??status: unique; type [223,8,111]; ??status: unique; type [239,8,119]; ??status: unique; type [255,8,128]; ??status: unique; type [254,8,127]; ??status: unique; type [252,8,126]; ??status: unique; type [248,8,124]; ??status: unique; type [189,8,94]; ??status: unique; (* Tilborg type II *); type [136,8,66]; ??status: unique; (* Tilborg type III *); type [256,9,128]; ??status: unique; type [384,9,192]; ??status: unique; type [511,9,256]; ??status: unique; ]! ) type [255,8,128]; DUAL_TRANSFORM([a], [20_8_8.a], ![8,12,16_{1,-2},16_{2}]!) at [base]; show y128 = 255; via unique wordtypes [base] implies [a]; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 255t^128) (* The following codes have parameters [2^8 - 2^r, 8, 2^7 - 2^(r-1)] for r = 7,6,5,4. They are all two-weight codes, which obviously form a series, no doubt admitting a simpler description. Presumably their uniqueness follows from something else. *); type [128,8,64]; DUAL_TRANSFORM([a], [20_8_8.a], ![8_{2},12_{2},16_{2}]!) at [base]; show y64 = 254, y128 = 1; =config 128 : {1}; via configuration search [a] implies [current]; via unique wordtypes [current] implies [a]; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 254t^64 + t^128) set auto joint list; type [192,8,96]; DUAL_TRANSFORM([a], [20_8_8.a], ![8_{1,-2},8_{2},12_{1,-2},12_{2},16_{1,-2}, 16_{2}]!) at [base]; show y96 = 252, y128 = 3; config from x_128|x_64_64; via configuration search [a] implies [current]; via unique wordtypes [current] implies [a]; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 252t^96 + 3t^128) [224_8_112] type [224,8,112]; DUAL_TRANSFORM([a], [20_8_8.a-20], ![7,8_{1,-2},8_{2},11,12_{1,-2},12_{2}, 15_{1,-2},15_{2},16_{1,2}]!) at [base]; show y112 = 248, y128 = 7; config from x_128|x_64_64|x_32_32_32_32; via configuration search [a] implies [current]; via unique wordtypes [current] implies [a]; classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 248t^112 + 7t^128) type [240,8,120]; DUAL_TRANSFORM_CH([a], [189_8_94.a], ![94,96_{1,-2},96_{2},126_{1,2}]!) at [base]; show y120 = 240, y128 = 15; (* Now one can show that jy128y128y120 = 0: in fact the variable itself isn't in the list of joint variables. This implies that the words of weight 0 and 128 comprise a subcode. Since the latter is a one-weight code, it is uniquely determined. Hence since the code has only two weights, it is uniquely determined. *); ??classification of [base]: [a]; STATUS_UNIQUE_WE(1 + 240t^120 + 15t^128) unset auto joint list; (* Justify the following lines, which follow by "print punctured codes": *); type [127,8,63]; ??status: unique; type [191,8,95]; ??status: unique; type [223,8,111]; ??status: unique; type [239,8,119]; ??status: unique; type [254,8,127]; ??status: unique; (* Justify the following lines: *); type [252,8,126]; ??status: unique; type [248,8,124]; ??status: unique; type [256,9,128]; ??status: unique; type [384,9,192]; ??status: unique; type [511,9,256]; ??status: unique; set dual constraint bound = -1; (* In case code.data is inputted via accept. *); set auto joint list; |-> inputs/knowns (* This file contains parameters of codes which are known to exist, but for which I have no examples. *); type [47,9,20]; ??status: realizable; type [63,9,28]; ??status: realizable; type [181,9,88]; ??status: realizable; type [81,10,36]; ??status: realizable; type [84,10,38]; ??status: realizable; type [87,10,40]; ??status: realizable; type [109,10,50]; ??status: realizable; type [125,10,58]; ??status: realizable; type [128,10,60]; ??status: realizable; type [195,10,94]; ??status: realizable; type [228,10,110]; ??status: realizable; type [231,10,112]; ??status: realizable; type [239,10,114]; ??status: realizable; type [249,10,120]; ??status: realizable; type [257,10,124]; ??status: realizable; type [42,11,16]; ??status: realizable; type [74,11,32]; ??status: realizable; type [106,11,48]; ??status: realizable; type [116,11,52]; ??status: realizable; type [122,11,56]; ??status: realizable; type [177,11,82]; ??status: realizable; type [183,11,86]; ??status: realizable; type [186,11,88]; ??status: realizable; type [199,11,96]; ??status: realizable; type [210,11,100]; ??status: realizable; type [217,11,104]; ??status: realizable; type [221,11,106]; ??status: realizable; type [224,11,108]; ??status: realizable; type [244,11,116]; ??status: realizable; type [60,12,24]; ??status: realizable; type [73,12,30]; ??status: realizable; type [84,12,34]; ??status: realizable; type [159,12,72]; ??status: realizable; type [186,12,86]; ??status: realizable; type [50,13,18]; ??status: realizable; type [58,13,22]; ??status: realizable; type [78,13,32]; ??status: realizable; type [104,13,44]; ??status: realizable; type [114,13,48]; ??status: realizable; type [156,13,68]; ??status: realizable; type [177,14,78]; ??status: realizable; type [180,14,80]; ??status: realizable; type [183,14,82]; ??status: realizable; type [115,15,46]; ??status: realizable; type [147,15,64]; ??status: realizable; type [231,15,102]; ??status: realizable; type [56,16,20]; ??status: realizable; type [96,16,36]; ??status: realizable; type [241,16,106]; ??status: realizable; type [249,17,110]; ??status: realizable; type [118,20,44]; ??status: realizable; |-> tex/code.tex \end{svb} \catcode`\@=11 \def\setlabel#1#2#3{\@bsphack\if@filesw {\let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{\write\@auxout{\string \newlabel{#1}{{#2}{#3}}}}% \expandafter}\@tempa \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} \setlabel{NewResultCount}{newresultcounter}{0} \catcode`\@=12 \newpage \part{The program} This printed document includes most (but not all) of the lines of code from the actual program. Lines of code relating to debugging, internal errors, and template instantiation are hidden, as are lines of code pertaining to or resulting from the splitting of code into multiple files. We do not show ``friend'' or {\tt extern "C"}$\ldots$ declarations. \block{Integer and rational classes} \begin{svb} set_include_file(intrat.h) HIDE( ![ #include "gmp.h" #include #include #include #include #include "NTL/ZZ_p.h" extern "C" int isspace(int); extern "C" int isdigit(int); #ifndef INTEGER_DEFINED #define INTEGER_DEFINED ]! ) index_method(minus1_to_the) index_method(lg) index_method(lcm) index_method(gcd) index_method(Ipow) index_method(even) index_method(odd) index_method(dec) index_method(INTOP) index_method(INTCMP) // Warning! Constructions of the type x = y = ... for x, y of class Integer // may result in spurious errors, for unknown reasons, if code is optimized. class Integer { public: mpz_t body; // Constructors. Integer( ) { mpz_init( body ); } Integer( const Integer& x ) { mpz_init_set( body, x.body ); } Integer( const int& x ) { mpz_init_set_si( body, x ); } Integer( const String& s ) { if ( s[0] == '+' ) { String t(s); t.del( '+' ); mpz_init_set_str( body, t, 10 ); } else mpz_init_set_str( body, s, 10 ); } // Destructor. ~Integer( ) { mpz_clear( body ); } // Assignment operator. Integer& operator=(const Integer& x) { mpz_set(body, x.body); } Integer& operator=(const int& x) { mpz_set_si( body, x ); } // Convert to other types. operator int( ) const { return mpz_get_si(body); } operator long( ) const { return mpz_get_si(body); } operator unsigned long( ) const { return mpz_get_ui(body); } operator double( ) const { return mpz_get_d(body); } Integer& Integer::operator+=(const int& x) \ { if ( x >= 0 ) mpz_add_ui( body, body, (unsigned int) x ); \ else mpz_sub_ui( body, body, (unsigned int) -x ); } Integer& Integer::operator-=(const int& x) \ { if ( x >= 0 ) mpz_sub_ui( body, body, (unsigned int) x ); \ else mpz_add_ui( body, body, (unsigned int) -x ); } Integer& Integer::operator*=(const int& x) \ { if ( x >= 0 ) mpz_mul_ui( body, body, (unsigned int) x ); \ else { mpz_mul_ui( body, body, (unsigned int) -x ); mpz_neg( body, body ); } } Integer& operator++( ) { mpz_add_ui( body, body, 1 ); } Integer& operator--( ) { mpz_sub_ui( body, body, 1 ); } // Set z = x/y, if it is known in advance that y divides x. friend void div_exact( Integer& z, const Integer& x, const Integer& y ) { mpz_divexact( z.body, x.body, y.body ); } friend Integer operator-(const Integer& x) { static Integer ans; mpz_neg( ans.body, x.body ); return ans; } Integer& negate( ) { mpz_neg( body, body ); } friend unsigned long operator%(const Integer& x, unsigned long& y) { static Integer rem; return mpz_mod_ui( rem.body, x.body, y ); } friend unsigned long operator%(const Integer& x, int y) { if ( y < 0 ) y = -y; static Integer rem; return mpz_mod_ui( rem.body, x.body, (unsigned long) y ); } #define INTOP(op, name) \ friend Integer operator ## op(const Integer& x, const Integer& y) \ { static Integer ans; \ mpz_ ## name( ans.body, x.body, y.body ); \ return ans; } \ Integer& Integer::operator ## op ## =(const Integer& x) \ { mpz_ ## name( body, body, x.body ); } INTOP(+, add)INTOP(*, mul)INTOP(-, sub)INTOP(/, fdiv_q) friend void mul(Integer& z, const Integer& x, const Integer& y) { mpz_mul( z.body, x.body, y.body ); } friend void sub(Integer& z, const Integer& x, const Integer& y) { mpz_sub( z.body, x.body, y.body ); } friend Integer operator+(const Integer& x, const int& y) { static Integer ans; if ( y >= 0 ) mpz_add_ui( ans.body, x.body, (unsigned long) y ); else mpz_sub_ui( ans.body, x.body, (unsigned long) -y ); return ans; } friend Integer operator-(const Integer& x, const int& y) { static Integer ans; if ( y >= 0 ) mpz_sub_ui( ans.body, x.body, (unsigned long) y ); else mpz_add_ui( ans.body, x.body, (unsigned long) -y ); return ans; } friend Integer operator*(const Integer& x, const int& y) { static Integer ans; if ( y >= 0 ) mpz_mul_ui( ans.body, x.body, (unsigned long) y ); else { mpz_mul_ui( ans.body, x.body, (unsigned long) -y ); mpz_neg( ans.body, ans.body ); } return ans; } friend Integer operator/(const Integer& x, const int& y) { static Integer ans; if ( y >= 0 ) mpz_fdiv_q_ui( ans.body, x.body, (unsigned long) y ); else { mpz_fdiv_q_ui( ans.body, x.body, (unsigned long) -y ); mpz_neg( ans.body, ans.body ); } return ans; } friend Integer operator+(const int& y, const Integer& x) { static Integer ans; if ( y >= 0 ) mpz_add_ui( ans.body, x.body, (unsigned long) y ); else mpz_sub_ui( ans.body, x.body, (unsigned long) -y ); return ans; } friend Integer operator-(const int& y, const Integer& x) { static Integer ans; if ( y >= 0 ) mpz_sub_ui( ans.body, x.body, (unsigned long) y ); else mpz_add_ui( ans.body, x.body, (unsigned long) -y ); return ans; } friend Integer operator*(const int& y, const Integer& x) { static Integer ans; if ( y >= 0 ) mpz_mul_ui( ans.body, x.body, (unsigned long) y ); else { mpz_mul_ui( ans.body, x.body, (unsigned long) -y ); mpz_neg( ans.body, ans.body ); } return ans; } friend Integer operator/(const int& y, const Integer& x) { static Integer ans; if ( y >= 0 ) mpz_fdiv_q_ui( ans.body, x.body, (unsigned long) y ); else { mpz_fdiv_q_ui( ans.body, x.body, (unsigned long) -y ); mpz_neg( ans.body, ans.body ); } return ans; } friend int lg( const Integer& x ) // return floor( log_2( x ) ) { // Very bad code!! char* c = mpz_get_str( 0, 2, x.body ); int len = 0; while( c[len] != 0 ) ++len; free(c); return len - 1; } friend Integer gcd( const Integer& x, const Integer& y ) { static Integer g; mpz_gcd( g.body, x.body, y.body ); return g; } friend void gcd( Integer& z, const Integer& x, const Integer& y ) { mpz_gcd( z.body, x.body, y.body ); } friend Integer lcm( const Integer& x, const Integer& y ) { static Integer ans, g; mpz_gcd( g.body, x.body, y.body ); mpz_mul( ans.body, x.body, y.body ); mpz_fdiv_q( ans.body, ans.body, g.body ); return ans; } friend void lcm( Integer& z, const Integer& x, const Integer& y ) { static Integer g; mpz_gcd( g.body, x.body, y.body ); mpz_mul( z.body, x.body, y.body ); mpz_fdiv_q( z.body, z.body, g.body ); } #define INTCMP(op,opop) \ friend bool operator op (const Integer& x1, const Integer& x2) \ { return mpz_cmp( x1.body, x2.body ) op 0; } \ friend bool operator op (const Integer& x1, const int& x2) \ { return mpz_cmp_si( x1.body, x2 ) op 0; } \ friend bool operator op (const int& x2, const Integer& x1) \ { return mpz_cmp_si( x1.body, x2 ) opop 0; } INTCMP(==,==)INTCMP(!=,!=)INTCMP(>=,<=)INTCMP(<=,>=)INTCMP(>,<)INTCMP(<,>) friend int max( int a, Integer b ) { if ( a >= b ) return a; return b; } friend Integer Ipow( unsigned long base, unsigned long exp ) { static Integer ans; mpz_ui_pow_ui( ans.body, base, exp ); return ans; } friend Integer Ipow( unsigned long base, Integer exp ) { static Integer ans; unsigned long e = mpz_get_ui(exp.body); mpz_ui_pow_ui( ans.body, base, e ); return ans; } friend Integer minus1_to_the(int j) { if ( even(j) ) return 1; else return -1; } friend bool even( const Integer& x ) { return ( mpz_get_ui(x.body) % 2 ) == 0; } friend bool odd( const Integer& x ) { return ( mpz_get_ui(x.body) % 2 ) != 0; } friend String dec( const Integer& x ) { static int l(0); static char* c; int space = mpz_sizeinbase( x.body, 10 ) + 2; if ( space > l ) { if ( l != 0 ) delete c; l = space + 100; c = new char[l]; } mpz_get_str( c, 10, x.body ); return String(c); } friend istream& operator>>(istream& s, Integer& x) { String chars; char c; int count = 0; while(1) { s.get(c); if ( !isspace(c) ) break; } while(1) { if ( isdigit(c) || ( count == 0 && ( c == '+' || c == '-' ) ) ) chars += c; else break; ++count; s.get(c); } s.unget( ); mpz_set_str( x.body, chars, 10 ); return s; } friend ostream& operator<<(ostream& s, const Integer& x) { static int l(0); static char* c; int space = mpz_sizeinbase( x.body, 10 ) + 2; if ( space > l ) { if ( l != 0 ) delete c; l = space + 100; c = new char[l]; } // The following line is expensive: mpz_get_str( c, 10, x.body ); return s << c; } }; TEX( \verb|as_int(s)|: Convert the {\tt String} object \verb|s| into an {\tt int} object. The assumption is that \verb|s| is a string of digits which defines a nonnegative integer small enough to fit into an {\tt int} object. The implementation is goofy and should be replaced. ) index_method(as_int) inline int as_int(const String& s) { return int( Integer(s) ); } index_method(yno) inline int yno( String var ) { var.del('y'); var.del('x'); var.del('_'); return as_int(var); } // If s is a string, and n is an integer, we want "s + n" to yield a string // obtained by concatenating s with the decimal expansion of n. inline String operator+(const String& s, int n) { return s + dec(n); } index_method(numerator) index_method(denominator) index_method(floor) index_method(ceil) index_method(RATOP) index_method(RATCMP) index_method(sign) class Rational { public: mpq_t body; Rational( ) { mpq_init( body ); } Rational( const Rational& x ) { mpq_init( body ); mpq_set( body, x.body ); } Rational( const int& x ) { mpq_init( body ); mpq_set_si( body, x, 1 ); } Rational( const Integer& x ) { mpq_init(body); mpq_set_z( body, x.body ); } Rational( const int& x, const int& y ) { mpq_init( body ); if ( y >= 0 ) mpq_set_si( body, x, (unsigned int) y ); else mpq_set_si( body, -x, (unsigned int) -y ); mpq_canonicalize(body); } Rational( const Integer& x, const Integer& y ) { mpq_init(body); mpq_set_num(body, x.body); mpq_set_den(body, y.body); mpq_canonicalize(body); } Rational( const int& xi, const Integer& y ) { Integer x(xi); mpq_init(body); mpq_set_num(body, x.body); mpq_set_den(body, y.body); mpq_canonicalize(body); } Rational( const Integer& y, const int& xi ) { Integer x(xi); mpq_init(body); mpq_set_num(body, y.body); mpq_set_den(body, x.body); mpq_canonicalize(body); } // The following code was taken (with small modifications) from libg++. Rational(double x) { if ( finite(x) == 0 ) { cerr << "\nInternal Error: " << "I have encountered a bad double precision number. " << "Try adding \"set precision = 3;\" to your command " << "file and repeating the calculation.\n"; exit(1); } mpq_init(body); mpq_set_ui(body, 0, 1); // Test if x is nonzero. On the Alpha, we also test for a denormal // x, which would otherwise give a floating exception. ifelse(UNAMEM,alpha, ![ if ( logb(x) > -1022 ) ]!, ![ if (x != 0.0) ]!) { int neg = x < 0; if (neg) x = -x; const long shift = 15; // a safe shift per step const double width = 32768.0; // = 2^shift const int maxiter = 20; // ought not be necessary, but just // in case, // max 300 bits of precision int expt; double mantissa = frexp(x, &expt); long exponent = expt; double intpart; int k = 0; while (mantissa != 0.0 && k++ < maxiter) { mantissa *= width; mantissa = modf(mantissa, &intpart); mpz_mul_2exp( mpq_numref(body), mpq_numref(body), shift ); if ( intpart >= 0 ) mpz_add_ui( mpq_numref(body), mpq_numref(body), (unsigned long) intpart ); else mpz_sub_ui( mpq_numref(body), mpq_numref(body), (unsigned long) -intpart ); exponent -= shift; } if (exponent > 0) mpz_mul_2exp(mpq_numref(body), mpq_numref(body), exponent); else if (exponent < 0) mpz_mul_2exp(mpq_denref(body), mpq_denref(body), -exponent); if (neg) mpz_neg( mpq_numref(body), mpq_numref(body) ); } mpq_canonicalize(body); } ~Rational( ) { mpq_clear( body ); } Rational& operator=(const Rational& x) { mpq_set(body, x.body); } Rational& operator=(const Integer& x) { mpq_set_z(body, x.body); } Rational& operator=(const int& x) { mpq_set_si( body, x, 1 ); } friend int sign( const Rational& x ) { return mpq_sgn(x.body); } Integer numerator( ) const { Integer ans; mpz_set( ans.body, mpq_numref(body) ); return ans; } Integer denominator( ) const { Integer ans; mpz_set( ans.body, mpq_denref(body) ); return ans; } operator double( ) const { return mpq_get_d( body ); } friend Rational operator-(const Rational& x) { Rational ans; mpq_neg( ans.body, x.body ); return ans; } #define RATOP(op, name) \ friend Rational operator ## op(const Rational& x, const Rational& y) \ { Rational ans; \ mpq_ ## name( ans.body, x.body, y.body ); \ return ans; } \ Rational& Rational::operator ## op ## =(const Rational& x) \ { mpq_ ## name( body, body, x.body ); } RATOP(+, add)RATOP(*, mul)RATOP(-, sub)RATOP(/, div) friend Rational operator-(const Rational& x, const Integer& y) { Rational ans, ry(y); mpq_sub( ans.body, x.body, ry.body ); return ans; } friend Rational operator-(const Integer& y, const Rational& x) { Rational ans, ry(y); mpq_sub( ans.body, x.body, ry.body ); return ans; } friend Rational operator/(const Rational& x, const Integer& y) { Rational ans, ry(y); mpq_div( ans.body, x.body, ry.body ); return ans; } friend Rational operator*(const Integer& x, const Rational& y ) { Rational ans(y); mpz_mul( mpq_numref(ans.body), mpq_numref(y.body), x.body ); mpq_canonicalize(ans.body); return ans; } friend Rational operator*(const Rational& y, const Integer& x ) { Rational ans(y); mpz_mul( mpq_numref(ans.body), mpq_numref(y.body), x.body ); mpq_canonicalize(ans.body); return ans; } #define RATCMP(op, opop) \ friend bool operator op (const Rational& x1, const Rational& x2) \ { return mpq_cmp( x1.body, x2.body ) op 0; } \ friend bool operator ## op ## (const Rational& x1, const int& x2) \ { if ( x2 >= 0 ) \ return mpq_cmp_ui( x1.body, (unsigned int) x2, 1 ) op 0; \ return mpq_cmp_ui( x1.body, (unsigned int) -x2, 1 ) opop 0; } RATCMP(>=, <=)RATCMP(<=, >=)RATCMP(>, <)RATCMP(<, >) friend bool operator==(const Rational& x1, const Rational& x2) { return mpq_equal( x1.body, x2.body ); } friend bool operator!=(const Rational& x1, const Rational& x2) { return !mpq_equal( x1.body, x2.body ); } friend bool operator==(const Rational& x1, const int& x2 ) { if ( x2 == 0 ) return mpz_cmp_ui( mpq_numref(x1.body), 0 ) == 0; if ( x2 > 0 ) return mpq_cmp_ui( x1.body, (unsigned int) x2, 1 ) == 0; Rational r( x2, 1 ); return mpq_cmp( x1.body, r.body ) == 0; } friend bool operator!=(const Rational& x1, const int& x2 ) { if ( x2 == 0 ) return mpz_cmp_ui( mpq_numref(x1.body), 0 ) != 0; if ( x2 > 0 ) return mpq_cmp_ui( x1.body, (unsigned int) x2, 1 ) != 0; Rational r( x2, 1 ); return mpq_cmp( x1.body, r.body ) != 0; } friend Integer floor( const Rational& x ) { Integer ans; mpz_fdiv_q( ans.body, mpq_numref(x.body), mpq_denref(x.body) ); return ans; } friend Integer ceil( const Rational& x ) { Integer ans; mpz_cdiv_q( ans.body, mpq_numref(x.body), mpq_denref(x.body) ); return ans; } friend Integer round( const Rational& x ) { Integer ans, f = floor(x); static Rational half(1,2); if ( x - f >= half ) return f + 1; else return f; } friend ostream& operator<<(ostream& s, const Rational& x) { long exp; char* num = mpz_get_str( 0, 10, mpq_numref(x.body) ); if ( mpz_cmp_ui( mpq_denref(x.body), 1 ) == 0 ) { s << num; free(num); return s; } char* den = mpz_get_str( 0, 10, mpq_denref(x.body) ); s << num << "/" << den; free(num); free(den); return s; } Rational( String s ) { mpq_init(body); if ( s.contains( '+' ) ) s.del( '+' ); if ( s.contains( '/' ) ) { String snum = s.before('/'); String sden = s.after('/'); mpz_t num; mpz_init_set_str( num, snum, 10 ); mpz_t den; mpz_init_set_str( den, sden, 10 ); mpq_set_num(body, num); mpq_set_den(body, den); mpq_canonicalize(body); } else { mpz_t num; mpz_init_set_str( num, s, 10 ); mpq_set_z(body, num); } } friend istream& operator>>(istream& s, Rational& x) { String chars; char c; int count = 0; while(1) { s.get(c); if ( !isspace(c) ) break; } while(1) { if ( isdigit(c) || c == '/' || ( count == 0 && ( c == '+' || c == '-' ) ) ) chars += c; else break; ++count; s.get(c); } s.unget( ); x = Rational(chars); return s; } }; TEX( ![ The class {\tt IntegerMod} is an interface to Victor Shoup's class \verb|ZZ_p|. It is used to represent integers mod $p$ for some prime $p$. Note that you have to call \verb|set_modulus| before you do anything, and that the modulus ($p$) is not recoverable from an {\tt IntegerMod}. ]! ) index_class(IntegerMod) class IntegerMod : public ZZ_p { public: friend void set_modulus(long x) { ZZ_pInit( ZZ(x) ); } friend void set_modulus(Integer x) { ZZ_pInit( ZZ( INIT_VAL, dec(x) ) ); } IntegerMod(int x) : ZZ_p(long(x)) { } IntegerMod( ) : ZZ_p( ) { } IntegerMod( ZZ_p x ) : ZZ_p(x) { } // The following dubious functions are to make lu_decompose work. friend IntegerMod abs( IntegerMod x ) { return x; } friend int operator>( const IntegerMod& x, const IntegerMod& y ) { return 0; } }; HIDE( ![ #endif ]! ) TEX( ![ \block{Definitions, string tools, list of classes, miscellanea} ]! ) TEX( ![ The following \verb|#define| directives should be adjusted to match your computer. ]! ) set_include_file(macros.h) #define LINCOLN #ifdef LINCOLN HIDE( ![ #ifndef DEMO #define CPLEX "cplex" #endif ]! ) #define CPLEX_VERSION "4.0.7" #endif #ifdef DELFT #define CPLEX "cplex" #define CPLEX_VERSION "4.0.4" #define ABSOLUTE_PATH_FOR_CPLEX #endif HIDE( ![ #ifdef DEMO #define CPLEX "/usr/local/cplex/cplex" #endif ]! ) extern String calculations_dir; index_method(test) template inline bool test(const T& a, const T& b, char sense) { if ( sense == '=' ) return a == b; if ( sense == '<' ) return a <= b; return a >= b; } // log2x -- return to log (base 2) of a power of 2 index_method(log2x) inline int log2x(unsigned long x) { if ( x == 1 ) return 0; #define TOBIT(a,b) else if ( x == a ## U ) return b; TOBIT(2,1) TOBIT(4,2) TOBIT(8,3) TOBIT(16,4) TOBIT(32,5) TOBIT(64,6) TOBIT(128,7) TOBIT(256,8) TOBIT(512,9) TOBIT(1024,10) TOBIT(2048,11) TOBIT(4096,12) TOBIT(8192,13) TOBIT(16384,14) TOBIT(32768,15) TOBIT(65536,16) TOBIT(131072,17) TOBIT(262144,18) TOBIT(524288,19) TOBIT(1048576,20) TOBIT(2097152,21) TOBIT(4194304,22) TOBIT(8388608,23) TOBIT(16777216,24) TOBIT(33554432,25) TOBIT(67108864,26) TOBIT(134217728,27) TOBIT(268435456,28) TOBIT(536870912,29) TOBIT(1073741824,30) TOBIT(2147483648,31) } // gray(i), i = 0,1,2,... : the sequence of bits to be successively toggled // to get the elements of the gray code index_method(gray) inline int gray(unsigned long i) { unsigned long x = i ^ (i + 1); unsigned long answer; if ( x == 1 ) answer = 1; else if ( x & 1 == 0 ) answer = x; else answer = (x + 1) >> 1; return log2x(answer); } TEX(We make a macro for an iteration syntax which gets used zillions of times.) index_method(forPix) index_method(forPixDef) #define forPix( pix, list ) for ( pix = (list).first( ); pix != 0; \ (list).next(pix) ) #define forPixDef( pix, list ) Pix pix; for ( pix = (list).first( ); \ pix != 0; (list).next(pix) ) index_method(if_match) index_method(if_no_match) TEX( ![ \verb|if_match( |{\it string}\verb|, |{\it pattern}\verb| )|: \ Convert {\it pattern\/} to a {\tt Regex} (regular expression) and test to see if {\it string\/} matches it. The macro code for \verb|if_match| is visible only in the source file. There is also a macro \verb|if_no_match|. ]! ) HIDE( ![ #define if_match( string, pattern ) ]! ) DEFINE(if_mat_ctr,0) DEFINE(if_match,![DEFINE(![if_mat_ctr]!,incr(if_mat_ctr))![if_match]!( $1, $2 ) |-> current_compile_file static Regex ![if_match]!if_mat_ctr ($2); if ( $1.matches( ![if_match]!if_mat_ctr ) ) |-> current_compile_file, tex/code.tex ]! ) HIDE( ![ #define if_no_match( string, pattern ) ]! ) DEFINE(if_no_mat_ctr,0) DEFINE(if_no_match,![DEFINE(![if_no_mat_ctr]!,incr(if_no_mat_ctr))![if_no_match]!( $1, $2 ) |-> current_compile_file static Regex ![if_no_match]!if_no_mat_ctr ($2); if ( !$1.matches( ![if_no_match]!if_no_mat_ctr ) ) |-> current_compile_file, tex/code.tex ]! ) HIDE( ![ // #define DEBUG ]! ) extern void print_time_used( ); #define ERROR(MSG) { cerr << "\nError: " << MSG << "\n"; \ remove( calculations_dir + "/lock" ); \ if ( calling_command != "" ) \ cerr << "The offending command was \"" << calling_command << ";\".\n"; \ cerr << "\nAbnormal termination!!\n"; \ print_time_used( ); \ if (demo) { cerr << "Press return to terminate and clear window..."; \ char cnull; cin >> cnull; } exit(1); } #define INTERNAL_ERROR(MSG) { \ remove( calculations_dir + "/lock" ); \ cerr << "\n---Internal Error---: " << MSG << "\n"; \ cerr << "Please send a copy of your program file to\n"; \ cerr << "jaffe@cpthree.unl.edu. "; \ cerr << "Please include the version number: VERSION.\n"; \ cerr << "Also please describe your hardware and operating system.\n"; \ if (demo) { cerr << "Press return to terminate and clear window..."; \ char cnull; cin >> cnull; } exit(1); } #define WARNING(MSG) { cerr << "\nWarning: " << MSG << "\n"; \ if ( calling_command != "" ) \ cerr << "The offending command was \"" << calling_command << ";\".\n"; \ if (warnings_are_fatal) \ { cerr << "\nAbnormal termination!!\n"; \ print_time_used( ); \ remove( calculations_dir + "/lock" ); \ exit(1); } } #define WARNX(MSG) { cerr << "\nWarning: " << MSG << "\n"; \ if (warnings_are_fatal) \ { cerr << "\nAbnormal termination!!\n"; \ print_time_used( ); \ remove( calculations_dir + "/lock" ); \ exit(1); } } #define WARNRET(MSG) { cerr << "\nWarning: " << MSG << " Command ignored.\n"; \ if ( calling_command != "" ) \ cerr << "The offending command was \"" << calling_command << ";\".\n"; \ if (warnings_are_fatal) \ { cerr << "\nAbnormal termination!!\n"; \ print_time_used( ); \ remove( calculations_dir + "/lock" ); \ exit(1); } \ return; } #define WARNGOTO(MSG) { cerr << "\nWarning: " << MSG << " Command ignored.\n";\ if ( calling_command != "" ) \ cerr << "The offending command was \"" << calling_command << ";\".\n"; \ if (warnings_are_fatal) \ { cerr << "\nAbnormal termination!!\n"; \ print_time_used( ); \ remove( calculations_dir + "/lock" ); \ exit(1); } \ goto time_report; } index_method(swap) template inline void swap(T& a, T& b) { static T temp; temp = a; a = b; b = temp; } index_method(dec) inline String dec( int x ) { static char s[100]; sprintf( s, "%d", x ); return s; } TEX(![ For both {\tt min} and {\tt max}, I tried to use a conditional expression, but it didn't work. Perhaps this is a compiler bug. ]!) index_method(abs) template T inline abs(const T& x) { return (x >= T(0)) ? x : -x; } index_method(min) template T inline min(const T& a, const T& b) { if ( a < b ) return a; return b; } index_method(max) template T inline max(const T& a, const T& b) { if ( b < a ) return a; return b; } index_method(require_char) inline void require_char(String& s, char c) { if ( c == 0 && s.length() == 0 ) return; if ( s.length() == 0 || s[0] != c ) ERROR("Syntax of string \"" << s << "\" is incorrect."); s.del(c); } #include index_method(make_list) template inline SLList make_list(const T& x) { SLList l; l.append(x); return l; } index_method(global_var) inline bool global_var(const String& v) { return v[0] == 'y' || v[0] == 'm' || v[0] == 'd'; } index_method(local_var) inline bool local_var(const String& v) { return v[0] == 'x' || v[0] == 's' || v[0] == 'z' || v[0] == 'q'; } index_method(joint_var) inline bool joint_var(const String& v) { return v[0] == 'j' || v[0] == 'c'; } set_include_file(gnutypes.h) #include "intrat.h" #include #include #include #include set_compile_file(code.c) bool demo; HIDE(![#include "gnutypes.h" String calling_command; String calculations_dir; #include "macros.h" ]!) #include ifelse(UNAME,Openstep, ![#include ]!, ![#include ]!) #include #include #include #include ifelse(UNAME,Openstep,![#include ]!) #include #include TEX( Set up global variables. ) int homebrew = 0; String homebrew_status; int refactorization_rate = 0; long time_used_by_CPLEX = 0; long time_used_by_subdivide = 0; long time_used_generating_Krawtchouk_table = 0; long time_used_by_list_extensions = 0; long time_used_by_build = 0; long time_used_by_igs; long time_used_by_smallcode_we; long time_used_by_Isomorphic; long time_used_presolving = 0; long time_used_by_check_infeasible = 0; long time_used_by_simple_simplex = 0; long time_used_setting_up_simplex_problem = 0; long time_used_generating_constraints = 0; long time_used_canonical_form = 0; long total_time_used; int gullible = 0, optimal = 0, secondary_echo = 1; int show_terminals = 0, show_all_configs = 0, use_joint_variables = 0; int via_building_show_extra_info = 0, ingredient_tracking = 1; int depth_first = 0, alternate_extension_method = 0; int tables_only = 0, partial_pricing = 50, gullible_silent = 0; int toldj_percent = 70; int tolpiv_percent = 87; int secondary_plus = 0, auto_group_computation = 1, force_precision = 1; int current_precision = 0, precision_lock = 0; int smart_dual = 0, homebrew_full_report = 0, silent = 0, force_homebrew = 0; int dump_cost = 0; int homebrew_dump = 0; int show_matrix = 1, show_roots = 0, try_to_kill_vocal = 0; int residual_check_for_kill = 0, auto_projection = 0, save_bounds = 0; int auto_projection_show_constraints = 0; int auto_projection_show_parameters = 0; int auto_macaulay = 0, auto_round = 0, limited_secondary_kill = 0; int sort_flag = 1, full_secondary_kill = 0, lower_bound_check = 1; int dual_constraint_bound = -1, secondary_kill_maxvars = 0, homebrew_speedy = 1; int total_dual_constraint_bound = -1; int vars, create_con_file_only = 0, show_variables = 0; int auto_dual_transform = 0, dual_transform_length_limit = 255; int show_residual_data = 0, full_reduction = 0; int ec_length_limit = 50, ec_fill = 0, auto_cyclic_test = 0; int search_vector_weight_max = 0, min_vector_weight = 0; int starting_length = 0, random_doubling_probability = 0; int max_doubles = 0, auto_residual_transform = 0, auto_puncture_transform = 0; int auto_enlarge_by_dual_word = 0, load_limit = 20; int delete_pairs = 0, delete_triples = 0; int crazy_code_search = 0, force_improvement = 0, alternate_quality_criterion = 0; int level_two_search = 0, max_create = 0; int cplex_verification_failure_accepted = 0; int auto_analyze_local_relations = 0; int auto_analyze_local_relations_vocal = 0; int configuration_search_to_end = 0, configuration_search_show_example = 0; int clear_newcodes = 0, bound_dual_search = 0; int show_quiet = 1, via_lp_quiet = 1, bound_quiet = 1, bound_verify = 0; int status_quiet = 1; int configuration_search_expand_final_count = 0; int configuration_search_print_final_list = 0; int configuration_search_group_level = 1; int configuration_search_group_size_cap = 0; int input_form = 0, adjoin_extra_brouwer_constraints = 0; int nauty_vocal = 0; int unresidue_show_all_configs = 0, unresidue_show_extra_info = 0; int low_memory_joint_generation = 0; int random_search = 0, seed_count = 10000, perturbation_count = 100000; int auto_group_residual_transform = 0, auto_dual_residual_transform = 0; int auto_group_residual_transform_alt = 0, group_size_limit = 10000; int show_distance_optimal = 0, find_regular_group_element = 0; int i1low = 0, i1high = 0, i2low = 0, i2high = 0; int auto_orbit_transform = 0, auto_transform_depth = 0, tuple_orbit_max = 5; int auto_dual_column_deletion = 0, nzv_length_max = 18; int price_refinement_count = 1, generate_noneven_bounds = 0; int purge_joints_on_type_exit = 0; int dcb_depth_limit = 0, doubly_even_test = 0, fill_weight = 0; int show_config_creation = 1, auto_joint_search = 0, auto_joint_test = 0; int use_dual_dual_for_joint = 5, no_test_if_classified = 0; int find_parameters_only = 0, auto_try_to_kill_jvars = 0; int try_to_kill_maxvars = 0; int nzv_length_max2 = 0, transform_pass_level = 5, auto_joint_list = 1; int matrix_isomorphism_silent = 1; int allowed_failures = 2, iteration_limit = 1000000, auto_mu1 = 0, debug = 0; int repeat_loop = 0, verify_feasibility = 0; int double_column_pairs = 0, starting_tuple_orbit = 1, no_column_deletion = 0; int limited_deletion = 0; int double_column_triples = 0, double_column_groups = 0; int show_even_if_known = 0; char* PATH_PREFIX = ""; HIDE( ![ extern "C" long randomx( ); extern "C" int isspace(int); extern "C" int isdigit(int); ]! ) set_compile_file(code.c) String orsign = "\\|"; String left = "\\("; String right = "\\)"; String leftbracket = "\\["; String rightbracket = "\\]"; String number_pat = left + "0" + orsign + "[1-9][0-9]*" + right; String signed_number = "[+-]?" + number_pat; String pos_number = "[1-9][0-9]*"; String var = "[a-zA-Z][a-zA-Z_0-9]*"; String pos_term = left + pos_number + var + orsign + var + right; String op = left + "=" + orsign + "<=" + orsign + "<" + orsign + ">" + orsign + ">=" + right; String LHS_pat = "[-]?" + pos_term + left + "[+-]" + pos_term + right + "*"; String constraint_pat = left + LHS_pat + op + "[-]?" + number_pat + orsign + op + "[-]?" + number_pat + right; String label_pat = "\\[[a-zA-Z_0-9]+\\]"; String bang_label_pat = left + label_pat + orsign + "\\[[a-zA-Z_0-9]+!\\]" + right; String gen_label_pat = "\\[[a-z.:A-Z_0-9!->]+\\]"; index_method(list_of) String list_of(const String& s, const String& delim = ",") { return left + left + s + right + delim + right + "*" + left + s + right; } index_method(nontrivial_list_of) String nontrivial_list_of(const String& s, const String& delim = ",") { return left + left + s + right + delim + right + "*" + left + s + right + delim + left + s + right; } index_method(zero_or_more) String zero_or_more(const String& s, const String& delim = ",") { return left + orsign + left + s + delim + right + "*" + s + right; } String config_list_piece = "\\[[->*{}a-z.,:A-Z_0-9!]+\\]"; String config_list = zero_or_more(config_list_piece); String pos_list = list_of(pos_number); TEX(![ If {\tt s} is a string and {\tt x} is a regular expression, {\tt take(s, x)} equals the largest part of {\tt s} which matches {\tt x}; {\tt s} is replaced s by what is left. ]!) String take(String& s, const Regex& x) { String y = s.at(x); s.del(x); return y; } index_method(take) inline String take(String& s, const String& t) { return take(s, Regex(t)); } inline String take(String& s, char* t) { return take(s, Regex(t)); } index_method(str) String str(Rational x) { if ( x.denominator( ) == 1 ) return dec( x.numerator( ) ); else { return String("(") + dec( x.numerator( ) ) + "/" + dec( x.denominator( ) ) + ")"; } } index_method(take_int) int take_int(String& s, const Regex& x) { return as_int( take(s,x) ); } index_method(even) inline int even(int i) { return !(i % 2); } index_method(odd) inline int odd(int i) { return i % 2; } TEX( ![ \verb|log2(n, low, high)|: For $n \in \N$, set \verb|low| $= \floor{\log_2(n)}$, \verb|high| $ = \ceiling{\log_2(n)}$. ]! ) index_method(log2) void log2( const Integer& n, Integer& low, Integer& high ) { low = Integer( lg(n) ); high = low; if ( n != Ipow(2, low) ) ++high; } index_method(round_down_to_power_of_2) Integer round_down_to_power_of_2( Integer n ) { return Ipow( 2, lg(n) ); } index_method(round_up_to_power_of_2) Integer round_up_to_power_of_2( Integer n ) { Integer low, high; log2( n, low, high ); return Ipow( 2, high ); } TEX( The following routine {\tt choose} for computing binomial coefficients is intended for occasional use only. \mindex{choose} ) Integer choose(int n, int k) BHIDE1( ![ if (debug) if ( n < 0 || k < 0 || k > n ) INTERNAL_ERROR( "Trying to calculate choose(" << n << "," << k << ")." ); ]!, ![ Integer prod = 1; ]! ) if ( 2 * k > n ) k = n - k; for ( int i = n - k + 1; i <= n; i++ ) prod *= i; for ( int i = 2; i <= k; i++ ) prod /= i; return prod; } TEX(![ \verb|class OSLList: | This is the GNU single-linked list ({\tt SLList}) class, templated over an ``ordered'' class, meaning a class with operators {\tt==} and {\tt>}. The list is supposed to be an ordered list, without repetition, and may be regarded as a set of T objects. However, occasionally I've used this class as a convenient way to work with an unordered list of objects, for which equality is defined. \mindex{add}\mindex{contains}\mindex{intersection} ]!) set_include_file(OSLList.h) index_class(OSLList) index_method(Min) index_method(Max) index_method(del) index_method(element) index_method(diff) index_method(intersection) index_method(contains) template class OSLList : public SLList { public: T element(int k) const { Pix g = first( ); for ( int i = 0; i < k; i++ ) next(g); return (*this)(g); } T Min( ) { return front( ); } T Max( ) const { Pix prev; forPixDef( p, *this ) prev = p; return (*this)(prev); } bool add( T x ) { Pix prev = 0; forPixDef( p, *this ) { if ( (*this)(p) == x ) return false; if ( (*this)(p) > x ) { ins_after( prev, x ); return true; } prev = p; } append(x); return true; } bool contains( T x ) const { forPixDef( p, *this ) { if ( (*this)(p) == x ) return true; if ( (*this)(p) > x ) return false; } return false; } void del( T x ) { Pix prev = 0; forPixDef( p, *this ) { if ( (*this)(p) > x ) return; if ( (*this)(p) == x ) { del_after(prev); return; } prev = p; } } friend bool operator==(const OSLList& a1, const OSLList& a2) { Pix p1 = a1.first( ), p2 = a2.first( ); while( p1 != 0 && p2 != 0 ) { if ( a1(p1) != a2(p2) ) return false; a1.next(p1); a2.next(p2); } return ( p1 == 0 && p2 == 0 ); } friend bool operator!=(const OSLList& a1, const OSLList& a2) { return !(a1 == a2); } friend bool operator<=(const OSLList& a1, const OSLList& a2) // subset? { Pix p1 = a1.first( ), p2 = a2.first( ); while( p1 != 0 && p2 != 0 ) { if ( a1(p1) == a2(p2) ) { a1.next(p1); a2.next(p2); } else if ( a2(p2) > a1(p1) ) return false; else a2.next(p2); } return p1 == 0; } friend OSLList intersection( const OSLList& a, const OSLList& b ) { OSLList c = a; forPixDef( p, a ) if ( !b.contains( a(p) ) ) c.del( a(p) ); return c; } friend OSLList diff( const OSLList& a, const OSLList& b ) { OSLList c = a; forPixDef( p, a ) if ( b.contains( a(p) ) ) c.del( a(p) ); return c; } }; TEX(![ The following definitions of {\tt pair} and \verb|make_pair| are taken from [.stepanov lee.]. The {\tt pair} class has been modified by adding a default constructor. (Otherwise we would just include \verb|pair.h| from the gnu {\tt libstdc++} distribution.) We give similar versions of {\tt triple} and \verb|make_triple|. The following copyright and permission statements apply to the definitions of \verb|pair| and \verb|make_pair|: {\footnotesize \begin{quote} Copyright(c) 1994 Hewlett-Packard Company\\ \ \\ Permission to use, copy, modify, distribute and sell this document for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. \end{quote} } \indexz{pair} ]!) set_include_file(pair_.h) template class pair { public: T1 first; T2 second; pair(const T1& x, const T2& y) : first(x), second(y) { } pair( ) { } }; index_method(make_pair) template inline pair make_pair(const T1& x, const T2& y) { return pair(x, y); } template inline bool operator==( const pair& p1, const pair& p2 ) { return ( p1.first == p2.first && p1.second == p2.second ); } template inline bool operator!=( const pair& p1, const pair& p2 ) { return ( p1.first != p2.first || p1.second != p2.second ); } index_class(triple) template class triple { public: T1 first; T2 second; T3 third; triple(const T1& x, const T2& y, const T3& z) : first(x), second(y), third(z) { } triple( ) { } friend bool operator==(const triple& t1, const triple& t2) { return t1.first == t2.first && t1.second == t2.second && t1.third == t2.third; } friend bool operator!=(const triple& t1, const triple& t2) { return !(t1 == t2); } }; index_method(make_triple) template inline triple make_triple(const T1& x, const T2& y, const T3& z) { return triple(x, y, z); } index_class(quadruped) template class quadruped { public: T1 first; T2 second; T3 third; T4 fourth; quadruped(const T1& x, const T2& y, const T3& z, const T4& w) : first(x), second(y), third(z), fourth(w) { } quadruped( ) { } friend bool operator==(const quadruped& t1, const quadruped& t2) { return t1.first == t2.first && t1.second == t2.second && t1.third == t2.third && t1.fourth == t2.fourth; } friend bool operator!=(const quadruped& t1, const quadruped& t2) { return !(t1 == t2); } }; index_method(make_quadruped) template inline quadruped make_quadruped(const T1& x, const T2& y, const T3& z, const T4& w) { return quadruped(x, y, z, w); } set_compile_file(code.c) HIDE(![ #include "OSLList.h" #include "pair_.h" template class matrix; template class ShareGraph; template class Map; class EquivRelIntList; class Permutation; class Permutationlist; class term; class term_sum; class constraint; class qvconstraint; class vconstraint; class constraintlist; class opt_card; class opt_table; class code; class partition; class wordtype; class mawhome; class mawhometable; class config; class config_share; class config_active; class weightlist; class codebase; class codehome; class codetable; ]! ) TEX(![ \block{Number, gf2, prevector, and vector classes} We give ``{\tt vector}'' and ``{\tt matrix}'' template classes with values in a class {\tt T}. Elements of vectors [resp.\ matrices] {\tt x} are accessed via expressions of the form {\tt x(}$i${\tt)} [resp.\ {\tt x(}$i${\tt,}$j${\tt)}] where $i,j \geq 0$. Also for a matrix, {\tt x(}$i${\tt)} will return the \th{i} row, viewed as a vector. Implementations of these classes are given (as needed in this program) for the cases {\tt T }$=${\tt\ number} and {\tt T }$=${\tt\ gf2}, where a {\tt number} represents a small nonnegative integer $(< 2^{15})$ and a ``{\tt gf2}'' object corresponds to an element of $\F_2$, represented here by a ``{\tt char}''. \indexz{number}\mindex{operator*(number, number)} ]!) set_include_file(numgf2.h) class number { public: short int x; number(const String&); number(int a) { x = a; } number( ) { x = 0; } operator int( ) { return x; } operator Rational( ) { return Rational(x); } number& operator++( ) { x++; } #define number_op(op) \ friend int operator op(number a, number b) { return a.x op b.x; } \ friend int operator op(int a, number b) { return a op b.x; } \ friend int operator op(number a, int b) { return a.x op b; } number_op(==) number_op(>=) number_op(<=) number_op(>) number_op(<) number_op(!=) number_op(+) number_op(-) number_op(*) friend int operator <(number a, Integer b) { return int(a.x) < b; } friend int operator !=(number a, Integer b) { return int(a.x) != b; } friend int operator >=(number a, Integer b) { return int(a.x) >= b; } friend int operator-(number a) { return -a.x; } number operator+=(number a) { x += a.x; } number operator/=(number a) { x /= a.x; } friend ostream& operator<<(ostream& s, number n) { return s << n.x; } }; set_compile_file(code.c) HIDE(![#include "numgf2.h"]!) number::number(const String& s) { if ( s.length( ) > 4 ) ERROR( "The string " << s << " is being processed as a small " << "integer. Either it is not an integer at all or else it is " << "too big." ); x = 0; for ( int i = 0; i < s.length( ); i++ ) { x *= 10; if ( s[i] < '0' || s[i] > '9' ) ERROR("non-digit encountered where not allowed"); x += s[i] - '0'; } } set_include_file(numgf2.h) index_method(operator*(gf2, gf2)) index_class(gf2) class gf2 { public: char x; gf2(int i = 0) { x = i; } friend gf2 operator+(gf2 a, gf2 b) { return a.x ^ b.x; } friend gf2 operator-(gf2 a, gf2 b) { return a.x ^ b.x; } friend gf2 operator*(gf2 a, gf2 b) { return a.x & b.x; } friend int operator==(gf2 a, gf2 b) { return a.x == b.x; } friend int operator!=(gf2 a, gf2 b) { return a.x != b.x; } friend int operator==(gf2 a, int b) { return a.x == b; } friend int operator!=(gf2 a, int b) { return a.x != b; } friend int operator==(int a, gf2 b) { return a == b.x; } friend int operator!=(int a, gf2 b) { return a != b.x; } friend int operator<(gf2 a, gf2 b) { return a.x < b.x; } friend int operator>(gf2 a, gf2 b) { return a.x > b.x; } operator int( ) { return x; } gf2 operator+=(gf2 a) { x ^= a.x; } friend gf2 operator-(gf2 a) { return a; } gf2(char c) { x = c - '0'; } gf2(String s) { x = s[0]; } friend ostream& operator<<(ostream& s, gf2 a) { return s << char(a.x + '0'); } }; TEX( ![ The following template class {\tt extend} is intended to encapsulate a notion of {\it extended real number}, where {\tt R} is some class of real numbers. ]! ) index_class(extend) index_method(MinusInfinity) index_method(PlusInfinity) index_method(SetMinusInfinity) index_method(SetPlusInfinity) index_method(nonzero) template class extend { public: R x; // value if finite // "inf" is -1 for -infinity, 0 for ordinary number, 1 for +infinity signed char inf; extend( ) { inf = 0; } extend(R a) : x(a), inf(0) { } extend(int a) : x(a), inf(0) { } bool MinusInfinity( ) const { return inf == -1; } bool PlusInfinity( ) const { return inf == 1; } void SetMinusInfinity( ) { x = 0; inf = -1; } void SetPlusInfinity( ) { x = 0; inf = 1; } operator R( ) const { return x; } extend operator+=(R a) { x += a; } friend bool operator==(extend a, extend b) { return a.x == b.x && a.inf == b.inf; } friend bool operator!=(extend a, R b) { return a.inf != 0 || a.x != b; } bool nonzero( ) { inf != 0 || x != R(0); } friend bool operator<(extend a, extend b) { if ( a.inf == 0 && b.inf == 0 ) return a.x < b.x; return a.inf < b.inf; } }; template inline bool operator==(R a, extend b) { return b.inf == 0 && a == b.x; } template inline bool operator<(R a, extend b) { return (b.inf == 0) ? (a < b.x) : (b.inf == 1); } template inline bool operator>(R a, extend b) { return (b.inf == 0) ? (a > b.x) : (b.inf == -1); } template inline ostream& operator<<(ostream& s, extend a) { if ( a.inf == 0 ) return s << a.x; if ( a.inf == -1 ) return s << "MinusInfinity"; return s << "PlusInfinity"; } TEX(![ The template class ``{\tt prevector}'' is for vectors over any class. Later we give a template class ``{\tt vector}'', for which one needs a base class equipped with operators ``{\tt+}'', ``{\tt==}'', ``\verb|!=|'', and as well a zero object. The elements of a {\tt prevector} are pointed to by its {\tt x} member. If {\tt x} $= 0$, the {\tt prevector} is said to be {\it uninitialized}. In that case its {\tt length} member is undefined, and the {\tt prevector} is usable only as an operand to {\tt operator=}, \verb|set_size|, the copy constructor, and the destructor. \indexz{prevector} ]!) index_method(set_size) index_method(merge) index_method(diff) index_method(resize) index_method(set_and_take) index_method(member) index_method(subset) index_method(intersection_size) index_method(pos) index_method(pos_del) index_method(make_listv) index_method(append) set_include_file(prevector.h) template class prevector { public: // the data T* x; // the elements int length; // number of elements // constructors, the destructor, and a resizer prevector( ) { x = 0; } prevector(int n) // Construct prevector with n default elements. { x = new T[n]; length = n; } prevector(String, char = ','); // constructor from String, using char // as delim prevector(const prevector& v) { if ( v.x == 0 ) x = 0; else { length = v.length; x = new T[length]; for ( int i = 0; i < length; i++ ) x[i] = v(i); } } prevector(const SLList& list) { length = list.length( ); x = new T[length]; int j = 0; forPixDef( i, list ) x[j++] = list(i); } prevector(const DLList&); prevector(int length, T* x) : length(length), x(x) { } ~prevector( ) { if ( x != 0 ) delete [ ] x; } void set_size(int n) // resize, destroying contents { if ( x != 0 && length == n ) return; if ( x != 0 ) delete [ ] x; x = new T[n]; length = n; } void resize(int n) // Boy is this inefficient! { T* x_new = new T[n]; for ( int i = 0; i < min( n, length ); i++ ) x_new[i] = x[i]; delete [ ] x; x = x_new; length = n; } void append( const T& t ) { resize( length + 1 ); (*this)( length - 1 ) = t; } // other methods void set_and_take( const prevector& v, int M ) { set_size(M); for ( int i = 0; i < M; i++ ) (*this)(i) = v(i); } prevector& operator=(const prevector& v) { if ( v.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 ) { length = v.length; x = new T[length]; } else if ( length != v.length ) { delete [ ] x; length = v.length; x = new T[length]; } for ( int i = 0; i < v.length; i++ ) (*this).x[i] = v(i); } } bool member( const T& t ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) == t ) return true; return false; } friend bool subset( const prevector& v, const prevector& w ) { for ( int i = 0; i < v.length; i++ ) if ( !w.member( v(i) ) ) return false; return true; } friend SLList make_listv(const prevector& v) { SLList l; for ( int i = 0; i < v.length; i++ ) l.append( v(i) ); return l; } friend number intersection_size( const prevector& v, const prevector& w ) { number count; for ( int i = 0; i < v.length; i++ ) if ( w.member( v(i) ) ) ++count; return count; } int find(const T& t) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) == t ) return i; return -1; } // Do binary search to return position in sorted vector, else -1. int pos( const T& t, int (*cmp)(const T&, const T&) ) const { if ( length == 0 ) return -1; int first = 0, last = length - 1, next, relationship; while (1) { if ( first == last ) return ( cmp( t, (*this)(last) ) == 0 ) ? last : -1; next = first + (last - first) / 2; relationship = cmp( t, (*this)(next) ); if ( relationship == 0 ) return next; if ( relationship > 0 ) first = next + 1; else last = next; } } // Do binary search to return position in sorted vector, else -1. // Then delete. int pos_del( const T& t, int (*cmp)(const T&, const T&) ) { int r = pos( t, cmp ); if ( r != -1 ) { prevector y( length - 1 ); for ( int i = 0; i < r; i++ ) y(i) = (*this)(i); for ( int i = r + 1; i < length; i++ ) y(i-1) = (*this)(i); *this = y; } return r; } prevector complement( ) const; T& operator( )(int i) const BHIDE2( ![ #ifdef DEBUG if ( x == 0 || i < 0 || i >= length ) INTERNAL_ERROR("illegal vector reference"); #endif ]!, ![ return x[i]; } ]! ) T& operator[ ](int i) { if ( i >= length ) resize( max( (length * 6)/5, length + 5 ) ); return x[i]; } void sort( int (*cmp)(const T&, const T&) ); void sort( int (*cmp)(const T&, const T&), Permutation& ); void unique_sort( int (*cmp)(const T&, const T&) ); }; template inline bool operator==(const prevector& v1, const prevector& v2) BHIDE2( ![ #ifdef DEBUG if ( v1.x == 0 || v2.x == 0 ) INTERNAL_ERROR("== invoked on uninitialized vector(s)"); #endif ]!, ![ if ( v1.length != v2.length ) return false; ]! ) for ( int i = 0; i < v1.length; i++ ) if ( v1(i) != v2(i) ) return false; return true; } template inline bool operator!=(const prevector& v1, const prevector& v2) { return !(v1 == v2); } TEX( \begin{quote} Merge two unique-sorted {\tt prevector}s having no overlap. \end{quote} ) template inline void merge( const prevector& Xa, const prevector& Xb, prevector& Xt, int (*cmp)(const T&, const T&) ) { int i = 0, j = 0; Xt.set_size(Xa.length + Xb.length); while(1) { if ( i == Xa.length && j == Xb.length ) break; if ( i == Xa.length ) goto grab_b; if ( j == Xb.length ) goto grab_a; if ( (*cmp)( Xa(i), Xb(j) ) > 0 ) goto grab_b; grab_a: Xt( i + j ) = Xa(i); i++; continue; grab_b: Xt( i + j ) = Xb(j); j++; } return; } TEX(![ \begin{quote} Set $Xb = Xc - Xa$, where $Xc$, $Xa$ are unique-sorted {\tt prevector}s. \end{quote} ]!) template inline void diff( const prevector& Xc, const prevector& Xa, prevector& Xb, int (*cmp)(const T&, const T&) ) { int i = 0, j = 0, k = 0, c; prevector Xt(Xc.length); while(1) { if ( j == Xc.length ) break; if ( i == Xa.length ) { Xt(k++) = Xc(j++); continue; } c = (*cmp)( Xa(i), Xc(j) ); if ( c == 0 ) { i++; j++; } else if ( c > 0 ) Xt(k++) = Xc(j++); else i++; } Xb.set_size(k); for ( i = 0; i < k; i++ ) Xb(i) = Xt(i); } HIDE( ![ template ostream& operator<<(ostream&, const prevector&); template istream& operator>>(istream&, prevector&); ]! ) set_compile_file(code.c) HIDE(![#include "prevector.h"]!) template prevector::prevector(const DLList& list) { length = list.length( ); x = new T[length]; int j = 0; forPixDef( i, list ) x[j++] = list(i); } set_compile_file(sort.cc) TEX(![ The following material, up through the routine ``\verb|prevector::sort|'' is taken essentially verbatim from the {\tt Vec} implementation in the GNU C++ Class Library. The only changes made are that comments have been deleted, spacing has been changed, the routine name and argument names have been changed. This material is covered by the GNU General Public License [.FSF general public license.]. { \footnotesize ]!) HIDE(![#include "homedefs.h" #include "generic.h" ]!) index_method(SWAP) template static inline void SWAP(T* A, T* B) { T tmp = *A; *A = *B; *B = tmp; } #define BYTES_PER_WORD 8 #define BYTES_PER_LONG 4 #define STACK_SIZE (BYTES_PER_WORD * BYTES_PER_LONG) #define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0) #define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0) #define STACK_NOT_EMPTY (stack < top) #define MAX_THRESH 4 index_method(sort) template void prevector::sort( int (*cmp)(const T&, const T&) ) { struct stack_node { T *lo; T *hi; }; T pivot_buffer; int max_thresh = MAX_THRESH; if (length > MAX_THRESH) { T *lo = x; T *hi = lo + (length - 1); T *left_ptr; T *right_ptr; stack_node stack[STACK_SIZE]; stack_node *top = stack + 1; while (STACK_NOT_EMPTY) { { T *pivot = &pivot_buffer; { T *mid = lo + ((hi - lo) >> 1); if ((*cmp) (*mid, *lo) < 0) SWAP (mid, lo); if ((*cmp) (*hi, *mid) < 0) { SWAP (mid, hi); if ((*cmp) (*mid, *lo) < 0) SWAP (mid, lo); } *pivot = *mid; pivot = &pivot_buffer; } left_ptr = lo + 1; right_ptr = hi - 1; do { while ((*cmp) (*left_ptr, *pivot) < 0) left_ptr += 1; while ((*cmp) (*pivot, *right_ptr) < 0) right_ptr -= 1; if (left_ptr < right_ptr) { SWAP (left_ptr, right_ptr); left_ptr += 1; right_ptr -= 1; } else if (left_ptr == right_ptr) { left_ptr += 1; right_ptr -= 1; break; } } while (left_ptr <= right_ptr); } if ((right_ptr - lo) <= max_thresh) { if ((hi - left_ptr) <= max_thresh) POP (lo, hi); else lo = left_ptr; } else if ((hi - left_ptr) <= max_thresh) hi = right_ptr; else if ((right_ptr - lo) > (hi - left_ptr)) { PUSH (lo, right_ptr); lo = left_ptr; } else { PUSH (left_ptr, hi); hi = right_ptr; } } } { T *end_ptr = x + 1 * (length - 1); T *run_ptr; T *tmp_ptr = x; T *thresh = (end_ptr < (x + max_thresh))? end_ptr : (x + max_thresh); for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr += 1) if ((*cmp) (*run_ptr, *tmp_ptr) < 0) tmp_ptr = run_ptr; if (tmp_ptr != x) SWAP (tmp_ptr, x); for (run_ptr = x + 1; (tmp_ptr = run_ptr += 1) <= end_ptr; ) { while ((*cmp) (*run_ptr, *(tmp_ptr -= 1)) < 0); if ((tmp_ptr += 1) != run_ptr) { T *trav; for (trav = run_ptr + 1; --trav >= run_ptr;) { T c = *trav; T *hi, *lo; for (hi = lo = trav; (lo -= 1) >= tmp_ptr; hi = lo) *hi = *lo; *hi = c; } } } } } TEX( } ) DEFINE(![INSTANTIATE0]!, ![ ifelse($#,2, ,$3, , , patsubst(template $1;, $2, ![ $3 ]!) ![INSTANTIATE0($1,$2,SHIFT(SHIFT(SHIFT($@))))]! ) ]!) DEFINE(![INSTANTIATE]!, ![ |-> current_compile_file INSTANTIATE0($@) |-> tex/code.tex, current_compile_file ]!) INSTANTIATE( ![class prevector]!, T, matrix, number, String, wordtype, Word, Permutation, vector, vector, int, vector, Pix, ![![pair< vector< vector >, matrix >]!]!, ![![pair]!]!, ![![pair]!]!, ![![pair< pair< matrix, int >, int >]!]! ) INSTANTIATE( ![void prevector::sort( int (*cmp)(const T&, const T&) )]!, T, number, String, wordtype, Word, Permutation, vector, vector, int, vector, vector, Pix, ![![pair< vector< vector >, matrix >]!]!, ![![pair< int, vector >]!]!, ![![pair]!]!, ![![pair]!]!, ![![pair< pair< matrix, int >, int >]!]! ) TEX( ![ The following sort routine returns a permutation which if applied to the original vector would cause it to be sorted. The implementation is a stupid bubble sort. ]! ) index_method(sort) template void prevector::sort( int (*cmp)(const T&, const T&), Permutation& p ) { bool no_change; p = Permutation(length); do { no_change = true; for ( int i = 1; i < length; i++ ) if ( (*cmp)( (*this)(i-1), (*this)(i) ) > 0 ) { swap( (*this)(i-1), (*this)(i) ); p.transpose( i, i+1 ); no_change = false; } } while( !no_change ); } INSTANTIATE( ![void prevector::sort( int (*cmp)(const T&, const T&), Permutation& )]!, T, number, int ) index_method(unique_sort) template void prevector::unique_sort( int (*cmp)(const T&, const T&) ) { if ( length <= 1 ) return; sort(cmp); prevector G = *this; int i, j = 0; for ( i = 1; i < length; i++ ) if ( G(i) != G(j) ) G(++j) = G(i); set_size(j + 1); for ( i = 0; i < j + 1; i++ ) (*this)(i) = G(i); } INSTANTIATE( ![void prevector::unique_sort(int (*cmp)(const T&, const T&))]!, T, vector, matrix, vector, wordtype, String, Permutation ) index_method(cmp_second) template int cmp_second( const pair& a, const pair& b ) { return a.second - b.second; } index_method(cmp_secondvc) int cmp_secondvc( const pair< int, vector >& a, const pair< int, vector >& b ) { return cmp(a.second, b.second); } index_method(cmp_secondm2) int cmp_secondm2( const pair< vector, matrix >& a, const pair< vector, matrix >& b ) { return cmp(a.second, b.second); } index_method(cmp_seconds) template int cmp_seconds( const pair& a, const pair& b ) { return compare(a.second, b.second); } |-> tex/code.tex, current_compile_file index_method(sort_by_second) template void sort_by_second( prevector< pair >& p ) { p.sort( &cmp_second ); } index_method(sort_by_seconds) template void sort_by_seconds( prevector< pair >& p ) { p.sort( &cmp_seconds ); } |-> current_compile_file template class pair; template class pair, int>; template class pair< pair, int>, int>; template class pair< pair, int>; template class prevector< pair >; template class prevector< pair, int> >; template void sort_by_second( prevector< pair,int> >& ); template void sort_by_second( prevector< pair >& ); template void sort_by_second( prevector< pair,int> >& ); template void sort_by_second( prevector< pair,int>,int> >& ); template void sort_by_second( prevector< pair >& ); template void sort_by_seconds( prevector< pair >& ); |-> tex/code.tex, current_compile_file set_compile_file(code.c) index_method(String_cmp) int String_cmp(const String& a, const String& b) { return compare(a, b); } index_method(rcmp) int rcmp(const number& a, const number& b) { return a - b; } index_method(rcmp) int rcmp(const int& a, const int& b) { return a - b; } set_compile_file(prevec1.cc) HIDE(![#include "basedefs.h"]!) index_method(complement) prevector prevector::complement( ) const { prevector answer(*this); for ( int i = 0; i < length; i++ ) if ( answer(i) ) answer(i) = 0; else answer(i) = 1; return answer; } TEX(![ {\tt prevector(string, delimiter)}:\ Construct a prevector from a string, consisting of string representations of {\tt T} objects, separated by the given delimiter, which defaults to a comma. If the delimiter is $0$, the string representations of {\tt T} objects are assumed to be single characters. For efficiency reasons and also because there is no uniform way to handle conversions from strings to {\tt T} objects, we give a separate implementation for each type. Note also that {\tt unpack} (given later) could also be handled as a constructor; this would be more consistent. ]!) prevector::prevector(String s, char delim) { if ( delim == 0 ) { length = s.length( ); x = new gf2[length]; for ( int i = 0; i < length; i++ ) { if ( s[i] != '0' && s[i] != '1' ) ERROR( s << " is not a string of 0's and 1's" ); x[i] = s[i] - '0'; } } else if ( s.length( ) == 0 ) { length = 0; x = new gf2[0]; } else { if ( s.length( )/2 * 2 != s.length( ) ) ERROR( s << " is not a " << delim << "-separated string of 0's and 1's" ); length = (s.length( ) + 1)/2; x = new gf2[length]; for ( int i = 0; i < length; i++ ) { if ( (s[2*i] != '0' && s[2*i] != '1') || (i > 0 && s[2*i-1] != delim) ) ERROR( s << " is not a " << delim << "-separated string of 0's and 1's" ); x[i] = s[2*i] - '0'; } } } prevector::prevector(String s, char delim) { static Regex any_char("."); static Regex signed_number_pat(signed_number); if ( delim == 0 ) length = s.length( ); else if ( s.length( ) == 0 ) length = 0; else length = s.freq(delim) + 1; x = new Integer[length]; for ( int i = 0; i < length; i++ ) { if ( delim == 0 ) x[i] = take(s, any_char)[0] - '0'; else { x[i] = take(s, signed_number_pat); if ( i < length - 1 ) require_char(s, delim); } } if ( s.length( ) > 0 ) ERROR("trailing junk?"); } prevector::prevector(String s, char delim) { prevector ss = unpack(s, delim); x = new Rational[ss.length]; length = ss.length; for ( int i = 0; i < length; i++ ) x[i] = Rational(ss(i)); } prevector::prevector(String s, char delim) { if ( delim == 0 ) length = s.length( ); else { if ( s.length( ) == 0 ) length = 0; else length = s.freq(delim) + 1; } x = new number[length]; int where = 0; for ( int i = 0; i < length; i++ ) { if ( delim == 0 ) { if ( !isdigit(s[where]) ) ERROR( "\"" << s << "\" is not a string of digits" ); x[i] = s[where] - '0'; } else { x[i] = 0; while ( where != s.length( ) && s[where] != delim ) { if ( !isdigit(s[where]) ) ERROR( "\"" << s << "\" is not a \"" << delim << "\"-separated list of numbers" ); x[i] = (10 * x[i]) + (s[where] - '0'); if ( x[i] > 10000 ) ERROR( "large integer encountered where not allowed"); where++; } } where++; } } index_method(set_zero) index_method(weight) index_method(as_poly) set_include_file(vector_.h) index_class(vector) template class vector : public prevector { public: TEX( ![ \classtextt{Constructors} ]! ) vector(const SLList& l) : prevector(l) { } vector(const DLList& l) : prevector(l) { } vector(const prevector& v) : prevector(v) { } vector( const vector& v1, const vector& v2 ) { length = v1.length + v2.length; x = new T[length]; for ( int i = 0; i < v1.length; i++ ) x[i] = v1(i); for ( int i = 0; i < v2.length; i++ ) x[i + v1.length] = v2(i); } vector( const vector& v1, const vector& v2, const vector& v3 ) { length = v1.length + v2.length + v3.length; x = new T[length]; for ( int i = 0; i < v1.length; i++ ) x[i] = v1(i); for ( int i = 0; i < v2.length; i++ ) x[i + v1.length] = v2(i); for ( int i = 0; i < v3.length; i++ ) x[i + v1.length + v2.length] = v3(i); } vector( ) { x = 0; } vector(int n) { x = new T[n]; length = n; } // construct default vector vector(String s, char c = ',') : prevector(s, c) { } TEX( ![ \classtextt{Other methods} ]! ) vector& vector::operator+=(const vector& v) { for ( int i = 0; i < v.length; i++ ) (*this).x[i] = (*this)(i) + v(i); } vector& vector::operator-=(const vector& v) { for ( int i = 0; i < v.length; i++ ) (*this).x[i] = (*this)(i) - v(i); } vector& vector::operator*=(const T&); bool if_zero( ) const; bool if_nonzero( ) const; void set_zero( ) { for ( int i = 0; i < length; i++ ) (*this)(i) = 0; } int weight( ) const; void set_random( ); bool advance( ); // get lexicographically next vector operator String( ) const; friend vector operator+(const vector& a, const vector& b) BHIDE2( ![ #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("operator+ invoked on uninitialized vector(s)"); #endif ]!, ![ vector c(a.length); ]! ) for ( int i = 0; i < a.length; i++ ) c(i) = a(i) + b(i); return c; } friend vector operator-(const vector& a, const vector& b) BHIDE2( ![ #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("operator- invoked on uninitialized vector(s)"); #endif ]!, ![ vector c(a.length); ]! ) for ( int i = 0; i < a.length; i++ ) c(i) = a(i) - b(i); return c; } friend vector operator+(const vector& a, const T& b) { vector c(a.length); for ( int i = 0; i < a.length; i++ ) c(i) = a(i) + b; return c; } friend vector operator-(const vector& a, const T& b) { vector c(a.length); for ( int i = 0; i < a.length; i++ ) c(i) = a(i) - b; return c; } friend int operator>(const vector& a, const vector& b) { return b < a; } }; inline String as_poly(const vector& v, bool brack = false ) { String p = "1"; for ( int i = 1; i < v.length; i++ ) if ( v(i) != 0 ) { p += " + "; if ( v(i) != 1 ) p += dec(v(i)); if (brack) p += (String("t^{") + dec(i) + "}"); else p += (String("t^") + dec(i)); } return p; } template inline vector operator-(const vector& a) { vector b(a.length); for ( int i = 0; i < b.length; i++ ) b(i) = -a(i); return b; } TEX(![ Lexicographically compare two vectors, which are supposed to be of the same length. The ``cmp'' routine returns $1$ if the first argument is bigger, $-1$ if it is smaller, $0$ if both arguments are equal. The cmp code is instantiated to {\tt T} = {\tt number} since otherwise the compiler forgets to instantiate it. Cmp moved lower in code. ]!) template inline int operator<(const vector& a, const vector& b) BHIDE1( ![ #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("operator< invoked on uninitialized vector(s)"); #endif ]!, ![ for ( int i = 0; i < a.length; i++ ) ]! ) { if ( a(i) < b(i) ) return 1; if ( a(i) > b(i) ) return 0; } return 0; } index_method(dominate) template inline bool dominate(const vector& a, const vector& b) { if ( a.length != b.length ) INTERNAL_ERROR( "dominate" ); for ( int i = 0; i < a.length; i++ ) if ( b(i) != 0 && a(i) == 0 ) return false; return true; } HIDE( ![ template inline int cmp(const vector&, const vector&); ]! ) set_compile_file(code.c) HIDE(![ #include "vector_.h" inline bool operator !=(OSLList< vector >, OSLList< vector >) { INTERNAL_ERROR( "operator!= for OSLList< vector > not defined"); } ]!) template vector& vector::operator*=(const T& m) { for ( int i = 0; i < length; i++ ) (*this).x[i] *= m; } HIDE( ![ template vector& vector::operator*=(const Integer& m); ]! ) HIDE( ![ prevector< vector >::prevector(const DLList< vector >& list) { length = list.length( ); x = new vector[length]; int j = 0; forPixDef( i, list ) x[j++] = list(i); } ]! ) index_method(if_zero) template bool vector::if_zero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) != 0 ) return false; return true; } index_method(if_nonzero) template bool vector::if_nonzero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) == 0 ) return false; return true; } HIDE( ![ bool vector::if_zero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) != 0 ) return false; return true; } bool vector::if_nonzero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) == 0 ) return false; return true; } bool vector::if_zero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) != 0 ) return false; return true; } bool vector::if_zero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) != 0 ) return false; return true; } bool vector::if_zero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) != 0 ) return false; return true; } bool vector::if_zero( ) const { for ( int i = 0; i < length; i++ ) if ( (*this)(i) != Rational(0) ) return false; return true; } ]! ) TEX( There appears to be duplication of what follows with {\tt ycmp}. ) set_include_file(cmp.h) index_method(cmp) template inline int cmp(const vector& a, const vector& b) BHIDE1( ![ #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("cmp invoked on uninitialized vector(s)"); #endif ]!, ![ register int i, n = a.length; ]! ) for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } inline int cmp(const vector< vector >& a, const vector< vector >& b) BHIDE1( ![ #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("cmp invoked on uninitialized vector(s)"); #endif ]!, ![ register int i, n = a.length, c; ]! ) for ( i = 0; i < n; i++ ) { c = cmp( a(i), b(i) ); if ( c > 0 ) return 1; if ( c < 0 ) return -1; } return 0; } HIDE( ![ inline int cmp(const vector& a, const vector& b) { #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("cmp invoked on uninitialized vector(s)"); #endif register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } ]! ) HIDE( ![ inline int cmp(const vector< vector >& a, const vector< vector >& b) { #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("cmp invoked on uninitialized vector(s)"); #endif register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } ]! ) // The following looks dangerous. Is this being applied to char's or // what should be unsigned char's? HIDE( ![ inline int cmp(const vector& a, const vector& b) { #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("cmp invoked on uninitialized vector(s)"); #endif register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } ]! ) set_include_file(cmp2.h) index_method(cmp) inline int cmp(const matrix& a, const matrix& b) BHIDE1( ![ #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("cmp invoked on an uninitialized matrix"); #endif ]!, ![ register int i, n = a.nrows; ]! ) for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } set_compile_file(misc.cc) HIDE(![#include "basedefs.h"]!) index_method(weight) int vector::weight( ) const { int sum = 0; for ( int i = 0; i < length; i++ ) sum += x[i].x; return sum; } int vector::weight( ) const { int sum = 0; for ( int i = 0; i < length; i++ ) sum += x[i].x; return sum; } int vector::weight( ) const { int sum = 0; for ( int i = 0; i < length; i++ ) sum += x[i]; return sum; } index_method(set_random) void vector::set_random( ) { for ( int i = 0; i < length; i++ ) x[i] = char(randomx( )) & 01; } template ostream& operator<<(ostream& s, const prevector& v) { s << "{"; for ( int i = 0; i < v.length; i++ ) { s << v(i); if ( i != v.length - 1 ) s << ","; } return s << "}"; } HIDE( ![ INSTANTIATE( ![ostream& operator<<(ostream&, const prevector&)]!, T, double, int, vector, String, doubledouble, Big, Rational, Integer, number, extend, extend, extend, extend ) template istream& operator>>(istream& s, prevector& v) { String x; int brack_count = 0; char c; while(1) { if ( s.peek( ) == EOF ) ERROR( "vector read failed" ); s.get(c); if ( c == '{' ) brack_count++; else if ( c == '}' ) brack_count--; x += c; if ( brack_count == 0 ) break; } x.del( '{', 0 ); x.del( '}', -1 ); v = prevector(x); return s; } INSTANTIATE( ![istream& operator>>(istream&, prevector&)]!, T, Integer, Rational ) ]! ) ostream& operator<<(ostream& s, const prevector& v) { for ( int i = 0; i < v.length; i++ ) s << v(i); return s; } ostream& operator<<(ostream& s, const prevector& v) { for ( int i = 0; i < v.length; i++ ) s << v(i); return s; } vector::operator String( ) const { String s; for ( int i = 0; i < length; i++ ) s += char( (*this)(i).x + '0' ); return s; } vector::operator String( ) const { String s = "{"; for ( int i = 0; i < length; i++ ) { s += dec((*this)(i).x); if ( i != length - 1 ) s += ","; } s += "}"; return s; } vector::operator String( ) const { String s = "{"; for ( int i = 0; i < length; i++ ) { s += dec((*this)(i)); if ( i != length - 1 ) s += ","; } s += "}"; return s; } HIDE( ![ vector::operator String( ) const { INTERNAL_ERROR("String(double) not implemented"); } vector::operator String( ) const { INTERNAL_ERROR("String(doubledouble) not implemented"); } vector::operator String( ) const { INTERNAL_ERROR("String(Big) not implemented"); } vector::operator String( ) const { INTERNAL_ERROR("String(Rational) not implemented"); } ]! ) vector::operator String( ) const { String s = "{"; for ( int i = 0; i < length; i++ ) { s += dec((*this)(i)); if ( i != length - 1 ) s += ","; } s += "}"; return s; } TEX( ![ Change a vector over {\tt gf2} to the vector which is lexicographically next. Return {\tt false} upon failure, i.e.\ if we're at the last vector $(11\ldots1)$; otherwise return {\tt true}. ]! ) index_method(advance) bool vector::advance( ) { int i, j; for ( i = length-1; i >= 0; i-- ) if ( x[i].x == 0 ) break; if ( i == -1 ) return false; for ( j = length-1; j > i; j-- ) x[j] = 0; x[i] = 1; return true; } TEX(![ Dot product. I've replaced {\tt v(i)} with {\tt v.x[i]} and likewise for {\tt w(i)}, but I haven't checked to see if this really speeds up the code. ]!) set_include_file(dot.h) index_method(operator*(vector$<$gf2$>$, vector$<$number$>$)) inline int operator*(const vector& v, const vector& w) { static int i, sum; sum = 0; for ( i = 0; i < v.length; i++ ) if ( v.x[i] ) sum += w.x[i]; return sum; } index_method(operator*(vector$<$T$>$, vector$<$T$>$)) template inline T operator*(const vector&v, const vector& w) { T dot = 0; for ( int i = 0; i < v.length; i++ ) dot += v(i) * w(i); return dot; } HIDE( ![ inline gf2 operator*(const vector&v, const vector& w) { gf2 dot = 0; for ( int i = 0; i < v.length; i++ ) dot += v(i) * w(i); return dot; } inline double operator*(const vector&v, const vector& w) { double dot = 0; for ( int i = 0; i < v.length; i++ ) dot += v(i) * w(i); return dot; } inline doubledouble operator*(const vector&v, const vector& w) { doubledouble dot = 0; for ( int i = 0; i < v.length; i++ ) dot += v(i) * w(i); return dot; } inline Big operator*(const vector&v, const vector& w) { Big dot = 0; for ( int i = 0; i < v.length; i++ ) dot += v(i) * w(i); return dot; } inline Rational operator*(const vector&v, const vector& w) { Rational dot = 0; for ( int i = 0; i < v.length; i++ ) dot += v(i) * w(i); return dot; } ]! ) index_method(idot) inline int idot(const vector& v, const vector& w) { static int i, sum; sum = 0; for ( i = 0; i < v.length; i++ ) sum += v.x[i].x & w.x[i].x; return sum; } set_include_file(big.h) #include "intrat.h" index_class(Big) index_method(set_precision) // The following class Big supports real numbers with arbitrarily large // mantissas. If a Big is constructed via Big( ), then it has "initialized" // set to false. So long as a Big is in this quasi-initialized state, when you // do an assignment to it, it inherits the precision of the RHS. class Big { public: mpf_t body; bool initialized; // On an alpha 21264, the following might as well have 64n-32 replaced // by 64n, because that's what you get. void set_precision(int n) // 64n - 32 bits of precision { mpf_set_prec( body, 64 * n - 32 ); initialized = true; } // Constructors Big( ) : initialized(false) { mpf_init(body); } Big( const Big& x ) : initialized( x.initialized ) { if ( !x.initialized ) mpf_init_set( body, x.body ); else { unsigned long prec = mpf_get_prec( x.body ); mpf_init2( body, prec ); mpf_set( body, x.body ); } } Big( const double& x ) : initialized(true) { mpf_init2( body, 64 ); mpf_set_d( body, x ); } Big( const int& x ) : initialized(true) { mpf_init2( body, 32 ); mpf_set_si( body, x ); } Big( const int& x, const unsigned long& prec ) : initialized(true) { mpf_init2( body, prec ); mpf_set_si( body, x ); } // Destructor ~Big( ) { mpf_clear( body ); } // Assignment operators Big& operator=(const Big& x) { if ( x.initialized ) { unsigned long prec = initialized ? mpf_get_prec(body) : 32; unsigned long precx = mpf_get_prec( x.body ); mpf_set_prec( body, max(prec, precx) ); initialized = true; mpf_set(body, x.body); } } Big& operator=(const int& x) { if ( !initialized ) { mpf_set_prec( body, 32 ); initialized = true; } mpf_set_si(body, x); } Big& operator=(const Integer& x) { if ( !initialized ) INTERNAL_ERROR( "Attempt to assign Integer to Big without " << "initializing first." ); mpf_set_z( body, x.body ); } Big& operator=(const Rational& x) { if ( !initialized ) INTERNAL_ERROR( "Attempt to assign Rational to Big without " << "initializing first." ); mpf_set_q( body, x.body ); } Big& operator=(const double& x) { if (initialized) { unsigned long prec = mpf_get_prec(body); mpf_set_prec( body, max( prec, (unsigned long)(64) ) ); } else initialized = true; mpf_set_d( body, x ); } Big& operator=(const float& x) { if (initialized) { unsigned long prec = mpf_get_prec(body); mpf_set_prec( body, max( prec, (unsigned long)(32) ) ); } else initialized = true; mpf_set_d( body, double(x) ); } // Convert Big to other types operator Rational( ) const { long exp; char* s = mpf_get_str( 0, &exp, 10, 0, body ); if ( s[0] == 0 ) return 0; int i = 0; while ( s[i] != 0 ) ++i; if ( s[0] == '-' ) --i; int r = exp - i; Integer x(s); free(s); if ( r >= 0 ) return Rational( x * Ipow(10, r), 1 ); else return Rational( x, Ipow(10, -r) ); } operator double( ) const { return mpf_get_d(body); } #define BIGXP(op, name) \ Big& Big::operator ## op ## =(const Big& x) \ { unsigned long precx = mpf_get_prec( x.body ); \ unsigned long prec = mpf_get_prec( body ); \ if ( prec < precx ) mpf_set_prec( body, precx ); \ mpf_ ## name( body, body, x.body ); } \ Big& Big::operator ## op ## =(const unsigned int& x) \ { mpf_ ## name ## _ui( body, body, x ); } BIGXP(+, add)BIGXP(*, mul)BIGXP(-, sub)BIGXP(/, div) friend Big operator-(Big x) { mpf_neg( x.body, x.body ); return x; } #define BIGOP(op, name) \ friend Big operator ## op(const Big& x, const Big& y) \ { unsigned long precx = mpf_get_prec( x.body ); \ unsigned long precy = mpf_get_prec( y.body ); \ Big ans( 0, max(precx, precy) ); \ mpf_ ## name( ans.body, x.body, y.body ); \ return ans; } \ friend Big operator ## op(const Big& x, const unsigned int& y) \ { unsigned long precx = mpf_get_prec( x.body ); \ Big ans( 0, max(precx, (unsigned long)(32)) ); \ mpf_ ## name ## _ui( ans.body, x.body, y ); \ return ans; } BIGOP(/, div)BIGOP(+, add)BIGOP(*, mul)BIGOP(-, sub) friend Big operator/(const double& x, const Big& y) { unsigned long precy = mpf_get_prec( y.body ); Big ans( 0, max(precy, (unsigned long)(64)) ); Big xb(x); mpf_div( ans.body, xb.body, y.body ); return ans; } friend Big operator+(const double& x, const Big& y) { unsigned long precy = mpf_get_prec( y.body ); Big ans( 0, max(precy, (unsigned long)(64)) ); Big xb(x); mpf_add( ans.body, xb.body, y.body ); return ans; } #define BIGCMP(op) \ friend bool operator op (const Big& x1, const Big& x2) \ { return mpf_cmp( x1.body, x2.body ) op 0; } \ friend bool operator op (const Big& x1, const int& x2) \ { return mpf_cmp_si( x1.body, x2 ) op 0; } BIGCMP(==)BIGCMP(!=)BIGCMP(>=)BIGCMP(<=)BIGCMP(>)BIGCMP(<) friend ostream& operator<<(ostream& s, const Big& x) { long exp; char* c = mpf_get_str( 0, &exp, 10, 0, x.body ); if ( c[0] == 0 ) s << '0'; else { int pos = 0; if ( c[0] == '-' ) { s << '-'; ++pos; } s << c[pos] << "." << c+pos+1 << "E" << exp-1; } free(c); return s; } }; HIDE( ![ extern int homebrew, force_homebrew, force_precision, current_precision, precision_lock; ]! ) index_method(accommodate) inline void accommodate(Integer x) { if ( precision_lock > 0 ) { current_precision = precision_lock; homebrew = 1; } else if ( x < Integer("3000000000000000000") && force_precision == 1 ) { current_precision = 1; homebrew = force_homebrew; } else if ( x < Ipow(2, 106 + 8) && force_precision <= 2 ) { current_precision = 2; homebrew = 1; } else { current_precision = max( force_precision, (int) ( (lg(x) - 40) / 64 + 2 ) ); homebrew = 1; } } set_compile_file(code.c) HIDE(![#include "doubledouble.h"]!) HIDE(![#include "inline.h"]!) HIDE(![#include "big.h"]!) HIDE(![#include "dot.h"]!) HIDE(![#include "unpack.h"]!) TEX(![ {\tt unpack(}{\it string}{\tt,}$d${\tt)}:\ Break a string up into pieces, using the given string $d$ as a delimiter. Return a prevector of strings. The default delimiter is a comma. If the delimiter is the null string, then the pieces will be single characters. ]!) set_include_file(unpack.h) index_method(unpack) prevector unpack(String s, String delim = ",") { SLList list; if ( s.length( ) == 0 ) return prevector(list); if ( delim.length( ) != 0 ) { if ( s.contains( delim, -1 ) ) ERROR( "Syntax error: unexpected use of " << delim << "." ); String part; while( s.length( ) != 0 ) { if ( s.contains( delim, 0 ) ) { s.del(delim); list.append(part); part = ""; } else { part += s[0]; s.del( s[0] ); } } list.append(part); } else { for ( int i = 0; i < s.length( ); i++ ) list.append(s[i]); } return prevector(list); } TEX(![ \block{Finite field arithmetic} This section contains some incredibly primitive, incredibly tentative routines for doing arithmetic over $\F_2$. ]! ) set_compile_file(finite.cc) HIDE( ![ #include "homedefs.h" ]! ) index_class(polyF2) typedef vector polyF2; index_method(deg) inline int deg( const polyF2& f ) { int i; for ( i = f.length-1; i >= 0; i-- ) if ( f(i).x != 0 ) break; return i; } TEX( ![ \verb|divides(|$f$\verb|,|$g$\verb|)|:\ Return the highest power of $f$ which divides $g$. ]! ) index_method(divides) int divides( const polyF2& f, polyF2 g ) { int i, dg = deg(g), df = deg(f), times = 0; if ( df > dg ) return 0; if ( df == -1 || dg == -1 ) INTERNAL_ERROR( "divides" ); g.resize(dg+1); while (1) { dg = deg(g); polyF2 q( dg - df + 1 ); while (1) { dg = deg(g); if ( dg == -1 ) break; if ( df > dg ) return times; q(dg - df) = 1; for ( i = 0; i <= df; i++ ) g(i + dg - df) += f(i); } g = q; times++; } } TEX( ![ \verb|remainder(|$f$\verb|,|$g$\verb|)|:\ Return the remainder of $f$ on division by $g$. ]! ) index_method(remainder) polyF2 remainder( polyF2 f, const polyF2& g ) { int i, dg = deg(g), df; if ( dg == -1 ) INTERNAL_ERROR( "remainder" ); while (1) { df = deg(f); if ( dg > df ) return f; for ( i = 0; i <= dg; i++ ) f(i + df - dg) += g(i); } } TEX( ![ \verb|primitive_poly(|$d$\verb|)|:\ Return a primitive polynomial of degree $d$ over $\F_2$, or else $0$ if such a polynomial is not known to the program. ]! ) index_method(primitive_poly) polyF2 primitive_poly(int d) { if ( d == 1 ) return word("11", 0); if ( d == 2 ) return word("111", 0); if ( d == 3 ) return word("1101", 0); if ( d == 4 ) return word("11001", 0); if ( d == 5 ) return word("101001", 0); if ( d == 6 ) return word("1100001", 0); if ( d == 7 ) return word("11000001", 0); if ( d == 8 ) return word("101110001", 0); if ( d == 9 ) return word("1000100001", 0); if ( d == 10 ) return word("10010000001", 0); if ( d == 11 ) return word("101000000001", 0); if ( d == 12 ) return word("1000100000111", 0); if ( d == 13 ) return word("10000000100111", 0); if ( d == 14 ) return word("101000000000111", 0); if ( d == 15 ) return word("1000000000000011", 0); if ( d == 16 ) return word("10001000000001011", 0); if ( d == 17 ) return word("100000000000001001", 0); if ( d == 18 ) return word("1000000000010000001", 0); if ( d == 19 ) return word("10000000000000100111", 0); if ( d == 20 ) return word("100000000000000001001", 0); return polyF2(0); } TEX( ![ \verb|roots_mod(|$f$\verb|,|$g$\verb|)|:\ Let $f \in \F_2[y]$, $g \in \F_2[x]$. For each $i$ ($0 \leq 1 < 2^{\deg(g)}$), determine if $x^i$ is a root of $f$ in $\F_2[x]/(g)$. Return a list of exponents for powers of $x$, allowing for multiple roots. Also return $-1$ for each time that $0$ occurs as a root. Normally this routine is called with $g$ a primitive polynomial. ]! ) index_method(roots_mod) vector roots_mod( polyF2 f, polyF2 g ) { if ( f.if_zero( ) ) INTERNAL_ERROR( "roots_mod called with f = 0" ); int dg = deg(g), df = deg(f); int r = Ipow( 2, dg ); int rm = r-1; int j, k; // First make a table of powers of x, mod g. matrix xpower( r-1, dg ); xpower( 0, 0 ) = 1; for ( j = 0; j < r-2; j++ ) { if ( xpower( j, dg-1 ) ) { for ( k = 0; k < dg; k++ ) xpower(j+1, k) = g(k); } for ( k = 0; k < dg-1; k++ ) xpower(j+1, k+1) += xpower(j, k); } // Now compute the roots of f. SLList roots; static polyF2 g0("11", 0); int m = divides( g0, f ); for ( k = 0; k < m; k++ ) roots.append(0); for ( k = 0; k < f.length; k++ ) if ( f(k) ) break; for ( j = 0; j < k; j++ ) roots.append(-1); vector times(r); for ( int i = 1; i < r-1; i++ ) { if ( even(i) ) times(i) = times(i/2); else { // First determine if there is a root at all. polyF2 sum( dg ); for ( j = 0; j <= df; j++ ) if ( f(j) ) sum += xpower( (i*j) % rm ); if ( !sum.if_zero( ) ) { times(i) = 0; continue; } // Now determine the multiplicity of the root. polyF2 fp( ((f.length-1) * i) + 1 ); for ( j = 0; j < f.length; j++ ) fp(i * j) = f(j); m = divides( g, fp ); times(i) = m; } for ( k = 0; k < times(i); k++ ) roots.append(i); } if ( roots.length( ) > deg(f) ) INTERNAL_ERROR( "roots_mod" ); return roots; } TEX( ![ \verb|roots(|$f$\verb|)|:\ Given a polynomial $f$ over $\F_2$, return the least degree of an extension of $\F_2$ into which $f$ splits into linear factors, and return the logarithms of the roots in such an extension, relative to a primitive generator for the extension. Return $-1$ in place of the logarithm, for each time that $0$ occurs as a root. ]! ) index_method(roots) pair< int, vector > roots( polyF2 f ) { int d = 1; while(1) { polyF2 g = primitive_poly(d); vector r = roots_mod( f, g ); if ( r.length == deg(f) ) return make_pair( d, r ); d++; } } TEX( ![ \verb|BCH(|$f$\verb|,|$n$\verb|,|$v$\verb|)|:\ Let $f \in \F_2[x]$, $n \in \N$, and let $v$ be a list of nonnegative integers. Let $R = \F_2[x]/(f)$. Form the $v{\tt.length} \times n$ matrix $M$ of elements of $R$ whose \th{ij} entry is $x^{v_i*(j-1)}$. Let $C$ be the code in $\F_2^n$ consisting of the elements orthogonal to the rowspace of $M$. Return a generator matrix for $C$. ]! ) index_method(BCH) matrix BCH( polyF2 f, int n, vector v ) { int i, j, k, df = deg(f); matrix M( v.length * df, n ), A; int vmax = v(0); for ( i = 1; i < v.length; i++ ) vmax = max( vmax, v(i) ); int max_power = vmax * (n-1); // Create a matrix whose ith row is the remainder on division by f of x^i. matrix rpow( max_power+1, df ); rpow(0, 0) = 1; for ( i = 0; i < max_power; i++ ) { if ( rpow(i, df-1).x == 0 ) { for ( j = 0; j < df-1; j++ ) rpow(i+1, j+1) = rpow(i,j); } else { rpow(i+1,0) = f(0); for ( j = 0; j < df-1; j++ ) rpow(i+1, j+1) = rpow(i,j) + f(j+1); } } // Create the parity check matrix for the BCH code. for ( i = 0; i < v.length; i++ ) for ( j = 0; j < n; j++ ) for ( k = 0; k < df; k++ ) M( i*df + k, j ) = rpow( v(i) * j, k ); M.reduce_nz( ); M.nullspace_equals(A); return A; } index_method(BCH) matrix BCH( polyF2 f, int n, int first, int last ) { vector v( last - first + 1 ); for ( int i = 0; i < v.length; i++ ) v(i) = first + i; return BCH( f, n, v ); } index_method(BCH) matrix BCH( int r, int n, int first, int last ) { polyF2 f = primitive_poly(r); if ( f.length == 0 ) ERROR( "I don't have enough primitive polynomials to process that." ); return BCH( f, n, first, last ); } TEX(![ \block{EquivRelIntList class} The class ``{\tt EquivRelIntList}'' manages an equivalence relation on the set $0,\ldots,n-1$. In essence, this is kept track of internally via a digraph which is a disjoint union of cycles. \indexz{EquivRelIntList} ]! ) set_include_file(permutation.h) index_method(minimal) index_method(min_in_class) class EquivRelIntList : public vector { public: EquivRelIntList(int n) : vector(n) // construct discrete ~ relation { for ( int i = 0; i < length; i++ ) (*this)(i) = i; } EquivRelIntList(const vector&, bool); // use equality as the // relation on a given list bool equiv(int,int) const; // test for equivalence void join(int,int); // make two integers equivalent int size(int) const; // compute size of an equivalence class int orbit_count( ) const; // compute number of orbits SLList orbit(int) const; // compute an orbit bool minimal(int x) // Is x the minimal element of its class? { int i = x; while ( (i = (*this)(i)) > x ); return x <= i; } int min_in_class(int x) { int best = x; int i = x; while(1) { i = (*this)(i); if ( i == x ) return best; if ( i < best ) best = i; } } }; set_include_file(somedefs.h) HIDE( ![ extern "C" long randomx( ); #include extern bool demo; #include extern String calling_command; #include "stdio.h" #include "macros.h" #include "big.h" #include "numgf2.h" #include "prevector.h" #include "vector_.h" #include "cmp.h" #include "doubledouble.h" #include "inline.h" ]! ) set_compile_file(permutation.cc) HIDE( ![ // #define DEBUG class Permutation; #include "somedefs.h" #include "permutation.h" ]! ) TEX(![ For the following routine, the {\tt bool} argument is not used -- it is just there to prevent the compiler from getting confused. ]!) EquivRelIntList::EquivRelIntList(const vector& v, bool b) : vector(v.length) { for ( int i = 0; i < length; i++ ) { int j; for ( j = i+1; j < length; j++ ) if ( v(j) == v(i) ) { (*this)(i) = j; break; } if ( j == length ) for ( j = 0; j <= i; j++ ) if ( v(j) == v(i) ) { (*this)(i) = j; break; } } } index_method(equiv) bool EquivRelIntList::equiv(int a, int b) const { if ( a == b ) return true; int c = a; while ( (c = (*this)(c)) != a ) if ( c == b ) return true; return false; } index_method(join) void EquivRelIntList::join(int a, int b) { if ( a == b ) return; // Determine if a is already equivalent to b. // Also, find out what comes before a. int c = (*this)(a), before_a = a; while( c != a ) { if ( c == b ) return; // a ~ b already before_a = c; c = (*this)(c); } // Make a equivalent to b. (*this)(before_a) = (*this)(b); (*this)(b) = a; } index_method(size) int EquivRelIntList::size(int a) const { int s = 1, b = a; while( (b = (*this)(b)) != a ) s++; return s; } index_method(orbit_count) int EquivRelIntList::orbit_count( ) const { int count = 0; for ( int i = 0; i < length; i++ ) { int a = (*this)(i); int b = a; while ( (b = (*this)(b)) != a ) if ( b < a ) break; if ( a == b ) count++; } return count; } index_method(orbit) SLList EquivRelIntList::orbit(int f) const { SLList L; L.append(f); int n = f; while(1) { n = (*this)(n); if ( n == f ) return L; L.append(n); } } TEX(![ \block{Permutation, Permutationlist classes} The {\tt Permutation} class we define is inefficient for a number of reasons, including the fact that for our implementation, a Permutation of $n$ requires (on most machines) $2n$ bytes to store, yet if $n < 256$, certainly $n$ bytes are sufficient. \indexz{Permutation}\mindex{mul} ]!) set_include_file(permutation.h) index_method(inverse) index_method(enlarge) index_method(order) index_method(pmul) class Permutation : public vector { public: Permutation(const String&); Permutation(int); // construct the identity Permutation Permutation(const EquivRelIntList&); Permutation( ) { } Permutation(const Permutation& p) : vector(p) { } Permutation(const vector& v) : vector(v) { } Permutation inverse( ) const { Permutation p(length); for ( int i = 0; i < length; i++ ) p( (*this)(i) - 1 ) = i + 1; return p; } void act(prevector&) const; void act(prevector&) const; void act(prevector&) const; void act(prevector&) const; void act(prevector&) const; void act(prevector&) const; void act(prevector< vector >&) const; void enlarge(int n) { int k = length; if ( n < k ) INTERNAL_ERROR( "Permutation::enlarge" ); resize(n); for ( int i = k; i < n; i++ ) (*this)(i) = i + 1; } void transpose(int,int); // p |--> transpose(i,j) o p String as_cycle_product( ) const; prevector< prevector > orbits( ); HIDE( ![ friend Permutation operator*(const Permutation&, const Permutation&); ]! ) int order( ) const { Permutation p(*this), id(length); int o = 1; while(1) { if ( p == id ) return o; o++; p = p * (*this); } } friend void pmul(const Permutation& p1, const Permutation& p2, Permutation& q) { q.set_size( p1.length ); for ( int i = 0; i < p1.length; i++ ) q(i) = p1( p2(i) - 1 ); } HIDE( ![ friend ostream& operator<<(ostream&, const Permutation&); ]! ) }; set_compile_file(permutation.cc) HIDE( ![ prevector unpack(String s, String delim = ","); ]! ) Permutation::Permutation(const String& s) { if ( s[0] != '(' ) { *this = vector(s); for ( int i = 1; i <= length; i++ ) { int j; for ( j = 0; j < length; j++ ) if ( (*this)(j) == i ) break; if ( j == length ) ERROR("invalid Permutation"); } } else { String t = s; t.gsub( ")(", "|" ); t.gsub( "(", "" ); t.gsub( ")", "" ); prevector cycles = unpack( t, '|' ); prevector< prevector > cyclesv( cycles.length ); int i, j; for ( i = 0; i < cycles.length; i++ ) cyclesv(i) = cycles(i); int n = 0; for ( i = 0; i < cyclesv.length; i++ ) for ( j = 0; j < cyclesv(i).length; j++ ) n = max(n, int(cyclesv(i)(j))); Permutation p(n); for ( i = cycles.length - 1; i >= 0; i-- ) { prevector v = cyclesv(i); Permutation cyc(n); for ( j = 0; j < v.length; j++ ) { if ( j < v.length - 1 ) cyc( v(j) - 1 ) = v(j + 1); else cyc( v(j) - 1 ) = v(0); } p = cyc * p; } *this = p; } } Permutation::Permutation(int n) : vector(n) { for ( int i = 0; i < n; i++ ) (*this)(i) = i+1; } index_method(act) #define PERMUTATION_ACT(TYPE) \ void Permutation::act(prevector& v) const \ { TYPE* x_new = new TYPE[v.length]; \ for ( int i = 0; i < v.length; i++ ) \ x_new[(*this)(i) - 1] = v(i); \ delete [ ] v.x; \ v.x = x_new; } PERMUTATION_ACT(gf2) PERMUTATION_ACT(number) PERMUTATION_ACT(Rational) PERMUTATION_ACT(double) PERMUTATION_ACT(doubledouble) PERMUTATION_ACT(Big) PERMUTATION_ACT(vector) TEX(![ There are two routines to compose two Permutations, using function composition order. The first is invoked by {\tt*}, whereas the second (see class definition) is a three-argument function {\tt pmul}, whose third argument is the result. These routines do no validity checking whatsoever. The second routine should be used where efficiency is critical. \mindex{operator*(Permutation, Permutation)} ]!) Permutation operator*(const Permutation& p1, const Permutation& p2) { Permutation p = Permutation(p1.length); for ( int i = 0; i < p1.length; i++ ) p(i) = p1( p2(i) - 1 ); return p; } index_method(transpose) void Permutation::transpose(int i, int j) { for ( int k = 0; k < length; k++ ) { if ( (*this)(k) == i ) (*this)(k) = j; else if ( (*this)(k) == j ) (*this)(k) = i; } } ostream& operator<<(ostream& s, const Permutation& p) { for ( int i = 0; i < p.length; i++ ) { s << p(i); if ( i < p.length-1 ) s << ","; } return s; } TEX( Construct a random Permutation which is subordinate to the given equivalence relation. The implementation is very inefficient. ) Permutation::Permutation(const EquivRelIntList& e) : vector(e.length) { int y, i, j; for ( i = 0; i < e.length; i++ ) { while(1) { y = (randomx( ) % length) + 1; for ( j = 0; j < i; j++ ) if ( y == (*this)(j) ) break; if ( j != i ) continue; if ( e.equiv(i, y-1) ) break; } (*this)(i) = y; } } index_method(as_cycle_product) String Permutation::as_cycle_product( ) const { String ans; vector used(length); for ( int i = 0; i < length; i++ ) { if ( used(i) || (*this)(i) == i+1 ) continue; used(i) = 1; ans += String("(") + dec(i+1); int j = i; while(1) { j = (*this)(j) - 1; if ( j == i ) break; used(j) = 1; ans += String(",") + dec(j+1); } ans += ")"; } return ans; } TEX( ![ \verb|Permutation::orbits|:\ Given a permutation $p$ of $n$, return a list of list of integers. The first list consists of the integers (between $0$ and $n-1$) which are fixed by $p$. The remaining lists consist of the nonsingleton orbits of the cyclic group generated by $p$, acting on $0,\ldots,n-1$. Each orbit is ordered so it has the form $i, p(i), p(p(i)), \ldots$ for some $i$. ]! ) index_method(orbits) prevector< prevector > Permutation::orbits( ) { SLList singletons; SLList< prevector > ns_orbits; for ( int i = 0; i < length; i++ ) { if ( (*this)(i) == i + 1 ) singletons.append(i); else { int order = 0; int j = i; SLList orb; do { j = (*this)(j) - 1; orb.append(j); ++order; } while ( j > i ); if ( j < i ) continue; ns_orbits.append( orb ); } } prevector< prevector > answer( ns_orbits.length( ) + 1 ); answer(0) = singletons; int count = 1; forPixDef( p, ns_orbits ) answer( count++ ) = ns_orbits(p); return(answer); } TEX(![ {\tt orbit}:\ Let a group $G = \inn{\VEC g1n}$ act on an ordered set $S$. Let $x \in S$. Compute $Gx$, or else an $M$-element subset of $Gx$ if $M \geq 0$. The method is very similar to that of {\tt minimal}, p.\ \pageref{bool-minimal}. ]!) set_compile_file(code.c) index_method(orbit) template void orbit( const prevector& Q, const S& x, prevector& X, int (*cmp)(const S&, const S&), void (*act)(const G&, const S&, S&), int M = -1 ) { prevector Xa(0), Xb(1), Xc, Xt; Xb(0) = x; int i, j, k, c, n = Q.length; while(1) { merge( Xa, Xb, Xt, cmp ); // Merge Xa and Xb to get new Xa. if ( M < 0 || Xt.length < M ) Xa = Xt; else { X.set_and_take(Xt, M); return; } Xc.set_size( n * Xb.length ); for ( i = 0; i < n; i++ ) for ( j = 0; j < Xb.length; j++ ) act( Q(i), Xb(j), Xc( i + n * j) ); Xc.unique_sort(cmp); diff( Xc, Xa, Xb, cmp ); // Set Xb = Xc - Xa. if ( Xb.length == 0 ) { X = Xa; return; } } } set_compile_file(permutation.cc) index_method(pcmp) int pcmp( const Permutation& a, const Permutation& b ) { register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i).x > b(i).x ) return 1; if ( a(i).x < b(i).x ) return -1; } return 0; } HIDE( ![ template void orbit( const prevector&, const S&, prevector&, int (*cmp)(const S&, const S&), void (*act)(const G&, const S&, S&), int = -1 ); ]! ) TEX( \indexz{Permutationlist} \mindex{clear} \mindex{generate} \mindex{append} ) set_include_file(permutationlist.h) class Permutationlist : public vector { public: int n; // length of the Permutation // generate -- see documentation given below void generate( const Permutationlist& S, int M = -1 ) { Permutation x(n); prevector& me = *this; orbit( prevector(S), x, me, pcmp, pmul, M ); } Permutationlist( String ); Permutationlist( int n = 0 ) : n(n) { set_size(0); } void append( const Permutation& p ) { Permutationlist l(n); l.set_size( length + 1 ); for ( int i = 0; i < length; i++ ) l(i) = (*this)(i); l(length) = p; *this = l; } void clear( ) { set_size(0); } bool minimal( const vector& ) const; void find_conjugacy_classes( const Permutationlist& S ) { Permutationlist G( S.n ); G.generate( S ); clear( ); int i, j; for ( i = 0; i < G.length; i++ ) { for ( j = 0; j < G.length; j++ ) { Permutation q1, q2; pmul( G(j), G(i), q1 ); pmul( q1, G(j).inverse( ), q2 ); if ( q2 < G(i) ) break; } if ( j == G.length ) append( G(i) ); } } }; set_compile_file(permutation.cc) HIDE(![#include "permutationlist.h"]!) Permutationlist::Permutationlist( String s ) { SLList perms; String perm; int i, j; int paren_count = 0; for ( i = 0; i < s.length( ); i++ ) { if ( paren_count == 0 && s[i] == ',' ) { perms.append(perm); perm = ""; continue; } if ( s[i] == '(' ) paren_count++; else if ( s[i] == ')' ) paren_count--; perm += s[i]; } perms.append(perm); set_size( perms.length( ) ); j = 0; forPixDef( p, perms ) (*this)(j++) = perms(p); n = 0; for ( j = 0; j < length; j++ ) n = max( n, (*this)(j).length ); for ( j = 0; j < (*this).length; j++ ) (*this)(j).enlarge(n); } TEX(![ {\tt Permutationlist::generate(S, M)} -- {\tt S} is to be an arbitrary list of Permutations, and {\tt M} is to be a positive integer (or $-1$, which is treated as $+\infty$). Replace {\tt*this} by the group generated by {\tt S}; upon exit it is sorted. However, if during the generation process more than {\tt M} elements are encountered, the ``group'' will consist only of the first {\tt M} elements generated. We use a primitive algorithm. A much better algorithm is due to Sims ([.sims 1970.]\ \S4) and there have been improvements since then due to Leon [.leon strong generating set.], [.leon finding order.] and others. There are implementations in the GAP [.groups algorithms programming.] and MAGMA packages, and others. More recent approaches are given in [.leon permutation group algorithms 1991.] and [.sims book 1994.]. The book [.butler fundamental algorithms.] has a very readable discussion. ]!) TEX(![ {\tt Permutationlist::minimal(vector v)} -- The {\tt Permutationlist} (call it {\tt G}) acts on the vector {\tt v}, which should be sorted. If {\tt sort(gv)} $\geq$ {\tt v} for all {\tt g} $\in$ {\tt G}, return {\tt true}. Otherwise, return {\tt false}. The action is not by permuting the entries of the vector, but rather via the action on the individual elements of the vector. \mindex{minimal} ]!) bool Permutationlist::minimal(const vector& v) const { static vector w; w = v; register int i, j, k, n = w.length, best; for ( i = 0; i < length; i++ ) { for ( j = 0; j < n; j++ ) w(j) = (*this)(i)(v(j) - 1); // Determine if after sorting, w would be smaller than v. for ( j = 0; j < n; j++ ) { best = j; for ( k = j + 1; k < n; k++ ) if ( w(k) < w(best) ) best = k; if ( w(best) < v(j) ) return false; if ( w(best) > v(j) ) break; if ( best != j ) w(best) = w(j); } } return true; } set_compile_file(code.c) HIDE(![ #include "permutation.h" template void orbit( const prevector&, const Permutation&, prevector&, int (*)(const Permutation&, const Permutation&), void (*)(const Permutation&, const Permutation&, Permutation&), int ); int pcmp( const Permutation&, const Permutation& ); #include "permutationlist.h" ]! ) TEX( \block{Matrix class} ) index_class(matrix) index_method(transpose_columns) index_method(mul) index_method(set_size) index_method(leading_ones) index_method(set_col) index_method(transpose_of) index_method(inverse) index_method(invertible) index_method(select_col) set_include_file(matrix.h) template class matrix { public: TEX( ![ \classtextt{Data items} ]! ) vector* x; // the elements int nrows, ncols; TEX( ![ \classtext{ Constructors, the assigner, a resizer, and the destructor. A ``null matrix'' is one with $\verb|x| = 0$.} ]! ) matrix(int, int); matrix(int, String); matrix(String); matrix( ) { x = 0; } matrix(const matrix& ); matrix(const vector&); // make a row vector matrix(int, const SLList< vector >&); matrix& operator=(const matrix&); void set_size(int r, int c) { if ( x != 0 && nrows == r && ncols == c ) return; if ( x != 0 ) delete [ ] x; x = new vector[r]; nrows = r; ncols = c; for ( int i = 0; i < r; i++ ) { x[i].x = new T[c]; x[i].length = c; } } void resize(int r, int c) // Very inefficient. { matrix M(r, c); for ( int i = 0; i < min( r, nrows ); i++ ) for ( int j = 0; j < min( c, ncols ); j++ ) M(i, j) = (*this)(i, j); (*this) = M; } ~matrix( ) { if ( x != 0 ) delete [ ] x; } TEX( ![ \classtextt{Access to elements, rows, and columns} ]! ) T& operator( )(int i, int j) const { #ifdef DEBUG if ( x == 0 || i < 0 || i >= nrows || j < 0 || j >= ncols ) INTERNAL_ERROR( "Illegal matrix reference." ); #endif return x[i].x[j]; } vector& operator( )(int i) const { #ifdef DEBUG if ( x == 0 || i < 0 || i >= nrows ) INTERNAL_ERROR( "Illegal row reference." ); #endif return x[i]; } void set_col(int c, vector v) { for ( int i = 0; i < nrows; i++ ) (*this)(i,c) = v(i); } vector col(int i) const { #ifdef DEBUG if ( x == 0 || i < 0 || i >= ncols ) INTERNAL_ERROR( "Illegal column reference." ); #endif vector answer(nrows); for ( int j = 0; j < nrows; j++ ) answer(j) = (*this)(j, i); return answer; } matrix select(const vector&, const vector&) const; matrix select_col(vector w) { matrix A( nrows, w.weight( ) ); int col_ptr = 0; for ( int i = 0; i < ncols; i++ ) if ( w(i) ) { for ( int j = 0; j < nrows; j++ ) A(j, col_ptr) = (*this)(j, i); col_ptr++; } return A; } matrix submatrix( int rows, int cols, int first_row, int first_col ) const { matrix A( rows, cols ); for ( int i = 0; i < rows; i++ ) for ( int j = 0; j < cols; j++ ) A(i, j) = (*this)( i + first_row, j + first_col ); return A; } TEX( ![ \classtextt{Permute entries} ]! ) void permute_columns(const Permutation&); void set_permutation_matrix(const Permutation&); void transpose_columns(int i, int j) { for ( int k = 0; k < nrows; k++ ) swap( (*this)(k,i), (*this)(k,j) ); } Permutation* column_fix( ); void transpose_equals(matrix&) const; friend matrix sort( matrix M ) { prevector< vector > cols(M.ncols); for ( int i = 0; i < M.ncols; i++ ) cols(i) = M.col(i); cols.sort( &cmp ); for ( int i = 0; i < M.ncols; i++ ) M.set_col(i, cols(i)); return M; } TEX( ![ \classtextt{Arithmetic} ]! ) bool fixes( const vector&); friend matrix transpose_of( const matrix& A ) { if ( A.x == 0 ) INTERNAL_ERROR( "transpose_of" ); matrix B( A.ncols, A.nrows ); for ( int i = 0; i < A.nrows; i++ ) for ( int j = 0; j < A.ncols; j++ ) B(j,i) = A(i,j); return B; } friend matrix operator+(const matrix& A, const matrix& B) { HIDE( ![ if (A.x == 0 || B.x == 0 || A.nrows != B.nrows || A.ncols != B.ncols) INTERNAL_ERROR("matrix addition"); ]! ) matrix M(A.nrows, A.ncols); for ( int i = 0; i < A.nrows; i++ ) for ( int j = 0; j < A.ncols; j++ ) M(i,j) = A(i,j) + B(i,j); return M; } TEX( ![ \classtextt{Other methods} ]! ) void set_zero( ) { int i, j; for ( i = 0; i < nrows; i++ ) for ( j = 0; j < ncols; j++ ) (*this)(i,j) = 0; } void delete_column(int r) { matrix B( nrows, ncols-1 ); for ( int j = 0; j < r; j++ ) for ( int l = 0; l < nrows; l++ ) B(l,j) = (*this)(l,j); for ( int j = r+1; j < ncols; j++ ) for ( int l = 0; l < nrows; l++ ) B(l,j-1) = (*this)(l,j); *this = B; } void delete_columns( vector dels ) { matrix B( nrows, ncols - dels.length ); int i, j, l = 0; for ( i = 0; i < ncols; i++ ) { if ( dels.member(i) ) continue; for ( j = 0; j < nrows; j++ ) B(j, l) = (*this)(j, i); l++; } *this = B; } vector leading_ones( ) const { vector leading1s = vector(nrows); for ( int i = 0; i < nrows; i++ ) for ( int j = i; j < ncols; j++ ) if ( (*this)(i,j) != T(0) ) { leading1s(i) = j; break; } return leading1s; } bool orthogonal_to(const vector&) const; bool lu_decompose(Permutation&); vector char_poly( ) const; bool nilpotent( ) const; void solve_from_lu(const Permutation&, const vector&, vector&); void solve_from_lu_t(const Permutation&, const vector&, vector&); friend inline bool operator!=(const matrix& m1, const matrix& m2) { return !(m1 == m2); } int reduce( ); // in place conversion to reduced row echelon form void reduce_i(matrix&); // same but the argument is set equal to an // invertible matrix which does it void remove_zero_rows_at_bottom( ); void reduce_nz( ); // nullspace_equals(D) -- The matrix "this" should be in RREF and have no // zero rows. Set D to a matrix whose rows form a basis for // nullspace(*this). void nullspace_equals(matrix&) const; vector enumerate_weights( ) const; bool rowspace_member(vector) const; vector coord_vector(vector) const; // Requires RREF. operator String( ) const { String s = "{"; for ( int i = 0; i < nrows; i++ ) { s += (*this)(i); if ( i < nrows - 1 ) s += ","; } return s + "}"; } void set_identity( int n ) { set_size(n, n); for ( int i = 0; i < n; i++ ) for ( int j = 0; j < n; j++ ) (*this)(i, j) = (i == j); } matrix inverse( ); // No safety test! bool invertible( ) const; bool reduced( ) const; int order( ) const; }; template inline void mul(const matrix& M, const vector& v, vector& prod) { prod.set_size(M.nrows); for ( int i = 0; i < M.nrows; i++ ) { T sum = 0; for ( int j = 0; j < v.length; j++ ) sum += M(i,j) * v(j); prod(i) = sum; } } HIDE( ![ template void mul(const matrix&, const matrix&, matrix&); template void mul(const vector&, const matrix&, vector&); template void xA_minus_c_eq(const vector&, const matrix&, const vector&, vector&); template void update(matrix&, Permutation&, Permutation&, const vector&, int); template void solve_Ax_eq_b(const matrix&, vector&, const vector&); template bool operator==(const matrix&, const matrix&); template void hcat(const matrix&, const matrix&, matrix&); template void vcat(const matrix&, const matrix&, matrix&); void rowspace_intersection(const matrix&, const matrix&, matrix&); void intersect_dual(const matrix&, matrix&); int rank_of_rowspace_sum(const matrix&, matrix&); template ostream& operator<<(ostream&, const matrix&); template istream& operator>>(istream&, matrix&); ]! ) set_compile_file(matreal.cc) HIDE( ![ // #define DEBUG class Permutation; #include "somedefs.h" #include "permutation.h" template void orbit( const prevector&, const S&, prevector&, int (*cmp)(const S&, const S&), void (*act)(const G&, const S&, S&), int = -1 ); int pcmp( const Permutation&, const Permutation& ); #include "permutationlist.h" #include "matrix.h" ]! ) TEX( ![ \verb|lu_decompose|:\ Compute the $LU$ decomposition of an $n \times n$ invertible matrix $A$ using row-oriented partial pivoting. We find a unit lower triangular matrix $L$, an upper triangular matrix $U$, and a permutation matrix $P$ such that $A = PLU$. Upon entry {\tt *this} is to be $A$. Upon exit it is replaced by $L - I + U$. If in the process of computation it is found that $A$ is not invertible, {\tt false} is returned; otherwise {\tt true} is returned. We start with $P = I$. As we proceed through the proof, $P$ changes, and for expository purposes, we let $M$ denote the matrix product $P^{-1} \cdot (\verb|*this|)$. ]! ) index_method(lu_decompose) template bool matrix::lu_decompose(Permutation& P) { matrix& me = *this; HIDE( ![ if ( nrows != ncols ) INTERNAL_ERROR( "lu_decompose called with non-square matrix" ); ]! ) int& n = nrows; static vector pivotindices; pivotindices.set_size(n-1); P = Permutation(n); int i, j, k, m, pivotindex; T x, biggest, pivot, mult; TEX( ![ \begin{quote} The current column is $k$. \end{quote} ]! ) for ( k = 0; k < n-1; k++ ) { TEX( ![ \begin{quoteaneg} Find the entry of $M$ in the current column (on or below the diagonal) which has the largest absolute value. Let {\tt pivotindex} be its row index. \end{quoteaneg} ]! ) biggest = 0; for ( i = k; i < n; i++ ) { x = abs( me( P(i)-1, k ) ); if ( x > biggest ) { biggest = x; pivotindex = i; } } if ( biggest == T(0) ) return false; TEX( ![ \begin{quotea} Replace $P$ by $P \circ (k \leftrightarrow \verb|pivotindex|)$, thereby in effect swapping rows $k$ and {\tt pivotindex} of $M$. \end{quotea} ]! ) if ( pivotindex != k ) swap( P(k), P(pivotindex) ); pivotindices(k) = pivotindex; TEX( ![ \begin{quotea} In effect execute the following code: \begin{classboxedquotefour} \verb|for ( i = k + 1; i < n; i++ )|\\ \verb|{ M(i,k) /= M(k,k);|\\ \verb| for ( j = k + 1; j < n; j++ )|\\ \verb| M(i,j) -= M(i,k) * M(k,j); }| \end{classboxedquotefour} \end{quotea} ]! ) pivot = me( P(k)-1, k ); m = P(k)-1; T* v = me(m).x; for ( i = k+1; i < n; i++ ) { T* w = me( P(i)-1 ).x; mult = w[k] / pivot; w[k] = mult; if ( mult != T(0) ) { for ( j = k + 1; j < n; j++ ) w[j] -= mult * v[j]; } } } TEX( ![ \begin{quote} At this point, {\tt *this} is $P(L - I + U)$. We change it into $L - I + U$. \end{quote} ]! ) for ( i = 0; i <= n-2; i++ ) if ( i != pivotindices(i) ) swap( me(i), me(pivotindices(i)) ); return me( n-1, n-1 ) != T(0); } HIDE( ![ template bool matrix::lu_decompose(Permutation&); template bool matrix::lu_decompose(Permutation&); template bool matrix::lu_decompose(Permutation&); template bool matrix::lu_decompose(Permutation&); template bool matrix::lu_decompose(Permutation&); ]! ) set_compile_file(woof.cc) HIDE(![#include "basedefs.h"]!) matrix matrix::inverse( ) { matrix calc, ans( nrows, nrows ), I; I.set_identity(nrows); hcat( *this, I, calc ); calc.reduce( ); for ( int i = 0; i < nrows; i++ ) for ( int j = 0; j < nrows; j++ ) ans(i, j) = calc(i, j + nrows); return ans; } bool matrix::invertible( ) const { if ( nrows != ncols ) return false; matrix M = *this; return M.reduce( ) == ncols; } index_method(reduced) bool matrix::reduced( ) const { matrix M = *this; M.reduce_nz( ); return M == *this; } index_method(order) int matrix::order( ) const { const matrix& M = *this; matrix A = M, I, A_temp; I.set_identity( nrows ); int count = 1; while(1) { if ( A == I ) return count; mul( A, M, A_temp ); A = A_temp; count++; } } TEX( ![ \verb|solve_from_lu|:\ Start with an invertible matrix $A$ and a vector $b$. Solve $Ax = b$ for $x$. Upon entry {\tt *this} and {\tt P} are to be the $LU$-decomposition of $A$ coming from \verb|lu_decompose|. The code is based on the code given in [.forsythe moler.]\ pp.\ 59--60. ]! ) index_method(solve_from_lu) template void matrix::solve_from_lu(const Permutation& P, const vector& b, vector& x ) { matrix& lu = *this; int i, j, n = nrows; x.set_size(n); T dot; T* xx = x.x; for ( i = 0; i < n; i++ ) { dot = 0; T* v = lu(i).x; for ( j = 0; j < i; j++ ) dot += v[j] * xx[j]; xx[i] = b(P(i)-1) - dot; } for ( i = n-1; i >= 0; i-- ) { dot = 0; T* v = lu(i).x; for ( j = i+1; j < n; j++ ) dot += v[j] * xx[j]; xx[i] = (xx[i] - dot) / v[i]; } } INSTANTIATE( ![class matrix]!, T, double, doubledouble, Big, Rational ) INSTANTIATE( ![void matrix::solve_from_lu(const Permutation&, const vector&, vector&) ]!, T, double, doubledouble, Big, Rational ) TEX( ![ \verb|solve_from_lu_t|:\ Start with an invertible matrix $A$ and a vector $c$. Solve $y^T A = c^T$ for $y$. Upon entry {\tt *this} and {\tt P} are to be the $LU$-decomposition of $A$ coming from \verb|lu_decompose|. ]! ) index_method(solve_from_lu_t) template void matrix::solve_from_lu_t(const Permutation& P, const vector& c, vector& y ) { matrix& lu = *this; static vector z; z.set_size(nrows); y.set_size(nrows); int i, j; T dot; T* zx = z.x; for ( i = 0; i < nrows; i++ ) { dot = 0; for ( j = 0; j < i; j++ ) dot += lu(j, i) * zx[j]; zx[i] = (c(i) - dot) / lu( i, i ); } for ( i = nrows-1; i >= 0; i-- ) for ( j = i+1; j < nrows; j++ ) zx[i] -= lu(j, i) * zx[j]; for ( i = 0; i < nrows; i++ ) y( P(i)-1 ) = z( i ); } INSTANTIATE( ![void matrix::solve_from_lu_t(const Permutation&, const vector&, vector&) ]!, T, double, doubledouble, Big, Rational ) set_compile_file(matreal.cc) index_method(solve_Ax_eq_b) template void solve_Ax_eq_b(const matrix& A, vector& x, const vector& b) BHIDE1( ![ if ( A.nrows != A.ncols ) INTERNAL_ERROR( "solve_Ax_eq_b is only defined for square matrices A" ); ]!, ![ matrix LU = A; ]! ) Permutation P( A.nrows ); LU.lu_decompose(P); LU.solve_from_lu(P, b, x); } HIDE( ![ template void solve_Ax_eq_b(const matrix&, vector&, const vector&); template void solve_Ax_eq_b(const matrix&, vector&, const vector&); template void solve_Ax_eq_b(const matrix&, vector&, const vector&); template void solve_Ax_eq_b(const matrix&, vector&, const vector&); ]! ) TEX( ![ {\tt update}:\ Let $A$ be an $n \times n$ invertible matrix, and suppose one has an equation $AQ = PLU$, in which $P,Q$ are permutation matrices, $L$ is unit lower triangular, and $U$ is upper triangular. Let $v$ be an $n$-vector, let $k$ ($0 \leq k < n$) be given, and (using superscripts to denote columns) let $B = [A^0 \cdots A^{k-1} \kern2.5pt v \kern2.5pt A^{k+1} \cdots A^{n-1}]$, which we assume is invertible. Find $\oP$, $\oQ$, $\oL$, and $\oU$ (of the same types as $P$, $Q$, $L$, and $U$) such that $B \oQ = \oP \kern1.5pt \oL \kern1.5pt \oU$. Upon entry, {\tt LU} is to be $L - I + U$; it is replaced by $\oL - I + \oU$. The method we use is outlined in [.nazareth updating.] (also in [.nazareth book.]\ \S6.5), which presents a reformulation of the Fletcher-Matthews update [.fletcher matthews.]. (Regarding the role of $Q$, see [.nazareth book.]\ p.\ 118.) Let $R$ be the permutation matrix associated to the cycle $(n-1 \kern5pt n-2 \kern5pt \cdots \kern5pt Q^{-1}(k) \kern5pt Q^{-1}(k)-1)$.% \footnote{Note the probably unfortunate convention made in the {\tt Permutation} class that if $\sigma$ is a permutation of $n$, then $\setof{\sigma(0),\ldots,\sigma(n-1)} = \setof{1,\ldots,n}$. Also, we have identified permutations with permutation matrices.} The starting point for the update is that the matrix $H := L^{-1}P^{-1}BQR^{-1}$ is upper Hessenberg, i.e.\ it would be upper triangular except that it has nonzero entries on the diagonal below the main diagonal, starting in column $Q^{-1}(k)-1$. We work from that column rightward to clear these subdiagonal elements. The running time for this algorithm is $O(n^2)$; its raison d'\^etre is that refactorization of $B$ from scratch costs $O(n^3)$. ]! ) template void update(matrix& LU, Permutation& P, Permutation& Q, const vector& v, int k) { int n = LU.nrows, i, j; R* U_i; // to represent ith row of U R* U_ip; // to represent (i+1)st row of U R* L_j; // to represent jth row of L static Permutation Qi; // inverse of Q Qi = Q.inverse( ); TEX( ![ \begin{quote} The first task is to set up $H$, which is $UR^{-1}$ with the last column replaced by the solution $x$ to the equation $Lx = P^{-1}v$. We put the entries of $H$ on or above the diagonal into the existing space for $U$ (the upper half of $\verb|LU|$), and put the subdiagonal entries of $H$ into a separate vector $\verb|h|$. \end{quote} ]! ) static vector h, x; h.set_size(n-1); x.set_size(n); R dot; R* xx = x.x; for ( i = 0; i < n; i++ ) // i is row { U_i = LU.x[i].x; dot = 0; for ( j = 0; j < i; j++ ) dot += U_i[j] * xx[j]; xx[i] = v(P(i)-1) - dot; if ( i >= Qi(k) ) h(i-1) = U_i[i]; for ( j = max(i + 1, int(Qi(k))); j < n; j++ ) U_i[j-1] = U_i[j]; } for ( i = 0; i < n; i++ ) LU(i, n-1) = xx[i]; TEX( ![ \begin{quote} We have $BQR^{-1} = PLH$. Our job is to progressively modify $P$, $L$, and $H$ so that the subdiagonal entries of $H$ are cleared one by one, while maintaining the equation. \end{quote} ]! ) for ( i = Qi(k)-1; i < n-1; i++ ) { TEX( ![ \begin{quoteaneg} At this point $\verb|h|(j) = 0$ for $j < i$. Since $U$ was invertible, its diagonal entries were nonzero, and so the entries of $\verb|h|$ (for $j \geq Q^{-1}(k)-1$) were nonzero. As $\verb|h|(i)$ has not been changed, it is still nonzero. Note that $\verb|h|(i) = H(i+1, i)$. The current $H(i,i)$ may be smaller (in absolute value), in which case one would think that a row exchange is called for. However, we shall see that this is not always the case. Supposing that $H(i,i) \not= 0$, let $E$ be the elementary matrix corresponding to subtracting $\alpha := H(i+1,i)/H(i,i)$ times row $i$ from row $i+1$, and let $F$ be the elementary matrix corresponding to subtracting $\alpha^{-1}$ times row $i$ from row $i+1$. Let $T$ be the permutation matrix which exchanges rows $i$ and $i+1$, so $T = T^{-1}$. If we were to do a row exchange on $H$, we would be led to the equation $LH = (LTF^{-1})(FTH)$. Now $FTH$ is upper Hessenberg, but $LTF^{-1}$ is $$\bordermatrix{&&&&i&i+1\cr &1&&&0&0\cr &&\ddots&&\vdots&\vdots\cr &&&1&0&0\cr i&&&&\alpha^{-1}&1\cr i+1&&&&1+\alpha^{-1} L_{i+1,i} & L_{i+1,i}\cr &&&&L_{i+2,i+1}+ \alpha^{-1} L_{i+2,i} & L_{i+2,i}&1\cr &&&&\vdots&\vdots&&\ddots\cr &&&&\vdots&\vdots&&&1\cr},$$% which is not unit lower triangular. (Unmarked entries agree with those of $L$.) One has to in turn do an $LU$ factorization of this matrix. Again one has a choice as to whether to do a row exchange. If $\abs{\alpha^{-1}} \geq \abs{1 + \alpha^{-1} L_{i+1,i}}$ (or equivalently $\abs{\alpha + L_{i+1,i}} \leq 1$), one should not do a row exchange. But then after one does the $LU$ factorization of $LTF^{-1}$ (say as $\oL\kern1.5pt\oU$), then in fact $\oL(\oU FTH)$ is exactly the $LU$ factorization one would have obtained if one had never done a row exchange at all! This follows from the uniqueness of $LU$ factorizations. \end{quoteaneg} ]! ) static R alpha, alpha_inv, li; if ( LU(i,i) != R(0) ) alpha = h(i) / LU(i,i); alpha_inv = LU(i,i) / h(i); U_i = LU.x[i].x; U_ip = LU.x[i+1].x; li = U_ip[i]; if ( abs(h(i)) <= abs(LU(i,i)) || (LU(i,i) != R(0) && abs( alpha + li ) <= R(1)) ) { TEX( ![ \begin{quotebneg} This is the easy case. We have $LH = (LE^{-1})(EH)$. Replace $L$ by $LE^{-1}$ (still unit lower triangular) and replace $H$ by $EH$ (still upper Hessenberg, but with one more zero subdiagonal entry). Note that the action on $L$ (of multiplying on the right by $E^{-1}$) is to add $\alpha$ times column $i+1$ to column $i$. \end{quotebneg} ]! ) // h(i) = 0; // Not necessary to actually do it. for ( j = i+1; j < n; j++ ) U_ip[j] -= alpha * U_i[j]; LU(i+1, i) += alpha; for ( j = i+2; j < n; j++ ) // row j LU(j, i) += alpha * LU(j, i+1); } else { TEX( ![ \begin{quotebneg} This is the hard case. We have $LH = (LTF^{-1})(FTH)$. Whereas $FTH$ is upper Hessenberg and improved as before, $LTF^{-1}$ is (as noted above) not unit lower triangular. What we have to do is define the needed operations which would in principle bring about the $LU$ factorization (say as $\oP \kern1.5pt\oL\kern1.5pt\oU$) of this matrix. To understand this one should focus on the \th{i} and $(i+1)^{\operatoratfont st}$ rows and columns, defining a $2 \times 2$ submatrix. Then there are two subcases. The first subcase $\abs{\alpha^{-1}} \geq \abs{1 + \alpha^{-1} L_{i+1,i}}$ has already been dealt with. In the second subcase, $\abs{\alpha^{-1}} < \abs{1 + \alpha^{-1} L_{i+1,i}}$. Let $\ell = L_{i+1,i}$, $\lambda = \alpha + \ell$. The defining $2 \times 2$ factorization is $$\brmat{\alpha^{-1}&1\cr 1+\alpha^{-1} \ell & \ell} = \brmat{0&1\cr1&0} \brmat{1&0\cr \lambda^{-1} & 1} \brmat{1+\alpha^{-1} \ell&\ell\cr 0 & \alpha \lambda^{-1} }.$$% Now $\oP$ is the permutation matrix associated to transposing $i$ and $i+1$. We have $$\oL = \bordermatrix{&&&&i&i+1\cr &1&&&0&0\cr &&\ddots&&\vdots&\vdots\cr &&&1&0&0\cr &L_{i+1,0}&\cdots&L_{i+1,i-1}&1&0\cr &L_{i,0}&\cdots&L_{i,i-1}&\lambda^{-1}&1\cr &&&&{\alpha\lambda^{-1} L_{i+2,i+1} \atop + \lambda^{-1} L_{i+2,i}} & {L_{i+2,i} - \atop \ell L_{i+2,i+1}} & 1 \cr &&&&\vdots&\vdots&&\ddots\cr &&&&\vdots&\vdots&&&1\cr},$$ where those entries not marked agree with those of $L$, and $$\oU = I_i \o+ \brmat{\alpha^{-1}\lambda & \ell\cr 0 & \alpha\lambda^{-1}} \o+ I_{n-i-2} \hbox{\ \ (block diagonal decomposition).}$$% From this one calculates that $$\oU F T = I_i \o+ \brmat{ \ell & 1\cr \alpha\lambda^{-1} & -\lambda^{-1} } \o+ I_{n-i-2}.$$ \end{quotebneg} ]! ) static R M11, M21, M22neg; M11 = li; M22neg = alpha_inv / (R(1) + li * alpha_inv); M21 = R(1) / (R(1) + li * alpha_inv); // M12 = 1; TEX( ![ \begin{quoteb} We are thinking of {\tt M} as the $2 \times 2$ matrix which appears in $\oU F T$. We let it act on rows $i$ and $i+1$ of $H$, thereby updating $H$. \end{quoteb} ]! ) R temp; for ( j = i; j < n; j++ ) { if ( j == i ) temp = M11 * U_i[j] + h(i); else temp = M11 * U_i[j] + U_ip[j]; if ( j > i ) U_ip[j] = M21 * U_i[j] - M22neg * U_ip[j]; U_i[j] = temp; } // h(i) = 0; // Not necessary to actually do it. TEX( ![ \begin{quoteb} Update $L$, by letting a $2 \times 2$ matrix $N$ act on columns $i$ and $i+1$ of $L$. The entry in spot $(i+1,i)$ has to be separately set. Also exchange rows $i$ and $i+1$, for columns less than $i$. \end{quoteb} ]! ) for ( j = 0; j < i; j++ ) swap( LU(i,j), LU(i+1,j) ); #define N11 M22neg #define N22neg M11 #define N21 M21 // N12 = 1; for ( j = i+1; j < n; j++ ) { L_j = LU.x[j].x; if ( j == i + 1 ) L_j[i] = N11; else { temp = N11 * L_j[i] + N21 * L_j[i+1]; L_j[i+1] = L_j[i] - N22neg * L_j[i+1]; L_j[i] = temp; } } TEX( ![ \begin{quoteb} Update $P$, by multiplying it on the right by the permutation of $i$ and $i+1$. \end{quoteb} ]! ) swap( P(i), P(i+1) ); } } TEX( ![ \begin{quote} Update $Q$, by replacing it by $QR^{-1}$. \end{quote} ]! ) number t = Q( Qi(k)-1 ); for ( i = Qi(k)-1; i < n-1; i++ ) Q(i) = Q(i+1); Q(n-1) = t; } HIDE( ![ template void update(matrix&, Permutation&, Permutation&, const vector&, int); template void update(matrix&, Permutation&, Permutation&, const vector&, int); template void update(matrix&, Permutation&, Permutation&, const vector&, int); template void update(matrix&, Permutation&, Permutation&, const vector&, int); ]! ) set_include_file(simplex.h) TEX( ![ \block{A provisional implementation of the simplex method} The class \verb|exact_lp_problem| encodes the following notion of a \LP\ problem. It is a list of linear constraints, equality or inequality, involving variables $\verb|v|1,\ldots\verb|v|n$ with integer coefficients (and an integer \RHS), together with a list of linear objectives (having $\Q$ coefficients), to be maximized or minimized over $(\Q^{\geq 0})^n$. The constraints ({\tt vconstraint}'s) are at present stored on a single file. It would be nice to later reimplement with a ``virtual prevector'' class, which would allow for multiple files (or pipes) or in-memory storage, transparent to the ``user''. We define the optimum value of an objective function as an extended real number. We regard two \verb|exact_lp_problem|s as being {\it equivalent\/} if they have the same number of objectives (= {\tt obj.length}) and those objectives have the same optimum value. ]! ) index_class(exact_lp_problem) class exact_lp_problem { public: TEX( ![ \classtext{ The first entry signals that the problem is infeasible (if it is). In that case, everything else is to be ignored.} ]! ) bool known_to_be_infeasible; int n; // number of variables int m; // total number of constraints int m_eq; // number of constraints which are equality constraints TEX( ![ \classtext{ The first part of the objective vector entry is its constant component. The second part contains the coefficients of the variables in the objective function. The third part is ``{\tt max}'' or ``{\tt min}''.} ]! ) prevector< triple< Rational, vector, String > > obj; String con_file; // constraint file exact_lp_problem( ) : known_to_be_infeasible(false), obj(0) { } Integer presolve( ); String show_infeasible_by_primal_simplex(const vconstraint&); String show_infeasible_by_primal_simplex_on_dual(const vconstraint&); extend bound_by_primal_simplex_on_dual( ); }; TEX( ![ The class \verb|canonical_lp_problem| encodes the following notion of a \LP\ problem in canonical form, as given e.g.\ in ([.nazareth book.]\ p.\ 5). For $A$ an $m \times n$ matrix over $\R$ (with $m \leq n$), $x, c \in \R^n$, $b \in \R^m$, and $l, u$ vectors, each of $n$ extended real numbers ($l \leq u$), we are to minimize $c^T x$, subject to the constraints $Ax = b$ and $l \leq x \leq u$. Moreover, we assume given a choice (the {\it basis}) of $m$ columns of $A$, preferably independent columns. The number {\tt slacks} gives the number of variables which are regarded as slack variables. (The first $\verb|n|-\verb|slacks|$ variables are to be regarded as non-slack variables.) This is at present used only by the input ({\tt istream}) routine, to facilitate the reading in of noncanonical lp problems. The class is templated over a class {\tt R} which is to be an exact or approximate real number class. For computational efficiency, we store the transpose of $A$ rather than $A$ itself. \def\AsubB{\verb|A|_{\tiny\verb|B|}}\def\AsubN{\verb|A|_{\tiny\verb|N|}} \def\ysubB{\verb|y|_{\tiny\verb|B|}}\def\ysubN{\verb|y|_{\tiny\verb|N|}} \def\xsubB{\verb|x|_{\tiny\verb|B|}}\def\xsubN{\verb|x|_{\tiny\verb|N|}} \def\csubB{\verb|c|_{\tiny\verb|B|}}\def\csubN{\verb|c|_{\tiny\verb|N|}} \def\ssubB{\verb|s|_{\tiny\verb|B|}}\def\ssubN{\verb|s|_{\tiny\verb|N|}} ]! ) index_class(canonical_lp_problem) index_method(valid) template class canonical_lp_problem { public: int m; // number of rows in A int n; // number of columns in A (number of variables) int slacks; // number of variables which are slack variables matrix At; // transpose of A vector b, c, x; vector< extend > l, u; TEX( ![ \classtextt{ To find the actual matrix {\tt A}, multiply row $i$ of it by {\tt row\string_dividers}$(i)$, for each $i$. } ]! ) vector row_dividers; TEX( ![ \classtextt{ The {\tt basis} is an unordered list of $m$ distinct integers between $0$ and $n-1$. } ]! ) prevector basis; prevector if_basis; TEX( ![ \classtext{The routine {\tt simple\string_simplex} maintains a factorization of the form $\AsubB \verb|Q| = \verb|PLU|$, where $P$ and $Q$ are permutation matrices. Here $\AsubB$ is the matrix whose columns are the basis rows of {\tt At}. } ]! ) matrix LU; Permutation P, Q; matrix A_B; vector x_B; vector b_minus; static R tolx; TEX( ![ \classtextt{Routine to recompute {\tt x}.} ]! ) void recompute_x( ) { b_minus = b; for ( int i = 0; i < n; i++ ) { if ( !if_basis(i) && x(i) != R(0) ) for ( int k = 0; k < m; k++ ) b_minus(k) -= At(i,k) * x(i); } LU.solve_from_lu( P, b_minus, x_B ); Q.act(x_B); for ( int i = 0; i < m; i++ ) x(basis(i)) = x_B(i); } TEX( ![ \classtextt{Routine to randomly perturb {\tt b}.} ]! ) void perturb(double pert_factor) { R max_random(tolx), pf(tolx); assign( pf, pert_factor ); assign( max_random, Ipow(2,31) - 1 ); R pfm = pf / max_random; for ( int i = 0; i < b.length; i++ ) { R bmult(tolx), rx(tolx); double drx = randomx( ); assign( rx, drx ); assign( bmult, R(1.0) + pfm * rx ); b(i) = bmult * b(i); } } canonical_lp_problem(int m, int n) : m(m), n(n), At(n,m), b(m), b_minus(m), c(n), x(n), l(n), u(n), basis(m), if_basis(n), A_B(m,m), LU(m,m), P(m), Q(m), x_B(m), row_dividers(m) { } R objective( ) { R obj = 0; for ( int i = 0; i < n; i++ ) if ( if_basis(i) || l(i).nonzero( ) ) obj += c.x[i] * x.x[i]; return obj; } R infeasibility( ) { R infeas = 0; for ( int i = 0; i < n; i++ ) if ( x(i) + tolx < l(i) ) infeas += R(l(i)) - x(i); return infeas; } pair status( ) { R inf = infeasibility( ); if ( inf > R(0) ) return make_pair(false, inf); else return make_pair(true, objective( )); } TEX( ![ \classtextt{Check if problem is correctly posed. } ]! ) bool valid( ) const { if ( m > n || At.x == 0 || b.x == 0 || c.x == 0 || l.x == 0 || u.x == 0 || basis.x == 0 ) return false; if ( At.nrows != n || At.ncols != m || b.length != m || c.length != n || l.length != n || u.length != n || basis.length != m ) return false; for ( int i = 0; i < m; i++ ) { if ( basis(i) < 0 || basis(i) >= n ) return false; for ( int j = i+1; j < m; j++ ) if ( basis(i) == basis(j) ) return false; } return true; } extend simple_simplex(vector&, vector&, bool&, bool = false); }; HIDE( ![ template istream& operator>>(istream&, canonical_lp_problem&); template bool check_infeasible(istream&, canonical_lp_problem&, vector&, const vconstraint&); ]! ) // Assignment operators ( x := y ). index_method(assign) template inline void assign(S& x, const T& y) { x = y; } inline void assign( Rational& x, const double& y ) { x = Rational(y); } inline void assign( doubledouble& x, const Integer& y ) { x = atodd(dec(y)); } inline void assign( double& x, const Rational& y ) { x = double(y); } inline void assign( doubledouble& x, const Rational& y ) { x = atodd(dec(y.numerator( ))) / atodd(dec(y.denominator( ))); } inline void assign( Rational& x, const doubledouble& y ) { x = Rational(y.h( )) + Rational(y.l( )); } inline void assign( Big& x, const doubledouble& y ) { Rational z; assign( z, y ); x.set_precision(2); x = z; } inline void assign( Rational& x, const Big& y ) { // The code here was "x = Rational(y);" but it wouldn't compile under // ecgs 1.1. So I copied operator Rational from class Big. long exp; char* s = mpf_get_str( 0, &exp, 10, 0, y.body ); if ( s[0] == 0 ) { x = 0; return; } int i = 0; while ( s[i] != 0 ) ++i; if ( s[0] == '-' ) --i; int r = exp - i; Integer m(s); free(s); if ( r >= 0 ) x = Rational( m * Ipow(10, r), 1 ); else x = Rational( m, Ipow(10, -r) ); } inline void assign( double& x, const doubledouble& y ) { x = y.h( ); } set_compile_file(simplex.cc) #include HIDE( ![ #include "homedefs.h" #include "simplex.h" #include "math.h" #include extern long time_used_presolving; extern long time_used_by_check_infeasible; extern long time_used_by_simple_simplex; extern long time_used_setting_up_simplex_problem; extern int refactorization_rate, partial_pricing, homebrew_dump; extern int homebrew_full_report, homebrew_speedy, iteration_limit; extern int price_refinement_count, full_reduction, warnings_are_fatal; extern int current_precision, toldj_percent, verify_feasibility; extern int tolpiv_percent, dump_cost; extern "C" long randomx( ); void log2( const Integer&, Integer&, Integer& ); Integer round_down_to_power_of_2(Integer); template bool check_infeasible(istream&, canonical_lp_problem&, vector&, const vconstraint&); void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans); void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans); void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans); void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans); inline bool test(const Rational& a, const Rational& b, char sense) { if ( sense == '=' ) return a == b; if ( sense == '<' ) return a <= b; return a >= b; } ]! ) TEX( ![ \verb|presolve|:\ Create a new problem, equivalent to the given problem, but which has no $\leq$ constraints, and for which (more importantly) the equality constraints are independent. Also, we determine if any of the inequalities can be deduced (or found contradictory) from the system of equations. Return an integer which is (usually) the maximum of the absolute value of the entries in the system. ]! ) index_method(presolve) Integer exact_lp_problem::presolve( ) { int i, j, k; Integer max_entry = 0; if ( known_to_be_infeasible ) return 1; time_used_presolving -= time(0); vconstraint v(n); SLList vs; ofstream out1( calculations_dir + "/elim_eq_temp" ); ifstream in1(con_file); while( in1.peek( ) != EOF ) { in1 >> v; if ( v.sense == '=' ) vs.append(v); if ( v.sense == '<' ) { for ( i = 0; i < n; i++ ) v.LHS(i) = -v.LHS(i); v.RHS = -v.RHS; v.sense = '>'; } if ( v.sense == '>' ) out1 << v; } in1.close( ); out1.close( ); TEX( ![ \begin{quote} Now put the equality constraints into a matrix and reduce it. \end{quote} ]! ) matrix eqs( vs.length( ), n+1 ); int current_row = 0; forPixDef( p, vs ) { for ( i = 0; i < n; i++ ) eqs( current_row, i ) = vs(p).LHS(i); eqs( current_row++, n ) = vs(p).RHS; } eqs.reduce_nz( ); m_eq = eqs.nrows; m -= vs.length( ) - m_eq; TEX( ![ \begin{quote} Check for inconsistency of equality constraints. \end{quote} ]! ) if ( eqs.nrows != 0 ) { for ( i = 0; i < n; i++ ) if ( eqs( eqs.nrows-1, i ) != 0 ) break; if ( i == n ) { known_to_be_infeasible = true; time_used_presolving += time(0); return 1; } } TEX( ![ \begin{quote} The included {\tt reduce} routine for {\tt Integer} matrices does not clear entries above the leading elements, so we do that here. Also make the leading elements positive. \end{quote} ]! ) int current_col = 0; Integer a, b, mm; for ( i = 0; i < eqs.nrows; i++ ) { while(1) { if ( eqs( i, current_col ) != 0 ) break; current_col++; } if ( eqs(i, current_col) < 0 ) for ( j = current_col; j < eqs.ncols; j++ ) eqs(i,j) = -eqs(i,j); for ( j = 0; j < i; j++ ) { a = eqs(i, current_col); b = eqs(j, current_col); if ( b != 0 ) { // Force b to be divisible by a. mm = a / gcd(a,b); eqs(j) *= mm; // Clear. mm = eqs(j, current_col) / a; for ( k = 0; k < eqs.ncols; k++ ) eqs(j, k) -= mm * eqs(i, k); // Reduce. mm = abs(eqs(j, 0)); for ( k = 1; k < eqs.ncols; k++ ) mm = gcd(mm, eqs(j, k)); for ( k = 0; k < eqs.ncols; k++ ) eqs(j, k) /= mm; } } } TEX( ![ \begin{quote} Reduce each row of the matrix. (Is this necessary?) \end{quote} ]! ) for ( i = 0; i < eqs.nrows; i++ ) { Integer g = 1; for ( j = 0; j <= n; j++ ) g = gcd( g, eqs(i, j) ); if ( g != 1 ) for ( j = 0; j <= n; j++ ) eqs(i, j) /= g; } TEX( ![ \begin{quote} Check for inequalities which can be deduced (or found contradictory) from the system of equations. Write the new constraint file. \end{quote} ]! ) ifstream in2( calculations_dir + "/elim_eq_temp" ); ofstream out2(con_file); vconstraint w(n); Integer l; while( in2.peek( ) != EOF ) { in2 >> v; w = v; int col = 0; for ( i = 0; i < eqs.nrows; i++ ) { while( eqs(i,col) == 0 ) col++; for ( j = 0; j < col; j++ ) if ( w.LHS(j) != 0 ) goto write_it; if ( w.LHS(col) != 0 ) { lcm( l, w.LHS(col), eqs(i,col) ); Integer m1 = l / w.LHS(col), m2 = l / eqs(i,col); if ( m1 < 0 ) m1 = -m1; for ( j = col; j < n; j++ ) { w.LHS(j) *= m1; w.LHS(j) -= m2 * eqs(i,j); } w.RHS = m1 * w.RHS - m2 * eqs(i,n); } } if ( w.LHS.if_zero( ) ) { if ( w.RHS <= 0 ) { m--; continue; } known_to_be_infeasible = true; in2.close( ); out2.close( ); remove( calculations_dir + "/elim_eq_temp" ); time_used_presolving += time(0); return 1; } write_it: for ( i = 0; i < v.LHS.length; i++ ) max_entry = max( max_entry, abs(v.LHS(i)) ); max_entry = max( max_entry, abs(v.RHS) ); out2 << v; } v.sense = '='; for ( i = 0; i < eqs.nrows; i++ ) { for ( j = 0; j < n; j++ ) v.LHS(j) = eqs(i,j); v.RHS = eqs(i,n); for ( j = 0; j < v.LHS.length; j++ ) max_entry = max( max_entry, abs(v.LHS(j)) ); max_entry = max( max_entry, abs(v.RHS) ); out2 << v; } in2.close( ); out2.close( ); TEX( ![ \begin{quote} Desparately try to find pairs of constraints which can be replaced by a single equality (or which are self-contradictory). \end{quote} ]! ) if ( full_reduction ) { ifstream in3( calculations_dir + "/elim_eq_temp" ); ofstream out3("reduced"); while( in3.peek( ) != EOF ) { in3 >> v; w = v; int col = 0; for ( i = 0; i < eqs.nrows; i++ ) { while( eqs(i,col) == 0 ) col++; if ( w.LHS(col) != 0 ) { lcm( l, w.LHS(col), eqs(i,col) ); Integer m1 = l / w.LHS(col), m2 = l / eqs(i,col); if ( m1 < 0 ) m1 = -m1; for ( j = 0; j < n; j++ ) { w.LHS(j) *= m1; w.LHS(j) -= m2 * eqs(i,j); } w.RHS = m1 * w.RHS - m2 * eqs(i,n); } } if ( w.LHS.if_zero( ) ) continue; w.reduce( ); out3 << w; } in3.close( ); out3.close( ); system( "sort -d -T calculations/tmp < reduced > reduced2" ); ifstream in4( "reduced2" ); ofstream out4( "reduced3" ); bool constraint_eliminated = false; vconstraint v1(n), v2(n); if ( in4.peek( ) == EOF ) goto end_of_cons; in4 >> v1; while( in4.peek( ) != EOF ) { in4 >> v2; if ( v1.sense == '>' && v2.sense == '>' && v1.RHS == -v2.RHS && (v1.LHS + v2.LHS).if_zero( ) ) { cerr << "presolve: eliminating constraint\n"; constraint_eliminated = true; v1.sense = '='; out4 << v1; m--; m_eq++; if ( in4.peek( ) == EOF ) goto end_of_cons; in4 >> v1; } else { out4 << v1; v1 = v2; } } out4 << v1; end_of_cons: v.sense = '='; for ( i = 0; i < eqs.nrows; i++ ) { for ( j = 0; j < n; j++ ) v.LHS(j) = eqs(i,j); v.RHS = eqs(i,n); out4 << v; } in4.close( ); out4.close( ); rename( "reduced3", con_file ); if ( constraint_eliminated ) { cerr << "restarting presolve\n"; presolve( ); } } remove( calculations_dir + "/elim_eq_temp" ); time_used_presolving += time(0); return max_entry; } TEX( ![ \verb|show_infeasible_by_primal_simplex|:\ First use floating-point arithmetic to try to show that the given problem is ``numerically infeasible''. If this step fails, return ``{\tt feasible}'', meaning that the problem may be feasible. Otherwise, use the output of the floating-point calculation, together with the given constraint \verb|bounding_con| to attempt to show that the problem (including \verb|bounding_con|) has no solution. Return ``{\tt infeasible}'' if the process shows that the given problem is infeasible. Otherwise return ``{\tt confused}''. Normally \verb|bounding_con| has the form $a_1 v_1 \many+ a_n v_n \leq r$, where the $a_i$ are all positive. Normally it would be a constraint included in or implied by the given problem, but this is not checked. The objective functions for the problem are ignored. The floating-point calculation is done with {\tt precision}-byte arithmetic. At this point the only allowed values for {\tt precision} are $8$ and $16$. ]! ) index_method(show_infeasible_by_primal_simplex) String exact_lp_problem::show_infeasible_by_primal_simplex( const vconstraint& bounding_con ) { if ( m == 0 ) return "feasible"; int i; ifstream con(con_file); #define SHOW_INFEASIBLE(PRECISION, TYPE) \ if ( current_precision == PRECISION ) \ { canonical_lp_problem prob(m, n + m - m_eq); \ prob.slacks = m - m_eq; \ con >> prob; \ con.seekg(0, ios::beg); /* rewind */ \ prob.c.set_zero( ); \ vector cost(n), improve; \ bool confused; \ extend obj = prob.simple_simplex( cost, \ improve, confused, false ); \ if (confused) return "confused"; \ if ( !obj.PlusInfinity( ) ) \ { con.close( ); \ return "feasible"; } \ if ( check_infeasible(con, prob, cost, bounding_con) ) \ { con.close( ); \ return "infeasible"; } \ else \ { con.close( ); \ return "confused"; } } SHOW_INFEASIBLE(1, double) else SHOW_INFEASIBLE(2, doubledouble) else INTERNAL_ERROR( "show_infeasible_by_primal_simplex called with " << "illegal precision value." ); } index_method(Set_precision) inline void Set_precision(double& x, int n) { } inline void Set_precision(doubledouble& x, int n) { } inline void Set_precision(Big& x, int n) { x.set_precision(n); } TEX( ![ \verb|bits_in_significand|:\ Return number of bits in significand (0 means infinity). ]! ) index_method(bits_in_significand) int bits_in_significand( double& x ) { return 53; } int bits_in_significand( doubledouble& x ) { return 106; } int bits_in_significand( Big& x ) { unsigned long prec = mpf_get_prec( x.body ); return int(prec); } int bits_in_significand( Rational& x ) { return 0; } index_method(bound_by_primal_simplex_on_dual) extend exact_lp_problem::bound_by_primal_simplex_on_dual( ) { if ( m == 0 ) INTERNAL_ERROR( "No constraints." ); int i, j; ifstream con(con_file); #define BOUND_D(PRECISION, TYPE) \ if ( current_precision == PRECISION || PRECISION == 3 ) \ { while(1) \ { ofstream homebrew_log0( \ calculations_dir + "/homebrew.log", ios::app ); \ homebrew_log0 << "precision level = " << \ current_precision << "\n"; \ homebrew_log0.close( ); \ canonical_lp_problem prob(n, n + m); \ prob.row_dividers.set_size(m); \ for ( i = 0; i < prob.At.nrows; i++ ) \ for ( j = 0; j < prob.At.ncols; j++ ) \ Set_precision(prob.At(i,j), current_precision); \ for ( i = 0; i < prob.b.length; i++ ) \ Set_precision( prob.b(i), current_precision ); \ for ( i = 0; i < prob.c.length; i++ ) \ Set_precision( prob.c(i), current_precision ); \ for ( i = 0; i < prob.x.length; i++ ) \ Set_precision( prob.x(i), current_precision ); \ for ( i = 0; i < prob.LU.nrows; i++ ) \ for ( j = 0; j < prob.LU.ncols; j++ ) \ Set_precision(prob.LU(i,j), current_precision); \ for ( i = 0; i < prob.A_B.nrows; i++ ) \ for ( j = 0; j < prob.A_B.ncols; j++ ) \ Set_precision(prob.A_B(i,j), current_precision); \ for ( i = 0; i < prob.x_B.length; i++ ) \ Set_precision( prob.x_B(i), current_precision ); \ for ( i = 0; i < prob.b_minus.length; i++ ) \ Set_precision( prob.b_minus(i), current_precision ); \ Set_precision( prob.tolx, current_precision ); \ for ( i = 0; i < prob.l.length; i++ ) \ Set_precision( prob.l(i).x, current_precision ); \ for ( i = 0; i < prob.u.length; i++ ) \ Set_precision( prob.u(i).x, current_precision ); \ prob.slacks = n; \ vconstraint v(n); \ for ( i = 0; i < m; i++ ) \ { con >> v; \ if ( v.sense == '<' ) INTERNAL_ERROR( \ "bound_by_primal_simplex_on_dual " \ << "may not be invoked on <= constraints." ) \ if ( v.sense == '=' ) prob.l(i).SetMinusInfinity( ); \ else prob.l(i) = 0; \ prob.u(i).SetPlusInfinity( ); \ Integer rowmax = abs(v.RHS); \ for ( j = 0; j < n; j++ ) \ rowmax = max( rowmax, abs( v.LHS(j) ) ); \ if ( rowmax == 0 ) \ INTERNAL_ERROR("The linear programming " << \ "problem has a zero constraint."); \ rowmax = round_down_to_power_of_2(rowmax); \ for ( j = 0; j < n; j++ ) \ assign( prob.At(i,j), \ Rational(v.LHS(j)) / Rational(rowmax) ); \ assign(prob.c(i), -Rational(v.RHS)/Rational(rowmax)); \ prob.row_dividers(i) = Rational(rowmax); } \ for ( i = 0; i < n; i++ ) \ for ( j = m; j < m + n; j++ ) \ prob.At(j,i) = (j == i + m); \ for ( i = m; i < m + n; i++ ) \ { prob.c(i) = 0; \ prob.l(i) = 0; \ prob.u(i).SetPlusInfinity( ); } \ if ( obj.length != 1 ) \ INTERNAL_ERROR( "Wrong numbers of objectives." ); \ Rational const_term = obj(0).first; \ String goal = obj(0).third; \ if ( goal == "max" ) goal = "min"; \ else goal = "max"; \ prevector objv = obj(0).second; \ if ( objv.length != n ) \ INTERNAL_ERROR( "Wrong objective length." ); \ if ( goal == "min" ) \ { for ( i = 0; i < n; i++ ) \ objv(i) = -objv(i); \ const_term = -const_term; } \ for ( i = 0; i < n; i++ ) \ assign( prob.b(i), objv(i) ); \ /* Form the crash basis. */ \ for ( i = 0; i < n; i++ ) \ prob.basis(i) = i + m; \ con.seekg(0, ios::beg); /* rewind */ \ vector cost(n), improve; \ bool confused; \ extend obj = prob.simple_simplex( \ cost, improve, confused, true ); \ if (confused) \ { ofstream homebrew_log( \ calculations_dir + "/homebrew.log", ios::app ); \ homebrew_log << "Calculation at precision level " << \ current_precision << " failed. Redoing at " << \ "next higher precision level.\n"; \ homebrew_log.close( ); \ con.seekg(0, ios::beg); /* rewind */ \ current_precision++; \ if ( PRECISION <= 2 ) break; } \ extend ans; \ if ( obj.MinusInfinity( ) ) \ { if ( goal == "max" ) ans.SetMinusInfinity( ); \ else ans.SetPlusInfinity( ); \ return ans; } \ if ( obj.PlusInfinity( ) ) \ ERROR( "Dual is infeasible. I can't determine if " \ << "the optimization problem has answer " << \ "+infinity or -infinity." ); \ Big ans0; \ assign( ans0, obj.x ); \ Big ct(ans0); \ assign( ct, const_term ); \ ans0 += ct; \ if ( goal == "min" ) ans0 = -ans0; \ ans0 = -ans0; \ ans = ans0; \ return ans; } } BOUND_D(1, double) BOUND_D(2, doubledouble) BOUND_D(3, Big) } index_method(show_infeasible_by_primal_simplex_on_dual) String exact_lp_problem::show_infeasible_by_primal_simplex_on_dual( const vconstraint& bounding_con ) { if ( m == 0 ) return "feasible"; int i, j; ifstream con(con_file); TEX( ![ \begin{quote} I don't know exactly how the right hand sides {\tt b} should be chosen. At first I tried making them all $1$, and encountered severe cycling. Then I tried making them random numbers, uniformly distributed on $[0.5, 1.5]$. Again cycling was encountered. Then I tried random numbers from $[0.5, 100.5]$. That worked, so that's what is used here. I originally used {\tt drand48} to get random numbers, but switched to {\tt random} to make this code more portable. \end{quote} ]! ) #define SHOW_INFEASIBLE_D(PRECISION, TYPE) \ if ( current_precision == PRECISION || PRECISION == 3 ) \ { while(1) \ { ofstream homebrew_log0( \ calculations_dir + "/homebrew.log", ios::app ); \ homebrew_log0 << "precision level = " << \ current_precision << "\n"; \ homebrew_log0.close( ); \ canonical_lp_problem prob(n, n + m); \ prob.row_dividers.set_size(m); \ for ( i = 0; i < prob.At.nrows; i++ ) \ for ( j = 0; j < prob.At.ncols; j++ ) \ Set_precision(prob.At(i,j), current_precision); \ for ( i = 0; i < prob.b.length; i++ ) \ Set_precision( prob.b(i), current_precision ); \ for ( i = 0; i < prob.c.length; i++ ) \ Set_precision( prob.c(i), current_precision ); \ for ( i = 0; i < prob.x.length; i++ ) \ Set_precision( prob.x(i), current_precision ); \ for ( i = 0; i < prob.LU.nrows; i++ ) \ for ( j = 0; j < prob.LU.ncols; j++ ) \ Set_precision(prob.LU(i,j), current_precision); \ for ( i = 0; i < prob.A_B.nrows; i++ ) \ for ( j = 0; j < prob.A_B.ncols; j++ ) \ Set_precision(prob.A_B(i,j), current_precision); \ for ( i = 0; i < prob.x_B.length; i++ ) \ Set_precision( prob.x_B(i), current_precision ); \ for ( i = 0; i < prob.b_minus.length; i++ ) \ Set_precision( prob.b_minus(i), current_precision ); \ Set_precision( prob.tolx, current_precision ); \ for ( i = 0; i < prob.l.length; i++ ) \ Set_precision( prob.l(i).x, current_precision ); \ for ( i = 0; i < prob.u.length; i++ ) \ Set_precision( prob.u(i).x, current_precision ); \ prob.slacks = n; \ vconstraint v(n); \ for ( i = 0; i < m; i++ ) \ { con >> v; \ if ( v.sense == '<' ) INTERNAL_ERROR( \ "show_infeasible_by_primal_simplex_on_dual " \ << "may not be invoked on <= constraints." ) \ if ( v.sense == '=' ) prob.l(i).SetMinusInfinity( ); \ else prob.l(i) = 0; \ prob.u(i).SetPlusInfinity( ); \ Integer rowmax = abs(v.RHS); \ for ( j = 0; j < n; j++ ) \ rowmax = max( rowmax, abs( v.LHS(j) ) ); \ if ( rowmax == 0 ) \ INTERNAL_ERROR("The linear programming " << \ "problem has a zero constraint."); \ rowmax = round_down_to_power_of_2(rowmax); \ for ( j = 0; j < n; j++ ) \ assign( prob.At(i,j), \ Rational(v.LHS(j)) / Rational(rowmax) ); \ assign(prob.c(i), -Rational(v.RHS)/Rational(rowmax)); \ prob.row_dividers(i) = Rational(rowmax); } \ for ( i = 0; i < n; i++ ) \ for ( j = m; j < m + n; j++ ) \ prob.At(j,i) = (j == i + m); \ for ( i = m; i < m + n; i++ ) \ { prob.c(i) = 0; \ prob.l(i) = 0; \ prob.u(i).SetPlusInfinity( ); } \ TYPE max_random; \ Set_precision( max_random, current_precision ); \ assign(max_random, Ipow(2,31) - 1); \ for ( i = 0; i < n; i++ ) \ prob.b(i) = 0.5 + 100.0 * randomx( ) / max_random; \ for ( i = 0; i < n; i++ ) \ prob.basis(i) = i + m; \ con.seekg(0, ios::beg); /* rewind */ \ vector cost(n), improve; \ bool confused; \ extend obj = prob.simple_simplex( \ cost, improve, confused, true ); \ if ( !confused && !obj.MinusInfinity( ) ) \ { if ( verify_feasibility >= 1 ) \ { /* Do exact calculation to verify feasible. */ \ /* First conserve memory. */ \ prob.At.set_size(0,0); \ prob.LU.set_size(0,0); \ prob.A_B.set_size(0,0); \ canonical_lp_problem probe(n, n + m); \ probe.row_dividers.set_size(m); \ probe.slacks = n; \ for ( i = 0; i < m; i++ ) \ { con >> v; \ if ( v.sense == '=' ) \ probe.l(i).SetMinusInfinity( ); \ else probe.l(i) = 0; \ probe.u(i).SetPlusInfinity( ); \ for ( j = 0; j < n; j++ ) \ assign( probe.At(i,j), \ Rational(v.LHS(j)) ); \ assign(probe.c(i), -Rational(v.RHS)); \ probe.row_dividers(i) = 1; } \ for ( i = 0; i < n; i++ ) \ for ( j = m; j < m + n; j++ ) \ probe.At(j,i) = (j == i + m); \ for ( i = m; i < m + n; i++ ) \ { probe.c(i) = 0; \ probe.l(i) = 0; \ probe.u(i).SetPlusInfinity( ); } \ for ( i = 0; i < n; i++ ) \ assign( probe.b(i), prob.b(i) ); \ probe.basis = prob.basis; \ con.seekg(0, ios::beg); /* rewind */ \ vector coste(n), improvee; \ extend obje = probe.simple_simplex( \ coste, improvee, confused, true ); \ if (confused) \ { cerr << "When I tried to verify feasibility"\ << ", simple_simplex got confused.\n"; \ if ( verify_feasibility == 1 ) \ ERROR( "Verification failed." ); \ cerr << "Raising precision.\n"; \ goto confused ## PRECISION; } \ if ( obje.MinusInfinity( ) ) \ { cerr << "When I tried to verify feasibility"\ << ", simple_simplex claimed it was " \ << "really infeasible.\n"; \ if ( verify_feasibility == 1 ) \ ERROR( "Verification failed." ); \ cerr << "Raising precision.\n"; \ goto confused ## PRECISION; } \ cerr << "Feasibility verified.\n"; } \ con.close( ); \ return "feasible"; } \ prob.slacks = prob.m = m; /* kluge */ \ if ( !confused && \ check_infeasible(con, prob, improve, bounding_con) ) \ { con.close( ); \ return "infeasible"; } \ else \ { confused ## PRECISION: \ ofstream homebrew_log( \ calculations_dir + "/homebrew.log", ios::app ); \ homebrew_log << "Calculation at precision level " << \ current_precision << " failed. Redoing at " << \ "next higher precision level.\n"; \ homebrew_log.close( ); \ con.seekg(0, ios::beg); /* rewind */ \ current_precision++; \ if ( PRECISION <= 2 ) break; } } } SHOW_INFEASIBLE_D(1, double) SHOW_INFEASIBLE_D(2, doubledouble) SHOW_INFEASIBLE_D(3, Big) } TEX( ![ The following input operator for class \verb|canonical_lp_problem| is a preliminary version; the file structure will likely change later. First, you have to know $m$ and $n$ in advance and you should have used the \verb|canonical_lp_problem(int m, int n)| constructor. Now a problem to be inputted consists of a sequence of $m$ vconstraints. These need not be equality constraints; slack variables will be added as needed. But you have to have preset $n$ to the total number of variables, including the slacks. By assumption, all variables are nonnegative. All constraints are normalized so that the maximum absolute value of an element is one. This improves the conditioning of the problem. (Cf.{\ }[.tomlin scaling.].) The member {\tt c} has to be separately set, except that the slack members are automatically set to zero. The input operator finds a {\it crash basis}, according to the following scheme. First, all the columns of $A$ containing slack variables are included. Second, we consider all the rows of $A$ coming from equations in the file, we form a matrix $M$ consisting of their left hand sides, and reduce it to row echelon form. (This is done exactly. For a problem with many equality constraints, this may be too time-consuming.) If $M$ then has a zero row we exit with error. (This is a temporary ``feature''.) Otherwise, adjoin to the chosen columns of $A$ those columns in the positions of the leadings ones of $M$. This method is perhaps counter to the advice in ([.nazareth book.]\ p.\ 163). ]! ) template istream& operator>>(istream& s, canonical_lp_problem& p) { time_used_setting_up_simplex_problem -= time(0); int n0 = p.n - p.slacks, slack_count = 0; vconstraint v(n0); int i, j, eq_rows_ctr = 0; matrix eq(p.m - p.slacks, n0); for ( i = 0; i < p.m; i++ ) { s >> v; Integer rowmax = abs(v.RHS); for ( j = 0; j < n0; j++ ) rowmax = max( rowmax, abs( v.LHS(j) ) ); HIDE( ![ if ( rowmax == 0 ) INTERNAL_ERROR( "The linear programming problem has a zero constraint." ); ]! ) rowmax = round_down_to_power_of_2(rowmax); for ( j = 0; j < n0; j++ ) assign( p.At(j,i), Rational(v.LHS(j))/Rational(rowmax) ); for ( j = n0; j < p.n; j++ ) p.At(j,i) = 0; assign( p.b(i), Rational(v.RHS)/Rational(rowmax) ); p.row_dividers(i) = Rational(rowmax); if ( eq_rows_ctr >= eq.nrows ) INTERNAL_ERROR( "Error reading canonical_lp_problem." ); if ( v.sense == '<' ) p.At( n0 + slack_count++, i ) = 1; else if ( v.sense == '>' ) p.At( n0 + slack_count++, i ) = -1; else { for ( j = 0; j < eq.ncols; j++ ) eq( eq_rows_ctr, j ) = v.LHS(j); eq_rows_ctr++; } } for ( i = 0; i < p.n; i++ ) { p.l(i) = 0; p.u(i).SetPlusInfinity( ); } for ( i = n0; i < p.n; i++ ) p.c(i) = 0; // Form the crash basis. HIDE( ![ if ( eq.reduce( ) != eq.nrows ) INTERNAL_ERROR( "The linear programming problem has some dependent" << " or inconsistent equality constraints." ); ]! ) int basis_ctr = 0, col_ctr = 0; for ( i = 0; i < eq.nrows; i++ ) for ( j = col_ctr; j < eq.ncols; j++ ) if ( eq(i,j) != 0 ) { p.basis( basis_ctr++ ) = j; col_ctr = j + 1; break; } for ( i = n0; i < p.n; i++ ) p.basis( basis_ctr++ ) = i; time_used_setting_up_simplex_problem += time(0); return s; } TEX( ![ \verb|check_infeasible|( vconstraint file, \verb|canonical_lp_problem|, cost vector, key ) \vspace{0.1in} \par\noindent The \verb|canonical_lp_problem| should have been previously read from the vconstraint file. This program verifies that the linear program (defined over $\Z$) given by the vconstraint file is infeasible. To do this, the cost vector should be the cost vector produced by \verb|simple_simplex| when it found that \verb|canonical_lp_problem| was numerically infeasible. We form the associated exact linear combination of constraints by reading the vconstraint file again. By adding to this a small multiple of the constraint key, we obtain (hopefully) a self-contradictory constraint. ]! ) index_method(check_infeasible) template bool check_infeasible(istream& s, canonical_lp_problem& p, vector& cost, const vconstraint& key) { time_used_by_check_infeasible -= time(0); int n0 = p.n - p.slacks; HIDE( ![ if ( cost.length != p.m ) INTERNAL_ERROR("check_infeasible: cost length wrong"); ]! ) vconstraint v(n0); qvconstraint qv(n0); qv.LHS.set_zero( ); qv.RHS = 0; qv.sense = '>'; Rational multiplier; int i, j; Integer mul_top, mul_bot; for ( i = 0; i < p.m; i++ ) { assign( multiplier, cost(i) ); s >> v; if ( (multiplier < Rational(0) && v.sense == '>') || (multiplier > Rational(0) && v.sense == '<') ) continue; multiplier /= p.row_dividers(i); mul_top = multiplier.numerator( ); mul_bot = multiplier.denominator( ); for ( j = 0; j < n0; j++ ) qv.LHS(j) += Rational( mul_top * v.LHS(j), mul_bot ); qv.RHS += multiplier * Rational(v.RHS); } HIDE( ![ if ( key.sense == '>' ) INTERNAL_ERROR( "check_infeasible: sense of key cannot be >" ); ]! ) Rational key_multiplier = 0; for ( i = 0; i < n0; i++ ) if ( qv.LHS(i) > Rational(0) ) { if ( key.LHS(i) <= 0 ) { time_used_by_check_infeasible += time(0); return false; } key_multiplier = min( key_multiplier, -qv.LHS(i) / Rational(key.LHS(i)) ); } time_used_by_check_infeasible += time(0); return qv.RHS + key_multiplier * Rational(key.RHS) > Rational(0); } ifelse(UNAME,SunOS, ![#include ]!, ![#include ]!) index_method(Finite) bool Finite(double x) { return finite(x); } bool Finite(doubledouble x) { return Finite( x.h( ) ) && Finite( x.l( ) ); } bool Finite(Big x) { return true; } bool Finite(Rational x) { return true; } index_method(dot) template T dot( T* x, T* y, int length ) { register T answer = 0; register int i; for ( i = 0; i < length; i++ ) answer += *(x+i) * *(y+i); return answer; } index_method(dot_plus) template T dot_plus( T* x, T* y, int length, T z ) { register T answer = z; register int i; for ( i = 0; i < length; i++ ) answer += *(x+i) * *(y+i); return answer; } index_class(finite_stack) template class finite_stack : public prevector { public: int depth; finite_stack(int n) : prevector(n), depth(0) { } void push(const T& t) { for ( int i = 0; i < min(depth-1, length-2); i++ ) (*this)(i+1) = (*this)(i); (*this)(0) = t; depth = min( depth+1, length ); } void clear( ) { depth = 0; } }; TEX( ![ The following routine \verb|simple_simplex| is a primitive solver (primal simplex) for a canonical \LP\ problem whose variables are not bounded above. Return the minimum value of the objective function ($c^T x$). If the objective is unbounded, return $-\infty$. If the feasible region is empty, return $+\infty$. If the solver fails, the variable {\tt confused} is set to true, in which case no meaningful objective function value is returned. For any $n$-vector {\tt y} we let \verb|y_B| (or $\ysubB$) denote the $m$-vector obtained from {\tt y} by selecting the entries defined by {\tt basis}. Similarly, for an $r \times n$ matrix {\tt C}, we let \verb|C_B| be the the corresponding $r \times m$ matrix. We likewise use the notation \verb|_N| to denote the selection of entries which are not defined by {\tt basis}. This is for expository purposes only. If the boolean argument \verb|b_any_pos| is set to {\tt true}, the program will proceed under the assumption that {\tt b} may be changed to any positive vector. This allows for perturbation in the event of cycling. One would presumably only want to use this option if the only goal of the calculation is to determine whether the objective is unbounded. The outline was originally based on [.nazareth book.]\ pp.\ 37--38. ]! ) index_method(REFACTOR) #define REFACTOR \ { refcount = -1; \ goto end_of_iteration; } index_method(simple_simplex) template extend canonical_lp_problem::simple_simplex( vector& cost, vector& improve, bool& confused, bool b_any_pos ) { time_used_by_simple_simplex -= time(0); ofstream homebrew_log( calculations_dir + "/homebrew.log", ios::app); homebrew_log.setf(homebrew_log.unitbuf); confused = false; int i, j, k, ll, nn, degenerates; prevector basis_save = basis; // We use "standard" as a "precision template". This is only relevant // when R = Big. Using tolx as the source is arbitrary. Any R member // of a canonical_lp_problem should work. R standard = tolx; HIDE( ![ if ( !valid( ) ) INTERNAL_ERROR( "simple_simplex invoked on invalid lp problem" ); ]! ) int candidate_count = 0; int partial_pricing0 = min( partial_pricing, n-m ); prevector candidates(partial_pricing0); double pert_factor = 0.001; HIDE( ![ if (homebrew_full_report) { for ( i = 0; i < n; i++ ) for ( j = i+1; j < n; j++ ) { if ( At(i) == At(j) ) homebrew_log << "column " << i << " equals column " << j << "\n"; } } ]! ) TEX( ![ \begin{quote} The global variable \verb|homebrew_speedy| (if set) will cause some internal error checking to be turned off. This checking is expensive. When an anomaly is encountered, we turn the error checking back on and restart the calculation. (There must be a better way.) Upon normal exit, we turn off \verb|speedy| and refactor to make sure we are really done. Sometimes an anomaly is then encountered, in which case we turn the error checking back on and restart the calculation. \end{quote} ]! ) bool speedy = homebrew_speedy; // local version bool speedy_toggled_because_apparently_done = false; TEX( ![ \begin{quote} When we think we are done, we do some things (such as refactor) to make sure. First set the following to the believed optimum: \end{quote} ]! ) extend preliminary_opt; preliminary_opt = standard; TEX( ![ \begin{quote} The object \verb|objective_history| keeps track of how the simplex iterations are progressing. It is a stack, each entry of which is a pair ({\it feasible?}, {\it value}), where ``{\it feasible?}'' is {\tt true} if we are at a feasible point, else {\tt false}, and {\it value\/} is the value of the objective function (in the first case), and the total infeasibility (in the second case). Stack entries are only made immediately after refactorization. Whenever we introduce or remove a perturbation, or rebuild the basis from scratch, the stack is cleared. \end{quote} ]! ) finite_stack< pair > objective_history(20); finite_stack loop_count_at_refactorization(50); OSLList entering_avoid; // variables to be avoided as entering // variables if possible bool normal_iteration = false; HIDE( ![ for ( i = 0; i < n; i++ ) if ( !u(i).PlusInfinity( ) ) INTERNAL_ERROR( "simple_simplex requires that variables be unbounded above" ); ]! ) for ( i = 0; i < m; i++ ) for ( j = 0; j < m; j++ ) A_B(i,j) = At( basis(j), i ); for ( i = 0; i < n; i++ ) if_basis(i) = false; for ( i = 0; i < m; i++ ) if_basis( basis(i) ) = true; vector x_save(n), x_save2(n); for ( i = 0; i < n; i++ ) x(i) = ( l(i).MinusInfinity( ) ? R(0) : R(l(i)) ); vector b_save = b; bool b_perturbed = false; int j_save, k_save, basis_k_save; Permutation P_save(m); prevector< pair > history(1000); bool cycling_detected = false; vector cycle_test(n); // Rough up b. R pertby(standard); pertby = ( bits_in_significand(standard) == 0 ? 0 : pow( 2, -bits_in_significand(standard) * 0.4) ); prevector initial_pert(m); R max_random(standard); assign(max_random, Ipow(2,31) - 1); for ( i = 0; i < m; i++ ) { initial_pert(i) = pertby * R(double(randomx( ))) / max_random; b(i) += initial_pert(i); } bool initial_perturbation = true; TEX( ![ \begin{quote} Imagining that the columns of \verb|A| and \verb|x| are permuted, write $\verb|A| = [\AsubB \kern4pt \AsubN]$, $\verb|x| = [\xsubB, \xsubN]$, $\verb|Ax| = \verb|b|$. Then $\AsubB\xsubB = \verb|b| - \AsubN\xsubN$. The values in $\xsubN$ come from {\tt l}, so we compute the \RHS\ and then solve for $\xsubB$. \end{quote} ]! ) b_minus = b; for ( i = 0; i < n; i++ ) { if ( !if_basis(i) && x(i) != R(0) ) for ( k = 0; k < m; k++ ) b_minus(k) -= At(i,k) * x(i); } solve_Ax_eq_b( A_B, x_B, b_minus ); Permutation Qi(m); vector pi(m), pi_err(m); for ( i = 0; i < n; i++ ) x(i) = ( l(i).MinusInfinity( ) ? R(0) : R(l(i)) ); for ( i = 0; i < m; i++ ) x(basis(i)) = x_B(i); vector c_curr(n); // current cost vector vector c_B(m); // part of current cost vector vector c_B_err(m); // error in part of current cost vector vector c_BQi(m); // result of Q^(-1) acting on c_B vector y(m); // improvement direction vector bool backwards; // set if improving by moving backwards int itcount = 0, loopcount = 0, itcount_floor = 0; int refcount = -1; // iterations since last refactorization // setting to -1 forces refactorization R theta(standard), theta_bestx(standard), theta_best(standard), infeas(standard), err(standard), lu_err(standard), errx(standard), abserr(standard), s(standard), s_best(standard), best_improve(standard); infeas = 0; extend opt; opt = standard; bool infeasible; // set if current x is outside feasible region static R tolpiv(standard), toldj(standard), tol_refactor(standard), abserr_max(standard); R tolerr(standard); // SET_TOLERANCE(var, percent) does (in effect) // var = ( bits_in_significand(standard) == 0 ? 0 : // pow( 2, -bits_in_significand(standard) * // double(percent)/double(100) ) ); // except that we avoid the use of pow, which is inadequate because // it yields a double. #define SET_TOLERANCE(var, percent) \ if ( bits_in_significand(standard) == 0 ) var = 0; \ else \ { double neg_exp = bits_in_significand(standard) * \ double(percent)/double(100); \ unsigned long neg_exp_floor = int(neg_exp); \ var = pow( 2, neg_exp_floor - neg_exp ); \ for ( i = 0; i < neg_exp_floor; i++ ) \ var /= 2; } SET_TOLERANCE( tolpiv, tolpiv_percent ) SET_TOLERANCE( toldj, toldj_percent ) SET_TOLERANCE( tolx, 55 ) SET_TOLERANCE( tolerr, 30 ) SET_TOLERANCE( tol_refactor, 100 ) int error_count = 0; while(1) { if ( homebrew_full_report || (itcount+1) % 100 == 0 ) homebrew_log << "\nIteration " << itcount+1 << ": "; for ( i = 0; i < n; i++ ) { if ( !Finite(x(i)) ) { homebrew_log << "Please retry this calculation using " << "higher precision arithmetic. " << "Exiting simple_simplex.\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } } if ( loopcount > iteration_limit ) { homebrew_log << "simple_simplex giving up after " << loopcount << " loops\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } TEX( ![ \begin{quotea} Factor the basis matrix. Although we use only partial pivoting (and not complete pivoting), we still maintain a factorization of the form $\AsubB \verb|Q| = \verb|PLU|$, where $P$ and $Q$ are permutation matrices. For now $Q$ is the identity, but when we update the $LU$ factorization, it will become nontrivial. We refactor the basis matrix whenever any of the pivot elements in the $LU$ factorization get smaller than $10^{-16}$ or so (relative to a double precision type). Also recompute {\tt x}. \end{quotea} ]! ) bool outcome; if (loopcount > 0) { for ( i = 0; i < m; i++ ) if ( abs(LU(i,i)) < tol_refactor ) break; } HIDE( ![ if (loopcount > 0 && i < m && homebrew_full_report) homebrew_log << "There is a pivot element " "of size " << abs(LU(i,i)) << ".\n"; ]! ) if ( loopcount == 0 || i < m || refcount == -1 || (refactorization_rate != 0 && itcount/refactorization_rate*refactorization_rate == itcount) ) { TEX( ![ \begin{quoteb} Check to see if we're stuck in a loop, refactoring over and over. \end{quoteb} ]! ) loop_count_at_refactorization.push(loopcount); if ( !normal_iteration && loop_count_at_refactorization.depth == loop_count_at_refactorization.length ) { if ( loopcount - loop_count_at_refactorization( loop_count_at_refactorization.length - 1 ) < 10 * loop_count_at_refactorization.length ) homebrew_log << "simple_simplex giving up\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } refactor: refcount = 0; homebrew_log << "\nrefactoring basis matrix\n"; LU = A_B; outcome = LU.lu_decompose(P); TEX( ![ \begin{quoteb} If a basis singularity is detected, we quit and request more precision. \end{quoteb} ]! ) if (outcome) { for ( i = 0; i < m; i++ ) if ( abs(LU(i,i)) < tol_refactor ) { outcome = false; break; } } if (!outcome) { homebrew_log << "Please retry this calculation using " << "higher precision arithmetic. " << "Exiting simple_simplex.\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } Q = Permutation(m); Qi = Permutation(m); recompute_x( ); } refcount++; TEX( ![ \begin{quotea} We always recompute {\tt x}. This should really only be done when there is evidence that roundoff error is a problem. \end{quotea} ]! ) if (!speedy) recompute_x( ); x_save2 = x_save; x_save = x; TEX( ![ \begin{quotea} If we just refactored, update \verb|objective_history|. \end{quotea} ]! ) if ( refcount == 0 ) objective_history.push( status( ) ); TEX( ![ \begin{quotea} Compute the error term $\norm{Ax-b}_1$. \end{quotea} ]! ) if (speedy) { entering_avoid.clear( ); goto bypass1; } abserr = 0; for ( ll = 0; ll < m; ll++ ) abserr += abs( dot_plus( A_B(ll).x, x_B.x, m, -b_minus(ll) ) ); if ( abserr > tolerr ) { homebrew_log << "Please retry this calculation using " << "higher precision arithmetic. " << "Exiting simple_simplex.\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } else if (normal_iteration) entering_avoid.clear( ); for ( i = 0; i < m; i++ ) for ( j = 0; j < m; j++ ) if ( !Finite(LU(i,j)) ) ERROR("An element of LU is not finite."); TEX( ![ \begin{quotea} If the current lower bound for a variable is very slightly below its given bound, we round up the current lower bound. The tolerance which determines ``very slightly below'' is the {\it primal feasibility tolerance\/} {\tt tolx}, which is discussed in ([.nazareth book.]\ p.\ 163) and ([.advanced orchard.]\ p.\ 130). The latter gives a value of about $10^{-8}$ on a machine with a $48$ bit significand. \end{quotea} ]! ) for ( i = 0; i < n; i++ ) if ( !Finite( x(i) ) ) { homebrew_log << "Please retry this calculation using " << "higher precision arithmetic. " << "Exiting simple_simplex.\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } bypass1: normal_iteration = false; if (!infeasible && (homebrew_full_report || (itcount+1) % 100 == 0)) homebrew_log << "Objective: " << objective( ); HIDE( ![ if (!infeasible && homebrew_full_report) homebrew_log << "\n"; ]! ) for ( i = 0; i < n; i++ ) if ( x(i) + tolx < l(i) ) break; if ( i == n ) // no variables below their bounds { infeasible = false; infeas = 0; c_curr = c; } else { infeasible = true; infeas = infeasibility( ); for ( i = 0; i < n; i++ ) c_curr(i) = ( (x(i) + tolx < l(i)) ? -1 : 0 ); if ((homebrew_full_report || (itcount+1) % 100 == 0)) homebrew_log << "Infeasibility: " << infeas; HIDE( ![ if (homebrew_full_report) homebrew_log << "\n"; ]! ) } for ( i = 0; i < m; i++ ) c_B(i) = c_curr( basis(i) ); // Test for degeneracy. degenerates = 0; for ( i = 0; i < m; i++ ) if ( !l(i).MinusInfinity( ) && x(basis(i)) < R(l(i)) + tolx ) degenerates++; if ( degenerates > 0 && homebrew_full_report ) homebrew_log << degenerates << " variables appear to be degenerate\n"; TEX( ![ \begin{quotea} Form the {\it price vector\/} {\tt pi} (also called the {\it vector of simplex multipliers}) by solving $\verb|pi|^T \AsubB = \csubB^T$. Note that {\tt pi} is characterized by the following property ([.nazareth book.]\ p.\ 29): If $x$ is nondegenerate, and we consider what happens as $b$ varies (and accordingly $x$ varies), the \th{i} component of {\tt pi} is $\partial(c^T x) / \partial b_i$. The following explanation is derived from ([.bazaraa jarvis sherali.]\ p.\ 93). For conceptual purposes, imagine that the columns of \verb|A| and \verb|x| are permuted, and write $\verb|A| = [\AsubB \kern4pt \AsubN]$, $\verb|x| = [\xsubB, \xsubN]$. Then $$\verb|b| = \verb|Ax| = \AsubB\kern4pt\xsubB + \AsubN\kern4pt\xsubN,$$% so $\xsubB = \AsubB^{-1} \verb|b| - \AsubB^{-1} \AsubN \kern2pt \xsubN$. Hence \begin{eqnarray*} \verb|c|^T \verb|x| & = & \csubB^T (\AsubB^{-1} \verb|b| - \AsubB^{-1} \AsubN \xsubN) + \csubN^T \xsubN\\ & = & (\csubB^T \AsubB^{-1} \verb|b|) + (\csubN^T - \csubB^T \AsubB^{-1} \AsubN) \xsubN. \end{eqnarray*} Note that the first parenthesized expression on the last line is the value of the objective function provided that $\xsubN = 0$. The second parenthesized expression is the vector $\ssubN$ of reduced costs. Note that $\ssubN \geq 0$ implies that $\verb|x|$ is optimal. We have $\verb|pi| = \csubB^T \AsubB^{-1}$, $\ssubN = \csubN^T - (\verb|pi|)\AsubN$. The \th{j} entry of $\ssubN$ is the rate of change of the objective function \WRT\ the nonbasic variable $\verb|x|_j$, provided that the other nonbasic variables are held at zero. \end{quotea} ]! ) c_BQi = c_B; Qi.act(c_BQi); LU.solve_from_lu_t( P, c_BQi, pi ); for ( i = 0; i < m; i++ ) if ( !Finite( pi(i) ) ) ERROR("A price vector element is infinite."); TEX( ![ \begin{quotea} In this version, we always do a one-step ``single precision'' refinement of {\tt pi}. Probably refinement should only be done selectively. I put this step in because I encountered a devastating error, which apparently resulted from dividing a big number by a relatively small number in \verb|solve_from_lu_t|. In turn it is conceivable that this came from degradation of the $LU$ decomposition arising from updating. It is also possible that with proper scaling, the problem would not occur. \end{quotea} ]! ) if ( !speedy ) { for ( i = 0; i < price_refinement_count; i++ ) { xA_minus_c_eq(pi, A_B, c_B, c_B_err); Qi.act(c_B_err); LU.solve_from_lu_t( P, c_B_err, pi_err ); pi -= pi_err; } } TEX( ![ \begin{quotea} Compute the reduced costs $\verb|s|_j$ and choose the entering variable $j$. That is, for each index $j$ corresponding to a nonbasic variable (so $j \notin \verb|basis|$) which is bounded below, we set $\verb|s|_j = \verb|c|_j - \verb|pi|^T \verb|A|^j$, where $\verb|A|^j$ denotes the \th{j} column of $A$. If no $\verb|s|_j$ is negative, and there is no nonbasic free variable $j$ with $\verb|s|_j \not= 0$, $\xsubB$ is optimal and we are done. Otherwise, let $j$ be such that $\abs{\verb|s|_j}$ is maximized. Actually, rather than check to see whether $\verb|s|_j < 0$, we check to see if it is less than $-{\tt toldj}$, where {\tt toldj} is the {\it optimality tolerance}, temporarily defined here to be $2^{-0.7s}$, where $s$ is the number of bits in the significand. For brief comments on {\tt toldj} (also denoted {\tt tol}$\sigma$), see ([.nazareth book.]\ pp.\ 144,163) and ([.murtagh advanced.]\ p.\ 34). We do not compute all reduced costs. Rather we follow a {\it partial pricing\/} scheme whereby we initially choose a pool of candidate entering variables, and try to use those exclusively, until no longer possible, at which time we recompute the pool of candidate entering variables. The size of the pool is controlled by the global variable \verb|partial_pricing|. Also, we always give preference to entering variables which are unbounded. \end{quotea} ]! ) s_best = -toldj; backwards = false; // Try to use an unbounded variable. for ( i = 0; i < n; i++ ) { if ( if_basis(i) ) continue; if ( !l(i).MinusInfinity( ) ) continue; if ( entering_avoid.contains(i) ) continue; // s = c_curr(i) - dot( At(i).x, pi.x, m ); s = -dot_plus( At(i).x, pi.x, m, -c_curr(i) ); if ( s < R(-10.0) * toldj && s < s_best ) { s_best = s; backwards = false; j = i; } if ( -s < R(-10.0) * toldj && -s < s_best ) { s_best = -s; backwards = true; j = i; } } if ( s_best != -toldj ) goto found_entering_variable; for ( i = 0; i < candidate_count; i++ ) { if ( if_basis( candidates(i) ) ) continue; if ( entering_avoid.contains( candidates(i) ) ) continue; // s = c_curr( candidates(i) ) - // dot( At( candidates(i) ).x, pi.x, m ); s = -dot_plus( At( candidates(i) ).x, pi.x, m, -c_curr(candidates(i)) ); if ( s < R(-10.0) * toldj && s < s_best ) { s_best = s; backwards = false; j = candidates(i); } if ( l(candidates(i)).MinusInfinity( ) && -s < R(-10.0) * toldj && -s < s_best ) { s_best = -s; backwards = true; j = candidates(i); } } if ( s_best == -toldj ) { candidate_count = 0; for ( i = 0; i < n; i++ ) { if ( entering_avoid.contains(i) ) continue; if ( !if_basis(i) ) { // s = c_curr(i) - dot( At(i).x, pi.x, m ); s = -dot_plus( At(i).x, pi.x, m, -c_curr(i) ); bool good_var = false; if ( s < s_best ) { s_best = s; good_var = true; backwards = false; j = i; } if ( l(i).MinusInfinity( ) && -s < s_best ) { s_best = -s; good_var = true; backwards = true; j = i; } if ( good_var && partial_pricing0 ) { candidates(candidate_count++) = i; if (candidate_count == partial_pricing0) break; } } } } found_entering_variable: if ( s_best == -toldj ) { if (b_perturbed) { b = b_save; homebrew_log << "[Removing perturbation.]"; b_perturbed = false; REFACTOR; } if (initial_perturbation) { homebrew_log << "Removing initial perturbation.\n"; for ( i = 0; i < m; i++ ) b(i) -= initial_pert(i); initial_perturbation = false; REFACTOR; } // The following test is clearly weak. if ( infeasible && (b_any_pos || infeas > R(1)) ) opt.SetPlusInfinity( ); else opt = objective( ); if ( speedy_toggled_because_apparently_done && opt.inf != preliminary_opt.inf ) goto restart_slowly; if ( refcount != 1 && (b_any_pos || !speedy) ) { HIDE( ![ if ( homebrew_full_report ) homebrew_log << "Optimum apparently " << "found. Refactor and test again to make sure.\n"; ]! ) if (speedy) speedy_toggled_because_apparently_done = true; speedy = false; preliminary_opt = opt; REFACTOR; } if (b_any_pos) { // Do an extra refinement of the price vector. xA_minus_c_eq(pi, A_B, c_B, c_B_err); Qi.act(c_B_err); LU.solve_from_lu_t( P, c_B_err, pi_err ); pi -= pi_err; } cost = pi; normal_exit: time_used_by_simple_simplex += time(0); HIDE( ![ if (homebrew_full_report) homebrew_log << "Leaving simple_simplex, " << "optimum = " << opt << ", basis = " << basis << "\n"; ]! ) if (dump_cost) { vector minus_cost( cost.length ); for ( i = 0; i < cost.length; i++ ) minus_cost(i) = -cost(i); ofstream dump( "calculations/minus_cost" ); dump << minus_cost << "\n"; dump.close( ); } homebrew_log.close( ); if (homebrew_dump) { Rational multiplier = 1; for ( j = 0; j < row_dividers.length; j++ ) multiplier = max( multiplier, row_dividers(j) ); double maxerr = 0; matrix A_B_int(m, m); for ( i = 0; i < m; i++ ) for ( j = 0; j < m; j++ ) { Rational xx; assign( xx, A_B(i, j) ); xx *= multiplier; A_B_int(i, j) = round(xx); maxerr = max( maxerr, double( abs( A_B_int(i,j) - xx ) ) ); } vector c_B_int(m); for ( i = 0; i < m; i++ ) { Rational xx; assign( xx, c_B(i) ); xx *= multiplier; c_B_int(i) = round(xx); maxerr = max( maxerr, double( abs( c_B_int(i) - xx ) ) ); } cerr << "(homebrew dump: maximum rounding error was about " << maxerr << ")\n"; ofstream dump1( "calculations/dump:A_B" ); dump1 << A_B_int << "\n"; dump1.close( ); ofstream dump2( "calculations/dump:c_B" ); dump2 << c_B_int << "\n"; dump2.close( ); } return opt; } HIDE( ![ if (homebrew_full_report) { homebrew_log << "Entering variable: " << j; if ( l(j).MinusInfinity( ) ) homebrew_log << " (unbounded)"; homebrew_log << ". "; } ]! ) TEX( ![ \begin{quotea} Find the vector {\tt y} defining the direction of improvement, which satisfies $\AsubB \verb|y| = \verb|A|^{\verb|j|}$. \end{quotea} ]! ) LU.solve_from_lu( P, At(j), y ); Q.act(y); if (backwards) y = -y; TEX( ![ \begin{quotea} Determine the exiting variable $\verb|basis|(k)$. This involves looking at those $\verb|y|(i)$ values which are ``positive''. (But free variables are not allowed to exit.) Positive is defined by being greater than a small positive number called the {\it pivot tolerance}, sometimes denoted {\tt tolpiv}. This is touched on in ([.nazareth book.]\ pp.\ 141, 163); a somewhat more detailed discussion may be found in ([.advanced orchard.]\ pp.\ 129--130). There it is stated that many systems employ three pivot tolerances. The smallest of these is about $10^{-12}$, on a machine with a $48$ bit significand. If there are $s$ bits in the significand, this would thus correspond to about $2^{-0.83s}$. For now we use the smaller value $2^{-0.87s}$. \end{quotea} ]! ) if (!infeasible) { k = -1; for ( i = 0; i < m; i++ ) if ( !l(basis(i)).MinusInfinity( ) && y(i) > tolpiv ) { theta = (x(basis(i)) - R(l(basis(i))) ) / y(i); if ( k == -1 || theta < theta_best ) { theta_best = theta; k = i; } } if ( k == -1 ) // objective is unbounded { if (b_perturbed) { b = b_save; homebrew_log << "[Removing perturbation.]"; b_perturbed = false; objective_history.clear( ); REFACTOR; } if ( speedy_toggled_because_apparently_done && preliminary_opt.inf != -1 ) goto restart_slowly; if ( refcount != 1 ) { HIDE( ![ if ( homebrew_full_report ) homebrew_log << "Objective is apparently unbounded. " << "Refactor and test again to make sure.\n"; ]! ) if (speedy) speedy_toggled_because_apparently_done = true; speedy = false; preliminary_opt.SetMinusInfinity( ); REFACTOR; } // Refine y and retest. vector y_err(m), y_add(m); if (backwards) y = -y; for ( ll = 0; ll < m; ll++ ) { errx = -At(j)(ll); for ( int jj = 0; jj < m; jj++ ) errx += A_B(ll,jj) * y(jj); y_err(ll) = errx; } LU.solve_from_lu( P, y_err, y_add ); Q.act(y_add); y -= y_add; if (backwards) y = -y; for ( i = 0; i < m; i++ ) if ( !l(basis(i)).MinusInfinity( ) && y(i) > tolpiv ) { theta = (x(basis(i)) - R(l(basis(i))) ) / y(i); if ( k == -1 || theta < theta_best ) { theta_best = theta; k = i; } } if ( k != -1 ) goto escape_from_here; improve.set_size(n - slacks); improve.set_zero( ); for ( i = 0; i < m; i++ ) if ( basis(i) < n - slacks ) improve(basis(i)) = -y(i); if ( j < n - slacks ) improve(j) = (backwards ? -1 : 1); opt.SetMinusInfinity( ); if (initial_perturbation) { homebrew_log << "Removing initial perturbation.\n"; for ( i = 0; i < m; i++ ) b(i) -= initial_pert(i); initial_perturbation = false; REFACTOR; } goto normal_exit; } escape_from_here: for ( i = 0; i < m; i++ ) if ( i != k ) x(basis(i)) -= y(i) * theta_best; x(basis(k)) = l(basis(k)); x(j) += theta_best; } TEX( ![ \begin{quotea} In the infeasible case (phase 1), the idea is to make theta as big as possible. We push theta up in increments. Each time a basic variable crosses over the lower bound (from above or below), we have to reassess whether increasing theta further will reduce infeasibility. At the point where no improvement can be achieved, we stop. This is probably the scheme given in [.wolfe composite.]. See also ([.fletcher practical.]\ pp.\ 165--166) and ([.nazareth book.]\ Chapter 8). \end{quotea} ]! ) else { R delta_theta(standard), delta_theta_best(standard), infeasibility_sum(standard); // The following line was added because delta_theta_best // gets used below (before its value has been set). So // there may be a bug. delta_theta_best = 0; k = -1; bool x_j_at_bound = false; while(1) { TEX( ![ \begin{quotecneg} The idea is that \verb|infeasibility_sum| should be the rate of change of infeasibility with respect to {\tt x(j)}, as {\tt x(j)} increases. \end{quotecneg} ]! ) // Is the following line correct?? infeasibility_sum = x(j) < l(j); for ( i = 0; i < m; i++ ) if ( x(basis(i)) < l(basis(i)) || (x(basis(i)) == l(basis(i))) && y(i) > tolpiv) infeasibility_sum -= y(i); if ( infeasibility_sum <= R(0) ) { if ( k == -1 && !x_j_at_bound) { // I don't understand this case. homebrew_log << "entering funny case\n" << "(infeasibility sum = " << infeasibility_sum << ")\n"; if (speedy || speedy_toggled_because_apparently_done) goto restart_slowly; for ( i = 0; i < m; i++ ) if ( !l(basis(i)).MinusInfinity( ) && y(i) > tolpiv ) { delta_theta = (x(basis(i)) - R(l(basis(i)))) / y(i); if ( k == -1 || delta_theta < delta_theta_best ) { delta_theta_best = delta_theta; k = i; } } if ( k != -1 && homebrew_full_report ) { homebrew_log << "k = " << k << "\n"; for ( i = 0; i < m; i++ ) if ( !l(basis(i)).MinusInfinity( ) && y(i) > tolpiv ) { delta_theta = (x(basis(i)) - R(l(basis(i)))) / y(i); homebrew_log << "i = " << i << ", " << "x(basis(i)) = " << x(basis(i)) << ", " << "l(basis(i)) = " << R(l(basis(i))) << ", y(i) = " << y(i) << ", delta_theta = " << delta_theta << "\n"; } } // Note: One can have delta_theta = 0 at this // point. if ( k == -1 ) // It's not clear how this can // happen, but it can. { homebrew_log << "Something screwy happened in " << "phase I.\n"; homebrew_log << "Please retry this " << "calculation using " << "higher precision arithmetic. " << "Exiting simple_simplex.\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } for ( i = 0; i < m; i++ ) x(basis(i)) -= y(i) * delta_theta_best; x(j) += delta_theta_best; } break; } k = -1; for ( i = 0; i < m; i++ ) { if ( l(basis(i)).MinusInfinity( ) ) continue; if ( (x(basis(i)) < l(basis(i)) && y(i) < -tolpiv) || (x(basis(i)) > l(basis(i)) && y(i) > tolpiv) ) { delta_theta = (x(basis(i)) - R(l(basis(i)))) / y(i); if (k == -1 || delta_theta < delta_theta_best) { delta_theta_best = delta_theta; k = i; } } } x_j_at_bound = false; if ( x(j) < l(j) && R(l(j)) - x(j) < delta_theta_best ) { delta_theta_best = R(l(j)) - x(j); homebrew_log << "x(j) will be at bound\n"; x_j_at_bound = true; } if ( k == -1 ) { if ( refcount != 1 ) { x = x_save; REFACTOR; } // The following code is weak. homebrew_log << "An auxiliary objective function used to " << "reduce infeasibility " << "was found to be unbounded.\n"; homebrew_log << "Please retry this calculation using " << "higher precision arithmetic. " << "Exiting simple_simplex.\n"; homebrew_log.close( ); confused = true; time_used_by_simple_simplex += time(0); return opt; } for ( i = 0; i < m; i++ ) x(basis(i)) -= y(i) * delta_theta_best; x(j) += delta_theta_best; TEX( ![ \begin{quotec} The following two lines force equalities that would otherwise be equalities only up to roundoff error. \end{quotec} ]! ) x(basis(k)) = R(l(basis(k))); if (x_j_at_bound && !l(j).MinusInfinity( )) x(j) = R(l(j)); } if ( x_j_at_bound ) goto end_of_iteration; } TEX( ![ \begin{quotea} Update iteration history and test for cycling. \end{quotea} ]! ) if ( itcount == history.length ) history.resize( history.length + 1000 ); history(itcount) = make_pair( j, int(basis(k)) ); cycling_detected = false; if ( itcount > itcount_floor ) { cycle_test.set_zero( ); for ( i = itcount; i >= 0; i-- ) { cycle_test( history(i).first )++; cycle_test( history(i).second )--; if ( cycle_test.if_zero( ) ) { cycling_detected = true; homebrew_log << "cycling detected\n"; R max_random(standard); assign(max_random, Ipow(2,31) - 1); TEX( ![ \begin{quoted} If \verb|b_any_pos| is set, the degree of perturbation depends on \verb|objective_history|. If there is evidence that progress has been made, the degree is low. Otherwise (within limits) we double the previous perturbation. One problem with this (as it stands) is that the current status is computed without refactoring first, so it could be highly inaccurate. \end{quoted} ]! ) bool improvement_detected = false; if (b_any_pos) { if ( objective_history.depth > 0 ) { pair oldest = objective_history( objective_history.depth - 1 ); pair current = status( ); if ( current.first && !oldest.first ) improvement_detected = true; else if ( current.first && oldest.first && current.second < R(101)/R(99)*oldest.second ) improvement_detected = true; else if ( !current.first && !oldest.first && current.second < R(99)/R(100)*oldest.second ) improvement_detected = true; } } if (b_any_pos) { if (improvement_detected) pert_factor = 0.001; else pert_factor = min(1.0, 2 * pert_factor); } else pert_factor = 0.01; if ( partial_pricing ) { TEX( ![ \begin{quotee} Here we deal with cycling encountered while in in the midst of partial pricing. First we end the current major iteration. If possible, we will attempt to back up over the current iteration and restart from there. But if there is evidence that we are stuck in an infinite loop, we perturb. This evidence we look for is whether the previous five loop counts (at this stage) constitute an arithmetic sequence. \end{quotee} ]! ) candidate_count = 0; #define LC_SZ 5 static int lc[LC_SZ] = {0,0,0,0,0}; // Does the above line correctly initialize? for ( i = 1; i < LC_SZ; i++ ) lc[i-1] = lc[i]; lc[LC_SZ - 1] = loopcount; int delta_lc = lc[1] - lc[0]; for ( i = 2; i < LC_SZ; i++ ) if ( lc[i] - lc[i-1] != delta_lc ) { x = x_save; homebrew_log << "attempting to back up" << " over previous iteration\n"; goto end_of_iteration; } } homebrew_log << "perturbing RHS, using perturbation " << "factor = " << pert_factor << "\n"; if (!b_any_pos) b_perturbed = true; objective_history.clear( ); refcount = -1; // force refactorization perturb(pert_factor); // The following added 6/11/99. R mr(standard), rx(standard); assign( mr, Ipow(2,31) - 1 ); for ( int ll = 0; ll < b.length; ll++ ) { double drx = randomx( ); assign( rx, drx ); rx /= mr; b(ll) += R(1000.0) * rx * tolerr; } if ( !b_any_pos ) { itcount_floor = ++itcount; goto end_of_iteration; } break; } } } itcount++; HIDE( ![ if (homebrew_full_report) homebrew_log << "Exiting variable: " << basis(k) << ". "; ]! ) TEX( ![ \begin{quotea} Update the basis, the basis matrix, and the $LU$ decomposition of it. \end{quotea} ]! ) normal_iteration = true; A_B.set_col( k, At(j) ); if_basis( basis(k) ) = false; if_basis(j) = true; j_save = j; k_save = k; basis_k_save = basis(k); P_save = P; basis(k) = j; update( LU, P, Q, At.x[j], k ); Qi = Q.inverse( ); end_of_iteration: loopcount++; continue; restart_slowly: loopcount = 0; refcount = -1; homebrew_log << "Restarting calculation from " << "scratch with \"homebrew speedy\" turned off\n"; speedy = false; speedy_toggled_because_apparently_done = false; candidate_count = 0; objective_history.clear( ); loop_count_at_refactorization.clear( ); entering_avoid.clear( ); basis = basis_save; for ( i = 0; i < n; i++ ) if_basis(i) = false; for ( i = 0; i < m; i++ ) if_basis( basis(i) ) = true; for ( i = 0; i < m; i++ ) for ( j = 0; j < m; j++ ) A_B(i,j) = At( basis(j), i ); for ( k = 0; k < n; k++ ) x(k) = (l(k).MinusInfinity( ) ? R(0) : R(l(k))); } } HIDE( ![ template class canonical_lp_problem; template class canonical_lp_problem; template class canonical_lp_problem; template class canonical_lp_problem; template istream& operator>>(istream&, canonical_lp_problem&); template istream& operator>>(istream&, canonical_lp_problem&); template istream& operator>>(istream&, canonical_lp_problem&); template istream& operator>>(istream&, canonical_lp_problem&); template bool check_infeasible(istream&, canonical_lp_problem&, vector&, const vconstraint&); template bool check_infeasible(istream&, canonical_lp_problem&, vector&, const vconstraint&); template bool check_infeasible(istream&, canonical_lp_problem&, vector&, const vconstraint&); template extend canonical_lp_problem ::simple_simplex(vector&, vector&, bool&, bool); template extend canonical_lp_problem ::simple_simplex(vector&, vector&, bool&, bool); template extend canonical_lp_problem ::simple_simplex(vector&, vector&, bool&, bool); template extend canonical_lp_problem ::simple_simplex(vector&, vector&, bool&, bool); ]! ) TEX( ![ \block{More matrix stuff} ]! ) set_compile_file(code.c) HIDE(![#include "matrix.h"]!) HIDE( ![ template void orbit( const prevector< matrix >&, const matrix&, prevector< matrix >&, int (*cmp)(const matrix&, const matrix&), void (*act)(const matrix&, const matrix&, matrix&), int = -1 ); ]! ) HIDE( ![ ifelse(UNAME,Openstep, ![ inline int cmp(const vector& a, const vector& b) { #ifdef DEBUG if ( a.x == 0 || b.x == 0 ) INTERNAL_ERROR("cmp invoked on uninitialized vector(s)"); #endif register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } void mul(const matrix& A, const matrix& B, matrix& P) { if ( A.ncols != B.nrows ) INTERNAL_ERROR("matrix multiplication"); P.set_size(A.nrows, B.ncols); int i, j, k; gf2 sum; for ( i = 0; i < P.nrows; i++ ) for ( j = 0; j < P.ncols; j++ ) { sum = 0; for ( k = 0; k < A.ncols; k++ ) sum += A(i,k) * B(k,j); P(i,j) = sum; } } ]! ) ]! ) template matrix::matrix(const vector& v) : nrows(1), ncols(v.length) { x = new vector[1]; x[0] = v; } set_compile_file(woof2.cc) HIDE(![#include "basedefs.h"]!) template matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new T[c]; x[i].length = c; } } HIDE( ![ matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new gf2[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new int[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new bool[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new char[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new doubledouble[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new Big[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new Integer[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new double[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new Rational[c]; x[i].length = c; } } matrix::matrix(int r, int c) : nrows(r), ncols(c) { x = new vector[r]; for ( int i = 0; i < r; i++ ) { x[i].x = new number[c]; x[i].length = c; } } ]! ) // matrix(nc, vl): make a matrix whose rows are the vectors in the list vl. // The vectors in vl must all have length nc. template matrix::matrix( int nc, const SLList< vector >& vl ) { int i; x = new vector[vl.length( )]; nrows = vl.length( ); ncols = nc; for ( i = 0; i < vl.length( ); i++ ) { x[i].x = new T[nc]; x[i].length = nc; } i = 0; forPixDef( p, vl ) (*this)(i++) = vl(p); } HIDE( ![ matrix::matrix( int nc, const SLList< vector >& vl ) { int i; x = new vector[vl.length( )]; nrows = vl.length( ); ncols = nc; for ( i = 0; i < vl.length( ); i++ ) { x[i].x = new gf2[nc]; x[i].length = nc; } i = 0; forPixDef( p, vl ) (*this)(i++) = vl(p); } ]! ) template matrix::matrix(const matrix& m) : nrows(m.nrows), ncols(m.ncols) { x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) x[i] = m.x[i]; } HIDE( ![ matrix::matrix(const matrix& m) { nrows = m.nrows; ncols = m.ncols; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) x[i] = m.x[i]; } matrix::matrix(const matrix& m) { nrows = m.nrows; ncols = m.ncols; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) x[i] = m.x[i]; } matrix::matrix(const matrix& m) { nrows = m.nrows; ncols = m.ncols; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) x[i] = m.x[i]; } matrix::matrix(const matrix& m) { nrows = m.nrows; ncols = m.ncols; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) x[i] = m.x[i]; } matrix::matrix(const matrix& m) { nrows = m.nrows; ncols = m.ncols; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) x[i] = m.x[i]; } matrix::matrix(const matrix& m) { nrows = m.nrows; ncols = m.ncols; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) x[i] = m.x[i]; } ]! ) set_compile_file(code.c) index_method(operator=(matrix)) template matrix& matrix::operator=(const matrix& m) { if ( m.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 || nrows != m.nrows || ncols != m.ncols ) { nrows = m.nrows; ncols = m.ncols; if ( x != 0 ) delete [ ] x; x = new vector[nrows]; } for ( int i = 0; i < m.nrows; i++ ) (*this).x[i] = m(i); } } HIDE( ![ matrix& matrix::operator=(const matrix& m) { if ( m.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 || nrows != m.nrows || ncols != m.ncols ) { nrows = m.nrows; ncols = m.ncols; if ( x != 0 ) delete [ ] x; x = new vector[nrows]; } for ( int i = 0; i < m.nrows; i++ ) (*this).x[i] = m(i); } } matrix& matrix::operator=(const matrix& m) { if ( m.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 || nrows != m.nrows || ncols != m.ncols ) { nrows = m.nrows; ncols = m.ncols; if ( x != 0 ) delete [ ] x; x = new vector[nrows]; } for ( int i = 0; i < m.nrows; i++ ) (*this).x[i] = m(i); } } matrix& matrix::operator=(const matrix& m) { if ( m.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 || nrows != m.nrows || ncols != m.ncols ) { nrows = m.nrows; ncols = m.ncols; if ( x != 0 ) delete [ ] x; x = new vector[nrows]; } for ( int i = 0; i < m.nrows; i++ ) (*this).x[i] = m(i); } } matrix& matrix::operator=(const matrix& m) { if ( m.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 || nrows != m.nrows || ncols != m.ncols ) { nrows = m.nrows; ncols = m.ncols; if ( x != 0 ) delete [ ] x; x = new vector[nrows]; } for ( int i = 0; i < m.nrows; i++ ) (*this).x[i] = m(i); } } matrix& matrix::operator=(const matrix& m) { if ( m.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 || nrows != m.nrows || ncols != m.ncols ) { nrows = m.nrows; ncols = m.ncols; if ( x != 0 ) delete [ ] x; x = new vector[nrows]; } for ( int i = 0; i < m.nrows; i++ ) (*this).x[i] = m(i); } } matrix& matrix::operator=(const matrix& m) { if ( m.x == 0 ) { if ( x != 0 ) delete [ ] x; x = 0; } else { if ( x == 0 || nrows != m.nrows || ncols != m.ncols ) { nrows = m.nrows; ncols = m.ncols; if ( x != 0 ) delete [ ] x; x = new vector[nrows]; } for ( int i = 0; i < m.nrows; i++ ) (*this).x[i] = m(i); } } ]! ) template bool operator==(const matrix& M1, const matrix& M2) BHIDE1( ![ if ( M1.x == 0 || M2.x == 0 ) INTERNAL_ERROR("operator== invoked on uninitialized matrice(s)"); ]!, ![ if ( M1.nrows != M2.nrows || M1.ncols != M2.ncols ) return false;]!) for ( int i = 0; i < M1.nrows; i++ ) for ( int j = 0; j < M1.ncols; j++ ) if ( M1(i,j) != M2(i,j) ) return false; return true; } HIDE( ![ template bool operator==(const matrix&, const matrix&); ]! ) HIDE( ![ template bool operator==(const matrix&, const matrix&); ]! ) HIDE( ![ template bool operator==(const matrix&, const matrix&); ]! ) index_method(remove_zero_rows_at_bottom) template void matrix::remove_zero_rows_at_bottom( ) { int i; for ( i = nrows - 1; i >= 0; i-- ) if ( !(x[i].if_zero( )) ) break; if ( i + 1 != nrows ) { vector* xnew = new vector[ i + 1 ]; for ( int j = 0; j < i + 1; j++ ) xnew[j] = x[j]; delete [ ] x; x = xnew; nrows = i + 1; } } TEX(![ \verb|column_fix|: Let $M$ := {\tt *this} be an $n \times k$ matrix in \RREF, having no zero rows. This routine permutes the columns of $M$ in a special way, and returns a pointer to the permutation $\sigma$ which was used. The most important thing about the new matrix (say $M'$) it that it is still in \RREF, but now moreover $M'_{11},\ldots,M'_{nn}$ are leading ones. Since there is in general more than one way to do this, we describe precisely how $\sigma$ is chosen. Let $\ell_1 < \cdots < \ell_n$ be the columns in which the leading ones of $M$ reside. Then $$ \sigma = (n,\ell_n) \circ (n-1,\ell_{n-1}) \circ \ldots \circ (1,\ell_1).$$% Henceforth in this paper we refer to $\sigma$ as the {\it column fix\/} of $M$. ]!) index_method(column_fix) template Permutation* matrix::column_fix( ) { Permutation* colfix = new Permutation(ncols); for ( int i = 0; i < nrows; i++ ) { for ( int j = i; j < ncols; j++ ) if ( (*this)(i,j) == 1 ) { if ( i != j ) { colfix->transpose(i+1, j+1); transpose_columns(i, j); } break; } } return colfix; } HIDE( ![ INSTANTIATE( ![Permutation* matrix::column_fix( )]!, T, gf2 ) ]! ) index_method(orthogonal_to) bool matrix::orthogonal_to(const vector& v) const { for ( int i = 0; i < nrows; i++ ) if ( odd ( (*this)(i) * v ) ) return false; return true; } index_method(permute_columns) template void matrix::permute_columns(const Permutation& p) { vector new_row = vector(ncols); for ( int i = 0; i < nrows; i++ ) { for ( int j = 0; j < ncols; j++ ) new_row(p(j).x-1) = (*this)(i,j); (*this)(i) = new_row; } } index_method(select) template matrix matrix::select(const vector& rows, const vector& cols) const { matrix A( rows.weight( ), cols.weight( ) ); int col_ptr = 0; for ( int i = 0; i < ncols; i++ ) if ( cols(i) ) { int row_ptr = 0; for ( int j = 0; j < nrows; j++ ) if ( rows(j) ) { A( row_ptr, col_ptr ) = (*this)(j, i); row_ptr++; } col_ptr++; } return A; } index_method(permutation_matrix) template void matrix::set_permutation_matrix(const Permutation& p) { matrix M; M.set_identity( p.length ); M.permute_columns(p); M.transpose_equals(*this); } index_method(nullspace_equals) template void matrix::nullspace_equals(matrix& n) const { n.set_size(ncols - nrows, ncols); matrix& M = const_cast< matrix& >(*this); Permutation* colfix = M.column_fix( ); int i, j; for ( i = 0; i < ncols - nrows; i++ ) { for ( j = 0; j < nrows; j++ ) n(i,j) = -M(j, i + nrows); for ( j = 0; j < ncols - nrows; j++ ) n(i, j + nrows) = (i == j); } Permutation colfix_i = colfix->inverse( ); n.permute_columns(colfix_i); M.permute_columns(colfix_i); delete colfix; } index_method(fixes) template bool matrix::fixes( const vector& v ) { vector w; mul( *this, v, w ); return v == w; } index_method(transpose_equals) template void matrix::transpose_equals(matrix& n) const BHIDE1( ![ if ( x == 0 ) INTERNAL_ERROR("You can't transpose a null matrix."); ]!, ![ n.set_size(ncols, nrows); ]! ) for ( int i = 0; i < nrows; i++ ) for ( int j = 0; j < ncols; j++ ) n(j,i) = (*this)(i,j); } TEX( Compute the weight enumerator of the code having as a basis the rows of the given matrix. ) HIDE( ![ vector dual_of_we(vector, bool = false); typedef vector word; void mul(const vector&, const matrix&, vector&); #include "bitvec.h" ]! ) index_method(enumerate_weights) vector matrix::enumerate_weights( ) const { vector y(ncols + 1); if ( 2 * nrows <= ncols ) { y.set_zero( ); if ( nrows <= 31 ) { bitmat A(*this); unsigned long M = Ipow(2, nrows); bitvec sum(ncols); y(0) = 1; for ( unsigned long i = 0; i < M - 1; i++ ) { sum += A.x[ gray(i) ]; ++y( sum.weight( ) ); } } else // This should be replaced! { vector indx(nrows), sum(ncols); do { mul( indx, *this, sum ); ++y( sum.weight( ) ); } while( indx.advance( ) != 0 ); } } else { matrix D; nullspace_equals(D); y = dual_of_we( D.enumerate_weights( ) ); } return y; } set_compile_file(matgf2.cc) HIDE( ![ // #define DEBUG class Permutation; #include "somedefs.h" typedef vector word; #include "permutation.h" template void orbit( const prevector&, const S&, prevector&, int (*cmp)(const S&, const S&), void (*act)(const G&, const S&, S&), int = -1 ); int pcmp( const Permutation&, const Permutation& ); #include "permutationlist.h" #include "matrix.h" #include ]! ) index_method(hcat) // horizontal concatenation template void hcat(const matrix& A, const matrix& B, matrix& C) BHIDE1( ![ if ( A.x == 0 || B.x == 0 || A.nrows != B.nrows ) INTERNAL_ERROR("hcat: input matrices don't make sense"); ]!, ![ C.set_size(A.nrows, A.ncols + B.ncols); ]! ) int i, j; for ( i = 0; i < A.nrows; i++ ) { for ( j = 0; j < A.ncols; j++ ) C(i,j) = A(i,j); for ( j = 0; j < B.ncols; j++ ) C(i,j + A.ncols) = B(i,j); } } HIDE( ![ template void hcat(const matrix&, const matrix&, matrix&); ]! ) index_method(vcat) // vertical concatenation template void vcat(const matrix& A, const matrix& B, matrix& C) BHIDE1( ![ if ( A.x == 0 || B.x == 0 || A.ncols != B.ncols ) INTERNAL_ERROR("vcat: input matrices don't make sense"); ]!, ![ C.set_size(A.nrows + B.nrows, A.ncols); ]! ) int i, j; for ( i = 0; i < A.ncols; i++ ) { for ( j = 0; j < A.nrows; j++ ) C(j,i) = A(j,i); for ( j = 0; j < B.nrows; j++ ) C(j + A.nrows,i) = B(j,i); } } HIDE( ![ template void vcat(const matrix&, const matrix&, matrix&); ]! ) index_method(mul) template void mul(const matrix& A, const matrix& B, matrix& P) BHIDE1( ![ if ( A.ncols != B.nrows ) INTERNAL_ERROR("matrix multiplication"); ]!, ![ P.set_size(A.nrows, B.ncols); ]! ) int i, j, k; T sum; for ( i = 0; i < P.nrows; i++ ) for ( j = 0; j < P.ncols; j++ ) { sum = 0; for ( k = 0; k < A.ncols; k++ ) sum += A(i,k) * B(k,j); P(i,j) = sum; } } index_method(mul) template void mul( const vector& v, const matrix& M, vector& prod ) BHIDE1( ![ if ( v.x == 0 || M.x == 0 || v.length != M.nrows ) INTERNAL_ERROR( "Multiplication of vector times matrix." ); ]!, ![ prod.set_size( M.ncols ); ]! ) int i, j; prod.set_zero( ); for ( i = 0; i < M.nrows; i++ ) for ( j = 0; j < M.nrows; j++ ) prod(j) += v(i) * M(i,j); } void mul( const vector& v, const matrix& M, vector& prod ) BHIDE1( ![ if ( v.x == 0 || M.x == 0 || v.length != M.nrows ) INTERNAL_ERROR( "Multiplication of vector times matrix." ); ]!, ![ prod.set_size( M.ncols ); ]! ) prod.set_zero( ); for ( int i = 0; i < v.length; i++ ) if ( v(i) ) prod += M(i); } index_method(xA_minus_c_eq) template void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans) { ans.set_size( A.ncols ); int i, j; for ( i = 0; i < A.ncols; i++ ) ans(i) = -c(i); for ( i = 0; i < A.nrows; i++ ) for ( j = 0; j < A.ncols; j++ ) ans(j) += x(i) * A(i,j); } HIDE( ![ void mul( const vector& v, const matrix& M, vector& prod ) { if ( v.x == 0 || M.x == 0 || v.length != M.nrows ) INTERNAL_ERROR( "Multiplication of vector times matrix." ); prod.set_size( M.ncols ); int i, j; prod.set_zero( ); for ( i = 0; i < M.nrows; i++ ) for ( j = 0; j < M.nrows; j++ ) prod(j) += v(i) * M(i,j); } void mul( const vector& v, const matrix& M, vector& prod ) { if ( v.x == 0 || M.x == 0 || v.length != M.nrows ) INTERNAL_ERROR( "Multiplication of vector times matrix." ); prod.set_size( M.ncols ); int i, j; prod.set_zero( ); for ( i = 0; i < M.nrows; i++ ) for ( j = 0; j < M.nrows; j++ ) prod(j) += v(i) * M(i,j); } void mul( const vector& v, const matrix& M, vector& prod ) { if ( v.x == 0 || M.x == 0 || v.length != M.nrows ) INTERNAL_ERROR( "Multiplication of vector times matrix." ); prod.set_size( M.ncols ); int i, j; prod.set_zero( ); for ( i = 0; i < M.nrows; i++ ) for ( j = 0; j < M.nrows; j++ ) prod(j) += v(i) * M(i,j); } void mul( const vector& v, const matrix& M, vector& prod ) { if ( v.x == 0 || M.x == 0 || v.length != M.nrows ) INTERNAL_ERROR( "Multiplication of vector times matrix." ); prod.set_size( M.ncols ); int i, j; prod.set_zero( ); for ( i = 0; i < M.nrows; i++ ) for ( j = 0; j < M.nrows; j++ ) prod(j) += v(i) * M(i,j); } void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans) { ans.set_size( A.ncols ); int i, j; for ( i = 0; i < A.ncols; i++ ) ans(i) = -c(i); for ( i = 0; i < A.nrows; i++ ) for ( j = 0; j < A.nrows; j++ ) ans(j) += x(i) * A(i,j); } void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans) { ans.set_size( A.ncols ); int i, j; for ( i = 0; i < A.ncols; i++ ) ans(i) = -c(i); for ( i = 0; i < A.nrows; i++ ) for ( j = 0; j < A.nrows; j++ ) ans(j) += x(i) * A(i,j); } void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans) { ans.set_size( A.ncols ); int i, j; for ( i = 0; i < A.ncols; i++ ) ans(i) = -c(i); for ( i = 0; i < A.nrows; i++ ) for ( j = 0; j < A.nrows; j++ ) ans(j) += x(i) * A(i,j); } void xA_minus_c_eq(const vector& x, const matrix& A, const vector& c, vector& ans) { ans.set_size( A.ncols ); int i, j; for ( i = 0; i < A.ncols; i++ ) ans(i) = -c(i); for ( i = 0; i < A.nrows; i++ ) for ( j = 0; j < A.nrows; j++ ) ans(j) += x(i) * A(i,j); } ]! ) index_method(rowspace_intersection) void rowspace_intersection(const matrix& A, const matrix& B, matrix& C) { matrix AT = transpose_of(A), BT = transpose_of(B), ATBT, D, CT, DT; HIDE( ![ if ( A.ncols != B.ncols ) INTERNAL_ERROR("rowspace_intersection"); ]! ) hcat(AT, BT, ATBT); ATBT.reduce_nz( ); ATBT.nullspace_equals(D); D.resize( D.nrows, AT.ncols ); D.transpose_equals(DT); mul(AT, DT, CT); CT.transpose_equals(C); C.reduce_nz( ); } TEX(![ If $M$ is a generator matrix for a code C, in \RREF, \verb|intersect_dual|$(M,N)$ will cause $N$ to be set equal to a generator matrix for $C \cap C^\perp$. ]!) index_method(intersect_dual) void intersect_dual(const matrix& M, matrix& N) { matrix nullspace_M; M.nullspace_equals(nullspace_M); rowspace_intersection(M, nullspace_M, N); } TEX(![ \verb|rowspace_member|: Given a matrix over {\tt gf2}, in \RREF\ and having no zero rows at the bottom, test to see if a given vector is in the rowspace. ]!) index_method(rowspace_member) bool matrix::rowspace_member( vector w ) const { int col = 0; for ( int row = 0; row < nrows; row++ ) { while ( (*this)(row, col).x == 0 ) col++; if ( w(col) ) w += (*this)(row); } return w.if_zero( ); } index_method(coord_vector) vector matrix::coord_vector( vector w ) const { vector coord(nrows); int col = 0; for ( int row = 0; row < nrows; row++ ) { while ( (*this)(row, col).x == 0 ) col++; if ( w(col) ) { w += (*this)(row); coord(row) = 1; } } if ( !w.if_zero( ) ) INTERNAL_ERROR("coord_vector failed" ); return coord; } TEX( ![ Convert (in place) a matrix to reduced row echelon form and return its rank. For the {\tt Integer} case, ``leading ones'' are not required to be one, and we don't clear out above them either. Whenever we subtract a multiple of a row from another, we divide the modified row by its gcd afterwards. But there is no guarantee that every row is reduced at the end of the process. ]! ) index_method(reduce) int matrix::reduce( ) { matrix& M = *this; int r, c, current_row = 0, current_col = 0; do { for ( r = current_row; r < nrows; r++ ) // find 1 in current column if ( M(r, current_col) ) break; if ( r > nrows-1 ) // no 1 in current column (at or below current row) { current_col++; continue; } if ( r != current_row ) // have to exchange rows for ( c = current_col; c < ncols; c++ ) swap( M(r, c), M(current_row, c) ); for ( r = 0; r < nrows; r++ ) // clear out the current column if ( r != current_row && M(r, current_col) ) { // The efficiency of the following code is extremely // critical. register gf2* rx = M.x[r].x; register gf2* crx = M.x[current_row].x; for ( c = current_col; c < ncols; c++ ) rx[c] += crx[c]; } current_row++; current_col++; } while(current_row < nrows && current_col < ncols); return current_row; } int matrix::reduce( ) { matrix& M = *this; int current_row = 0, current_col = 0, r, c, pivot_row; Integer pivot; do { // Find nonzero entry in current column with smallest absolute value. pivot = 0; pivot_row = -1; for ( r = current_row; r < nrows; r++ ) if( M(r, current_col) != 0 && (pivot_row == -1 || abs(M(r, current_col)) < pivot) ) { pivot = abs(M(r, current_col)); pivot_row = r; } if ( pivot_row == -1 ) //from current row down, current column is zero { current_col++; continue; } if ( pivot_row != current_row ) // have to exchange rows for ( c = current_col; c < ncols; c++ ) swap( M(pivot_row, c), M(current_row, c) ); // Clear out the current column, below the current row. for ( r = current_row + 1; r < nrows; r++ ) if ( M(r, current_col) != 0 ) { // The following should work but gives segmentation faults: // Rational multiplier // ( M(r, current_col), M(current_row, current_col) ); Rational multiplier = Rational(M(r, current_col)) / Rational(M(current_row, current_col)); Integer md = multiplier.denominator( ); Integer mn = multiplier.numerator( ); // Multiply row r by the denominator of the multiplier. for ( c = current_col; c < ncols; c++ ) M(r, c) *= md; // Clear. for ( c = current_col; c < ncols; c++ ) M(r, c) -= M(current_row, c) * mn; // Compute the gcd of row r. Integer g = M(r, current_col); for ( c = current_col + 1; c < ncols; c++ ) gcd( g, g, M(r, c) ); // Divide row r by its gcd. if ( g != 0 ) { for ( c = current_col; c < ncols; c++ ) M(r, c) /= g; } } current_row++; current_col++; } while(current_row < nrows && current_col < ncols); return current_row; } index_method(reduce_nz) template void matrix::reduce_nz( ) { reduce( ); remove_zero_rows_at_bottom( ); } HIDE( ![ INSTANTIATE( ![void matrix::reduce_nz( )]!, T, Integer, gf2 ) ]! ) index_method(reduce_i) void matrix::reduce_i(matrix& Q) { matrix& M = *this; Q.set_size(nrows, nrows); int r, c, current_row = 0, current_col = 0; for ( r = 0; r < nrows; r++ ) for ( c = 0; c < nrows; c++ ) Q(r,c) = (r == c); do { for ( r = current_row; r < nrows; r++ ) // find 1 in current column if( M(r, current_col) ) break; if ( r > nrows-1 ) // no 1 in current column (at or below current row) { current_col++; continue; } if ( r != current_row ) // have to exchange rows { for ( c = current_col; c < ncols; c++ ) swap( M(r, c), M(current_row, c) ); for ( c = 0; c < nrows; c++ ) swap( Q(r, c), Q(current_row, c) ); } for ( r = 0; r < nrows; r++ ) // clear out the current column if ( r != current_row && M(r, current_col) ) { for ( c = current_col; c < ncols; c++ ) M(r, c) += M(current_row, c); Q(r) += Q(current_row); } current_row++; current_col++; } while(current_row < nrows && current_col < ncols); } TEX(![ \verb|rank_of_rowspace_sum(M, N)|: Let \verb|M|, \verb|N| be matrices having the same number of columns. Compute the rank of $\rowspace($\verb|M|$) + \rowspace($\verb|N|$)$. It is assumed that the matrix \verb|M| is in reduced row echelon form, that it has no zero rows, and that it has leading $1$'s in the $(0,0), (1,1), \ldots$ spots. The matrix \verb|N| is modified. The implementation is inefficient in so far as it does row exchanges. ]!) index_method(rank_of_rowspace_sum) int rank_of_rowspace_sum(const matrix& M, matrix& N) { int current_row = 0, current_col = 0, r, rx, c, cx; // First reduce to the case where the first M.nrows columns of N are zero. for ( r = 0; r < M.nrows; r++ ) for ( rx = 0; rx < N.nrows; rx++ ) if ( N(rx, r) ) for ( cx = r; cx < N.ncols; cx++ ) N(rx, cx) += M(r, cx); // Now convert N to row echelon form. The code here is very similar // to that of matrix::reduce. current_col = M.nrows; current_row = 0; int rank = M.nrows; while(current_row < N.nrows && current_col < N.ncols) { for ( r = current_row; r < N.nrows; r++ ) // find 1 in current column if( N(r, current_col) ) break; if ( r > N.nrows-1 ) // no 1 in current col (at or below current row) { current_col++; continue; } if ( r != current_row ) // have to exchange rows for ( c = current_col; c < N.ncols; c++ ) swap( N(r, c), N(current_row, c) ); for ( r = current_row+1; r < N.nrows; r++ ) { // clear out the current column (below current row) if ( N(r, current_col) ) for ( c = current_col; c < N.ncols; c++ ) N(r, c) += N(current_row, c); } rank++; current_row++; current_col++; } return rank; } HIDE( ![ #include "OSLList.h" inline bool operator !=(OSLList< vector >, OSLList< vector >) { INTERNAL_ERROR( "operator!= for OSLList< vector > not defined"); } inline int even(int i) { return !(i % 2); } #include "bitvec.h" ]! ) int bitmat::reduce( ) { bitmat& M = *this; int r, c, current_row = 0, current_col = 0; int first_word = 0, last_word = (ncols - 1) >> LOG2_BPI; int w; do { for ( r = current_row; r < nrows; r++ ) // find 1 in current column if ( M.nonzero(r, current_col) ) break; if ( r > nrows-1 ) // no 1 in current column (at or below current row) { current_col++; first_word = current_col >> LOG2_BPI; continue; } if ( r != current_row ) // have to exchange rows for ( w = first_word; w <= last_word; w++ ) swap( M.x[r].x[w], M.x[current_row].x[w] ); for ( r = 0; r < nrows; r++ ) // clear out the current column if ( r != current_row && M.nonzero(r, current_col) ) { register unsigned int* rx = M.x[r].x; register unsigned int* crx = M.x[current_row].x; for ( w = first_word; w <= last_word; w++ ) rx[w] ^= crx[w]; } current_row++; current_col++; first_word = current_col >> LOG2_BPI; } while(current_row < nrows && current_col < ncols); return current_row; } HIDE( ![ #include "NTL/BBFactoring.h" #include "NTL/mat_poly_zz_p.h" ]! ) index_method(char_poly) vector matrix::char_poly( ) const { zz_pInit(2); ntl_matrix(zz_p) M(INIT_SIZE, nrows, nrows); for ( int i = 1; i <= nrows; i++ ) for ( int j = 1; j <= nrows; j++ ) M(i, j) = (*this)(i-1, j-1).x; zz_pX f; CharPoly( f, M ); vector v(nrows + 1); for ( int i = 0; i <= nrows; i++ ) v(i).x = rep( coeff(f, i) ); return v; } index_method(nilpotent) bool matrix::nilpotent( ) const { vector p = char_poly( ); for ( int i = 0; i < p.length - 1; i++ ) if ( p(i) ) return false; return true; } set_compile_file(solve.cc) #include "homedefs.h" #include "simplex.h" // ------------------------- begin solve section ------------------------------ // solve0: Solve by doing an exact LU decomposition. void solve0(const matrix& A, vector& x, const vector& b) { Permutation P( A.nrows ); matrix LU( A.nrows, A.ncols ); for ( int i = 0; i < A.nrows; i++ ) for ( int j = 0; j < A.ncols; j++ ) LU(i,j) = A(i,j); vector b_rat( b.length ); for ( int i = 0; i < b.length; i++ ) b_rat(i) = b(i); if ( !LU.lu_decompose(P) ) ERROR( "The matrix fed to Solve is not invertible." ); LU.solve_from_lu(P, b_rat, x); } // solve1: Compute at precision level 3, and round to the answer to rationals. // (Of course, this will usually give the wrong answer.) void solve1(const matrix& A, vector& x, const vector& b) { Permutation P( A.nrows ); matrix LU( A.nrows, A.ncols ); for ( int i = 0; i < A.nrows; i++ ) for ( int j = 0; j < A.ncols; j++ ) { LU(i,j).set_precision(3); assign( LU(i,j), A(i,j) ); } vector bb( b.length ); for ( int i = 0; i < b.length; i++ ) { bb(i).set_precision(3); assign( bb(i), b(i) ); } if ( !LU.lu_decompose(P) ) ERROR( "The matrix fed to Solve appears to be singular." ); x.set_size( A.nrows ); vector xx( x.length ); LU.solve_from_lu(P, bb, xx); for ( int i = 0; i < x.length; i++ ) assign( x(i), xx(i) ); } // solve: Test inputs and invoke the current solvei. void solve(const matrix& A, vector& x, const vector& b, int version) { if ( A.nrows != A.ncols ) ERROR( "Solve is only defined for square matrices A." ); if ( A.nrows != b.length ) ERROR("Your use of Solve does not make sense."); if ( version == 0 ) solve0( A, x, b ); else if ( version == 1 ) solve1( A, x, b ); else ERROR( "Illegal version of Solve." ); } // ------------------------- end solve section ------------------------------ set_compile_file(code.c) template ostream& operator<<(ostream& s, const matrix& m) { s << "{"; for ( int i = 0; i < m.nrows; i++ ) { s << m(i); if ( i < m.nrows - 1 ) s << ","; } return s << "}"; } INSTANTIATE( ![ostream& operator<<(ostream&, const matrix&)]!, T, gf2, int, double, doubledouble, Big, Integer, Rational ) template istream& operator>>(istream& s, matrix& m) { char c; s.get(c); if ( c != '{' ) ERROR( "matrix read failed" ); SLList< vector > ml; while(1) { s.get(c); if ( c != '{' ) ERROR( "matrix read failed" ); String x; while(1) { s.get(c); if ( c == EOF ) ERROR( "matrix read failed" ); if ( c == '}' ) break; x += c; } ml.append(x); s.get(c); if ( c == '}' ) break; if ( c == ',' ) continue; else ERROR( "matrix read failed" ); } vector< vector > mlv(ml); for ( int i = 1; i < mlv.length; i++ ) if ( mlv(i).length != mlv(i-1).length ) ERROR( "matrix read -- unequal row lengths" ); m.set_size( mlv.length, mlv(0).length ); for ( int i = 0; i < m.nrows; i++ ) for ( int j = 0; j < m.ncols; j++ ) m(i,j) = mlv(i)(j); return s; } INSTANTIATE( ![istream& operator>>(istream&, matrix&)]!, T, Integer, Rational ) TEX(![ Initialize a matrix over {\tt gf2} from an integer (the number of columns), and a white-space-free string, which gives the rows of the matrix. For example, valid arguments would be \par\noindent\kern1.5cm\verb|4, "{1111,1100,1010}"| or \verb|7, "{}"|. The brackets are optional. ]!) matrix::matrix( int nc, String s ) : ncols(nc) { static Regex curlybracks( "[{}]" ); static Regex wordpat( "[01]*" ); // Check for valid matrix. // The following three lines caused segmentation faults under // NeXTStep/Intel when s was very long (around 4000 characters). I could // not trace the source of the problem, but it could be a bug in the // regular expression package. Therefore the ten lines which follow // are a substitute. // static Regex matrixpat( "" + orsign + "{}" + orsign + list_of("[01]*") + // orsign + "{" + list_of("[01]*") + "}" ); // if( !s.matches(matrixpat) ) ERROR("01 matrix is garbage"); bool brackets = false; int j, n = s.length( ); for ( j = 0; j < n; j++ ) { if ( j == 0 && s[0] == '{' ) { brackets = true; continue; } if ( j == n - 1 && s[j] == '}' && brackets ) break; if ( s[j] != '0' && s[j] != '1' && s[j] != ',' ) ERROR( "01 matrix is garbage." ); } if ( brackets && j == n ) ERROR( "01 matrix is garbage." ); s.gsub(curlybracks, ""); // delete brackets { } nrows = s.empty( ) ? 0 : s.freq(",") + 1; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) { (*this)(i) = vector( take(s, wordpat), 0 ); if ( (*this)(i).length != ncols ) ERROR("A row in the matrix " << s << " has the wrong length."); if ( i < nrows - 1 ) require_char(s, ','); } } TEX( ![ \verb|is_zero_one_matrix|:\ In effect, check against the regular expression \verb|"{" + list_of( "[01]+" ) + "}"|. Actually doing the latter sometimes resulted in segmentation faults under NeXTStep. (See \verb|::matrix|.) ]! ) index_method(is_zero_one_matrix) bool is_zero_one_matrix( const String& s, bool naked_allowed = false ) { int n = s.length( ); bool brackets_used = false; for ( int j = 0; j < n; j++ ) { if ( j == 0 ) { if ( s[0] == '{' ) { brackets_used = true; continue; } if ( !naked_allowed ) return false; } if ( brackets_used && j == n - 1 && s[j] == '}' ) return true; if ( s[j] != '0' && s[j] != '1' && s[j] != ',' ) return false; } return false; } matrix::matrix(String s) { static Regex curlybracks( "[{}]" ); static Regex wordpat( "[01]*" ); if ( !is_zero_one_matrix( s, true ) ) ERROR("01 matrix is garbage"); s.gsub(curlybracks, ""); // delete brackets { } nrows = s.empty( ) ? 0 : s.freq(",") + 1; ncols = -1; x = new vector[nrows]; for ( int i = 0; i < nrows; i++ ) { (*this)(i) = vector( take(s, wordpat), 0 ); if ( ncols == -1 ) ncols = (*this)(i).length; else if ( (*this)(i).length != ncols ) ERROR("A row in the matrix " << s << " has the wrong length."); if ( i < nrows - 1 ) require_char(s, ','); } } INSTANTIATE( ![class matrix]!, T, gf2, Integer ) INSTANTIATE( ![void matrix::remove_zero_rows_at_bottom( )]!, T, gf2, Integer ) INSTANTIATE( ![void matrix::permute_columns(const Permutation&)]!, T, gf2 ) INSTANTIATE( ![void matrix::nullspace_equals(matrix&) const]!, T, gf2 ) INSTANTIATE( ![void matrix::transpose_equals(matrix&) const]!, T, gf2 ) INSTANTIATE( ![matrix matrix::select(const vector& rows, const vector& cols) const]!, T, Integer ) TEX(![ \block{Bit vector and graph classes} This section contains an interface to Brendan McKay's graph automorphism/isomorphism program nauty. We first give a class {\tt bitvec}, which is a vector of bits, like nauty's {\tt set} structure. Because we are not using {\tt bitvec}'s in any computationally intensive way, the class has not been optimized, but it could be by looking at how {\tt set} is implemented in nauty. I wanted to give an operator so that {\tt b(i)} could be use to set or retrieve the \th{\hbox{\tt i}} bit of a {\tt bitvector} {\tt b}, but I don't know how to do it. The bits are divided into words each having (say) $r$ bits. The bits in the first word are numbered $r-1,r-2,\ldots,1,0$. The bits in the second word are numbered $2r-1,2r-2,\ldots,r+1,r$, and so forth. However, we think of the bits in a {\tt bitvec} as being arranged from left to right: $0,1,2,\ldots$. A {\tt bitvec} can also be regarded as a set of finitely many nonnegative integers, an on bit signifying membership. Then we give a class \verb|vertex_colored_graph|, which contains the interface to nauty. ]! ) set_include_file(bitvec.h) #undef CHAR_BIT #define CHAR_BIT 8 index_class(bitvec) index_method(nwords) index_method(set_size) index_method(set) index_method(add) index_method(value) index_method(apply) index_method(weight) index_method(clear) index_method(intersection) index_method(Union) index_method(even_part) index_method(odd_part) index_method(left_shift1) index_method(right_shift1) index_method(set_zero) index_method(if_zero) index_method(nonzero) #define BITS_PER_INT ( sizeof(unsigned int) * CHAR_BIT ) #define LOG2_BPI 5 class bitvec { public: unsigned int* x; int length; // number of bits static void test_sizes( ); int nwords( ) const { if ( length == 0 ) return 0; else return 1 + ((length - 1) >> LOG2_BPI); } bitvec(int n = 0) // define a bitvec with n bits, preset to 0 { length = n; int nw = nwords( ); x = new unsigned int[nw]; for ( int i = 0; i < nw; i++ ) x[i] = 0; } bitvec( const bitvec& b ) { length = b.length; int bnw = b.nwords( ); x = new unsigned int[ bnw ]; for ( int i = 0; i < bnw; i++ ) x[i] = b.x[i]; } ~bitvec( ) { delete [ ] x; } void set_size(int n) { if ( n == length ) return; delete [ ] x; length = n; int nw = nwords( ); x = new unsigned int[nw]; for ( int i = 0; i < nw; i++ ) x[i] = 0; } bitvec& operator=(const bitvec& b) { int bnw = b.nwords( ); if ( nwords( ) != bnw ) { delete [ ] x; x = new unsigned int[bnw]; } for ( int i = 0; i < bnw; i++ ) x[i] = b.x[i]; length = b.length; } void set(int i, bool j = true) // set the ith bit to j BHIDE2( ![ if ( i < 0 || i >= length ) INTERNAL_ERROR("set: invalid bit reference."); ]!, ![ int word_no = i >> LOG2_BPI; ]! ) int bit_no = i % BITS_PER_INT; if (j) x[word_no] |= (1 << bit_no); else x[word_no] &= ~(1 << bit_no); } void add(int i, bool j) // add j to the ith bit { HIDE( ![ if ( i < 0 || i >= length ) INTERNAL_ERROR("add: invalid bit reference."); ]! ) if (j) { int bit_no = i % BITS_PER_INT; int word_no = i >> LOG2_BPI; x[word_no] ^= (1 << bit_no); } } bitvec( const vector& w ) { if ( w.x == 0 ) { length = 0; x = new unsigned int[0]; } else { length = w.length; int nw = nwords( ); x = new unsigned int[nw]; int i; for ( i = 0; i < nw; i++ ) x[i] = 0; for ( i = 0; i < length; i++ ) if ( w(i) ) set(i); } } // nonzero: return nonzero iff ith bit is defined and nonzero int nonzero(int i) const { return i < length && x[ i >> LOG2_BPI ] & (1 << (i % BITS_PER_INT)); } bool value(int i) const // return value of ith bit { HIDE( ![ if ( i < 0 || i >= length ) INTERNAL_ERROR("value: invalid bit reference."); ]! ) return nonzero(i) != 0; } void set_zero( ) { int nw = nwords( ); for ( int i = 0; i < nw; i++ ) x[i] = 0; } bool if_zero( ) { int nw = nwords( ); for ( int i = 0; i < nw; i++ ) if ( x[i] != 0 ) return false; return true; } operator word( ) { word v(length); for ( int i = 0; i < length; i++ ) v(i) = value(i); return v; } friend bool operator==(const bitvec& b1, const bitvec& b2) { if ( b1.length != b2.length ) return false; int nw = b1.nwords( ); for ( int i = 0; i < nw; i++ ) if ( b1.x[i] != b2.x[i] ) return false; return true; } friend bool operator!=(const bitvec& b1, const bitvec& b2) { return !(b1 == b2); } bitvec apply(const Permutation&p) const { bitvec ans(length); for ( int i = 0; i < length; i++ ) if ( value(i) ) ans.set( p(i) - 1 ); return ans; } TEX( ![ \begin{quote} If we regard a {\tt bitvec\/} as a set of nonnegative integers, then {\tt intersection} intersects these sets. \end{quote} ]! ) friend bitvec intersection(const bitvec& x, const bitvec& y) { int r = min( x.nwords( ), y.nwords( ) ); bitvec ans( max(x.length, y.length) ); for ( int i = 0; i < r; i++ ) ans.x[i] = x.x[i] & y.x[i]; return ans; } friend bitvec Union(const bitvec& x, const bitvec& y) { int r = min( x.nwords( ), y.nwords( ) ); bitvec ans( max(x.length, y.length) ); for ( int i = 0; i < r; i++ ) ans.x[i] = x.x[i] | y.x[i]; if ( x.nwords( ) > r ) for ( int j = r; j < x.nwords( ); j++ ) ans.x[j] = x.x[j]; else if ( y.nwords( ) > r ) for ( int j = r; j < y.nwords( ); j++ ) ans.x[j] = y.x[j]; return ans; } TEX( ![ \begin{quote} Convert an ordered list of nonnegative integers to a set of nonnegative integers, regarded as a {\tt bitvec}. \end{quote} ]! ) bitvec( const OSLList& l ) { if ( l.length( ) == 0 ) { length = 0; int nw = nwords( ); x = new unsigned int[nw]; for ( int i = 0; i < nw; i++ ) x[i] = 0; return; } length = l.Max( ) + 1; int nw = nwords( ); x = new unsigned int[nw]; for ( int i = 0; i < nw; i++ ) x[i] = 0; forPixDef( p, l ) set( l(p) ); } TEX( ![ \begin{quote} Extract the odd elements from a bitvec. (The first bit is numbered $0$.) \end{quote} ]! ) bitvec odd_part( ) const { bitvec ans(length); HIDE( ![ if (BITS_PER_INT != 32) INTERNAL_ERROR( "Sorry, bitvec::odd_part assumes an int has " << "32 bits in it. The code will need to be rewritten." ); ]! ) static unsigned int odd_bits = 025252525252; int nw = nwords( ); for ( int i = 0; i < nw; i++ ) ans.x[i] = x[i] & odd_bits; return ans; } bitvec even_part( ) const { bitvec ans(length); HIDE( ![ if (BITS_PER_INT != 32) INTERNAL_ERROR( "Sorry, bitvec::even_part assumes an int has " << "32 bits in it. The code will need to be rewritten." ); ]! ) static unsigned int even_bits = 012525252525; int nw = nwords( ); for ( int i = 0; i < nw; i++ ) ans.x[i] = x[i] & even_bits; return ans; } TEX( ![ \begin{quote} Left shift one bit, with the leftmost bit falling off into the bit bucket. \end{quote} ]! ) void left_shift1( ) { int nw = nwords( ); static unsigned int high_bit = 020000000000; HIDE( ![ if (BITS_PER_INT != 32) INTERNAL_ERROR( "Sorry, bitvec::left_shift1 assumes an int has " << "32 bits in it. The code will need to be rewritten." ); ]! ) for ( int i = 0; i < nw; i++ ) { x[i] = x[i] >> 1; if ( i > 0 && even(x[i]) ) x[i-1] |= high_bit; } } TEX( ![ \begin{quote} Right shift one bit, adding a zero bit to fill the hole. \end{quote} ]! ) void right_shift1( ) { int nw = nwords( ); bool high_bit_saved = false; static unsigned int high_bit = 020000000000; HIDE( ![ if (BITS_PER_INT != 32) INTERNAL_ERROR( "Sorry, bitvec::right_shift1 assumes an int has " << "32 bits in it. The code will need to be rewritten." ); ]! ) for ( int i = 0; i < nw; i++ ) { bool hb = (x[i] & high_bit) != 0; x[i] = x[i] << 1; if (high_bit_saved) x[i] |= 01; high_bit_saved = hb; } if ( length % 32 == 0 ) { bitvec me(length + 1); for ( int j = 0; j < nw; j++ ) me.x[j] = x[j]; me.x[nw] = high_bit_saved; *this = me; } } friend bitvec operator+(const bitvec& x, const bitvec& y) BHIDE2( ![ if ( x.length != y.length ) INTERNAL_ERROR("bitvec length inconsistency"); ]!, ![ bitvec ans(x.length); ]! ) int nw = x.nwords( ); for ( int i = 0; i < nw; i++ ) ans.x[i] = x.x[i] ^ y.x[i]; return ans; } HIDE( ![ friend bitvec operator-(const bitvec&) { INTERNAL_ERROR("There is no unary bitvec operator-."); } ]! ) friend inline bitvec operator-(const bitvec& x, const bitvec& y) { return x + y; } bitvec& operator+=(const bitvec& v) BHIDE2( ![ if (length != v.length) INTERNAL_ERROR("bitvec length inconsistency"); ]!, ![ int nw = nwords( ); ]! ) for ( int i = 0; i < nw; i++ ) x[i] ^= v.x[i]; } int weight( ) { int wt = 0, nw = nwords( ); static int bw[512]; // weight of each possible byte static bool first_call(true); if (first_call) { first_call = false; HIDE( ![ if (CHAR_BIT != 8) INTERNAL_ERROR("bitvec::weight is designed to work with " << "8 bit bytes. It will need to be rewritten."); if (BITS_PER_INT != 32) INTERNAL_ERROR( "Sorry, bitvec::weight assumes an int has " << "32 bits in it. The code will need to be " << "rewritten." ); ]! ) for ( int i = 0; i < 512; i++ ) { bw[i] = 0; unsigned int z = i; for ( int j = 0; j < 8; j++ ) { if ( z & 1 ) ++bw[i]; z >>= 1; } } } register unsigned char* yp; register int i; for ( i = 0; i < nw; i++ ) { yp = (unsigned char*) &(x[i]); wt += bw[yp[0]] + bw[yp[1]] + bw[yp[2]] + bw[yp[3]]; } return wt; } void clear( ) { int nw = nwords( ); for ( int i = 0; i < nw; i++ ) x[i] = 0; } HIDE( ![ friend bool operator<(const bitvec& a, const bitvec& b) { INTERNAL_ERROR("operator< for bitvec not defined"); } friend bool operator>(const bitvec& a, const bitvec& b) { INTERNAL_ERROR("operator> for bitvec not defined"); } ]! ) friend ostream& operator<<(ostream& s, const bitvec& b) { for ( int i = 0; i < b.length; i++ ) s << b.value(i); return s; } }; set_compile_file(code.c) HIDE( ![ #include "simplex.h" double canonical_lp_problem::tolx; doubledouble canonical_lp_problem::tolx; Big canonical_lp_problem::tolx; Rational canonical_lp_problem::tolx; ]! ) index_method(test_sizes) void bitvec::test_sizes( ) { if ( BITS_PER_INT != 32 ) ERROR( "The bitvec class was designed to work with 32-bit int's," << " whereas you have " << BITS_PER_INT << " int's. Some " << "adjustments to the source code will have to be made." ); } set_include_file(bitvec.h) index_class(bitmat) index_method(nonzero) index_method(set_zero) index_method(remove_zero_rows_at_bottom) class bitmat : public vector { public: int nrows; int ncols; bitmat(const matrix& M) : vector(M.nrows) { nrows = M.nrows; ncols = M.ncols; for ( int i = 0; i < length; i++ ) x[i] = M(i); } bitmat(int nr, int nc) : vector(nr), nrows(nr), ncols(nc) { for ( int i = 0; i < nrows; i++ ) x[i].set_size(ncols); } bitmat( ) : vector(0) { nrows = 0; ncols = 0; } void set_zero( ) { for ( int i = 0; i < length; i++ ) (*this)(i).set_zero( ); } int reduce( ); void remove_zero_rows_at_bottom( ) { int i; for ( i = length - 1; i >= 0; i-- ) if ( !(x[i].if_zero( )) ) break; nrows = i + 1; if ( i + 1 != length ) resize( i + 1 ); } void reduce_nz( ) { reduce( ); remove_zero_rows_at_bottom( ); } int nonzero(int r, int c) // Return nonzero iff the (r,c)'th entry is != 0. { return x[r].nonzero(c); } operator matrix( ) const { matrix M( nrows, ncols ); for ( int i = 0; i < nrows; i++ ) for ( int j = 0; j < ncols; j++ ) M(i, j) = x[i].value(j); return M; } }; set_include_file(graph.h) index_class(vertex_colored_graph) class vertex_colored_graph { public: int n; // number of vertices prevector a; // the adjacency matrix prevector c; // c(i) is the "color" of vertex i // The constructor initializes to an n-vertex graph with no edges and // each vertex colored "0". vertex_colored_graph(int n = 0) : n(n), a(n), c(n) { for ( int i = 0; i < n; i++ ) a(i) = bitvec(n); } void apply(const Permutation& p) { // The following is inefficient. p.act(c); vertex_colored_graph g(n); for ( int i = 0; i < n; i++ ) g.a( p(i) - 1 ) = a(i); for ( int i = 0; i < n; i++ ) a(i) = g.a(i).apply(p); } HIDE( ![ friend bool Isomorphic(vertex_colored_graph, vertex_colored_graph); ]! ) pair find_automorphism_group( ) const; }; set_compile_file(graph.cc) HIDE( ![ #include "homedefs.h" int rcmp(const number&, const number&); #include "bitvec.h" #include "graph.h" #include extern long time_used_by_Isomorphic; extern long time_used_canonical_form; extern int nauty_vocal; prevector invariant_generating_set(const matrix&, const partition&); ]! ) #define MAXN 8192 #include "nauty.h" Integer group_size; Permutationlist generators_for_group; index_method(perm_store) void perm_store(int, permutation *perm, nvector *orbits, int, int, int n) { Permutation p(n); for ( int i = 0; i < n; i++ ) p(i) = perm[i] + 1; generators_for_group.append(p); } index_method(level_store) void level_store( nvector *lab, nvector *ptn, int, nvector *orbits, statsblk *stats, int, int index, int, int, int, int n ) { group_size *= index; } index_method(find_automorphism_group) pair< Permutationlist, Integer > vertex_colored_graph::find_automorphism_group( ) const { if ( n > MAXN ) ERROR("You are trying to find the automorphism group" << " of a graph with > " << MAXN << " vertices."); graph g[n * MAXM]; nvector orbits[n], lab[n], ptn[n]; static DEFAULTOPTIONS(options); statsblk(stats); int m = (n + WORDSIZE - 1) / WORDSIZE; int workroom = 50 * m; // See page 4 of nauty manual. setword workspace[workroom]; options.writemarkers = FALSE; options.writeautoms = FALSE; options.defaultptn = FALSE; options.userautomproc = (void (*)()) &perm_store; options.userlevelproc = (void (*)()) &level_store; // Set up coloring information for nauty. vertex_colored_graph G = *this; int i, j; Permutation p; vector cc = G.c; cc.sort(rcmp, p); Permutation pi = p.inverse( ); G.apply(p); for ( i = 0; i < n; i++ ) { lab[i] = i; ptn[i] = !( i == n - 1 || G.c(i) != G.c(i+1) ); } // Build the graph for nauty. for ( j = 0; j < n; ++j ) { SET* gv = GRAPHROW(g, j, m); EMPTYSET(gv, m); for ( i = 0; i < n; i++ ) if ( G.a(i).value(j) ) ADDELEMENT( gv, i ); } // Invoke nauty. group_size = 1; generators_for_group.n = n; generators_for_group.clear( ); if (nauty_vocal) cerr << "[invoking nauty on a graph with " << n << " vertices]\n"; nauty( g, lab, ptn, NILSET, orbits, &options, &stats, workspace, workroom, m, n, NILGRAPH); for ( i = 0; i < generators_for_group.length; i++ ) generators_for_group(i) = pi * generators_for_group(i) * p; return make_pair( generators_for_group, group_size ); } index_method(Isomorphic) bool Isomorphic(vertex_colored_graph g1, vertex_colored_graph g2) { time_used_by_Isomorphic -= time(0); if ( g1.n != g2.n ) return false; if ( g1.n > MAXN ) ERROR("You are trying to find the automorphism group" << " of a graph with > " << MAXN << " vertices."); int i, j, k, n = g1.n; Permutation p1, p2; vector c1 = g1.c, c2 = g2.c; c1.sort(rcmp, p1); c2.sort(rcmp, p2); if ( c1 != c2 ) { time_used_by_Isomorphic += time(0); return false; } g1.apply(p1); g2.apply(p2); // Set up for nauty. graph g[n * MAXM], canong[n * MAXM]; nvector orbits[n], lab[n], ptn[n]; static DEFAULTOPTIONS(options); statsblk(stats); int m = (n + WORDSIZE - 1) / WORDSIZE; int workroom = 50 * m; setword workspace[workroom]; options.writemarkers = FALSE; options.writeautoms = FALSE; options.defaultptn = FALSE; options.getcanon = TRUE; // Build the graph for nauty, then invoke it. for ( j = 0; j < 2; j++ ) { // Prepare the graph coloring information for nauty. for ( i = 0; i < n; i++ ) { lab[i] = i; ptn[i] = !( i == n - 1 || g1.c(i) != g1.c(i+1) ); } for ( int col = 0; col < n; ++col ) { SET *gv = GRAPHROW(g, col, m); EMPTYSET(gv, m); for ( int row = 0; row < n; row++ ) { if ( j == 0 && g1.a(row).value(col) ) ADDELEMENT( gv, row ); if ( j == 1 && g2.a(row).value(col) ) ADDELEMENT( gv, row ); } } if (nauty_vocal) cerr << "[invoking nauty on a graph with " << n << " vertices]\n"; nauty( g, lab, ptn, NILSET, orbits, &options, &stats, workspace, workroom, m, n, canong); Permutation p(n); for ( i = 0; i < n; i++ ) p(i) = lab[i] + 1; Permutation pi = p.inverse( ); if ( j == 0 ) g1.apply(pi); else g2.apply(pi); } bool answer = (g1.a == g2.a); time_used_by_Isomorphic += time(0); return answer; } index_method(get_canonical) Permutation get_canonical( vertex_colored_graph& g, int nv ) { int np = g.n; graph G[np * MAXM], canong[np * MAXM]; nvector orbits[np], lab[np], ptn[np]; static DEFAULTOPTIONS(options); statsblk(stats); int m = (np + WORDSIZE - 1) / WORDSIZE; int workroom = 50 * m; setword workspace[workroom]; options.writemarkers = FALSE; options.writeautoms = FALSE; options.defaultptn = FALSE; options.getcanon = TRUE; for ( int i = 0; i < np; i++ ) { lab[i] = i; ptn[i] = !( i == np - 1 || g.c(i) != g.c(i+1) ); } for ( int col = 0; col < np; ++col ) { SET *gv = GRAPHROW(G, col, m); EMPTYSET(gv, m); for ( int row = 0; row < np; row++ ) if ( g.a(row).value(col) ) ADDELEMENT( gv, row ); } if (nauty_vocal) cerr << "[invoking nauty on a graph with " << g.n << " vertices]\n"; nauty( G, lab, ptn, NILSET, orbits, &options, &stats, workspace, workroom, m, np, canong); Permutation q(nv); for ( int i = 0; i < nv; i++ ) q(i) = lab[i] + 1; Permutation qi = q.inverse( ); return qi; } index_method(canonical_form) config_core canonical_form( config_core c, bool fully_refined ) { time_used_canonical_form -= time(0); int i, j, k; partition part; code small, dualsmall; int nparts; Permutation p; int n = c.part.n; if ( !fully_refined ) { part = c.part; small.basis = c.smallbasis; dualsmall.basis = c.dualsmallbasis; part.sort( rcmp, p ); nparts = c.part.length; for ( j = 0; j < small.basis.nrows; j++ ) p.act( small.basis(j) ); for ( j = 0; j < dualsmall.basis.nrows; j++ ) p.act( dualsmall.basis(j) ); } else { part.set_all_ones(n); p = Permutation(n); small.basis = c.basic_small( ); dualsmall.basis = c.basic_dualsmall( ); nparts = n; } prevector cd, dcd; cd = invariant_generating_set( small.basis, part ); dcd = invariant_generating_set( dualsmall.basis, part ); vertex_colored_graph g; g = vertex_colored_graph(nparts + cd.length + dcd.length); for ( i = 0; i < nparts; i++ ) g.c(i) = part(i); for ( i = nparts; i < nparts + cd.length; i++ ) g.c(i) = n + 1; // a color different from the others for ( i = nparts + cd.length; i < g.n; i++ ) g.c(i) = n + 2; // another color for ( i = 0; i < cd.length; i++ ) for ( k = 0; k < nparts; k++ ) if ( cd(i)(k) ) { g.a(k).set(nparts + i); g.a(nparts + i).set(k); } for ( i = 0; i < dcd.length; i++ ) for ( k = 0; k < nparts; k++ ) if ( dcd(i)(k) ) { g.a(k).set(nparts + cd.length + i); g.a(nparts + cd.length + i).set(k); } if ( g.n > MAXN ) ERROR("Attempt to invoke nauty on graph with > " << MAXN << " vertices."); Permutation qi = get_canonical( g, nparts ); small.basis.permute_columns(qi); c.smallbasis = small.basis; c.smallbasis.reduce_nz( ); dualsmall.basis.permute_columns(qi); c.dualsmallbasis = dualsmall.basis; c.dualsmallbasis.reduce_nz( ); qi.act( part ); c.part = part; time_used_canonical_form += time(0); return c; } SLList< vector > dual_words_of_given_weight(matrix, int); index_method(permute_to_canonical) Permutation permute_to_canonical( matrix L ) { // I used to do L.reduce_nz( ) here, but deleted it. Danger? int i, j, k = L.nrows, n = L.ncols; partition part; part.set_all_ones(n); prevector cd; time_used_canonical_form += time(0); cd = invariant_generating_set( L, part ); time_used_canonical_form -= time(0); vertex_colored_graph g(n + cd.length); for ( i = 0; i < n; i++ ) g.c(i) = 1; for ( i = n; i < n + cd.length; i++ ) g.c(i) = 2; for ( i = 0; i < cd.length; i++ ) for ( j = 0; j < n; j++ ) if ( cd(i)(j) ) { g.a(j).set(n + i); g.a(n + i).set(j); } if ( g.n > MAXN ) ERROR("You are trying to find the automorphism group" << " of a graph with > " << MAXN << " vertices."); int np = g.n; graph G[np * MAXM], canong[np * MAXM]; nvector orbits[np], lab[np], ptn[np]; static DEFAULTOPTIONS(options); statsblk(stats); int m = (np + WORDSIZE - 1) / WORDSIZE; int workroom = 50 * m; setword workspace[workroom]; options.writemarkers = FALSE; options.writeautoms = FALSE; options.defaultptn = FALSE; options.getcanon = TRUE; for ( i = 0; i < np; i++ ) { lab[i] = i; ptn[i] = !( i == np - 1 || g.c(i) != g.c(i+1) ); } for ( int col = 0; col < np; ++col ) { SET *gv = GRAPHROW(G, col, m); EMPTYSET(gv, m); for ( int row = 0; row < np; row++ ) if ( g.a(row).value(col) ) ADDELEMENT( gv, row ); } if (nauty_vocal) cerr << "[invoking nauty on a graph with " << g.n << " vertices]\n"; nauty( G, lab, ptn, NILSET, orbits, &options, &stats, workspace, workroom, m, np, canong); Permutation q(n); for ( i = 0; i < n; i++ ) q(i) = lab[i] + 1; return q.inverse( ); } Permutation isomorphism( matrix L, matrix M ) { Permutation pL = permute_to_canonical(L), pM = permute_to_canonical(M); L.permute_columns(pL); L.reduce_nz( ); M.permute_columns(pM); M.reduce_nz( ); if ( L != M ) ERROR("Attempt to find isomorphism between nonisomorphic matrices."); return pM.inverse( ) * pL; } TEX( ![ Given a matrix over $\F2$, return a canonical form for it. That is, two matrices are isomorphic \IFF\ upon being fed to this routine as inputs, the resulting outputs are the same. Here we define two matrices to be isomorphic if they have the same number of columns and after some permutation of columns (applied to one of the matrices), the \RREF's of the two matrices are equal. ]! ) index_method(canonical_form) matrix canonical_form( matrix L ) { time_used_canonical_form -= time(0); // I used to do L.reduce_nz( ) here, but deleted it. Danger? int i, j, k = L.nrows, n = L.ncols; TEX( ![ \begin{quote} Test for codes with exactly one odd weight. A direct approach to these leads often to intractible calculations, which can sometimes be avoided. \end{quote} ]! ) for ( i = 0; i < L.nrows; i++ ) if ( odd( L(i).weight( ) ) ) break; if ( i < L.nrows ) { L.reduce_nz( ); vector y = L.enumerate_weights( ); int odd_count = 0; for ( i = 0; i <= n; i++ ) if ( odd(i) && y(i) != 0 ) odd_count++; if (odd_count == 1) { matrix M, Me, Mh; // code, even subcode, half of it M = L; for ( i = 0; i < k; i++ ) if ( odd( M(i).weight( ) ) ) break; if ( !odd( M( k-1 ).weight( ) ) ) M( k-1 ) += M(i); for ( j = 0; j < k-1; j++ ) if ( odd( M(j).weight( ) ) ) M(j) += M( k-1 ); Me = M; Me.resize( k-1, n ); SLList< vector > d2 = dual_words_of_given_weight( Me, 2 ); if ( d2.length( ) * 2 != n ) goto special_fails; forPixDef( p, d2 ) { forPixDef( q, d2 ) if ( intersection_size( d2(p), d2(q) ) == 1 ) goto special_fails; } forPix( p, d2 ) if ( int(M(k-1, d2(p)(0))) + int(M(k-1, d2(p)(1))) != 1 ) goto special_fails; Mh.set_size(k-1, n/2); i = 0; forPix( p, d2 ) { for ( j = 0; j < k-1; j++ ) Mh(j,i) = Me(j, d2(p)(0)); i++; } matrix Mh_can = canonical_form( Mh ), L_can( k, n ); for ( j = 0; j < n/2; j++ ) { L_can(k-1, 2*j) = 1; for ( i = 0; i < k-1; i++ ) L_can(i, 2*j) = L_can(i, 2*j + 1) = Mh_can(i, j); } return L_can; } } special_fails: Permutation qi = permute_to_canonical(L); L.permute_columns( qi ); L.reduce_nz( ); time_used_canonical_form += time(0); return L; } TEX(![ \block{ShareGraph and multiedge classes} First we consider a rudimentary paradigm for exploratory computations involving abstract mathematical structures. Then we will exhibit a template class {\tt ShareGraph} which partially implements the paradigm. The only purpose of all of this is to clarify what we do in this program. It may be merged into the {\tt codehome} definition at a later date. \begin{center} \begin{tabular}{|c|}\hline node\\ \hline \end{tabular} \kern10pt\lower2pt\hbox{\LARGE$\equiv$}\kern10pt \begin{tabular}{|c|}\hline object\\ \hline facts about\\ the object\\ \hline \end{tabular} \kern40pt \begin{tabular}{|c|}\hline constructive\\ edge\\ \hline \end{tabular} \kern10pt\lower2pt\hbox{\LARGE$\equiv$}\kern10pt \begin{tabular}{|c|}\hline construction method\\ \hline \&node\\ \hline \&node\\ \hline \end{tabular} \end{center} \begin{center} \begin{tabular}{|c|}\hline logical\\ statement\\ \hline \end{tabular} \kern10pt\lower2pt\hbox{\LARGE$\equiv$}\kern10pt \begin{tabular}{|c|}\hline $f(\VEC x1n)$\\ \hline \&(node $1$)\\ \hline $\cdots$\\ \hline \&(node $n$)\\ \hline \end{tabular} \kern40pt \begin{tabular}{|c|}\hline equivalence\\ class\\ \hline \end{tabular} \kern10pt\lower2pt\hbox{\LARGE$\equiv$}\kern10pt \begin{tabular}{|c|}\hline shared facts\\ \hline \&node\\ \hline $\cdots$\\ \hline \&node\\ \hline \end{tabular} \end{center} We describe the paradigm in terms of the above pictures, along the way illustrating the paradigm by means of the coding language in this paper. First, a specific instance of the entities in the above pictures (nodes, constructive edges, logical statements, equivalence classes, and the components of each) comprise a {\it world}. In our usage, a world would correspond to a code type, and the objects (or nodes) would be configurations. A {\it logical statement\/} is just a boolean formula $f$ (without quantifiers) between references to nodes. For example, $x_1$ would mean that node $1$ exists, and $x_1 \rightarrow x_2$ (i.e.\ $(\neg x_1) \vee x_2$) would mean that if node $1$ exists, then so does node $2$. The situation where $x_1 \Longleftrightarrow x_2 \Longleftrightarrow \cdots \Longleftrightarrow x_n$ arises sufficiently frequently that a special entity (equivalence class) is given. The equivalent nodes share facts which are meaningful and known to be true for all of them. One often arrives at a logical statement like $x_1 \Leftrightarrow x_2$ by way of a specific construction which starts with $x_1$ and builds $x_2$. A {\it constructive edge\/} ``remembers'' that the logical statement was gotten in this way. Thereafter, certain facts (obtained after the construction) may flow along the edge from $x_1$ to $x_2$, or perhaps the other way. Thus the constructive edge codifies an active conduit for information flowing between two nodes. Now we turn to a real structure, the template class {\tt ShareGraph}. It is based on a vertex class ({\tt V}), a vertex share class ({\tt VS}), and an edge class ({\tt E}). The idea is that a {\tt ShareGraph} object {\tt G} is a directed multigraph\footnote{Multiple edges and loops are allowed; here we follow the terminology of [.bollobas course.], p.\ 5.} whose vertices are objects of {\tt V}, whose edges are objects of {\tt E}, and such that to each connected component of {\tt G} there is associated an object of {\tt VS}. The vertex class {\tt V} must have a member ``{\tt share}'' of type {\tt VS*}. The vertices are expected to be unequal objects, and so {\tt V} must be provided with an equality operator {\tt ==}. (This should not test the {\tt share} member.) Likewise, given vertices $i$ and $j$, the edges from $i$ to $j$ are expected to be unequal objects, and so {\tt E} must be provided with an equality operator {\tt ==}. The vertex share class must have a {\it merge} operator {\tt +} which is to be invoked whenever (by adding an edge) two connected components of {\tt G} are coalesced. To declare and initialize (to null) a {\tt ShareGraph} {\tt G} one uses the command: \par\noindent\kern0.5in{\tt ShareGraph G;}\par\noindent where {\tt V}, {\tt VS}, and {\tt E} are replaced by the appropriate classes. To create a vertex one uses the command: \par\noindent\kern0.5in% {\tt Pix i = G.add(}{\it vertex object}{\tt );}% \par\noindent which will add the object as a vertex if the vertex object does not already exist. (If it already exists, no action is taken.) To search for a vertex object {\tt x} of {\tt V}, use \par\noindent\kern0.5in{\tt Pix i = G.find(x);} \par\noindent which returns $0$ if {\tt x} is not found. The find function has nothing to do with {\tt VS}. From now on, when we refer to a {\it vertex\/} {\tt i}, we really mean a {\tt Pix} {\tt i} which corresponds to a vertex of {\tt G}. Now if {\tt i} and {\tt j} are vertices, then \par\noindent\kern0.5in% {\tt Pix k = G.join(i, j, }{\it edge object}{\tt);}\par\noindent makes an edge from vertex {\tt i} to vertex {\tt j}, labelled with the given edge object, provided that it does not already exist. The edge object may be omitted. If {\tt i} is a vertex of {\tt G}, {\tt woof} is a member of {\tt V}, and {\tt bark} is a member of {\tt VS}, one may access these members via \par\noindent\kern0.5in{\tt G(i).woof} \par\noindent\kern0.5in{\tt G(i).share->bark}. \par\noindent To search for an edge object {\tt e} of {\tt E}, from vertex {\tt i} to vertex {\tt j}, use \par\noindent\kern0.5in\verb|G.find_edge(i,j,e);| \par\noindent which returns $0$ if {\tt e} is not found. Traversal by pixes of vertices is provided in the usual way: \par\noindent\kern0.5in% {\tt for ( Pix i = G.first( ); i != 0; G.next(i) ) use(G(i));} \par\noindent One can traverse the edges from vertex {\tt i} to vertex {\tt j} via: \par\noindent\kern0.5in% {\tt for ( Pix e = G(i,j).first( ); e != 0; G(i,j).next(e) ) use(G(i,j)(e));} The implementation follows. It is not particularly efficient, and is intended for situations where this does not matter. First we give a primitive {\tt Map} class. \indexz{Map} \mindex{first}\mindex{next} ]!) set_include_file(share.h) template class Map { public: SLList< pair< key, contents > > data; contents Default; Pix first( ) { return data.first( ); } void next(Pix& p) { data.next(p); } key& operator( )(Pix p) { return data(p).first; } contents& take(Pix p) { return data(p).second; } inline contents& operator[ ](const key&); Map(const contents& d) : Default(d) { } Map( ) { } }; template inline contents& Map::operator[ ](const key& k) { forPixDef ( i, data ) if ( k == data(i).first ) return data(i).second; Pix p = data.append( make_pair(k, contents(Default)) ); return data(p).second; } index_class(ShareGraph) template class ShareGraph { public: DLList vertices; Map< pair, SLList > edges; ShareGraph( ) : edges( SLList( ) ) { } // I don't quite understand why the following const_cast is needed. V& operator( )(Pix i) const { return const_cast(vertices(i)); } Pix first( ) { return vertices.first( ); } void next(Pix& i) { vertices.next(i); } V& operator[ ](Pix i) { return (V&) vertices(i); } SLList operator( )(Pix i, Pix j) // Perhaps broken. { return edges[ make_pair(i,j) ]; } index_method(add) Pix add(const V& vert) { forPixDef( i, vertices ) if ( vertices(i) == vert ) return i; return vertices.append(vert); } index_method(del) void del(Pix p) { VS* sh = vertices(p).share; vertices.del(p); forPixDef( i, vertices ) if ( vertices(i).share == sh ) break; if ( i == 0 ) delete sh; } index_method(join) void join(Pix i, Pix j) { if ( vertices(i).share != vertices(j).share ) { VS* merge = *(vertices(i).share) + *(vertices(j).share); delete vertices(i).share; delete vertices(j).share; VS* old_i = vertices(i).share; VS* old_j = vertices(j).share; forPixDef( k, vertices ) if ( vertices(k).share == old_i || vertices(k).share == old_j ) vertices(k).share = merge; } } void join(Pix i, Pix j, const E& e) { if ( find_edge(i, j, e) ) return; edges[ make_pair(i,j) ].append(e); join(i, j); } SLList sharelist( ) { OSLList s; forPixDef( i, vertices ) s.add( vertices(i).share ); return s; } ~ShareGraph( ) { SLList s = sharelist( ); forPixDef( i, s ) delete s(i); } index_method(find) Pix find(const V& x) { forPixDef( i, vertices ) if ( vertices(i) == x ) return i; return 0; } index_method(find_edge) // This code was changed 3/26/98. The old code seemed to cause segmentation // faults on Intel hardware, and in any case it was less efficient. However, // I don't understand why it should have caused hardware errors, so perhaps // the new code will cause them as well, but less often. Pix find_edge(Pix i, Pix j, const E& e) { const SLList& ed = (*this)(i,j); forPixDef( k, ed ) if ( ed(k) == e ) return k; return 0; } }; set_compile_file(code.c) HIDE(![#include "share.h"]!) TEX( Objects of class {\tt multiedge} encode logical relationships of the form $a \Longrightarrow (b_1 \kern5pt\hbox{or} \cdots \hbox{or}\kern5pt b_n)$. ) set_include_file(multiedge.h) template class multiedge : public pair< T, OSLList > { }; set_compile_file(code.c) HIDE(![#include "multiedge.h"]!) set_include_file(state.h) template class state_list : public Map { public: void propagate( SLList< multiedge > ); void reverse_propagate( SLList< multiedge > ); }; TEX( Propagate according to the rule $\VEC b1n$ true $\Longrightarrow$ $a$ true. ) index_method(propagate) template inline void state_list::propagate( SLList< multiedge > m ) { state_list& s = *this; Pix p, q; while(1) { forPix( p, m ) { multiedge& me = m(p); forPix( q, me.second ) if ( !s[me.second(q)] ) break; if ( q == 0 && !s[me.first] ) { s[me.first] = true; break; } } if ( p == 0 ) return; } } TEX( Propagate according to the rule $n = 1$ and $a$ true $\Longrightarrow$ $b_1$ true. ) index_method(reverse_propagate) template inline void state_list::reverse_propagate( SLList< multiedge > m ) { state_list& s = *this; Pix p, q; while(1) { forPix( p, m ) { multiedge& me = m(p); if ( me.second.length( ) == 1 && !s[me.second.front( )] && s[me.first] ) { s[me.second.front( )] = true; break; } } if ( p == 0 ) return; } } set_compile_file(code.c) HIDE(![#include "state.h"]!) TEX(![ \block{Terms, term{\tt\_}sums, constraints, qvconstraints, vconstraints, constraintlists, constraint files} Abstractly, a {\it constraint\/} is a relation of the form $$a_1 v_1 \many+ a_n v_n \kern3pt\square\kern3pt k,$$% where $\VEC v1n$ are variables, $\VEC a1n \in \Q$, $k \in \Z$, and $\square$ is either $\leq$, $\geq$, or $=$. Constraints are represented in several different ways, according to what variables and coefficients are allowed: \begin{enumerate} \item When constraints appear in commands, the variables are arbitrary (within the confines of the language), and the coefficients are in $\Z$. \item These constraints are internally represented (using the ``{\tt constraint}'' class) in the same way, except that $\Q$-coefficients are allowed. This is because some internal operations may result in constraints whose coefficients are not integers. (This can happen when the ``{\tt incorporate}'' command is used.) \item For split linear programming calculations, constraints are first converted to constraints involving {\tt v} variables and having coefficients in $\Q$ (class {\tt qvconstraint}). \item Clearing denominators yields constraints having {\tt v} variables and coefficients in $\Z$\\ (class {\tt vconstraint}). The constraints which are generated automatically (for split linear programming) naturally have this form. The raison d'\^etre for the separate class ``{\tt vconstraint}'' is that there are huge numbers of these automatically generated constraints. \end{enumerate} Lists of constraints (class {\tt constraint}) are managed by the class {\tt constraintlist}. The following diagram summarizes some of the conversions which take place in this section, with emphasis on strings and input-output: \diagramx{\hbox{\tt String}& \mapE{} &\hbox{\tt term\string_sum}&&&&&& \hbox{\tt String}\cr &&\mapS{}&&&&&&\mapS{}\cr &&\hbox{\tt String}&\mapE{}&\hbox{\tt term}&&\hbox{input} &&\hbox{\tt constraintlist}\cr &&\mapS{}&&&&\mapS{}&&\mapS{}\cr \hbox{input} & \mapE{} & \hbox{\tt constraint} & \mapE{} & \hbox{\tt qvconstraint} & \mapE{} & \hbox{\tt vconstraint} & \mapE{} & \hbox{output}\cr &&\mapS{}\cr &&\hbox{\tt String}} \indexz{term} ]!) set_include_file(basedefs.h) HIDE( ![ // #define DEBUG class Permutation; extern "C" long randomx( ); #include "gnutypes.h" extern bool demo; extern String calling_command; #include "macros.h" #include "OSLList.h" #include "pair_.h" #include "numgf2.h" #include "prevector.h" #include "vector_.h" inline bool operator !=(OSLList< vector >, OSLList< vector >) { INTERNAL_ERROR( "operator!= for OSLList< vector > not defined"); } #include "cmp.h" #include "doubledouble.h" #include "big.h" #include "inline.h" #include "dot.h" #include "permutation.h" template void orbit( const prevector&, const S&, prevector&, int (*cmp)(const S&, const S&), void (*act)(const G&, const S&, S&), int = -1 ); int pcmp( const Permutation&, const Permutation& ); #include "permutationlist.h" #include "matrix.h" #include "cmp2.h" #include "constraint.h" String take(String&, const Regex&); Integer choose(int, int); String str(Rational); extern String var, pos_term, signed_number, op, constraint_pat, left, right, number_pat, orsign, pos_number, pos_list; inline int even(int i) { return !(i % 2); } prevector unpack(String s, String delim = ","); extern "C" int isspace(int); extern "C" int isdigit(int); ]! ) typedef vector word; set_include_file(constraint.h) class term { public: Rational coeff; // coefficient String var; // variable name term(const Rational& m, const String& s) : coeff(m), var(s) { } // constructor, e.g. from -5, "y3" term(String); // constructor from a white-space-free // string, e.g. from "-5y3" // (coefficient must be an integer) term( ) { } }; set_compile_file(constraint.cc) HIDE(![ #include "homedefs.h" extern int warnings_are_fatal, debug; ]!) term::term(String s) { static Regex signed_number_pat("[+-]?[0-9]*"); String s1 = take(s, signed_number_pat); if ( s1 == "" || s1 == "+" ) coeff = 1; else coeff = (s1 == "-") ? Integer(-1) : Integer(s1); var = s; } TEX(![ A \verb|term_sum| is a list of terms, to be regarded as a sum. ]!) set_include_file(constraint.h) index_class(term_sum) HIDE( ![ extern String pos_term; extern String take(String&, const Regex&); ]! ) class term_sum : public DLList { public: term_sum(String t) { static Regex term_pat( "[+-]?" + pos_term ); while ( !t.empty( ) ) append(term(take(t, term_pat))); } term_sum( ) { } operator String( ) const; void merge(const term& t) { forPixDef( p, *this ) if ( (*this)(p).var == t.var ) break; if ( p == 0 ) append(t); else (*this)(p).coeff += t.coeff; } friend ostream& operator<<(ostream&s, const term_sum& t) { return s << String(t); } }; set_compile_file(constraint.cc) term_sum::operator String( ) const { const term_sum& t = *this; String s; bool first_nonzero_term = true; forPixDef( i, t ) { if ( sign ( t(i).coeff ) != 0 ) { if (!first_nonzero_term && sign ( t(i).coeff ) > 0) s += " + "; if ( t(i).coeff == Rational(1) ); else if ( t(i).coeff > Rational(0) ) s += str(t(i).coeff); else { s += first_nonzero_term ? "-" : " - "; if ( t(i).coeff != Rational(-1) ) s += str(-t(i).coeff); } s += t(i).var; first_nonzero_term = false; } } return s; } index_class(constraint) index_method(simple) index_method(simple_local) index_method(simple_local_zero) index_method(simple_global) index_method(addterm) index_method(adjoin) index_method(clear_denominators) index_method(global) index_method(local) index_method(joint) set_include_file(constraint.h) class constraint { public: term_sum LHS; // left hand side char sense; // >, <, or =, where > means >=, < means <= Integer RHS; // right hand side void addterm(const Rational& k, const String& s) // add term to LHS { if ( k != Rational(0) ) LHS.append(term(k, s)); } constraint(String); // constructor from white-space-free string constraint( ) { } constraint(char sense, const Integer& RHS) : sense(sense), RHS(RHS) { } operator String( ) const; bool global( ) const { forPixDef( p, LHS ) if ( !global_var( LHS(p).var ) ) return false; return true; } bool local( ) const { forPixDef( p, LHS ) if ( !global_var( LHS(p).var ) && !local_var( LHS(p).var ) ) return false; return true; } bool joint( ) const { forPixDef( p, LHS ) if ( !global_var( LHS(p).var ) && !joint_var( LHS(p).var ) ) return false; return true; } void adjoin(const term_sum& t) { forPixDef( p, t ) LHS.merge( t(p) ); } bool simple( ) const { return LHS.length( ) == 1 && LHS.front( ).coeff == Rational(1); } bool simple_local( ) const { return simple( ) && LHS.front( ).var[0] == 'x'; } bool simple_local_zero( ) const { return simple_local( ) && sense == '=' && RHS == 0; } bool simple_global( ) const { return simple( ) && LHS.front( ).var[0] == 'y'; } friend bool operator==(const constraint& c1, const constraint& c2) { return c1.LHS == c2.LHS && c1.sense == c2.sense && c1.RHS == c2.RHS; } friend bool operator!=(const constraint& c1, const constraint& c2) { return !(c1 == c2); } HIDE( ![ friend istream& operator>>(istream&, constraint&); ]! ) friend ostream& operator<<(ostream& s, const constraint& t) { return s << String(t); } void clear_denominators( ) { Integer multiplier = 1; forPixDef( p, LHS ) multiplier = lcm( multiplier, LHS(p).coeff.denominator( ) ); forPix( p, LHS ) LHS(p).coeff *= multiplier; RHS *= multiplier; } }; set_compile_file(constraint.cc) constraint::constraint(String t) { static Regex var_pat(var); static Regex beetle( "[+-]?" + pos_term ); static Regex signed_number_pat(signed_number); static Regex op_plus(op + ".*"); if_match( t, var + "!=0" ) { addterm(1, take(t, var_pat)); sense = '>'; RHS = 1; } else { if_no_match( t, constraint_pat ) ERROR( "\"" << t << "\" is not a valid constraint" ); while ( !t.matches(op_plus) ) LHS.append(term(take(t, beetle))); sense = t[0]; t.del(sense); int equals = (t[0] == '='); if (equals) t.del('='); RHS = Integer(take(t, signed_number_pat)); if ( equals == 0 ) { if ( sense == '<' ) --RHS; if ( sense == '>' ) ++RHS; } } } constraint::operator String( ) const { if ( LHS.length( ) > 1000 ) WARNING( "A request has been made to convert a very large " << "constraint into a string. The constraint has " << LHS.length( ) << " terms. It is possible that a string-related " "abortion will result." ); String s = String(LHS); return s + (sense == '=' ? " = " : (sense == '>' ? " >= " : " <= ")) + dec(RHS); } istream& operator>>(istream&s, constraint& t) { String con; char c; do { s.get(c); if ( !isspace(c)) con += c; } while ( c != '=' ); do { s.get(c); if ( !isspace(c) ) con += c; } while ( !isdigit(c) ); do { s.get(c); if ( !isspace(c)) con += c; } while ( c != '\n' ); t = constraint(con); return s; } index_method(eat_constraint) void eat_constraint(istream& s) { char c; do s.get(c); while ( c != '=' ); do s.get(c); while ( !isdigit(c) ); do s.get(c); while ( c != '\n' ); } TEX( The following routine translates constraints for the ``{\tt incorporate}'' command. If the {\tt verbatim} flag is set, the working weight list will not be used to simplify constraints. This is necessary when the constraint is an assumed constraint. \mindex{translate} ) constraint translate( const config& cs, const constraint& c, const String& sub_var, int nparts, int insertion_point, bool verbatim = false ) { constraint new_c( c.sense, c.RHS ); config_core csc(cs); term_sum ts = csc.simplify_global_vars(c.LHS, cs.share->ww, cs.home->dim, verbatim); forPixDef( q, ts ) { String v = ts(q).var; Rational cf = ts(q).coeff; if ( v[0] == 'y' ) v.at(0,1) = "sub" + sub_var + "_"; else if ( v[0] == 'x' ) { String zero = (v[1] == '_') ? "_0" : "0"; v.at("x") = "x" + replicate(zero, insertion_point); v += replicate(zero, nparts - insertion_point - 1); } else if ( v[0] == 's' ) { v.at("sub") = "sub" + replicate("0", insertion_point); String zeros = replicate("0", nparts - insertion_point - 1); if ( v.contains("_") ) v.at("_") = zeros + "_"; else v += zeros; } else if ( v[0] == 'z' ) { v.at("z") = "q" + replicate("_z", insertion_point); v += replicate("_z", nparts - insertion_point - 1); cf /= Ipow(2, cs.home->dim); } else /* q variable */ { v.at("q") = "q" + replicate("_z", insertion_point); v += replicate("_z", nparts - insertion_point - 1); } new_c.addterm( cf, v ); } return new_c; } set_compile_file(code.c) HIDE( ![ #include "constraint.h" typedef vector word; void eat_constraint(istream&); constraint translate(const config&, const constraint&, const String&, int, int, bool = false); int cmp_secondvc( const pair< int, vector >&, const pair< int, vector >&); int cmp_secondm2( const pair< vector, matrix >&, const pair< vector, matrix >&); template void sort_by_second( prevector< pair >&); ]! ) index_method(cmp_secondI) template inline int cmp_secondI( const pair& a, const pair& b ) { return sign(a.second - b.second); } index_method(sort_by_secondx) void sort_by_secondx( prevector< pair >& p ) { p.sort( &cmp_secondI ); } index_method(sort_by_secondy) void sort_by_secondy( prevector< pair< int, vector > >& p ) { p.sort( &cmp_secondvc ); } index_method(sort_by_secondz) void sort_by_secondz( prevector< pair< vector, matrix > >& p ) { p.sort( &cmp_secondm2 ); } set_include_file(vconstraint.h) index_method(set) index_class(qvconstraint) class qvconstraint { public: vector LHS; char sense; Rational RHS; qvconstraint(const constraint&, codehome*); qvconstraint(int nvars) : LHS(nvars) { } qvconstraint( ) { } void set(char s, const Rational& R) { sense = s, RHS = R; } }; index_class(vconstraint) index_method(if_zero) class vconstraint { public: vector LHS; char sense; Integer RHS; vconstraint(int nvars) : LHS(nvars) { } vconstraint( ) { } void set(char s, const Integer& I) { sense = s, RHS = I; } bool if_zero( ) { return RHS == 0 && LHS.if_zero( ); } HIDE( ![ friend ostream& operator<<(ostream&, const vconstraint&); friend istream& operator>>(istream&, vconstraint&); friend Rational clear_denom(const qvconstraint&, vconstraint&); friend bool operator==(const vconstraint&, const vconstraint&) { INTERNAL_ERROR("operator== for vconstraint not defined"); } friend bool operator!=(const vconstraint&, const vconstraint&) { INTERNAL_ERROR("operator!= for vconstraint not defined"); } ]! ) void reduce( ); }; set_compile_file(constraint.cc) istream& operator>>(istream& s, vconstraint& vcon) { vcon.LHS.set_zero( ); char c; Integer coeff; int var_no, signx; while(1) // Read left hand side. { s >> c; if ( c == '=' || c == '<' || c == '>' ) break; // Read a coefficient. signx = 1; if ( c == '+' ) s >> c; else if ( c == '-' ) { s >> c; signx = -1; } if ( c == 'v' ) { coeff = signx; s.unget( ); } else { s.unget( ); s >> coeff; if ( signx == -1 ) coeff = -coeff; } // Process variable. s >> c >> var_no; vcon.LHS( var_no - 1 ) = coeff; } // Determine sense and right hand side. vcon.sense = c; if ( vcon.sense != '=' ) s.get(c); s >> vcon.RHS; while( c != '\n' ) s.get(c); } TEX( Divide the coefficients and \RHS\ of a {\tt vconstraint} by their $\gcd$. Do not call with a zero constraint. ) index_method(reduce) void vconstraint::reduce( ) { Integer divider = RHS; for ( int i = 0; i < LHS.length; i++ ) gcd( divider, divider, LHS(i) ); if ( divider == 1 ) return; HIDE( ![ if (debug) { if ( divider == 0 ) INTERNAL_ERROR( "Attempting to divide by zero in vconstraint::reduce." ); } ]! ) for ( int i = 0; i < LHS.length; i++ ) // LHS(i) /= divider; div_exact( LHS(i), LHS(i), divider ); // RHS /= divider; } div_exact( RHS, RHS, divider ); } TEX(![ \verb|clear_denom|:\ Replace a given constraint with rational coefficients by a constraint {\tt c} whose coefficients are integers and relatively prime, returning the rational number which one has to multiply by to accomplish this. In case the constraint is identically zero, return garbage for {\tt c} but a multiplier of zero. ]!) index_method(clear_denom) Rational clear_denom(const qvconstraint& qc, vconstraint& c) { Integer multiplier = qc.RHS.denominator( ); Integer divider = abs(qc.RHS.numerator( )); for ( int i = 0; i < qc.LHS.length; i++ ) { multiplier = lcm( multiplier, qc.LHS(i).denominator( ) ); divider = gcd( divider, qc.LHS(i).numerator( ) ); } if ( divider == 0 ) return 0; for ( int i = 0; i < qc.LHS.length; i++ ) c.LHS(i) = (qc.LHS(i).numerator( ) * multiplier) / (qc.LHS(i).denominator( ) * divider); c.RHS = (qc.RHS.numerator( ) * multiplier) / (qc.RHS.denominator( ) * divider); c.sense = qc.sense; return Rational(multiplier, divider); } ostream& operator<<(ostream& s, const vconstraint& t) { bool first_nonzero = true; for ( int i = 0; i < t.LHS.length; i++ ) if ( t.LHS(i) != 0 ) { if (first_nonzero) { first_nonzero = false; if ( t.LHS(i) == -1 ) s << "-"; else if ( t.LHS(i) != 1 ) s << t.LHS(i); } else { if ( t.LHS(i) > 0 ) { if ( t.LHS(i) != 1 ) s << " + " << t.LHS(i); else s << " + "; } else { if ( t.LHS(i) != -1 ) s << " - " << -t.LHS(i); else s << " - "; } } s << "v" << i + 1; } s << " " << t.sense; return s << ((t.sense == '=') ? " " : "= ") << t.RHS << "\n"; } set_include_file(constraint.h) index_class(constraintlist) index_method(merge) index_method(global) index_method(joint) index_method(local) index_method(intersection) class constraintlist : public DLList { public: constraintlist(const String&); constraintlist( ) { } constraintlist( const constraint& c ) { append(c); } // The following line was added to circumvent an internal compiler // error message. This error should be reported. ~constraintlist( ) { } void evaluate(const String&, Integer&, Integer&) const; bool known(const constraint&) const; void merge(const constraintlist& l) { forPixDef( i, l ) if ( !known( l(i) ) ) append( l(i) ); } void merge( const constraint& c ) { if ( !known(c) ) { // Delete any constraints which are obvious consequences // of c. Then append c. forPixDef( i, *this ) { const constraint& c_known = (*this)(i); if ( c.LHS != c_known.LHS ) continue; if ( (c.sense == c_known.sense || c.sense == '=') && test ( c.RHS, c_known.RHS, c_known.sense ) ) del(i, -1); } append(c); } } bool global( ) const { forPixDef( p, *this ) if ( !(*this)(p).global( ) ) return false; return true; } bool local( ) const { forPixDef( p, *this ) if ( !(*this)(p).local( ) ) return false; return true; } bool joint( ) const { forPixDef( p, *this ) if ( !(*this)(p).joint( ) ) return false; return true; } friend bool operator<=(const constraintlist& c1, const constraintlist& c2) { forPixDef( i, c1 ) if ( !c2.known( c1(i) ) ) return false; return true; } friend bool operator>=(const constraintlist& c1, const constraintlist& c2) { return c2 <= c1; } friend bool operator==(const constraintlist& c1, const constraintlist& c2) { return c1 <= c2 && c2 <= c1; } friend bool operator!=(const constraintlist& c1, const constraintlist& c2) { return !(c1 == c2); } operator String( ) const { String s; forPixDef( i, *this ) { if ( i != first( ) ) s += ", "; s += (*this)(i); } return s; } friend ostream& operator<<(ostream& s, const constraintlist& l) { forPixDef( i, l ) { if ( i != l.first( ) ) s << ", "; s << l(i); } return s; } friend constraintlist intersection(const constraintlist& l1, const constraintlist& l2) { constraintlist ans; forPixDef( p, l1 ) { if ( l2.known( l1(p) ) ) ans.merge( l1(p) ); else if ( l1(p).sense == '=' ) { constraint c = l1(p); c.sense = '>'; if ( l2.known(c) ) ans.merge(c); c.sense = '<'; if ( l2.known(c) ) ans.merge(c); } } forPix( p, l2 ) { if ( l1.known( l2(p) ) ) ans.merge( l2(p) ); else if ( l2(p).sense == '=' ) { constraint c = l2(p); c.sense = '>'; if ( l1.known(c) ) ans.merge(c); c.sense = '<'; if ( l1.known(c) ) ans.merge(c); } } return ans; } }; set_compile_file(constraint.cc) TEX(![ {\tt evaluate(v, low, high):}\ Let {\tt v} be a nonnegative linear combination of variables. Search for constraints whose \LHS\ is {\tt v}, to get integer lower and upper bounds. If no upper bound is found, {\tt high} is set to $-1$. The preexisting values for {\tt low} and {\tt high} are assumed to be known bounds, with the same convention regarding {\tt high} $= -1$. ]!) index_method(evaluate) void constraintlist::evaluate(const String& s, Integer& low, Integer& high) const { term_sum t(s); forPixDef( i, *this ) { const constraint& c = (*this)(i); if ( c.LHS != t ) continue; if ( c.sense == '=' || c.sense == '<' ) { // If the RHS of the constraint is negative, it is inherently // contradictory. This isn't likely to happen, so we just // give up in that case. if ( c.RHS < 0 ) return; if ( high == -1 ) high = c.RHS; else high = min( high, c.RHS ); } if ( c.sense == '=' || c.sense == '>' ) low = max( low, c.RHS ); } } TEX(![ The following constructor for a {\tt constraintlist} has as its argument a comma-separated list of constraints, allowing for compound forms, as discussed in the description of the {\tt show} command. ]!) constraintlist::constraintlist(const String& s) { static Regex snort( "[^<]*" ); static Regex wheeze( "[-0-9]+" ); prevector v = unpack(s); for ( int i = 0; i < v.length; i++ ) if ( v(i).freq("<") <= 1 ) append( constraint(v(i)) ); else // compound form { Integer low = take(v(i), wheeze); require_char( v(i), '<' ); if ( v(i)[0] == '=' ) v(i).del("="); else ++low; append(constraint( v(i).at(snort) + ">=" + dec(low) )); append(constraint(v(i))); } } TEX(![ Determine if a constraint is in a constraintlist. This is at present checked in a more or less literal way, as follows. A constraint with ``{\tt=}'' in it must appear verbatim in the constraintlist in order for {\tt true} to be returned. A constraint with ``{\tt<=}'' or ``{\tt>=}'' will be ``found'' if a stronger constraint with the same \LHS\ appears. Thus for example {\tt y10 <= 15} will be found if {\tt y10 = 12} is in the constraintlist. ]!) index_method(known) bool constraintlist::known(const constraint& c) const { if ( c.LHS.length( ) == 0 ) return test ( Integer(0), c.RHS, c.sense ); forPixDef( i, *this ) { const constraint& c_known = (*this)(i); if ( c.LHS != c_known.LHS ) continue; if ( (c.sense == c_known.sense || c_known.sense == '=') && test ( c_known.RHS, c.RHS, c.sense ) ) return true; } return false; } set_compile_file(code.c) HIDE(![#include "vconstraint.h"]!) TEX( \block{Word and code classes} \indexz{word} ) TEX( ![ Note that a code may exist in a built state (with {\tt x} defined), or in an unbuilt state (with {\tt x} undefined). The default is undefined. ]! ) set_include_file(code.h) index_class(code) class code { public: matrix basis; // rows are basis for the code matrix x; // rows are the elements themselves code(int, const String&); code( ) { } void build( ) const; // build x ("const", but modifies x) void unbuild( ) const; code& operator=(const code& c) { basis = c.basis; } }; set_compile_file(code.c) HIDE(![#include "code.h"]!) code::code(int nc, const String& s) : basis(nc, s) { basis.reduce( ); if ( basis.nrows != 0 && basis(basis.nrows-1).if_zero( ) ) ERROR("The alleged basis elements are dependent."); } index_method(build) void code::build( ) const { matrix& x_mutable = const_cast&>(x); if ( x.x == 0 ) { int i = 0, d = basis.nrows; if (d > 30) ERROR("I was about to compute all the elements of a code " << "of length > 30, which is probably a bad idea."); x_mutable.set_size( (int) Ipow(2,d), basis.ncols ); if ( d == 0 ) return; word indx(d); do mul( indx, basis, x_mutable(i++) ); while ( indx.advance( ) != 0 ); } } index_method(unbuild) void code::unbuild( ) const { matrix& x_mutable = const_cast&>(x); if ( x_mutable.x != 0 ) { delete [ ] x_mutable.x; x_mutable.x = 0; } } TEX( ![ \block{Partition, wordtype, mawhome, and mawhometable classes}% \label{partition-wordtype-mawhome-section} \indexz{partition} ]! ) set_include_file(partition.h) index_method(operator*(vector$<$gf2$>$, partition)) index_method(set_all_ones) class partition : public vector { public: int n; // sum of the elements partition(const String&); partition( ) { } partition(int l) : vector(l) { } partition( vector v, int N ) : vector(v), n(N) { } void set_all_ones(int r) { set_size(r); n = r; for ( int i = 0; i < r; i++ ) (*this)(i) = 1; } }; set_compile_file(code.c) HIDE(![#include "partition.h"]!) TEX(![ Constructor of partition from a string, which should be a white-space-free comma-separated list of $\geq 1$ positive integers. ]!) partition::partition(const String& s) : vector(s) { n = 0; for ( int i = 0; i < length; i++ ) { if ( (*this)(i) == 0 ) ERROR( "0 element in partition " << s ); n += (*this)(i); } } TEX(![ A ``{\tt wordtype}'' is the data structure which represents basic local variables, as well as the dual analog. We define here what it means for a wordtype $w$ to be {\it minimal}, as was promised on page \pageref{minimal-promise}. For the configuration $c$ to which $w$ is associated, let $M$ be the unique matrix in \RREF\ whose rows form a basis for the small code. Then $w$ is {\it minimal\/} if the following two conditions are satisfied: \begin{enumerate} \item for each $i$ such that $M$ has a leading $1$ in column $i$ (where the columns are numbered starting at $0$), we have $w(i) \leq p(i)/2$, where $p$ is the partition of $c$; \item amongst all wordtypes which are equivalent to $w$ and satisfy (1), $w$ is lexicographically minimal. \end{enumerate} \indexz{wordtype} ]!) set_include_file(wordtype.h) index_method(wcmp) class wordtype : public vector { public: const config* c; // pointer to associated config wordtype(const config*); // constructor of zero wordtype wordtype(const config*, String); // e.g. (1,2,3) from "x_1_2_3" wordtype(const vector& v) : vector(v) { } wordtype( ) { }; String variable( ) const; // make a variable name (string) int advance(config_active*, codetable&); // get next minimal admissible // wordtype int dual_advance(bool); void act(const word&, const wordtype&); void act(const word&); // Lexicographically compare two wordtypes. friend bool operator<(const wordtype& w1, const wordtype& w2) { for ( int i = 0; i < w1.length; i++ ) { if ( w1(i) < w2(i) ) return true; if ( w1(i) > w2(i) ) return false; } return false; } friend bool operator>(const wordtype& w1, const wordtype& w2) { return w2 < w1; } HIDE( ![ friend int sum(const wordtype&); friend bool is_pullback(const wordtype&, const wordtype&, const wordtype&); ]! ) friend int wcmp(const wordtype& a, const wordtype& b) { register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } }; set_compile_file(wordtype.cc) HIDE(![#include "homedefs.h" matrix subdivide_matrix(const matrix&, const partition&, const wordtype&, bool, bool = true); int String_cmp(const String&, const String&); bool sub_to_dual_radius(int, partition, matrix, int); extern int auto_joint_list; String make_j_var(int, int, int); void parse_j_var(String, int&, int&, int&); ]!) wordtype::wordtype(const config* c, String v) : c(c) { static Regex alt_wordtype_pattern( "x[0-9]+" ); prevector args; String v_save = v; if ( v[0] == 'y' ) v.at("y") = "x_"; if_match( v, "x" + left + "_" + number_pat + right + "+" ) args = unpack(v.after("x_"), "_"); else if ( v.matches(alt_wordtype_pattern) ) args = unpack(v.after("x"), ""); else goto error_exit; if ( args.length != c->part.length ) goto error_exit; set_size(args.length); for ( int i = 0; i < args.length; i++ ) { (*this)(i) = as_int(args(i)); if ( (*this)(i) > c->part(i) ) goto error_exit; } return; error_exit: ERROR( "\"" << v_save << "\" is not a valid basic local variable." ); } // Construct zero wordtype. wordtype::wordtype(const config* c) : vector(c->part.length), c(c) { } index_method(variable) String wordtype::variable( ) const { String s = "x"; int i; for ( i = 0; i < length; i++ ) if ( x[i].x > 9 ) break; if ( i == length ) { for ( i = 0; i < length; i++ ) s += dec(x[i].x); } else { for ( i = 0; i < length; i++ ) s += String("_") + dec(x[i].x); } return s; } // Compute the sum of the elements of a wordtype. index_method(sum) int sum(const wordtype& w) { int sum = 0; for ( int i = 0; i < w.c->part.length; i++ ) sum += w(i); return sum; } index_method(joint_adm_table) // Return adm: We define adm(i)(j)(k) to be false iff it is known that there // cannot be words of weights i and j which add to a word of weight k. prevector< prevector< prevector > > joint_adm_table( config* c, codetable& results) { prevector< prevector< prevector > > adm; if ( c->share->wjv.length == 0 ) c->home->basic_joint_vars( c, results ); int N = c->home->n; adm.set_size(N+1); for ( int i = 0; i <= N; i++ ) { adm(i).set_size(N+1); for ( int j = 0; j <= N; j++ ) { adm(i)(j).set_size(N+1); for ( int k = 0; k <= N; k++ ) adm(i)(j)(k) = false; } } for ( int i = 0; i < c->share->wjv.length; i++ ) { int i1, i2, i3; parse_j_var( c->share->wjv(i), i1, i2, i3 ); adm(i1)(i2)(i3) = true; adm(i1)(i3)(i2) = true; adm(i2)(i1)(i3) = true; adm(i2)(i3)(i1) = true; adm(i3)(i1)(i2) = true; adm(i3)(i2)(i1) = true; } return adm; } index_method(advance) int wordtype::advance(config_active* a, codetable& results) { int i, j, s, n = c->part.length; bool first_pass = if_zero( ); static vector border_rows; border_rows.set_size(c->small.basis.nrows); weightlist& rww = a->rww; if ( rww.empty( ) ) return 0; int rwwm = a->rww.Min( ), ss = sum(*this); wordtype alttype = *this; try_again: TEX( ![ \begin{quote} Advance to the next wordtype, and at the same time check that the wordtype cannot be ruled inadmissible simply because of its weight. This code has been somewhat optimized. \end{quote} ]! ) for ( i = n-1; i >= 0; i-- ) if ( x[i] != a->bound(i) ) break; if ( i == -1 ) return 0; for ( j = n-1; j > i; j-- ) { ss -= x[j]; x[j] = 0; } ++x[i]; ss++; if ( ss < rwwm || !rww.contains(ss) ) goto try_again; TEX( ![ \begin{quote} Check for admissibility, looking only at small code. This code has been somewhat optimized. \end{quote} ]! ) for ( i = 1; i < c->small.x.nrows; i++ ) { register int l, sum = 0; register gf2 *si = c->small.x.x[i].x; for ( l = 0; l < c->part.length; l++ ) sum += (si[l].x ? c->part.x[l] - x[l] : x[l].x); if ( !rww.contains(sum) ) goto try_again; } TEX( ![ \begin{quote} Check for admissibility, looking only at dual small code. \end{quote} ]! ) if ( !a->dualsmall_working.basis.orthogonal_to( (*this) ) ) goto try_again; TEX( ![ \begin{quote} Do complete check for minimality. Compare with \verb|config::make_minimal|. \end{quote} ]! ) int border_count = 0, col; for ( i = 0; i < c->leading1s.length; i++ ) { col = c->leading1s(i); if ( 2 * (*this)(col).x == c->part(col)) border_rows(border_count++) = i; } if ( border_count != 0 ) { vector indx(border_count); do { alttype = *this; for ( j = 0; j < border_count; j++ ) if ( indx(j) ) alttype.act(c->small.basis(border_rows(j))); if ( alttype < *this ) goto try_again; } while( indx.advance( ) != 0 ); } TEX( ![ \begin{quote} Check to see if a constraint sets a basic local variable to zero, thereby forcing the wordtype to be inadmissible. \end{quote} ]! ) forPixDef( p, c->con ) { const constraint& cn = c->con(p); if ( cn.simple_local_zero( ) ) { wordtype wt2( c, cn.LHS.front( ).var ); if ( equiv( c->part, c->small.basis, *this, wt2 ) ) goto try_again; } } TEX( ![ \begin{quote} Check to see if a constraint sets an upper bound on a basic global variable, thereby forcing the wordtype to be inadmissible. For this, first determine the weight enumerator of the basic code associated to the small code that would result if the configuration were subdivided along the given wordtype. \end{quote} ]! ) config_core d; d.part = subdivide_partition(c->part, *this); d.smallbasis = subdivide_matrix( c->small.basis, c->part, *this, true ); vector wt = d.smallcode_we( ); for ( i = 0; i <= c->home->n; i++ ) if ( wt(i) != 0 && a->global_bound(i).second != -1 && wt(i) > a->global_bound(i).second ) goto try_again; TEX( ![ \begin{quote} Check to see if the basic local variable would violate the zeroness of a joint variable which is known to be zero. This is in principle very simple, but owing to complexity considerations, we have to do more complicated things. \end{quote} ]! ) if (auto_joint_list) { config* cc = const_cast(c); // Shouldn't be needed! c->home->basic_joint_vars(cc, results); if ( c->share->wjv.length == 0 ) INTERNAL_ERROR( "wordtype::advance - unrealizability oddly encountered" ); int k, N = c->home->n; static prevector< prevector< prevector > > adm; config* cconst = const_cast< config* >(c); if (first_pass) { if ( N <= 200 ) adm = joint_adm_table(cconst, results); else adm.set_size(0); } // Low memory approach for large N: if ( N > 200 ) { int i1x = sum(*this); // weight of one word for ( i = 1; i < c->small.x.nrows; i++ ) { word wd = c->small.x(i); int i1 = i1x; int i2 = wd * c->part; // weight of another word int i3 = i1 + i2 - 2 * (wd * (*this)); // weight of sum if ( i2 > i3 ) swap( i2, i3 ); if ( i1 > i2 ) swap( i1, i2 ); if ( i2 > i3 ) swap( i2, i3 ); String var = String("jy") + dec(i1) + "y" + dec(i2) + "y" + dec(i3); if ( c->share->wjv.pos( var, &String_cmp ) == -1 ) goto try_again; } goto dual_radius; } // We define wtij(i,j) to be the weight of v(i) + v(j), where // v(i) and v(j) are the ith and jth words in the smallcode. static matrix wtij; if (first_pass) { wtij.set_size( c->small.x.nrows, c->small.x.nrows ); word wdi; int val; for ( i = 0; i < c->small.x.nrows; i++ ) { wdi = c->small.x(i); for ( j = i; j < c->small.x.nrows; j++ ) { gf2* wdjx = c->small.x.x[j].x; val = 0; for ( k = 0; k < n; k++ ) if ( wdi.x[k].x ^ wdjx[k].x ) val += c->part.x[k]; wtij(i,j) = val; } } first_pass = false; } int i1x = sum(*this); // weight of one word prevector wts( c->small.x.nrows ); for ( i = 0; i < c->small.x.nrows; i++ ) { word wdi = c->small.x(i); wts(i) = i1x + wdi * c->part - 2 * (wdi * (*this)); } int wti; for ( i = 0; i < c->small.x.nrows; i++ ) { wti = wts(i); for ( j = i; j < c->small.x.nrows; j++ ) if ( !adm(wti)(wts.x[j])(wtij.x[i].x[j]) ) goto try_again; } } TEX( ![ \begin{quote} Check to see if {\tt dual radius} is violated. \end{quote} ]! ) dual_radius: if ( c->home->opt.dual_radius > 0 ) { if ( c->home->opt.dual_radius_length == c->home->n ) { if (!sub_to_dual_radius( c->home->opt.dual_radius, d.part, d.smallbasis, c->home->opt.dual_radius_dim ) ) goto try_again; } else { partition dp( d.part.length + 1 ); for ( i = 0; i < d.part.length; i++ ) dp(i) = d.part(i); dp(d.part.length) = c->home->opt.dual_radius_length - c->home->n; matrix ds( d.smallbasis ); ds.resize( ds.nrows, ds.ncols + 1 ); if ( !sub_to_dual_radius( c->home->opt.dual_radius, dp, ds, c->home->opt.dual_radius_dim ) ) goto try_again; } } return 1; } index_method(dual_advance) int wordtype::dual_advance(bool reset) { static vector border_rows; static int border_count; static vector indx; int i, j, col; config_active* a = c->home->active; if (reset) { border_rows.set_size(a->dualsmall_working.basis.nrows); border_count = 0; for ( i = 0; i < a->dual_leading1s.length; i++ ) { col = a->dual_leading1s(i); if ( 2 * (*this)(col).x == c->part(col)) border_rows(border_count++) = i; } indx = vector(border_count); return 1; } int n = c->part.length; wordtype alttype = *this; try_again: for ( i = n-1; i >= 0; i-- ) if ( x[i] != a->dual_bound(i) ) break; if ( i == -1 ) return 0; for ( j = n-1; j > i; j-- ) x[j] = 0; ++x[i]; // Check for admissibility: if ( !c->small.basis.orthogonal_to( *this ) ) goto try_again; // Do complete check for minimality. if ( border_count == 0 ) return 1; indx.set_zero( ); do { alttype = *this; for ( j = 0; j < border_count; j++ ) if ( indx(j) ) alttype.act(a->dualsmall_working.basis(border_rows(j))); if ( alttype < *this ) goto try_again; } while( indx.advance( ) != 0 ); return 1; } index_method(act) void wordtype::act(const word& w, const wordtype& t) { for ( int i = 0; i < t.c->part.length; i++ ) x[i] = (w(i).x == 0) ? t(i).x : t.c->part(i) - t(i); } index_method(act) void wordtype::act(const word& w) { for ( int i = 0; i < c->part.length; i++ ) if ( w(i) ) x[i] = c->part(i) - x[i]; } TEX( Determine if the pullback of {\tt v} along {\tt edge} is {\tt w}. Used only by the ``{\tt infer}'' command. ) index_method(is_pullback) bool is_pullback( const wordtype& v, const wordtype& w, const wordtype& edge ) { int j = 0; // index for v for ( int i = 0; i < w.length; i++ ) { if ( (edge(i) == 0 || edge(i) == w.c->part(i)) && v(j) == w(i) ) j++; else if ( 0 < edge(i).x && edge(i) < w.c->part(i) && v(j) + v(j+1) == w(i) ) j += 2; else return false; } HIDE( ![ if ( j != v.length ) INTERNAL_ERROR( "is_pullback" ); ]! ) return true; } set_include_file(wordtype.h) TEX(![ A {\tt mawhome} is the data structure associated to the equivalence class of an admissible basic local variable. The {\tt maw} member gives the minimal element $y$ of the equivalence class. The elements $x$ of the list {\tt w} are chosen so that $x + y$ ranges over the variables equivalent to $y$, without repetition. \indexz{mawhome} ]!) class mawhome { public: wordtype maw; SLList w; HIDE( ![ friend bool operator==(const mawhome& m1, const mawhome& m2) { INTERNAL_ERROR("mawhome== is not implemented"); } friend bool operator!=(const mawhome& m1, const mawhome& m2) { INTERNAL_ERROR("mawhome!= is not implemented"); } ]! ) }; index_class(mawhometable) class mawhometable : public prevector { public: static Pix w_ptr; // Used for iteration. static int maw_ptr; // Used for iteration. mawhometable( ) { } mawhometable(SLList l) : prevector(l) { } int find(const wordtype&) const; int mfind(wordtype) const; bool admissible(wordtype) const; void first(wordtype&); bool advance(wordtype&); SLList has_member_of_weight(int) const; }; set_compile_file(config.cc) HIDE( ![ #include "homedefs.h" int rcmp(const number&, const number&); #include "bitvec.h" #include "graph.h" #include "codetable.h" #include extern "C" int isalpha(int); extern long time_used_by_subdivide; extern long time_used_by_igs, time_used_by_smallcode_we; extern long time_used_canonical_form; extern int show_variables, secondary_plus, silent, no_create; extern int warnings_are_fatal, debug, configuration_search_to_end, configuration_search_group_level, configuration_search_show_example, configuration_search_expand_final_count, configuration_search_print_final_list, auto_joint_list, configuration_search_group_size_cap, show_residual_data, auto_analyze_local_relations_vocal; int String_cmp(const String&, const String&); String list_of(const String&, const String& = ","); vector dual_of_we(vector, bool = false); int take_int(String&, const Regex&); matrix subdivide_matrix(const matrix&, const partition&, const wordtype&, bool, bool = true); void parse_j_var(String, int&, int&, int&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); void sort_by_secondz( prevector< pair< vector, matrix > >& ); String bitlist(const word&, bool=false, int=1); String make_j_var(int, int, int); bool sub_to_dual_radius(int, partition, matrix, int); void mul( const vector&, const matrix&, vector&); ostream& operator<<(ostream&, const prevector&); ]! ) index_method(mfind) int mawhometable::mfind(wordtype w) const { w.c->home->active->c->make_minimal(w); return find(w); } index_method(admissible) bool mawhometable::admissible(wordtype w) const { w.c->home->active->c->make_minimal(w); return (find(w) != -1); } TEX( Return a list of all minimal admissible basic local variables which are equivalent to a basic local variable of given weight. ) index_method(has_member_of_weight) SLList mawhometable::has_member_of_weight(int d) const { SLList list; const mawhometable& me = *this; for ( int i = 0; i < length; i++ ) { forPixDef( p, me(i).w ) { wordtype alttype = me(i).maw; alttype.act( me(i).w(p) ); if ( sum(alttype) == d ) { list.append( me(i).maw ); break; } } } return list; } set_compile_file(code.c) HIDE( ![ #include "wordtype.h" // template void sort_by_second( prevector< pair >& ); // template void sort_by_second( // prevector< pair< pair< matrix, int>, int> >& ); // template inline bool operator==(const prevector&, // const prevector&); ]! ) Pix mawhometable::w_ptr; int mawhometable::maw_ptr; TEX( The following two routines allow one to iterate through all admissible wordtypes. Do not in any way nest such iterations: it won't work. ) set_compile_file(mawhome.cc) HIDE(![#include "homedefs.h" matrix subdivide_matrix(const matrix&, const partition&, const wordtype&, bool, bool = true); int take_int(String&, const Regex&); String list_of(const String&, const String& = ","); ]!) void mawhometable::first(wordtype& wt) { maw_ptr = 0; mawhome& m = (*this)(0); w_ptr = m.w.first( ); wt = m.maw; wt.act( m.w(w_ptr) ); } bool mawhometable::advance(wordtype& wt) { mawhometable& t = *this; t(maw_ptr).w.next(w_ptr); if ( w_ptr == 0 ) { if ( ++maw_ptr == length ) return false; w_ptr = t(maw_ptr).w.first( ); } wt = t(maw_ptr).maw; wt.act( t(maw_ptr).w(w_ptr) ); return true; } TEX(![ {\tt table.find(w)}: Search the mawhometable {\tt table} for the wordtype {\tt w}, returning $-1$ if it is not found, else its index. Probably instead we should sort the mawhometable (when it is created) and do a binary search here. ]!) index_method(find) int mawhometable::find(const wordtype& w) const { for ( int i = 0; i < length; i++ ) if ( w == (*this)(i).maw ) return i; return -1; } TEX( \block{Weightlist class} ) set_include_file(weightlist.h) TEX( A weightlist is an ordered list of integers $0 = n_1 < n_2 < \cdots < n_r$ which represent the weights in a code. We also use this class for other lists of weights. \indexz{weightlist}\mindex{divisible} ) class weightlist : public OSLList { public: weightlist(String, int); weightlist(const OSLList& w) : OSLList(w) { } bool divisible(int d) const { forPixDef( i, *this ) if ( (*this)(i) % d != 0 ) return false; return true; } void make_divisible(int); // replace list by its subset consisting // of elements divisible by the argument int min( ) const // return smallest nonzero element { Pix a = first( ); next(a); return (*this)(a); } weightlist( ) { } operator String( ) const; HIDE( ![ friend ostream& operator<<(ostream&, const weightlist&); ]! ) }; set_compile_file(mawhome.cc) ostream& operator<<(ostream& s, const weightlist& w) { s << "{"; forPixDef( p, w ) { if ( p != w.first( ) ) s << ","; s << w(p); } return s << "}"; } weightlist::operator String( ) const { String s = "{"; forPixDef( p, *this ) { if ( p != first( ) ) s += ","; s += dec((*this)(p)); } return s + "}"; } index_method(make_divisible) void weightlist::make_divisible(int d) { weightlist w; for ( Pix i = first( ); i != 0; next(i) ) if ( (*this)(i) % d == 0 ) w.add( (*this)(i) ); *this = w; } index_method(int_set) OSLList int_set(String s) { weightlist ans; static Regex pos_pattern( pos_number ); s = s.after("{"); while( s[0] != '}' ) { int p1 = take_int(s, pos_pattern); if ( s[0] != '.' ) ans.add(p1); else { s = s.after( ".." ); int p2 = take_int(s, pos_pattern); if ( p2 < p1 ) ERROR("Integer list doesn't make sense."); for ( int i = p1; i <= p2; i++ ) ans.add(i); } if ( s[0] == ',' ) s.del(','); } return ans; } weightlist::weightlist(String s, int n) { String set_pat( "{" + list_of( pos_number + orsign + pos_number + "\\.\\." + pos_number ) + "}" ); static Regex set_pattern( set_pat ); static Regex weightlist_pat( pos_number + orsign + pos_number + "_" + pos_number + orsign + set_pat + orsign + pos_number + "-" + set_pat + orsign + pos_number + "_" + pos_number + "-" + set_pat ); static Regex number_pattern( number_pat ); if ( !s.matches( weightlist_pat ) ) ERROR("Weightlist syntax wrong."); if ( s[0] == '{' ) *this = int_set(take(s, set_pattern)); else { int divider = 1; // number by which all weights are divisible by int d = as_int(take(s, number_pattern)); if ( d <= 0 || d > n ) ERROR("Weight data doesn't make sense."); if ( s.contains("_", 0) ) { s.del("_"); divider = take_int(s, number_pattern); } if ( d % divider != 0 ) d += divider - (d % divider); for ( int i = d; i <= n; i += divider ) add(i); } if ( s.contains("-", 0) ) { weightlist dels = int_set(s.after("-")); forPixDef( p, dels ) del( dels(p) ); } add(0); } TEX(![ \block{Config and related classes}\label{main-config-section} Configurations are stored in a {\tt ShareGraph}. Whenever there is an edge in this graph, the source is realizable \IFF\ the target is realizable. There is therefore certain information which is shared amongst the members of a connected component of the graph. This information is carried by the class \verb|config_share|. An object of this class is used to record inferred constraints which involve only global variables. How they get recorded depends on what the constraint is. If it has the form {\tt y}\kern1pt$i$\kern5pt{\tt = 0}, then it is recorded by modifying the {\tt ww} (working weightlist) member of the \verb|config_share| object. Similarly, a constraint of the form {\tt mu}\kern1pt$i$\kern5pt{\tt = 0} may get recorded by modifying the \verb|dual_min_low| member of the \verb|config_share| object. Otherwise, the constraint is appended to the \verb|ycon| member. By the {\it computational state\/} of a configuration, we mean, generally, whether or not certain auxiliary data items (used to facilitate computation) exist at a given time. Because these data items are expensive (i.e.\ require lots of time to produce, or lots of memory/disk space to store), choices have to made as to which data items will exist at any given time. The computational state is managed at three levels: the {\tt config} class itself, the {\tt codehome} class, and the \verb|config_active| class. There is always a {\it current\/} configuration, pointed to by the {\tt current} member of the {\tt codehome} object. This configuration may or may not be {\it active}: if it is, the {\tt active} member of the {\tt codehome} object points to a \verb|config_active| object; otherwise, the {\tt active} member is set to zero. In the {\tt config} class is found a pointer to the associated {\tt codehome}, the four items which comprise the configuration definition, and a pointer to a \verb|config_share| object. These items exist for the lifetime of the {\tt codehome}. Certain items (labelled temporary) exist so long as the code type is current. The other items in the {\tt config} class are maintained indefinitely, unless at some point the configuration is proved unrealizable. Then the configuration is cleaned, to save space. This cleaning process also applies to the associated \verb|config_share| object. Only one configuration can be current at any given time. When a configuration is made current, this fact is registered by setting the {\tt current} member of the {\tt codehome} object. This means that the previous current configuration is no longer current, and as a consequence the old \verb|config_active| object is deleted and the {\tt active} member is reset to $0$. Various actions trigger the activation of the current configuration. The most expensive component of the \verb|config_active| object is a table of local variables (the mawhometable). If there are a lot of components in the partition, it will take a long time to build the mawhometable. The \verb|config_active| object also contains various and sundry working data items which facilitate computation. A configuration can moreover be {\it very active}: this means that a constraint file has been built. Again, this can be time consuming. Being in the very active state is indicated by the \verb|file_status| flag in the \verb|config_active| object. The following routines manage the status of configurations: \begin{itemize} \item \verb|codehome::set_current|: Set the current configuration. This invokes {\tt deactivate}. \item \verb|codehome::activate|: If the \verb|config_active| object already exists, do nothing. Otherwise, build it. \item \verb|codehome::deactivate|: Delete the constraint file (\verb|cplex_in|), if it exists, and then delete the \verb|config_active| object, if it exists. The routine {\tt deactivate} gets invoked whenever {\tt[current]} is changed and whenever a constraint is added that would necessitate the recomputation of the list of minimal admissible basic local variables (mawhometable). \item \verb|codehome::set_unrealizable(p)|: Set the configuration with Pix {\tt p} (and thus its logical equivalence class) to unrealizable. Do some cleaning. \item \verb|config_active::split|: This routine is the split linear programming routine. It is the creator and the only direct user of \verb|cplex_in|. Invoking it will make the current configuration very active. \item \verb|config_active::config_active|: invoked by activate. \item \verb|config_active::~config_active|: invoked by deactivate. \end{itemize} \indexz{config} ]!) set_include_file(config.h) index_method(basal) index_method(mostly_equal) class config { public: // who this belongs to codehome* home; TEX( \classbreak ) // the data items which comprise the configuration definition String title; String alt_title; String credit_e; // credit for existence String credit_u; // credit for uniqueness (base only) String credit_c; // credit for classification (base only) String note; // note regarding the configuration bool no_auto; // set to true if automorphism group is not to be computed matrix gen; // the original generator matrix partition part; code small; code dualsmall; constraintlist assumed_cons; TEX( \classbreak ) // the data items which are proved after the configuration has been defined // (see also config_share) constraintlist con; Permutationlist aut; // automorphisms known for this configuration TEX( \classbreak ) // pointer to other things which are proved, shared with other configs config_share* share; TEX( \classbreak ) // The following item keeps track of automorphism labels. The first // part of the pair is the label, including the brackets. The second // part is the index of an automorphism in auto. SLList< pair > auto_labels; TEX( \classbreak ) // temporary data items vector leading1s; // column indices of leading ones in small.basis TEX( \classbreak ) // methods config(codehome*, const String&); config( ) { } config(const config&); config(codehome*, matrix); HIDE( ![ friend bool operator==(const config&, const config&); ]! ) // Return weight enumerator of the basic code associated to the small code // of a configuration. vector smallcode_we( ) const; matrix basic_small( ) const; bool is_automorphism(const Permutation&, codetable&); bool known(const constraint&) const; void evaluate(const String&, Integer&, Integer&) const; bool basal( ) const { return small.basis.nrows == 0 && dualsmall.basis.nrows == 0 && part.length == 1; } bool full( ) const; bool terminal( ) const; bool del_weight(int, codetable&); void add_constraint(constraint, codetable&, bool&, bool = false); void add_constraint(String, codetable&, bool&); void check_secondary_residuals(codetable&); void check_variable(String) const; HIDE( ![ friend partition subdivide_partition(const partition&, const wordtype&); friend bool configuration_search(const config&, const config&, String, String); ]! ) bool no_bad_weights( ) const; constraintlist known_cons( ) const; friend bool mostly_equal( const config& c1, const config& c2 ) { return (c1.part == c2.part && c1.small.basis == c2.small.basis && c1.dualsmall.basis == c2.dualsmall.basis); } HIDE( ![ friend ostream& operator<<(ostream&, const config&); ]! ) HIDE( ![ friend bool equiv(const partition&, const matrix&, const wordtype&, const wordtype&); ]! ) pair< Permutationlist, Integer > find_automorphism_group( ) const; void make_minimal(wordtype&) const; friend Pix subdivide(const config&, const wordtype&, codetable&); }; index_class(config_core) class config_core { public: partition part; matrix smallbasis; matrix dualsmallbasis; config_core( ) { } config_core(const config& c) : part(c.part), smallbasis(c.small.basis), dualsmallbasis(c.dualsmall.basis) { } config_core( const matrix& M ) : smallbasis(M), dualsmallbasis(0, M.ncols) { part.set_all_ones(M.ncols); } vector smallcode_we( ) const; matrix basic_small( ) const; matrix basic_dualsmall( ) const; term_sum simplify_global_vars(const term_sum&, const weightlist&, int dim, bool = false) const; HIDE( ![ friend bool operator==(const config_core& a, const config_core& b) { return a.part == b.part && a.smallbasis == b.smallbasis && a.dualsmallbasis == b.dualsmallbasis; } friend word subdivide_word(const partition&, const wordtype&, const word&); ]! ) }; index_class(config_share) class config_share { public: int realizable; // 1 if realizable, -1 if unrealizable, 0 if unknown weightlist ww; // working weightlist, possibly smaller // than the weightlist for the codehome prevector wjv; // sorted working list of basic joint variables, // or empty if it has not been computed short int dual_min_low; // lower bound for minimum weight of dual code short int dual_min_high; // upper bound for minimum weight of dual code constraintlist ycon; // constraintlist involving only // global and joint variables config_share( ) : wjv(0) { } HIDE( ![ friend config_share* operator+(const config_share&, const config_share&); ]! ) }; index_class(config_active) class config_active { public: // data config* c; mawhometable vtable; TEX( ![ \classtext{ {\tt bound}:\ This is a vector whose \th{i} entry is\\ {\tt c->part(}$i${\tt)}, or $\floor{\hbox{{\tt c->part(}$i${\tt)}/2}}$, if {\tt c->small.basis} has a leading $1$ in column $i$. It is used in constructing the mawhometable. The vector {\tt dual\string_bound} is like {\tt bound}, but is based on {\tt dualsmall} instead of {\tt small}. It is used in constructing the main constraint file.} ]!) vector bound, dual_bound; TEX( ![ \classtext{ {\tt global\string_bound}:\ Gives the best known low and high values for $y_i$, $0 \leq i \leq n$. A high value of $-1$ means that no upper bound is known.} ]!) prevector< pair > global_bound; TEX( ![ \classtext{ {\tt small\string_we}:\ The weight enumerator of the basic code associated to the small code.} ]! ) vector small_we; TEX( ![ \classtext{ restricted working weightlist({\tt rww}): this is {\tt c->share->ww}, with the weight $i$ deleted if the constraint $y_i \leq r$ is known, where $r$ is the number of words of weight $i$ in the basic code associated to the small code. Consider a basic local variable $x_I$ which is not equivalent to the trivial basic local variable. If $x_I$ is admissible, then $\abs{I} \in$ {\tt rww}.} ]!) weightlist rww; code dualsmall_working; // working dualsmall code, possibly larger than // dualsmall vector dual_leading1s; // column indices of leading ones in // dualsmall_working.basis prevector y_as_vsum; // express y's in terms of v's; indexed by // share.working weightlist int file_status; // 1 if constraint file built, else 0 // constructor and destructor config_active(config*, codetable&, bool, bool = false); ~config_active( ) { if ( file_status ) remove( calculations_dir + "/cplex_in" ); } // other methods void expand_term_sum(const term_sum&, vector&) const; void split(bool, codetable&, constraintlist = constraintlist( )); void convert_dual_variable(const word&, const wordtype&, Integer**, vector&) const; EquivRelIntList auto_equiv( ) const; int x_to_v(const String&) const; HIDE( ![ friend term_sum subdivide_basic_local_variable(const partition&, const matrix&, const config_active&, const wordtype&, const wordtype&, bool); friend constraint subdivide_constraint(const config&, const config&, const wordtype&, constraint, codetable&); ]! ) }; set_compile_file(code.c) HIDE(![#include "weightlist.h"]!) HIDE(![#include "config.h"]!) TEX(![ \block{Codebase, codehome, and codetable classes} There are two classes for codes: a {\tt codebase}, and the derived class {\tt codehome}. When a code type is first defined, an object of the larger class {\tt codehome} is created. This will exist until the program terminates unless the code type is proven nonexistent. In that case only the {\tt codebase} object is kept, and it is appended to \verb|results.dead|. \indexz{codebase} ]!) set_include_file(codehome.h) HIDE( ![ typedef triple< int, int, OSLList< vector > > packed_matrix_list; ]! ) class matrix_list_on_disk { public: int n; int k; int count; String filename; int chars_to_skip_over; matrix fetch(int); packed_matrix_list fetch_all( ); }; class config_list_on_disk : public matrix_list_on_disk { public: String title; String descrip; int member(String); }; class codebase_options { public: bool dual_may_be_code_of_design; int k, lambda; bool partition_of_word_by_dual_words; int w, d; bool doubly_even_part_is_subcode; int dual_radius; int dual_radius_length; int dual_radius_dim; String maybe_subcode_of; codebase_options( ) { dual_may_be_code_of_design = false; k = 0; lambda = 0; partition_of_word_by_dual_words = false; w = 0; d = 0; dual_radius = 0; dual_radius_length = 0; dual_radius_dim = 0; doubly_even_part_is_subcode = false; } bool none_chosen( ) const { return !dual_may_be_code_of_design && !partition_of_word_by_dual_words && !doubly_even_part_is_subcode && dual_radius == 0 && maybe_subcode_of == ""; } friend bool operator==(codebase_options a, codebase_options b) { return a.dual_may_be_code_of_design == b.dual_may_be_code_of_design && a.k == b.k && a.lambda == b.lambda && a.partition_of_word_by_dual_words == b.partition_of_word_by_dual_words && a.w == b.w && a.d == b.d && a.doubly_even_part_is_subcode == b.doubly_even_part_is_subcode && a.dual_radius == b.dual_radius && a.dual_radius_length == b.dual_radius_length && a.dual_radius_dim == b.dual_radius_dim && a.maybe_subcode_of == b.maybe_subcode_of; } }; class codebase { public: int n; // dimension of the ambient space int dim; // dimension of the code weightlist w; // assumed weight list constraintlist assumed_cons; // assumed constraints codebase_options opt; // options String defining_command; codebase( int n, int dim, const weightlist& w ) : n(n), dim(dim), w(w) { } codebase( int n, int dim, const weightlist& w, const constraintlist& ac ) : n(n), dim(dim), w(w), assumed_cons(ac) { } codebase( int n, int dim, int d ) : n(n), dim(dim), w( dec(d), n ) { } codebase( ) { } TEX(![ \begin{quote} Compute the ``Griesmer sum'' $\sum_{i=0}^{\hbox{\small\tt dim}-1} \ceiling{d / 2^i}$, where $d =$ {\tt w.min( )}. \end{quote} ]!) int griesmer( ) { int sum = 0; for ( int i = 0; i < dim; i++ ) sum += int( ceil( Rational( w.min( ), Ipow(2, i) ) ) ); return sum; } friend ostream& operator<<(ostream& s, const codebase& c) { return s << "[" << c.n << "," << c.dim << "," << c.w << "]{" << c.assumed_cons << "}"; } friend bool operator==(codebase a, codebase b) { return a.n == b.n && a.dim == b.dim && a.w == b.w && a.assumed_cons == b.assumed_cons && a.opt == b.opt; } }; TEX(![ The configurations in a given code type exist in a {\tt codehome} as vertices of a {\tt ShareGraph}. Recall that edges come in two flavors: constructive and logical. Logical edges are not actually represented by {\tt ShareGraph} edges. The member {\tt implications} is a list of pairs. The first member of each pair is a {\tt Pix} referring (via {\tt configs}) to a configuration (call it $c$). The second member of the pair is a list of {\tt Pix}'es referring to a list of configurations (call them $\VEC c1r$), with the property that ${\cal R}(c) \IN {\cal R}(c_1) \manycup {\cal R}(c_r)$. \indexz{codehome} ]!) index_method(deactivate) class codehome : public codebase { public: TEX( ![ \classtextt{Data items which contain information of lasting importance} ]! ) ShareGraph configs; SLList config_lists; SLList< pair< String, String > > notes_to_config_lists; SLList< pair< Pix, SLList > > implications; DLList< pair > implications2; OSLList incorporate_labels; // used only to insure no repeats SLList< pair< Pix, Pix > > disjoint; pair< char, prevector > dc; // summarizes last "disjoint" (d) or // "classification of" command (c) SLList< pair > labels; // the Pix refers to a config in // configs Pix base; // index of base configuration bool classified; // set to true if code type gets classified // up to isomorphism bool unique; // set to true if the code type is found to // contain a unique code bool we_known; // set to true if the weight enumerator of the // codes (if any) in the realization of the code // type is uniquely determined and known TEX( ![ \classtext{Data items which are used during computations, and should get deleted when attention shifts to another code type} ]! ) Pix current; // index of current configuration config_active* active; TEX( ![ \classtextt{Constructors and destructors} ]! ) codehome(int, int, const weightlist&, codetable&, int = 0, int = 0, int = 0, const constraintlist = constraintlist( ) ); codehome(int, int, const weightlist&, const constraintlist = constraintlist( ) ); codehome( ) { } HIDE( ![ codehome(const codehome&) { INTERNAL_ERROR("You can't copy a codehome."); } ]! ) ~codehome( ) { deactivate( ); } TEX( ![ \classtextt{Methods} ]! ) weightlist& ww( Pix p ) { return configs(p).share->ww; } void set_current(Pix); // Set discussion preceeding class config. void activate(bool, codetable&, bool = false); // Ditto above comment. void deactivate( ) // Ditto above comment. { delete active; active = 0; } SLList< multiedge > convert_implications( ) const; bool show(constraintlist, codetable& results, bool = false, constraintlist = constraintlist( ), bool = false, bool = false ); SLList< matrix > list_extensions(bool, bool, codetable&); Pix merge_config(config&); void set_config(config&, codetable&, const String& = ""); void set_config(const String&, codetable&); bool contradiction(bool, codetable&, bool = false); Pix label_to_Pix(String, const codetable&, int=0); bool check_globals(const constraintlist&, const vector&, const config_core&) const; void set_unrealizable(Pix); bool isomorphic(const config&, const config&, bool = false) const; bool isomorphic(const config_core&, const config_core&, bool = false) const; bool options_satisfied(const config_core&); void basic_joint_vars(config*, codetable&); void generate_joint_constraints(codetable&, bool = false, constraintlist = constraintlist( )); void expand_jdi(String , vector&, const prevector&, Integer***); HIDE( ![ friend bool infeasible(codehome&, codetable&, bool); friend bool known_global(codehome*, config_share*, constraint); ]! ) }; set_compile_file(codehome.cc) extern char* PATH_PREFIX; HIDE( ![ #include "homedefs.h" #include #include "bitvec.h" #include "codetable.h" #include #include #include #include #include #include #include #include bool operator !=(const weightlist&, const weightlist&); extern int warnings_are_fatal; void eat_constraint(istream&); extern String homebrew_status; extern int homebrew, auto_round, use_dual_dual_for_joint, auto_analyze_local_relations, verify_feasibility, low_memory_joint_generation; int String_cmp(const String&, const String&); void execute_round_local(codehome*, codetable&); pair lp_crunch(const prevector&, int, const vconstraint&, bool = false); void add_to_rational_constraint(qvconstraint&, const vconstraint&, Rational&); bool joint_infeasible(codehome&, codetable&, constraintlist = constraintlist( )); bool sub_to_dual_radius(int, partition, matrix, int); Integer choose(int, int); void parse_j_var(String, int&, int&, int&); void analyze_local_relations(config*, codetable&); void round_div4(Integer&, Integer&, int, int, const config&, codetable&); void round_variable(String, Integer&, Integer&, int, int, const config&, codetable&); void log2( const Integer&, Integer&, Integer& ); constraintlist generate_shared_constraints(config*, codetable&); template void sort_by_seconds( prevector< pair >& ); ]! ) index_method(member) int config_list_on_disk::member(String label) { static Regex numdotdot( pos_number + "\\.\\." ); static Regex pos_number_pattern(pos_number); String title_head = title.before( numdotdot ); String label_end = label.after( title_head ); if ( !label.contains( title_head, 0 ) ) return 0; String target = label.after( title_head ); target.del( ']' ); if ( !target.matches( pos_number_pattern ) ) return 0; String first_no = title.at( numdotdot ); first_no.del( ".." ); String last_no = title.after( ".." ); last_no = take( last_no, pos_number_pattern ); if ( as_int(first_no) <= as_int(target) && as_int(target) <= as_int(last_no) ) return as_int(target) - as_int(first_no) + 1; return 0; } index_method(unpack) matrix unpack( char* v, int k, int n ) { matrix M(k, n); for ( int i = 0; i < k; i++ ) for ( int j = 0; j < n; j++ ) { int bit_no = n * i + j; int rbn = bit_no % 8; int byte_no = bit_no / 8; M(i, j) = (v[byte_no] & (1 << rbn)) != 0; } return M; } index_method(fetch) matrix matrix_list_on_disk::fetch(int r) { if ( r <= 0 || r > count ) INTERNAL_ERROR( "Illegal fetch." ); int nbytes = (n * k - 1)/8 + 1; long position = chars_to_skip_over + (r - 1) * nbytes; int fd = open( filename, O_RDONLY ); lseek( fd, position, SEEK_SET ); char buf[nbytes]; size_t actual_length = read( fd, buf, nbytes ); close( fd ); if ( actual_length != nbytes ) ERROR( "My attempt to read the file " << filename << " has failed." << " This could be because it has somehow been damaged. You" << " should probably delete it and try executing Split again." ); return unpack( buf, k, n ); } index_method(fetch_all) packed_matrix_list matrix_list_on_disk::fetch_all( ) { int nbytes = (n * k - 1)/8 + 1; int fd = open( filename, O_RDONLY ); char buf[nbytes]; OSLList< vector > l; vector vc( nbytes ); for ( int r = 1; r <= count; r++ ) { long position = chars_to_skip_over + (r - 1) * nbytes; lseek( fd, position, SEEK_SET ); size_t actual_length = read( fd, buf, nbytes ); if ( actual_length != nbytes ) ERROR( "My attempt to read the file " << filename << " has " << "failed. This could be because it has somehow been " << "damaged. You should probably delete it and try " << "executing Split again." ); for ( int i = 0; i < nbytes; i++ ) vc(i) = buf[i]; l.append( vc ); } close( fd ); return make_triple( k, n, l ); } codehome::codehome(int n, int dim, const weightlist& w, codetable& results, int dual_radius, int dual_radius_length, int dual_radius_dim, const constraintlist assumed_cons ) : codebase( n, dim, w, assumed_cons ), base(0), active(0) { current = base = configs.add( config( this, String(dec(n)) + ":{}" ) ); config_share* s = new config_share; dc = make_pair( '0', prevector(0) ); weightlist wp = w; HIDE( ![ if ( dim == 0 ) INTERNAL_ERROR("codehome constructor called with dim = 0"); ]! ) s->realizable = 0; labels.append( make_pair( String("[base]"), base ) ); classified = we_known = unique = false; forPixDef( p, results.open ) { codehome* h = results.open(p); if ( h->n == n && h->dim == dim && w <= h->w && h->assumed_cons == assumed_cons && h->opt.none_chosen( ) ) { // Merge weightlist and constraint information. But why are we // creating a new codehome at all?? wp = intersection( w, h->ww(h->base) ); s->ycon.merge( h->configs(h->base).share->ycon ); } } int d = wp.min( ); bool even = wp.divisible(2); s->ww = intersection( wp, results.possible_weights( n, dim, d, even ) ); if (dual_radius > 0) { weightlist wt; partition par(2); matrix B(1,2); B(0,0) = 1; B(0,1) = 0; forPix( p, s->ww ) { int w = s->ww(p); par(0) = w; par(1) = dual_radius_length - w; if ( w == 0 || sub_to_dual_radius( dual_radius, par, B, dual_radius_dim ) ) wt.add(w); } s->ww = wt; } if ( s->ww.length( ) == 1 ) { s->realizable = -1; s->dual_min_low = 1; s->dual_min_high = n; configs(base).share = s; return; } if ( s->ww.length( ) > 2 ) { p = s->ww.first( ); s->ww.next(p); s->ww.next(p); if ( results.not_exist( n, dim, s->ww(p) ) ) s->ycon.merge( constraint( String("y") + dec( s->ww.min( ) ) + ">=1" ) ); } s->dual_min_low = 1; for ( int j = 1; j <= n-1; j++ ) { Integer low = 0, high = -1; assumed_cons.evaluate( String("mu") + dec(j), low , high ); if ( high == 0 ) s->dual_min_low = j+1; else break; } for ( short int dp = dim + 1; dp >= 2; dp-- ) if (results.not_exist(n - dp + 1, dim - dp + 2, s->ww)) { s->dual_min_low = dp; break; } for ( int j = 1; j <= n; j++ ) if ( results.not_exist( n, n - dim, j + 1 ) ) { s->dual_min_high = j; break; } if ( s->dual_min_low == s->dual_min_high ) s->ycon.merge( constraint( String("mu") + dec(s->dual_min_low) + ">=1" ) ); for ( int j = s->dual_min_low; j <= min(2 * s->dual_min_low - 1, n); j++ ) if ( n - j > 0 && n - dim - 1 > 0 ) if (results.not_exist(n - j, n - dim - 1, s->dual_min_low - j/2)) s->ycon.merge( constraint( String("mu") + dec(j) + "=0" ) ); TEX( ![ \begin{quote} Get upper bound for dimension of a doubly even subcode. Then use Brouwer's result to bound the number of words whose weight is divisible by $4$. \end{quote} ]! ) if ( s->ww.divisible(2) && d+2 <= n && dim > 1 ) { int i, max_DE_dim = dim; String sss( dec(d+2) ); sss += "_4"; weightlist wt( sss, n ); if ( d % 4 != 0 && (results.not_exist(n, dim, wt) || results.not_exist(n-1, dim, d+1)) ) { for ( i = dim-1; i >= 1; i-- ) if ( !( results.not_exist(n, i, wt) || results.not_exist(n-1, i, d+1) ) ) break; max_DE_dim = i; } Integer DE_low = Ipow(2,dim-1) - Ipow(2, min(max_DE_dim, dim-2)); Integer DE_high = Ipow(2,dim-1) + Ipow(2, max_DE_dim - 1); s->ycon.merge( constraint( "div4>=" + String(dec(DE_low)) ) ); s->ycon.merge( constraint( "div4<=" + String(dec(DE_high)) ) ); } configs(base).share = s; } codehome::codehome(int n, int dim, const weightlist& w, const constraintlist assumed_cons ) : codebase( n, dim, w, assumed_cons ), base(0), active(0) { current = base = configs.add( config( this, String(dec(n)) + ":{}" ) ); config_share* s = new config_share; dc = make_pair( '0', prevector(0) ); s->ww = w; s->realizable = (s->ww.length( ) == 1 ? -1 : 0); labels.append( make_pair( String("[base]"), base ) ); classified = we_known = unique = false; s->dual_min_low = 1; s->dual_min_high = n; configs(base).share = s; } index_method(set_current) void codehome::set_current(Pix p) { if ( p != 0 ) ww(p) = intersection( ww(p), ww(base) ); if ( current != 0 ) deactivate( ); current = p; } index_method(convert_implications) SLList< multiedge > codehome::convert_implications( ) const { SLList< multiedge > ml; forPixDef( q, implications ) { multiedge m; const pair< Pix, SLList >& imp = implications(q); m.first = configs( imp.first ).share; forPixDef( r, imp.second ) m.second.add( configs(imp.second(r)).share ); forPixDef( p, ml ) if ( ml(p).first == m.first && ml(p).second <= m.second ) break; if ( p == 0 ) ml.append(m); } return ml; } index_method(activate) void codehome::activate(bool quiet, codetable& results, bool weak) { if ( active == 0 ) { active = new config_active(&configs(current), results, quiet, weak); if (auto_analyze_local_relations) analyze_local_relations( &configs(current), results ); } } index_method(set_unrealizable) void codehome::set_unrealizable(Pix p) { config& c = configs(p); c.share->realizable = -1; TEX( ![ \begin{quote} Clear out stuff to save memory. But we don't want to clear out so much that another command might crash if accidentally invoked on an unrealizable configuration. In particular, we don't clear out the working weight list. \end{quote} ]! ) c.share->ycon.clear( ); forPixDef( q, configs ) { if ( configs(p).share == configs(q).share ) { config& d = configs(q); d.con.clear( ); d.aut.clear( ); d.auto_labels.clear( ); } } } TEX( ![ Determine if the current configuration leads to a contradiction. ]! ) index_method(contradiction) bool codehome::contradiction(bool quiet, codetable& results, bool verify = false) { if ( configs(current).share->realizable == -1 ) return true; int verify_feasibility_save; if (verify) { verify_feasibility_save = verify_feasibility; verify_feasibility = 2; } if ( infeasible(*this, results, quiet) ) { set_unrealizable(current); if (verify) verify_feasibility = verify_feasibility_save; return true; } if (auto_round && choose(n, dim) <= Integer("3000000000000000000") ) { execute_round_local( this, results ); if ( infeasible(*this, results, quiet) ) { set_unrealizable(current); if (verify) verify_feasibility = verify_feasibility_save; return true; } } if (verify) verify_feasibility = verify_feasibility_save; return false; } TEX( ![ \verb|merge_config|:\ Merge a configuration {\tt c} into the {\tt configs} member of a {\tt codehome}. We proceed by comparing {\tt c} with each configuration {\tt d} in {\tt configs} which has the same partition, small basis, and dual small basis as {\tt c}, and for which every assumed constraint is known to {\tt c}. If the assumed constraints of {\tt d} are not the same as those of {\tt c}, we merge the known facts for {\tt d} into {\tt c}. Otherwise we merge the known facts for {\tt c} into {\tt d}. We do not merge in automorphisms. This code appears to supersede the redundancy checking of {\tt ShareGraph::add}. ]! ) index_method(merge_config) Pix codehome::merge_config(config& c) { Pix cref = 0; forPixDef( p, configs.vertices ) { config& d = configs(p); if ( mostly_equal(c, d) ) { if ( c.gen.x != 0 && d.gen.x == 0 ) continue; if ( c.gen.x == 0 && d.gen.x != 0 ) continue; if ( c.gen.x != 0 && c.gen != d.gen ) continue; forPixDef( q, d.assumed_cons ) if ( !c.known( d.assumed_cons(q) ) ) break; if ( q == 0 ) { if ( c.assumed_cons == d.assumed_cons ) { if ( cref == 0 ) { config_share* merge = *(c.share) + *(d.share); *(d.share) = *merge; delete merge; delete c.share; c.share = d.share; d.con.merge( c.con ); cref = p; } } else { if ( cref == 0 ) { config_share* merge = *(c.share) + *(d.share); *(c.share) = *merge; delete merge; c.con.merge( d.con ); } else { config_share* merge = *(configs(cref).share) + *(d.share); *(configs(cref).share) = *merge; delete merge; configs(cref).con.merge( d.con ); } } } } } if ( cref == 0 ) { p = configs.add(c); implications.append( make_pair( p, make_list(base) ) ); return p; } else return cref; } index_method(sub_to_dual_radius) TEX( ![ \verb|sub_to_dual_radius(r,p,M,k)|: Return {\tt true} if it is plausible that $M$ could be extended to a $k$-rowed matrix, the dual of whose rowspace has covering radius $\leq r$. The partition $p$ gives multiplicities for $M$'s columns. ]! ) bool sub_to_dual_radius( int r, partition p, matrix M, int k ) { if ( M.nrows > k || p.length != M.ncols ) INTERNAL_ERROR( "sub_to_dual_radius" ); Integer x = Ipow(2, k - M.nrows); int i, j, l, rad; word indx(M.nrows); do { int count = indx.if_zero( ) ? 1 : 0; if ( r == 2 ) { for ( i = 0; i < M.ncols; i++ ) { // Does column i of M equal indx? for ( l = 0; l < M.nrows; l++ ) if ( M(l,i) != indx(l) ) break; if ( l == M.nrows ) count += p(i); if ( indx.if_zero( ) ) count += (p(i) * (p(i)-1)) / 2; for ( j = i + 1; j < M.ncols; j++ ) { // Does column i + column j of M equal indx? for ( l = 0; l < M.nrows; l++ ) if ( M(l,i) + M(l,j) != indx(l) ) break; if ( l == M.nrows ) count += p(i) * p(j); } if ( count >= x ) break; } } else { config_core cc; cc.part = p; cc.smallbasis = M; matrix A = cc.basic_small( ); matrix B = transpose_of(A); for ( rad = 1; rad <= r; rad++ ) { vector bit_on(rad); for ( i = 0; i < rad; i++ ) bit_on(i) = i; gf2 dot; while(1) { word sum(A.nrows); for ( i = 0; i < bit_on.length; i++ ) sum += B( bit_on(i) ); if ( sum == indx ) count++; if ( bit_on( rad-1 ) < A.ncols - 1 ) ++bit_on( rad-1 ); else { for ( i = rad-1; i >= 0; i-- ) if ( bit_on(i) != A.ncols - rad + i ) break; if ( i == -1 ) break; j = bit_on(i) - i + 1; for ( l = i; l < rad; l++ ) bit_on(l) = j + l; } } } } if ( count < x ) return false; } while( indx.advance( ) ); return true; } index_method(basic_joint_vars) TEX( ![ \verb|basic_joint_vars|:\ Generate a list of the minimal basic joint variables, in lexicographical order, using only the weights which occur in the working weightlist for {\tt[current]}. We should (but don't) use known restrictions on the joint variables of even codes to get restrictions on the joint variables of an arbitrary code. This routine returns its answer by setting the {\tt wjv} member of {\tt share}. If the configuration is known to be unrealizable, {\tt wjv} is set to the empty list. If called a second time on the same configuration, this routine does nothing. One defect in this routine is that it does not take account of changes to the value of \verb|possible_weights| which might occur if new types had been proven nonexistent since the initial definition of the current type. Another defect is that if the working weightlist for {\tt[base]} changes after {\tt wjv} for a configuration has been computed, the {\tt wjv} for that configuration may not be recomputed. ]! ) void codehome::basic_joint_vars(config* c, codetable& results) { // Determine if there is no work to do. if ( c->share->realizable == -1 ) { c->share->wjv.set_size(0); return; } if ( c->share->wjv.length > 0 ) return; // Compute wjv for [base] if not done already. if ( configs(base).share->wjv.length == 0 ) { SLList vars; weightlist& w = configs(base).share->ww; bool de_is_subcode = w.divisible(2) && configs(base).known( String("div4=") + dec(Ipow(2,dim-2)) ); bool self_dual = configs(base).known( String("co=") + dec(Ipow(2,dim)) ); de_is_subcode = de_is_subcode || opt.doubly_even_part_is_subcode || self_dual; int i, d = w.min( ); prevector poss(2*d); for ( i = d; i < min(2*d, n); i++ ) if ( dim-1 <= n-i ) poss(i) = results.possible_weights(n-i, dim-1, d-i/2, false); SLList joints_to_zero0; static Regex basic_joint_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); forPixDef( s, c->assumed_cons ) { constraint cc = c->assumed_cons(s); if ( cc.simple( ) && cc.sense == '=' && cc.RHS == 0 && cc.LHS.front( ).var.matches(basic_joint_pattern) ) joints_to_zero0.append(cc.LHS.front( ).var); } forPix( s, c->share->ycon ) { constraint cc = c->share->ycon(s); if ( cc.simple( ) && cc.sense == '=' && cc.RHS == 0 && cc.LHS.front( ).var.matches(basic_joint_pattern) ) joints_to_zero0.append(cc.LHS.front( ).var); } prevector joints_to_zero( joints_to_zero0 ); String nstring = dec(n); char varx[ 5 + 3 * nstring.length( ) ]; // We now go to some lengths to insure that the joint variables are // generated in lexicographical order. This is to avoid a sort at // the end, which is somewhat silly, since the sort contributes little // to running time unless one has a stupendously long list of joint // variables, in which case one shouldn't generate them at all. // We proceed by putting the weightlist in two different orders. SLList< pair > w1, w2; forPixDef( p, w ) { w1.append( make_pair( w(p), String(dec(w(p))) + "y" ) ); w2.append( make_pair( w(p), String(dec(w(p))) ) ); } prevector< pair > w1v(w1), w2v(w2); sort_by_seconds(w1v); sort_by_seconds(w2v); SLList w1x, w2x; for( i = 0; i < w1v.length; i++ ) w1x.append( w1v(i).first ); for( i = 0; i < w2v.length; i++ ) w2x.append( w2v(i).first ); forPix( p, w1x ) { int i1 = w1x(p); forPixDef( q, w1x ) { int i2 = w1x(q); forPixDef( r, w2x ) { int i3 = w2x(r); if ( i1 <= i2 && i2 <= i3 && i1 + i2 + i3 <= 2*n && i1 + i3 >= i2 && i1 + i2 >= i3 && i2 + i3 >= i1 && even( i1 + i2 + i3 ) ) { if ( d <= i1 && i1 < 2*d ) { if ( !poss(i1).nonzero( (i2+i3-i1)/2 ) ) continue; } if ( d <= i2 && i2 < 2*d ) { if ( !poss(i2).nonzero( (i1+i3-i2)/2 ) ) continue; } if ( d <= i3 && i3 < 2*d ) { if ( !poss(i3).nonzero( (i1+i2-i3)/2 ) ) continue; } if (de_is_subcode) { if ( i1 % 4 == 0 && i2 % 4 == 0 && i3 % 4 != 0 ) continue; if ( i1 % 4 == 0 && i3 % 4 == 0 && i2 % 4 != 0 ) continue; if ( i2 % 4 == 0 && i3 % 4 == 0 && i1 % 4 != 0 ) continue; } if (self_dual) { if ( i1 % 4 != 0 && i2 % 4 != 0 && i3 % 4 != 0 ) continue; if ( i1 % 4 != 0 && i3 % 4 != 0 && i2 % 4 != 0 ) continue; if ( i2 % 4 != 0 && i3 % 4 != 0 && i1 % 4 != 0 ) continue; } if ( opt.dual_radius > 0 && i1 > 0 ) { int w1 = i1, w2 = i2, w3 = i3; int s = ( w1 + w2 - w3 ) / 2; partition par(4); par(0) = w1 - s; par(1) = s; par(2) = w2 - s; par(3) = opt.dual_radius_length - w1 - w2 + s; matrix B( 4, "{1100,0110}" ); if ( !sub_to_dual_radius( opt.dual_radius, par, B, opt.dual_radius_dim ) ) continue; } sprintf( varx, "jy%dy%dy%d", i1, i2, i3 ); if ( joints_to_zero.length != 0 ) { String var(varx); if ( joints_to_zero.member(var) ) continue; } vars.append( varx ); } } } } configs(base).share->wjv = vars; } // Now compute wjv for [current]. if ( c->share != configs(base).share ) { weightlist& w = c->share->ww; bool self_dual = c->known( String("co=") + dec(Ipow(2,dim)) ); bool de_is_subcode = w.divisible(2) && c->known( String("div4=") + dec(Ipow(2,dim-2)) ); de_is_subcode = de_is_subcode || opt.doubly_even_part_is_subcode || self_dual; prevector& jb = configs(base).share->wjv; SLList vars; for ( int i = 0; i < jb.length; i++ ) { int i1, i2, i3; parse_j_var( jb(i), i1, i2, i3 ); if (de_is_subcode) { if ( i1 % 4 == 0 && i2 % 4 == 0 && i3 % 4 != 0 ) continue; if ( i1 % 4 == 0 && i3 % 4 == 0 && i2 % 4 != 0 ) continue; if ( i2 % 4 == 0 && i3 % 4 == 0 && i1 % 4 != 0 ) continue; } if (self_dual) { if ( i1 % 4 != 0 && i2 % 4 != 0 && i3 % 4 != 0 ) continue; if ( i1 % 4 != 0 && i3 % 4 != 0 && i2 % 4 != 0 ) continue; if ( i2 % 4 != 0 && i3 % 4 != 0 && i1 % 4 != 0 ) continue; } if ( w.contains(i1) && w.contains(i2) && w.contains(i3) && !c->known( jb(i) + "=0" ) ) vars.append( jb(i) ); } c->share->wjv = vars; } } HIDE( ![ Integer*** make_krawtchouk(int); int take_int(String&, const Regex&); ]! ) index_method(COMBO) #define COMBO(A,I,J) ((J <= I) ? combo[A][I][J] : \ (even(A) ? combo[A][J][I] : -combo[A][J][I])) index_method(parse_j_var) void parse_j_var( String v, int& r, int& s, int& t ) { static Regex number_pattern( number_pat ); v.del("j"); v = v.after( v[0] ); r = take_int( v, number_pattern ); v = v.after( v[0] ); s = take_int( v, number_pattern ); if ( v.empty( ) ) t = 0; else { v = v.after( v[0] ); t = take_int( v, number_pattern ); } } index_method(make_j_var) String make_j_var( int i1, int i2, int i3 ) { if ( i2 > i3 ) swap( i2, i3 ); if ( i1 > i2 ) swap( i1, i2 ); if ( i2 > i3 ) swap( i2, i3 ); return String("jy") + dec(i1) + "y" + dec(i2) + "y" + dec(i3); } index_method(MULT) #define MULT(J,K,L) \ ((J != K && J != L && K != L) ? 6 : ((J == K && K == L) ? 1 : 3)) TEX( ![ \verb|joint_to_qv|:\ Convert a constraint {\tt c} involving only joint and global variables to a {\tt qvconstraint}. Upon entry {\tt vars} should be the list of joint variables defined by \verb|basic_joint_vars|, and {\tt combo} should be the Krawtchouk coefficient table made by \verb|make_krawtchouk|. ]! ) index_method(joint_to_qv) void joint_to_qv( constraint c0, qvconstraint& ex, const prevector& vars, Pix cur, codehome& home, Integer ***combo ) { ex.LHS.set_size(vars.length); if ( cur == 0 ) INTERNAL_ERROR( "joint_to_qv entered with cur = 0." ); weightlist& ww = home.configs(cur).share->ww; static Regex number_pattern( number_pat ); static Regex j_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); static Regex jd_pattern( "jd" + number_pat + "d" + number_pat + "d" + number_pat ); static Regex jdi_pattern( "jy" + number_pat + "d" + number_pat + "i" + number_pat ); static Regex jyd_pattern( "jy" + number_pat + "d" + number_pat ); int i, j, k, l, r, s, t; TEX( ![ \begin{quote} First expand {\tt co} variables. \end{quote} ]! ) constraint c( c0.sense, c0.RHS ); forPixDef( p, c0.LHS ) { if ( c0.LHS(p).var[0] != 'c' ) c.LHS.append( c0.LHS(p) ); else { String v = c0.LHS(p).var; if ( v == "co" ) { forPixDef( q, ww ) { String var2 = String("jy") + dec(ww(q)) + "d" + dec(ww(q)) + "i" + dec(ww(q)); c.addterm( c0.LHS(p).coeff, var2 ); } } else { v = v.after( "co" ); c.addterm( c0.LHS(p).coeff, "jy" + v + "d" + v + "i" + v); } } } Integer total = Ipow( 2, home.dim ), total_squared = total * total; config_core core( home.configs(cur) ); c.LHS = core.simplify_global_vars(c.LHS, home.ww(cur), home.dim); ex.LHS.set_zero( ); ex.set( c.sense, c.RHS ); forPixDef( qq, c.LHS ) { term te = c.LHS(qq); if ( te.var[0] == 'y' ) { r = yno( te.var ); i = vars.find(String("jy0y") + dec(r) + "y" + dec(r)); if ( i >= 0 ) ex.LHS(i) += te.coeff; } else if ( te.var.matches( j_pattern ) ) { parse_j_var( te.var, r, s, t ); if ( s > t ) swap( s, t ); if ( r > s ) swap( r, s ); if ( s > t ) swap( s, t ); i = vars.find( String("jy") + dec(r) + "y" + dec(s) + "y" + dec(t) ); if ( i >= 0 ) ex.LHS(i) += te.coeff; } else if ( te.var.matches(jdi_pattern) || te.var.matches(jyd_pattern) ) { parse_j_var( te.var, r, s, t ); int ii = home.n - (r + s - t); int jj = s - t, kk = r - t, ll = t; for ( int m = 0; m < vars.length; m++ ) { parse_j_var( vars(m), r, s, t ); i = home.n - (r+s+t)/2; j = (s+t-r)/2; k = (r+t-s)/2; l = (r+s-t)/2; // If 2 of j,k,l are equal, insure that the first two are. if ( j == l ) swap(k, l); if ( k == l ) swap(j, l); for ( int h = 0; h < MULT(j,k,l); h++ ) { if ( jj <= i + j && ll <= k + l && kk == k+l-ll ) ex.LHS(m) += te.coeff * Rational( COMBO(jj,i,j) * COMBO(ll,k,l), total ); if ( even(h) ) swap( k, l ); else swap( j, k ); } } } else if ( te.var.matches( jd_pattern ) ) { TEX( ![ \begin{quoteb} Use the formula\\ $\displaystyle{\cal J}_{C^\perp,C^\perp}(a,b,c,d) = {1\over\abs{C}^2}{\cal J}_{C,C}( (a+c)+(b+d), (a+c)-(b+d), (a-c)+(b-d), (a-c)-(b-d) ).$ \end{quoteb} ]! ) parse_j_var( te.var, r, s, t ); if ( (r + s + t) % 2 != 0 ) continue; int ii = home.n - (r+s+t)/2; int jj = (s+t-r)/2, kk = (r+t-s)/2, ll = (r+s-t)/2; if ( ii < 0 || jj < 0 || kk < 0 || ll < 0 ) continue; for ( int m = 0; m < vars.length; m++ ) { parse_j_var( vars(m), r, s, t ); i = home.n - (r+s+t)/2; j = (s+t-r)/2; k = (r+t-s)/2; l = (r+s-t)/2; // If 2 of j,k,l are equal, insure that the first two are. if ( j == l ) swap(k, l); if ( k == l ) swap(j, l); for ( int h = 0; h < MULT(j,k,l); h++ ) { for ( int a = max(0, home.n - ii - kk - k - l); a <= min(i+j, home.n - ii - kk); a++ ) { int b = home.n - a - ii - kk; ex.LHS(m) += te.coeff * Rational( COMBO(a, i, j) * COMBO(b, k, l) * COMBO(kk, i+j-a, k+l-b) * COMBO(ll, a, b), total_squared ); } if ( even(h) ) swap( k, l ); else swap( j, k ); } } } else if ( te.var == "jdiv2" ) { for ( int m = 0; m < vars.length; m++ ) { parse_j_var( vars(m), r, s, t ); int ds = 0; if ( r % 2 != 0 || s % 2 != 0 || t % 2 != 0 ) continue; j = (s+t-r)/2; if ( j % 2 != 0 ) continue; ex.LHS(m) += te.coeff * Rational(MULT(r,s,t)); } } else if ( te.var == "jdiv4" ) { for ( int m = 0; m < vars.length; m++ ) { parse_j_var( vars(m), r, s, t ); int ds = 0; if ( r % 4 != 0 || s % 4 != 0 || t % 4 != 0 ) continue; ex.LHS(m) += te.coeff * Rational(MULT(r,s,t)); } } else INTERNAL_ERROR("Unrecognized variable \"" << te.var << "\" in joint_to_qv."); } } TEX( ![ \verb|output_joint_constraint|:\ Convert a constraint {\tt c} involving joint and global variables to a constraint involving {\tt v} variables, and output it to the given stream. Upon entry {\tt vars} should be the list of joint variables defined by \verb|basic_joint_vars|, and {\tt combo} should be the Krawtchouk coefficient table made by \verb|make_krawtchouk|. ]! ) index_method(output_joint_constraint) int output_joint_constraint( constraint c, const prevector& vars, ostream& out, codehome& home, Integer ***combo ) { qvconstraint qv; vconstraint vc(vars.length); joint_to_qv( c, qv, vars, home.current, home, combo ); if ( clear_denom( qv, vc ) != Rational(0) ) { if ( vc.LHS.if_zero( ) && test( Integer(0), vc.RHS, vc.sense ) ) return 0; out << vc; return 1; } return 0; } index_method(make_j_var_x) String make_j_var_x( int i1, int i2, int i3 ) { return String("jy") + dec(i1) + "y" + dec(i2) + "y" + dec(i3); } index_method(expand_joint_variable_list) prevector expand_joint_variable_list( prevector vars ) { SLList nvars; for ( int i = 0; i < vars.length; i++ ) { nvars.append( vars(i) ); int i1, i2, i3; parse_j_var( vars(i), i1, i2, i3 ); if ( i1 == i2 && i2 != i3 ) { nvars.append( make_j_var_x(i3,i1,i2) ); nvars.append( make_j_var_x(i1,i3,i2) ); } else if ( i1 == i3 && i1 != i2 ) { nvars.append( make_j_var_x(i2,i1,i3) ); nvars.append( make_j_var_x(i1,i3,i2) ); } else if ( i2 == i3 && i1 != i2 ) { nvars.append( make_j_var_x(i2,i3,i1) ); nvars.append( make_j_var_x(i2,i1,i3) ); } else if ( i1 != i2 ) { nvars.append( make_j_var_x(i2,i3,i1) ); nvars.append( make_j_var_x(i2,i1,i3) ); nvars.append( make_j_var_x(i1,i3,i2) ); nvars.append( make_j_var_x(i3,i1,i2) ); nvars.append( make_j_var_x(i3,i2,i1) ); } } return nvars; } index_method(generate_joint_constraints) TEX( ![ \verb|generate_joint_constraints|:\ The joint weight enumerator identity $${\cal J}_{C,C^\perp}(a,b,c,d) = {1\over\abs{C}}{\cal J}_{C,C} (a+b,a-b,c+d,c-d)$$% (see [.macwilliams sloane book.]\ p.\ 148) implies certain linear inequalities involving the minimal basic joint variables. Generate the corresponding constraints (in terms of {\tt v} variables), and write them to the file \verb|joint_in|. In this preliminary version, we generate one constraint for each monomial $a^i b^j c^k d^l$, thus in total $(n+1)^4$ of them! ]! ) void codehome::generate_joint_constraints(codetable& results, bool nofold, constraintlist forced) { config& c = configs(current); basic_joint_vars(&c, results); prevector vars = c.share->wjv; ofstream vardef( calculations_dir + "/joint_variable_definitions" ); for ( int i = 0; i < vars.length; i++ ) vardef << "v" << dec(i+1) << " = " << vars(i) << "\n"; vardef.close( ); if ( vars.length == 0 ) INTERNAL_ERROR( "I'm generating a list of joint constraints " << "for an unrealizable configuration." ); int constraint_count = 0, i, j, k, l, m, r, s, t; static Regex number_pattern(number_pat); Integer ***combo = make_krawtchouk(n); int multiplicity[ vars.length ]; weightlist& ww = c.share->ww; int dl = c.share->dual_min_low; static codehome *last_home(0); static Pix last_current; static int last_vars_length; static weightlist last_ww; static int last_dl; static int last_use_dual_dual_for_joint; bool same_as_last_time = ( this == last_home && current == last_current && vars.length == last_vars_length && ww == last_ww && dl == last_dl && use_dual_dual_for_joint == last_use_dual_dual_for_joint ); if ( !same_as_last_time ) cerr << "[setting up linear program with " << vars.length << " variables and "; last_home = this; last_current = current; last_vars_length = vars.length; last_ww = ww; last_dl = dl; last_use_dual_dual_for_joint = use_dual_dual_for_joint; static int last_main_constraint_count; if (!homebrew) { system( "echo maximize 0 > " + calculations_dir + "/joint_in" ); system( "echo subject to >> " + calculations_dir + "/joint_in" ); } else remove( calculations_dir + "/joint_in" ); if ( !same_as_last_time ) { String pipe_command0; if (nofold) pipe_command0 = "sort -u -T calculations/tmp > " + calculations_dir + "/joint_in0"; else pipe_command0 = "sort -u -T calculations/tmp | fold -s > " + calculations_dir + "/joint_in0"; procbuf joint_inp0( pipe_command0, ios::out ); ostream joint_in0( &joint_inp0 ); // Note lack of indentation. if (!low_memory_joint_generation) { prevector vc[n+1]; for ( int J = 0; J <= n; J++ ) { for ( k = 0; k <= n-J; k++ ) { vc[k].set_size(n-J-k+1); for ( l = 0; l <= n-J-k; l++ ) { vc[k](l).LHS.set_size(vars.length); for ( m = 0; m < vars.length; m++ ) vc[k](l).LHS(m) = 0; vc[k](l).sense = (ww.contains(k+l) && even(l) && (J+l == 0 || J+l >= dl)) ? '>' : '='; vc[k](l).RHS = 0; } } for ( m = 0; m < vars.length; m++ ) { TEX( ![ \begin{quoteb} Put $v$ in the form $a^i b^j c^k d^l$, as in the joint weight enumerator. \end{quoteb} ]! ) parse_j_var( vars(m), r, s, t ); i = n - (r+s+t)/2; j = (s+t-r)/2; k = (r+t-s)/2; l = (r+s-t)/2; // If 2 of j,k,l are equal, insure that the first two are. if ( j == l ) swap(k, l); if ( k == l ) swap(j, l); multiplicity[m] = MULT(j,k,l); for ( int h = 0; h < multiplicity[m]; h++ ) { if ( J <= i + j ) for ( int k1 = 0; k1 <= k+l; k1++ ) vc[k+l-k1](k1).LHS(m) += ((j <= i) ? combo[J][i][j] : (even(J) ? combo[J][j][i] : -combo[J][j][i])) * ((l <= k) ? combo[k1][k][l] : (even(k1) ? combo[k1][l][k] : -combo[k1][l][k])); if ( even(h) ) swap( k, l ); else swap( j, k ); } } for ( k = 0; k <= n-J; k++ ) for ( l = 0; l <= n-J-k; l++ ) { vconstraint& vcx = vc[k](l); if ( !vcx.LHS.if_zero( ) ) { vcx.reduce( ); joint_in0 << vcx; constraint_count++; } } } } // Note lack of indentation. if (low_memory_joint_generation) { prevector vc; for ( int J = 0; J <= n; J++ ) { for ( int kk = 0; kk <= n-J; kk++ ) { vc.set_size(n-J-kk+1); for ( l = 0; l <= n-J-kk; l++ ) { vc(l).LHS.set_size(vars.length); for ( m = 0; m < vars.length; m++ ) vc(l).LHS(m) = 0; vc(l).sense = (ww.contains(kk+l) && even(l) && (J+l == 0 || J+l >= dl)) ? '>' : '='; vc(l).RHS = 0; } for ( m = 0; m < vars.length; m++ ) { TEX( ![ \begin{quotec} Put $v$ in the form $a^i b^j c^k d^l$, as in the joint weight enumerator. \end{quotec} ]! ) parse_j_var( vars(m), r, s, t ); i = n - (r+s+t)/2; j = (s+t-r)/2; k = (r+t-s)/2; l = (r+s-t)/2; // If 2 of j,k,l are equal, insure that the first two are. if ( j == l ) swap(k, l); if ( k == l ) swap(j, l); multiplicity[m] = MULT(j,k,l); for ( int h = 0; h < multiplicity[m]; h++ ) { if ( J <= i + j ) { int k1 = k + l - kk; if ( k1 >= 0 && k1 <= k+l ) vc(k1).LHS(m) += ((j <= i) ? combo[J][i][j] : (even(J) ? combo[J][j][i] : -combo[J][j][i])) * ((l <= k) ? combo[k1][k][l] : (even(k1) ? combo[k1][l][k] : -combo[k1][l][k])); } if ( even(h) ) swap( k, l ); else swap( j, k ); } } for ( l = 0; l <= n-J-kk; l++ ) { vconstraint& vcx = vc(l); if ( !vcx.LHS.if_zero( ) ) { vcx.reduce( ); joint_in0 << vcx; constraint_count++; } } } } } vconstraint ex(m); for ( i = 0; i < vars.length; i++ ) ex.LHS(i) = (i == 0) ? 1 : 0; ex.set( '=', 1 ); joint_in0 << ex; constraint_count++; TEX( ![ \begin{quote} Create a constraint corresponding to the fact that $\displaystyle{\sum_{r,s,t} \verb|jy|r\verb|y|s\verb|y|t = \abs{C}^2}$. \end{quote} ]! ) for ( i = 0; i < vars.length; i++ ) ex.LHS(i) = multiplicity[i]; ex.set( '=', Ipow(2, 2*dim) ); joint_in0 << ex; constraint_count++; TEX( ![ \begin{quote} Create a constraint corresponding to the fact that $\displaystyle{\sum_r \verb|jy|0\verb|y|r\verb|y|r = \abs{C}}$. \end{quote} ]! ) ex.LHS.set_zero( ); forPixDef( q, ww ) { r = ww(q); i = vars.find( String("jy0y") + dec(r) + "y" + dec(r) ); if ( i != -1 ) ex.LHS(i) = 1; } ex.set( '=', Ipow(2, dim) ); joint_in0 << ex; constraint_count++; TEX( ![ \begin{quote} Adjoin lower bounds coming from existence of words in small code. \end{quote} ]! ) vector we = c.smallcode_we( ); for ( i = 1; i <= n; i++ ) if ( we(i) > 0 ) constraint_count += output_joint_constraint( constraint( String("y") + dec(i) + ">=" + dec(we(i)) ), vars, joint_in0, *this, combo ); TEX( ![ \begin{quote} Adjoin constraints arising from the fact that the coefficients of the joint weight enumerator of $C^\perp$ with itself are nonnegative. \end{quote} ]! ) if (use_dual_dual_for_joint > 0) { for ( i = dl; i <= min(n, use_dual_dual_for_joint+dl); i++ ) for ( j = i; j <= min(n, use_dual_dual_for_joint+dl); j++ ) for ( k = j; k <= min(n, use_dual_dual_for_joint+dl); k++ ) { if ( i <= j+k && j <= i+k && k <= i+j && i+j+k <= 2*n ) { constraint_count += output_joint_constraint( constraint( String("jd") + dec(i) + "d" + dec(j) + "d" + dec(k) + ">=0" ), vars, joint_in0, *this, combo ); } } } TEX( ![ \begin{quote} Create constraints corresponding to the fact that for each $r$, $$\sum_{s,t} \verb|jy|r\verb|y|s\verb|y|t = \abs{C} \cdot \verb|jy|r\verb|y|r\verb|y|0.$$ \end{quote} ]! ) ex.set( '=', 0 ); forPix( q, ww ) { r = ww(q); ex.LHS.set_zero( ); i = vars.find( String("jy0y") + dec(r) + "y" + dec(r) ); if ( i == -1 ) continue; ex.LHS(i) -= Ipow(2, dim); for ( i = 0; i < vars.length; i++ ) { String v = vars(i).after("jy"); int rp = take_int( v, number_pattern ); v = v.after("y"); int sp = take_int( v, number_pattern ); v = v.after("y"); int tp = take_int( v, number_pattern ); if ( r != rp && r != sp && r != tp ); else if ( r == rp && r == sp && r == tp ) ex.LHS(i) += 1; else if ( (r == rp && r == sp) || (r == sp && r == tp) ) ex.LHS(i) += 2; else if ( multiplicity[i] == 6 ) ex.LHS(i) += 2; else if ( multiplicity[i] == 3 ) ex.LHS(i) += 1; } joint_in0 << ex; constraint_count++; } joint_inp0.close( ); last_main_constraint_count = constraint_count; } else constraint_count += last_main_constraint_count; system( "cat " + calculations_dir + "/joint_in0 >> " + calculations_dir + "/joint_in" ); String pipe_command; if (nofold) pipe_command = "sort -u -T calculations/tmp >> " + calculations_dir + "/joint_in"; else pipe_command = "sort -u -T calculations/tmp | fold -s >> " + calculations_dir + "/joint_in"; procbuf joint_inp( pipe_command, ios::out ); ostream joint_in( &joint_inp ); TEX( ![ \begin{quote} Generate constraints coming from weight restrictions on the subcode disjoint from a dual word of weight \verb|dl|. \end{quote} ]! ) weightlist dw = results.possible_weights(n-dl, dim-dl+1, ww.min( ), ww.divisible(2)); weightlist dwc = diff(ww, dw); forPixDef(q, dwc) { if ( dwc(q) <= n-dl ) constraint_count += output_joint_constraint( constraint( String("jy") + dec(dwc(q)) + "d" + dec(dl) + "=0" ), vars, joint_in, *this, combo ); } TEX( ![ \begin{quote} Adjoin ``linearized quadratic'' constraints coming from the quadratic constraints $$\sum_t \verb|jy|r\verb|y|s\verb|y|t = \verb|y|r \cdot \verb|y|s$$% by replacing $\verb|y|r$ by known bounds on it and converting to an inequality. \end{quote} ]! ) forPixDef( p1, ww ) { forPixDef( p2, ww ) { Integer low = 0, high = -1; c.evaluate(String("y") + dec(ww(p1)), low, high); forced.evaluate(String("y") + dec(ww(p1)), low, high); constraint cc1, cc2; forPixDef( p3, ww ) cc1.addterm( 1, String("jy") + dec(ww(p1)) + "y" + dec(ww(p2)) + "y" + dec(ww(p3)) ); cc1.RHS = 0; cc2 = cc1; if ( low != 0 ) { cc1.addterm( -low, String("y") + dec(ww(p2)) ); cc1.sense = '>'; constraint_count += output_joint_constraint( cc1, vars, joint_in, *this, combo ); } if ( high != -1 ) { cc2.addterm( -high, String("y") + dec(ww(p2)) ); cc2.sense = '<'; constraint_count += output_joint_constraint( cc2, vars, joint_in, *this, combo ); } } } TEX( ![ \begin{quote} ym * div4 \end{quote} ]! ) k = dim; if ( ww.divisible(2) ) { Integer dlow = 0, dhigh = -1; c.evaluate( "div4", dlow, dhigh ); round_div4( dlow, dhigh, n, k, c, results ); prevector varsplus = expand_joint_variable_list(vars); forPixDef( p, ww ) { int m = ww(p); if ( m % 4 != 0 ) continue; term_sum LHS; for ( i = 0; i < varsplus.length; i++ ) { int i1, i2, i3; parse_j_var( varsplus(i), i1, i2, i3 ); if ( i1 == m && i2 % 4 == 0 ) LHS.append( term( 1, varsplus(i) ) ); } Integer ylow = 0, yhigh = -1; c.evaluate( String("y") + dec(m), ylow, yhigh ); if ( dlow == dhigh ) { constraint con; con.LHS = LHS; con.addterm( -dlow, String("y") + dec(m) ); con.sense = '='; con.RHS = 0; constraint_count += output_joint_constraint( con, vars, joint_in, *this, combo ); } else if ( ylow == yhigh ) { constraint con; con.LHS = LHS; con.addterm( -ylow, String("div4") ); con.sense = '='; con.RHS = 0; constraint_count += output_joint_constraint( con, vars, joint_in, *this, combo ); } else { constraint con1, con2, con3, con4; con1.LHS = LHS; con1.addterm( -ylow, "div4" ); con1.sense = '>'; con1.RHS = 0; constraint_count += output_joint_constraint( con1, vars, joint_in, *this, combo ); con2.LHS = LHS; con2.addterm( -yhigh, "div4" ); con2.sense = '<'; con2.RHS = 0; constraint_count += output_joint_constraint( con2, vars, joint_in, *this, combo ); con3.LHS = LHS; con3.addterm( -dlow, String("y") + dec(m) ); con3.sense = '>'; con3.RHS = 0; constraint_count += output_joint_constraint( con3, vars, joint_in, *this, combo ); con4.LHS = LHS; con4.addterm( -dhigh, String("y") + dec(m) ); con4.sense = '<'; con4.RHS = 0; constraint_count += output_joint_constraint( con4, vars, joint_in, *this, combo ); } } } TEX( ![ \begin{quote} If the code is even and $\verb|div4| != 2^{k-1}$, it follows that $\verb|co|m = 0$ for all $m$ which are not divisible by $4$. Also there are bounds on {\tt co} induced by the bounds on {\tt div4}, and there is an expression for \verb|jdiv2|. \end{quote} ]! ) if ( ww.divisible(2) ) { Integer dlow = 0, dhigh = -1, clow = 1, chigh = -1; c.evaluate( "div4", dlow, dhigh ); c.evaluate( "co", clow, chigh ); round_div4( dlow, dhigh, n, k, c, results ); if ( dlow > Ipow(2, k-1) || dhigh < Ipow(2, k-1) ) { forPixDef( p, ww ) { int m = ww(p); if ( m % 4 == 0 ) continue; constraint con; con.addterm( 1, String("co") + dec(ww(p)) ); con.sense = '='; con.RHS = 0; constraint_count += output_joint_constraint( con, vars, joint_in, *this, combo ); } Integer div4x = abs( dlow - Ipow(2,k-1) ); Integer div4y = abs( dhigh - Ipow(2,k-1) ); Integer xl, xh, yl, yh; log2( div4x, xl, xh ); // xl should equal xh log2( div4y, yl, yh ); // yl should equal yh long lxl = xl, lyl = yl; Integer co1 = Ipow( 2, 2 * (lxl + 1) - k ); Integer co2 = Ipow( 2, 2 * (lyl + 1) - k ); if ( co2 < co1 ) swap( co1, co2 ); clow = max( clow, co1 ); chigh = min( chigh, co2 ); } round_variable( "co", clow, chigh, n, k, c, results ); if ( clow == chigh ) { constraint con; con.addterm( 1, String("co") ); con.sense = '='; con.RHS = clow; constraint_count += output_joint_constraint( con, vars, joint_in, *this, combo ); } else { constraint con1, con2; con1.addterm( 1, String("co") ); con1.sense = '>'; con1.RHS = clow; constraint_count += output_joint_constraint( con1, vars, joint_in, *this, combo ); con2.addterm( 1, String("co") ); con2.sense = '<'; con2.RHS = chigh; constraint_count += output_joint_constraint( con2, vars, joint_in, *this, combo ); } constraint jd; jd.addterm( 1, "jdiv2" ); jd.addterm( -Ipow(2, k-1), "co" ); jd.sense = '='; jd.RHS = Ipow(2, 2*k - 1); constraint_count += output_joint_constraint( jd, vars, joint_in, *this, combo ); } TEX( ![ \begin{quote} Adjoin extra constraints if the code is even. For each $m$ which is nonzero and divisible by $4$, one has the quadratic constraint: $$\sum_{4|i,j} \verb|jy|_m\verb|y|_i\verb|y|_j = (\verb|div4| - 2^{k-2}) \verb|y|_m + 2^{k-2}\verb|co|_m.$$% We linearize this. \end{quote} ]! ) if ( ww.divisible(2) ) { Integer dlow = 0, dhigh = -1; c.evaluate( "div4", dlow, dhigh ); prevector varsplus = expand_joint_variable_list(vars); forPixDef( p, ww ) { int m = ww(p); if ( m == 0 || m % 4 != 0 ) continue; term_sum LHS; for ( i = 0; i < varsplus.length; i++ ) { int i1, i2, i3; parse_j_var( varsplus(i), i1, i2, i3 ); if ( i1 == m && i2 % 4 == 0 && i3 % 4 == 0 ) LHS.append( term( 1, varsplus(i) ) ); } LHS.append( term( -Ipow(2, k-2), String("co") + dec(m) ) ); Integer ylow = 0, yhigh = -1; c.evaluate( String("y") + dec(m), ylow, yhigh ); if ( dlow == dhigh ) { constraint con; con.LHS = LHS; con.addterm( -(dlow - Ipow(2,k-2)), String("y") + dec(m) ); con.sense = '='; con.RHS = 0; constraint_count += output_joint_constraint( con, vars, joint_in, *this, combo ); } else if ( ylow == yhigh ) { constraint con; con.LHS = LHS; con.addterm( -ylow, "div4" ); con.sense = '='; con.RHS = -Ipow(2, k-2) * ylow; constraint_count += output_joint_constraint( con, vars, joint_in, *this, combo ); } else { constraint con1, con2, con3, con4; con1.LHS = LHS; con1.addterm( -ylow, "div4" ); con1.sense = '>'; con1.RHS = -Ipow(2, k-2) * ylow; constraint_count += output_joint_constraint( con1, vars, joint_in, *this, combo ); con2.LHS = LHS; con2.addterm( -yhigh, "div4" ); con2.sense = '<'; con2.RHS = -Ipow(2, k-2) * yhigh; constraint_count += output_joint_constraint( con2, vars, joint_in, *this, combo ); con3.LHS = LHS; con3.addterm( -(dlow - Ipow(2,k-2)), String("y") + dec(m) ); con3.sense = '>'; con3.RHS = 0; constraint_count += output_joint_constraint( con3, vars, joint_in, *this, combo ); con4.LHS = LHS; con4.addterm(-(dhigh - Ipow(2,k-2)), String("y") + dec(m)); con4.sense = '<'; con4.RHS = 0; constraint_count += output_joint_constraint( con4, vars, joint_in, *this, combo ); } } } TEX( ![ \begin{quote} Adjoin constraints coming from constraints on the weight enumerators of residual codes. \end{quote} ]! ) prevector varsplus = expand_joint_variable_list(vars); int d = ww.min( ); forPixDef( p, ww ) { int m = ww(p); if ( m >= d && m < 2*d ) { int nr = n - m; int kr = dim - 1; int dr = d - m/2; // Compute possible weights for residual code. weightlist wr; for ( i = 0; i < varsplus.length; i++ ) { int i1, i2, i3; parse_j_var( varsplus(i), i1, i2, i3 ); if ( i1 == m ) wr.add( i2 - (i1 + i2 - i3)/2 ); } forPix( q, results.olabels ) { String hlabel = results.olabels(q).first; codehome* h = results.open(results.olabels(q).second); if ( h->n != nr || h->dim != kr ) continue; if ( !h->assumed_cons.empty( ) || !h->opt.none_chosen( ) ) continue; if ( !h->assumed_cons.empty( ) ) { int low = c.share->dual_min_low; forPixDef( pp, h->assumed_cons ) { constraint co = h->assumed_cons(pp); if ( !co.simple( ) ) break; if ( co.RHS != 0 || co.sense != '=' ) break; String var = co.LHS.front( ).var; static Regex mu_pat( "mu" + pos_number ); if ( var.matches(mu_pat) ) { if( as_int( var.after("mu") ) >= low ) break; } else break; } if ( pp != 0 ) continue; } if ( wr <= h->ww(h->base) ) { constraintlist& rc = h->configs(h->base).share->ycon; config_core cc( h->configs(h->base) ); forPixDef( xx, rc ) { if ( rc(xx).global( ) ) { term_sum t = cc.simplify_global_vars( rc(xx).LHS, h->ww(h->base), h->dim ); constraint con; forPixDef( yy, t ) { int nt = yno( t(yy).var ); for ( i = 0; i < varsplus.length; i++ ) { int i1, i2, i3; parse_j_var(varsplus(i), i1, i2, i3); if ( i1 == m && i2 - (i1 + i2 - i3)/2 == nt ) con.addterm( t(yy).coeff, varsplus(i) ); } } con.addterm( -2 * rc(xx).RHS, make_j_var(0, m, m) ); con.sense = rc(xx).sense; con.RHS = 0; constraint_count += output_joint_constraint( con, vars, joint_in, *this, combo ); } } } } } } TEX( ![ \begin{quote} Adjoin shared constraints and known joint constraints. \end{quote} ]! ) constraintlist aux = c.known_cons( ); aux.merge(forced); constraintlist shared = generate_shared_constraints( &c, results ); aux.merge(shared); forPix( q, aux ) { if ( c.part.length == 1 ) { forPixDef( qq, aux(q).LHS ) { String& av = aux(q).LHS(qq).var; if ( av[0] == 'x' ) av = String("y") + dec(yno(av)); } } if ( aux(q).joint( ) ) constraint_count += output_joint_constraint( aux(q), vars, joint_in, *this, combo ); } joint_inp.close( ); if ( !same_as_last_time ) cerr << constraint_count << " constraints]\n"; } TEX( Before calling \verb|set_config|, the {\tt share} member of {\tt c} should be initialized. This routine may delete the {\tt share} member of {\tt c}. ) index_method(set_config) void codehome::set_config(config& c, codetable& results, const String& label) { if ( label != "" ) { forPixDef( j, labels ) if ( labels(j).first == label && !(c == configs(labels(j).second)) ) ERROR("If a configuration label is reused, the " << "two configurations must be identical." ); } Pix i = merge_config(c); set_current(i); if ( configs(i).share->wjv.length > 0 ) basic_joint_vars( &configs(i), results ); if ( label != "" ) labels.append( make_pair(label, i) ); } void codehome::set_config(const String& s, codetable& results) { config c = config(this, s); set_config(c, results); } // label_to_Pix: the argument "request" can be // 0: don't allow failure, use config_lists [default] // 1: allow failure, use config_lists // 2: allow failure, don't use config_lists index_method(label_to_Pix) Pix codehome::label_to_Pix(String label, const codetable& results, int request = 0) { if ( label == "[current]" ) { if ( current == 0 ) { if ( request != 0 ) return 0; ERROR("The current configuration is undefined."); } return current; } // Check for known configuration. forPixDef( i, labels ) if ( labels(i).first == label ) return labels(i).second; // Check for colon syntax. static Regex alpha_pat( "[a-zA-Z_0-9]+" ); if_match( label, "\\[[a-zA-Z_0-9]+:.*\\]" ) { String new_config_name = label; String labelx = label.after("["); String codehome_name = "[" + take(labelx, alpha_pat) + "]"; String config_name = labelx.after(":"); if ( config_name[ config_name.length( ) - 1 ] = ']' ) { config_name = "[" + config_name; forPixDef( p, results.olabels ) { if ( codehome_name == results.olabels(p).first ) { codehome* h = results.open(results.olabels(p).second); if ( h->n != n ) ERROR("Code length descrepancy."); forPix( i, h->labels ) if ( h->labels(i).first == config_name ) break; if ( i != 0 ) { config c; config& d = h->configs(h->labels(i).second); c.home = this; c.part = d.part; c.small = d.small; c.dualsmall = d.dualsmall; c.assumed_cons = d.assumed_cons; c.leading1s = d.leading1s; c.share = new config_share; *(c.share) = *(configs(base).share); Pix q = configs.add(c); labels.append( make_pair(new_config_name, q) ); return q; } } } } } if ( request == 2 ) return 0; forPix( i, config_lists ) { int r = config_lists(i).member(label); if ( r != 0 ) { matrix M = config_lists(i).fetch(r); matrix M_red = M; M_red.reduce_nz( ); config c = config( this, "1" + replicate(",1", n - 1) + ":" + String(M_red) ); forPixDef( j, labels ) if ( labels(j).first == label && !(c == configs(labels(j).second)) ) ERROR("If a configuration label is reused, the " << "two configurations must be identical." ); Pix ii = merge_config(c); labels.append( make_pair(label, ii) ); configs(ii).title = config_lists(i).descrip + String(" (#") + dec(r) + ")"; c.gen = M; c.share->realizable = 1; configs(base).share->realizable = 1; return ii; } } if ( request > 0 ) return 0; ERROR("Configuration label " << label << " is unknown."); } TEX(![ {\tt check(c, y)}: Given a constraint {\tt c} involving only global variables, determine if it holds when {\tt y[i]} is substituted in for the variable {\tt yi}, for each {\tt i}. It is assumed that after this substitution, the \LHS\ of the constraint will be an integer. There is some funny stuff in the code. The case where {\tt c} involves only basic global variables is treated differently to avoid the need for a \verb|config_share| object in that case. ]!) HIDE( ![ inline bool test(const Rational& a, const Rational& b, char sense) { if ( sense == '=' ) return a == b; if ( sense == '<' ) return a <= b; return a >= b; } ]! ) index_method(check) bool check(const constraint& c, const vector& y, const config_core& cc, int dim, const weightlist& w) { Rational LHS = 0; forPixDef( q, c.LHS ) if ( c.LHS(q).var[0] != 'y' ) break; term_sum ts = (q == 0) ? c.LHS : cc.simplify_global_vars(c.LHS, w, dim); forPix( q, ts ) { String& v = ts(q).var; LHS += ts(q).coeff * Rational( y( yno(v) ) ); } return test( LHS, c.RHS, c.sense ); } index_method(check_globals) bool codehome::check_globals(const constraintlist& l, const vector& y, const config_core& cc) const { weightlist w; w.add(0); for ( int i = 0; i < y.length; i++ ) if ( y(i) != 0 ) w.add(i); forPixDef( p, l ) if ( l(p).global( ) && !check( l(p), y, cc, dim, w ) ) return false; return true; } HIDE(![ SLList process_cplex_report(String, int&); ]! ) TEX(![ {\tt show}:\ Assuming that each of the constraints in the list {\tt forced} holds, attempt to show by split linear programming that each of the constraints in {\tt con} holds. Note that it is generally faster to simultaneously show that a bunch of constraints hold. This is because a lot of time gets spent just finding a feasible point, and if you show that the constraints hold simultaneously, you only have to find the feasible point once. However, if one uses the {\tt homebrew} option, as currently implemented, this advantage will not be exploited. To make more sense out of what's done here, it may be helpful to look at the comments attached to the code for {\tt infeasible}. ]!) index_method(show) bool codehome::show(constraintlist con0, codetable& results, bool quiet, constraintlist forced, bool joint, bool allow_stupid_show) { if ( configs(base).share->realizable == -1 ) ERROR( "You're trying to do a show on an unrealizable code type." ); if (joint) { if (!con0.joint( ) ) { cerr << "Attempt to use joint linear programming " << "to prove a constraint involving local variables\n."; return false; } constraint c, cneg; forPixDef( i, con0 ) { c = con0(i); c.clear_denominators( ); if ( c.sense == '>' || c.sense == '=' ) { cneg = c; cneg.sense = '<'; --cneg.RHS; forPixDef( p, cneg.LHS ) if ( cneg.LHS(p).coeff < Rational(0) ) break; if ( !(p == 0 && cneg.RHS < 0) ) { constraintlist forcedplus = forced; forcedplus.append(cneg); if ( !joint_infeasible( *this, results, forcedplus ) ) return false; } } if ( c.sense == '<' || c.sense == '=' ) { cneg = c; cneg.sense = '>'; ++cneg.RHS; forPixDef( p, cneg.LHS ) if ( cneg.LHS(p).coeff > Rational(0) ) break; if ( p == 0 && cneg.RHS > 0 ) continue; constraintlist forcedplus = forced; forcedplus.append(cneg); if ( !joint_infeasible( *this, results, forcedplus ) ) return false; } } return true; } if ( !con0.local( ) ) { cerr << "Attempt to use split linear " << "programming to prove a constraint involving joint variables\n."; return false; } activate(quiet, results); constraintlist con, con1; forPixDef( i, con0 ) { constraint& c = con0(i); if ( c.simple_local( ) && c.sense == '>' && c.RHS == 1 && active->vtable.length == 2 ) { wordtype w( &configs(current), c.LHS.front( ).var ); active->c->make_minimal(w); if ( w == active->vtable(1).maw ) continue; } if ( c.simple_local( ) && c.sense == '>' && c.RHS == 1 ) { wordtype w( &configs(current), c.LHS.front( ).var ); active->c->make_minimal(w); for ( int j = 0; j <= n; j++ ) if ( configs(current).known( String("y") + dec(j) + ">" + dec(active->small_we(j)) ) ) { int ii; for ( ii = 1; ii < active->vtable.length; ii++ ) { forPixDef( p, active->vtable(ii).w ) { wordtype alttype = active->vtable(ii).maw; if ( alttype == w ) continue; alttype.act( active->vtable(ii).w(p) ); if ( sum(alttype) == j ) break; } if ( p != 0 ) break; } if ( ii == active->vtable.length ) return true; } } con1.append( con0(i) ); } TEX( ![ Test for constraints whose \LHS\ evaluates to a zero linear combination of basic local variables. In general, a warning is issued. An exception is where a constraint of the form $y_i = 0$ is to be proved and $i$ is in the working weight list. ]! ) forPix( i, con1 ) { activate(quiet, results); qvconstraint qvc = qvconstraint( con1(i), this ); if ( qvc.LHS.if_zero( ) ) { if ( !test( 0, qvc.RHS, qvc.sense ) ) return false; if ( con1(i).simple_global( ) && qvc.sense == '=' ) { int yn = yno( con1(i).LHS.front( ).var ); if ( ww(current).contains(yn) ) { bool nan; configs(current).add_constraint(con1(i), results, nan); deactivate( ); continue; } if ( !allow_stupid_show ) WARNING( "I already know that " << con1(i) << "." ); continue; } if ( !allow_stupid_show ) WARNING( "When I convert " << con1(i) << " to a constraint " << "involving only basic local variables, I get zero." << " This suggests that what you are doing is silly." << " If not, I apologize!" ); continue; } con.append( con1(i) ); } if ( con.length( ) == 0 ) return true; activate(quiet, results); accommodate( choose(n, dim) ); if (homebrew) { constraint c, cneg; forPix( i, con ) { c = con(i); if ( c.simple_global( ) && (c.sense == '>' || (c.sense == '=' && c.RHS == 0)) ) { int yn = yno(c.LHS.front( ).var); if ( active->small_we(yn) == c.RHS ) { int ii; for ( ii = 1; ii < active->vtable.length; ii++ ) { forPixDef( p, active->vtable(ii).w ) { wordtype alttype = active->vtable(ii).maw; alttype.act( active->vtable(ii).w(p) ); if ( sum(alttype) == yn ) break; } if ( p != 0 ) break; } if ( ii == active->vtable.length ) return true; } } c.clear_denominators( ); if ( c.sense == '>' || c.sense == '=' ) { cneg = c; cneg.sense = '<'; --cneg.RHS; forPixDef( p, cneg.LHS ) if ( cneg.LHS(p).coeff < Rational(0) ) break; if ( !(p == 0 && cneg.RHS < 0) ) { constraintlist forcedplus = forced; forcedplus.append(cneg); active->split(quiet, results, forcedplus); prevector files(2); files(0) = "cplex_in"; files(1) = "cplex_in2"; vconstraint tot(active->vtable.length); tot.sense = '='; tot.RHS = Ipow( 2, dim ); for ( int ii = 0; ii < tot.LHS.length; ii++ ) tot.LHS(ii) = active->vtable(ii).w.length( ); lp_crunch(files, active->vtable.length, tot); if ( homebrew_status == "confused" ) { WARNING( "Verification of linear program " << "calculation failed." ); return false; } if ( homebrew_status == "feasible" ) return false; } } if ( c.sense == '<' || c.sense == '=' ) { cneg = c; cneg.sense = '>'; ++cneg.RHS; forPixDef( p, cneg.LHS ) if ( cneg.LHS(p).coeff > Rational(0) ) break; if ( p == 0 && cneg.RHS > 0 ) continue; constraintlist forcedplus = forced; forcedplus.append(cneg); active->split(quiet, results, forcedplus); prevector files(2); files(0) = "cplex_in"; files(1) = "cplex_in2"; vconstraint tot(active->vtable.length); tot.sense = '='; tot.RHS = Ipow( 2, dim ); for ( int ii = 0; ii < tot.LHS.length; ii++ ) tot.LHS(ii) = active->vtable(ii).w.length( ); lp_crunch( files, active->vtable.length, tot ); if ( homebrew_status == "confused" ) { WARNING( "Verification of linear program calculation " << "failed." ); return false; } if ( homebrew_status == "feasible" ) return false; } } return true; } remove( calculations_dir + "/cplex_commands0" ); ofstream command_file( calculations_dir + "/cplex_commands0" ); command_file << "set logfile *\n"; if ( CPLEX_VERSION[0] <= '2' ) { command_file << "set presolve n\n"; command_file << "set aggregate n\n"; } else { command_file << "set preprocessing presolve n\n"; command_file << "set preprocessing aggregator n\n"; } int opt_count = 0; int nvars = active->vtable.length; SLList vcons; int j, k; SLList ops; SLList multipliers; forPix( i, con ) { // For a constraint which is an equality, we normally have to // break it up into two constraints (>=, <=). However, if the // constraint had the form "variable = 0", we only need one. if ( con(i).simple( ) && con(i).sense == '=' && con(i).RHS == 0 ) con(i).sense = '<'; vconstraint vc(nvars); qvconstraint qvc = qvconstraint( con(i), this ); Rational multiplier = clear_denom( qvc, vc ); HIDE( ![ if ( multiplier == Rational(0) ) INTERNAL_ERROR( "zero multiplier in show" );]!) for ( j = 0; j < nvars; j++ ) command_file << "change coeff obj v" << j + 1 << " " << vc.LHS(j) << "\n"; if ( vc.sense == '<' || vc.sense == '=' ) { char sense_save = vc.sense; vc.sense = '<'; vcons.append(vc); vc.sense = sense_save; command_file << "change sense obj max\n" << "opt\n"; ops.append("max"); remove( calculations_dir + "/cplex" + String(dec(opt_count)) + ".bin" ); command_file << "w " << PATH_PREFIX << calculations_dir << "/cplex" << opt_count++ << ".bin\n"; multipliers.append(multiplier); } if ( vc.sense == '>' || vc.sense == '=' ) { vc.sense = '>'; vcons.append(vc); command_file << "change sense obj min\n" << "opt\n"; ops.append("min"); remove( calculations_dir + "/cplex" + String(dec(opt_count)) + ".bin" ); command_file << "w " << PATH_PREFIX << calculations_dir << "/cplex" << opt_count++ << ".bin\n"; multipliers.append(multiplier); } } command_file.close( ); active->split(quiet, results, forced); prevector files(2); files(0) = "cplex_in"; files(1) = "cplex_in2"; vconstraint tot(active->vtable.length); tot.sense = '='; tot.RHS = Ipow( 2, dim ); for ( int ii = 0; ii < tot.LHS.length; ii++ ) tot.LHS(ii) = active->vtable(ii).w.length( ); lp_crunch( files, active->vtable.length, tot, true ); SLList dual_activity[opt_count]; prevector opsv(ops); vector mult(multipliers); for ( k = 0; k < opt_count; k++ ) { int status; dual_activity[k] = process_cplex_report( calculations_dir + "/cplex" + dec(k) + ".bin", status ); forPixDef( ppp, dual_activity[k] ) dual_activity[k](ppp) /= mult(k); // If we maximized, negate the dual activity numbers. if ( opsv(k) == "max" ) { forPix( ppp, dual_activity[k] ) dual_activity[k](ppp) = -dual_activity[k](ppp); } if ( status == 0 ) { if ( k == 0 ) { if (allow_stupid_show) return infeasible( *this, results, quiet ); else cerr << "show: system is infeasible; perhaps you " << "should be using via lp instead. Or perhaps you're " << "using \"kill by\" when you only need \"kill\".\n";} else cerr << "show: system is infeasible now, but it wasn't " << "a moment ago -- cplex has failed\n"; return false; } } ifstream conf( calculations_dir + "/cplex_in" ); char c; for ( j = 1; j <= 2; j++ ) // skip over "maximize 0 subject to" { do conf.get(c); while ( c != '\n' ); } qvconstraint qv[opt_count]; for ( k = 0; k < opt_count; k++ ) qv[k].LHS.set_size(nvars); vconstraint vcx(nvars); Pix d[opt_count]; for ( k = 0; k < opt_count; k++ ) d[k] = dual_activity[k].first( ); bool first_file = true; while(1) { if ( conf.peek( ) == EOF ) { if (first_file) { first_file = false; conf.close( ); conf.open( calculations_dir + "/cplex_in2" ); if ( conf.peek( ) == EOF ) break; } else break; } HIDE( ![ for ( k = 0; k < opt_count; k++ ) if ( d[k] == 0 ) INTERNAL_ERROR("show: not enough dual activity numbers"); ]! ) for ( k = 0; k < opt_count; k++ ) if ( sign(dual_activity[k](d[k])) != 0 ) break; if ( k != opt_count ) // at least one is nonzero { conf >> vcx; for ( k = 0; k < opt_count; k++ ) if ( sign(dual_activity[k](d[k])) != 0 ) add_to_rational_constraint( qv[k], vcx, dual_activity[k](d[k]) ); } else eat_constraint(conf); for ( k = 0; k < opt_count; k++ ) dual_activity[k].next(d[k]); } HIDE( ![ for ( k = 0; k < opt_count; k++ ) if ( d[k] != 0 ) INTERNAL_ERROR("show: too many dual activity numbers"); ]! ) conf.close( ); k = 0; forPix( i, con ) { vector vc; active->expand_term_sum( con(i).LHS, vc ); if ( con(i).sense == '<' || con(i).sense == '=' ) { Rational RHSx = qv[k].RHS - Rational(con(i).RHS); if ( RHSx >= Rational(1) ) return false; for ( j = 0; j < nvars; j++ ) { Rational vx = qv[k].LHS(j) - vc(j); if ( sign(vx) < 0 ) { if ( -vx * Rational(Ipow(2, dim)) >= Rational(active->vtable(j).w.length( )) * (Rational(1) - RHSx) ) return false; } } k++; } if ( con(i).sense == '>' || con(i).sense == '=' ) { Rational RHSx = qv[k].RHS + Rational(con(i).RHS); if ( RHSx >= Rational(1) ) return false; for ( j = 0; j < nvars; j++ ) { Rational vx = qv[k].LHS(j) + vc(j); if ( sign(vx) < 0 ) { if ( -vx * Rational(Ipow(2, dim)) >= Rational(active->vtable(j).w.length( )) * (Rational(1) - RHSx) ) return false; } } k++; } } return true; } TEX(![ The class {\tt codetable} is a placeholder for cumulated information about codes kept by the program. \indexz{codetable} ]!) set_include_file(codetable.h) index_method(classified) index_method(weakly_classified) index_method(get_codehome_name) class codetable { public: DLList open; // codes which may exist DLList< pair > olabels; // the Pix refers to a codehome in // open SLList dead; // codes which don't exist SLList< pair > dlabels; // the Pix refers to a codehome in // dead SLList< triple > ignore; // Don't look for new codes with // these parameters. String get_codehome_name(codehome* h) { forPixDef( q, open ) if ( open(q) == h ) { forPixDef( r, olabels ) if (q == olabels(r).second) return olabels(r).first; } return ""; } codehome* get_home( String& label, bool failure_allowed = true ) const { forPixDef( p, olabels ) { if ( olabels(p).first == label ) return open(olabels(p).second); } if ( !failure_allowed ) ERROR( "Code type " << label << " is not a known open type." ); return 0; } TEX( ![ \classtext{ For a given triple $(n,k,d)$, give (as a {\tt bitvec}) a weightlist which (for {\tt div1w}) all $[n,k,d]$ codes must have weights in and which (for {\tt div2w}) all even $[n,k,d]$ codes must have weights in.} ]! ) SLList< pair< triple, bitvec > > div1w, div2w; TEX( ![ \classtext{ For $1 \leq k \leq n$, {\tt lower\string_bound(}$n$\verb|,|$k$\verb|)| {\tt upper\string_bound(}$n$\verb|,|$k$\verb|)| gives the best known lower and upper bounds for the minimum distance of an $[n,k]$ code.} ]! ) matrix lower_bound, upper_bound; bool update_lower_bound(int, int, int); codetable( ); SLList< triple< int, int, int > > live_nkd; // some codes which exist void kill(const codebase&, String = ""); void kill(int, int, int); bool not_exist(int, int, int); bool not_exist(int, int, const weightlist&); bool not_exist(const codebase&); bool exist(int, int, int, bool = false); void recompute_lower_bound(int, int); bool is_unique(int n, int k, int d) { forPixDef( p, open ) if ( open(p)->unique && codebase(*(open(p))) == codebase(n,k,d) ) return true; return false; } void save(codehome&, String); bool new_not_exist(int, int, int, int, codehome*, String&, int = 2); int max_dim_of_code(int, const weightlist&); weightlist possible_weights(int, int, int, bool); bool classified(const codebase& cb) const { forPixDef( p, dead ) if ( dead(p) == cb ) return true; forPix( p, open ) { if ( open(p)->classified && codebase(*(open(p))) == cb ) return true; } return false; } bool weakly_classified(const codebase& cb) const { forPixDef( p, dead ) if ( dead(p) == cb ) return true; forPix( p, open ) { if ( (open(p)->classified || open(p)->we_known) && codebase(*(open(p))) == cb ) return true; } return false; } bool identify(matrix, String&, codehome*); }; set_compile_file(codetable.cc) HIDE( ![ #include "homedefs.h" #include "bitvec.h" #include "codetable.h" #include "opt.h" extern int homebrew, limited_secondary_kill, full_secondary_kill; extern int secondary_kill_maxvars, auto_joint_search, auto_joint_test; extern int residual_check_for_kill, save_bounds, generate_noneven_bounds, auto_try_to_kill_jvars, repeat_loop, purge_joints_on_type_exit; int String_cmp(const String&, const String&); extern String juxt(String, String); void execute_round_local(codehome*, codetable&); bool joint_infeasible(codehome&, codetable&, constraintlist = constraintlist( )); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); String make_j_var(int, int, int); void try_to_kill_jvars(codehome*, codetable&, int = -1); ]! ) index_method(identify) TEX(![ \verb|identify(M, l)|: Let $M$ be a matrix in \RREF. Determine if its rowspace is isomorphic to a known code, and return a label $l$ for that code if one has been specified. ]!) bool codetable::identify(matrix M, String& label, codehome* home) { forPixDef( p, open ) { codehome* h = open(p); if ( h->n != M.ncols || h->dim != M.nrows ) continue; forPixDef( q, h->configs ) { config& c = h->configs(q); if ( c.small.basis.nrows != h->dim ) continue; if ( isomorphic( M, c.basic_small( ) ) ) { forPixDef( p2, olabels ) if ( olabels(p2).second == p ) break; if ( p2 == 0 ) label = ""; else { forPixDef( q2, h->labels ) if ( h->labels(q2).second == q ) break; if ( q2 == 0 ) label = ""; else label = juxt( olabels(p2).first, h->labels(q2).first ); } return true; } } } if ( home == 0 ) return false; codehome* h = home; if ( h->n != M.ncols || h->dim != M.nrows ) return false; forPixDef( q, h->configs ) { config& c = h->configs(q); if ( c.small.basis.nrows != h->dim ) continue; if ( isomorphic( M, c.basic_small( ) ) ) { label = ""; return true; } } return false; } index_method(griesmer) TEX( ![ \verb|griesmer(|$n$\verb|,|$k$\verb|)|:\ Return the largest $d$ for which (according to the Griesmer bound) an $[n,k,d]$ code might exist. ]! ) int griesmer(int n, int k) { int i, d = 0, s, q; do { d++; s = 0; q = d; for ( i = 0; i < k; i++ ) { s += q; q++; q >>= 1; } } while ( s <= n ); return d - 1; } codetable::codetable( ) { lower_bound.set_size(100,100); upper_bound.set_size(100,100); for ( int n = 1; n < 100; n++ ) for ( int k = 1; k <= n; k++ ) { lower_bound(n,k) = 1; upper_bound(n,k) = griesmer(n,k); } } index_method(possible_weights) TEX( ![ \verb|possible_weights|:\ Return a list which all weights in an $[n,k,d]$ code must lie in. Do this by using the method of residual codes, by checking for known restrictions on the weights of $[n,k,d]$ codes, and by checking for known restrictions on the weights of $[n+1,k,d+1]$ codes in the case where $d$ is odd. ]! ) weightlist codetable::possible_weights(int n, int k, int d, bool if_even) { bitvec w(n+1), w_even; if ( even(d) && !if_even ) { int sum = 0; for ( int i = 0; i < k; i++ ) sum += int( ceil( Rational( d, Ipow(2, i) ) ) ); if ( sum == n ) if_even = true; } if ( !if_even && even(d) ) w_even = bitvec( possible_weights(n, k, d, true) ); w.set(0); for ( int i = d; i <= n; i += (if_even ? 2 : 1) ) if (k == 1 || i >= 2*d || !not_exist(n - i, k - 1, d - i/2)) w.set(i); if ( odd(d) ) { bitvec w_parity_check = bitvec( possible_weights(n+1, k, d+1, true) ); bitvec we3 = w_parity_check; we3.left_shift1( ); bitvec w_plus = Union(w_parity_check, we3); w = intersection( w, w_plus ); } Pix p, q, r; forPix( p, div1w ) { int n2 = div1w(p).first.first; int k2 = div1w(p).first.second; int d2 = div1w(p).first.third; bitvec ww = div1w(p).second; if ( n == n2 && k == k2 && d >= d2 ) w = intersection(w, ww); else if ( odd(d) && n2 == n+1 && k2 == k && d2 == d+1 ) { bitvec wo = ww.even_part( ); wo.left_shift1( ); w = intersection( w, Union( ww, wo ) ); } else if ( n2 == n-1 && k2 == k-1 && d2 == d ) { bool topbit = w.value(n); w = intersection(w, ww); if (topbit) w.set(n); } else if ( n2 == n-2 && k2 == k-2 && d2 == d ) { bool topbit = w.value(n); bool nextbit = w.value(n-1); w = intersection(w, ww); if (topbit) w.set(n); if (nextbit) w.set(n-1); } } forPix( p, div2w ) { int n2 = div2w(p).first.first; int k2 = div2w(p).first.second; int d2 = div2w(p).first.third; bitvec ww = div2w(p).second; if (n == n2 && k == k2 && d >= d2 && if_even) w = intersection(w, ww); else if ( odd(d) && n2 == n+1 && k2 == k && d2 == d+1 ) { bitvec wo = ww; wo.left_shift1( ); w = intersection( w, Union( ww, wo ) ); } else if ( n2 == n-1 && k2 == k-1 && d2 == d && if_even ) { bool topbit = w.value(n); w = intersection(w, ww); if (topbit) w.set(n); } else if ( n2 == n-2 && k2 == k-2 && d2 == d && if_even ) { bool topbit = w.value(n); bool nextbit = w.value(n-1); w = intersection(w, ww); if (topbit) w.set(n); if (nextbit) w.set(n-1); } } if ( !if_even && even(d) ) { bitvec we2 = w_even, we3 = w_even; we2.left_shift1( ); we3.right_shift1( ); bitvec w_even_plus = Union( Union(w_even, we2), we3 ); w = intersection( w, w_even_plus ); } weightlist ans; for ( int j = 0; j < w.length; j++ ) if ( w.value(j) ) ans.add(j); return ans; } TEX( Return the best known upper bound for the dimension of a code with given length and weightlist. ) index_method(max_dim_of_code) int codetable::max_dim_of_code(int n, const weightlist& w) { for ( int r = 1; r <= n; r++ ) if ( not_exist(n, r, w) ) return r-1; return n; } index_method(kill) void codetable::kill(const codebase& cb, String code_label) { int i, d = cb.w.min( ); for ( i = d; i <= cb.n; i++ ) if ( !cb.w.contains(i) ) break; if ( i == cb.n + 1 && cb.assumed_cons.empty( ) && cb.opt.none_chosen( ) ) { kill( cb.n, cb.dim, d ); if ( code_label == "" ) return; } Pix p = dead.append(cb); if ( code_label != "" ) dlabels.append( make_pair( code_label, p ) ); } TEX(![ \verb|not_exist(|$n,k,d$\verb|)|: Let $n,k,d$ be integers. Return {\tt true} if we know there is no $[n,k,d]$ code, else {\tt false}. ]! ) index_method(not_exist) bool codetable::not_exist(int n, int k, int d) { if ( k > n || (k == n && d > 1) || d > n ) return true; if ( n >= upper_bound.nrows ) kill(n,n,n); // force table enlargement return d > upper_bound(n,k); } TEX(![ \verb|not_exist(|$n${\tt,}\kern5pt$k${\tt,}\kern5pt$S${\tt)}: Let $n$ and $k$ be integers, and let $S$ be a weightlist. Return {\tt true} if we know there is no $[n,k,S]$ code, else {\tt false}. Weights in $S$ larger than $n$ are ignored. ]!) index_method(not_exist) bool codetable::not_exist(int n, int k, const weightlist& S) { weightlist T; if ( k <= 0 ) INTERNAL_ERROR( "not_exist called with k = " << k << "." ); if ( n >= upper_bound.nrows ) kill(n,n,n); // force table enlargement int d = S.min( ); if ( d > upper_bound(n,k) ) return true; if ( k >= 2 && d/2 > upper_bound(n-d,k-1) ) return true; forPixDef( i, S ) if ( S(i) <= n ) T.add( S(i) ); forPix( i, dead ) { const codebase& code = dead(i); if ( !code.assumed_cons.empty( ) ) continue; if ( !code.opt.none_chosen( ) ) continue; forPixDef( t, T ) { if ( T(t) > code.n ) continue; if ( !code.w.contains( T(t) ) ) break; } if ( t != 0 ) continue; if ( n <= code.n && k >= code.dim ) return true; if ( n > code.n && k >= code.dim + (n-code.n) ) return true; } if ( 2*k > n && T.divisible(4) ) return true; return false; } index_method(not_exist) bool codetable::not_exist(const codebase& cb) { int d = cb.w.min( ); if ( cb.n >= upper_bound.nrows ) kill(cb.n,cb.n,cb.n); // force table enlargement if ( d > upper_bound( cb.n, cb.dim ) ) return true; forPixDef( i, dead ) { const codebase& code = dead(i); if ( cb.n == code.n && cb.dim == code.dim && cb.w <= code.w && cb.assumed_cons >= code.assumed_cons ) return true; } return false; } TEX( ![ \verb|update_lower_bound|:\ Record the existence of an $[n,k,d]$ code. Return {\tt true} if this modifies the $[n,k]$ entry of the \verb|lower_bound| table. ]! ) index_method(update_lower_bound) bool codetable::update_lower_bound(int N, int K, int D) { int n, k; // Resize lower_bound table if needed. if ( N + 3 > lower_bound.nrows ) { int old_size = lower_bound.nrows, new_size = 2*N + 3; lower_bound.resize( new_size, new_size ); for ( n = old_size; n < new_size; n++ ) for ( k = 1; k <= n; k++ ) lower_bound(n, k) = 1; } if ( lower_bound(N, K) < D ) { lower_bound(N, K) = D; return true; } return false; } index_method(kill) void codetable::kill(int N, int K, int D) { if ( even(D) ) kill( N-1, K, D-1 ); int n, k; static SLList< triple > history; // Resize upper_bound table if needed. if ( N >= upper_bound.nrows ) { int old_size = upper_bound.nrows, new_size = N + 20; upper_bound.resize( new_size, new_size ); for ( n = old_size; n < new_size; n++ ) for ( k = 1; k <= n; k++ ) upper_bound(n, k) = griesmer(n, k); forPixDef( p, history ) { int N0 = history(p).first; int K0 = history(p).second; int D0m = history(p).third - 1; int g = griesmer(N0, K0) - D0m; for ( n = old_size; n < upper_bound.nrows; n++ ) for ( k = K0 + (n-N0); k <= K0 + (n-N0) + g; k++ ) if ( D0m < upper_bound(n,k) ) upper_bound(n,k) = D0m; } } int Dm = D - 1; int g = griesmer(N, K) - Dm; if ( g <= 0 ) return; history.append( make_triple( N, K, D ) ); for ( n = N - g; n <= N; n++ ) for ( k = K; k <= K + g - (N - n); k++ ) if ( Dm < upper_bound(n,k) ) upper_bound(n,k) = Dm; for ( n = N + 1; n < upper_bound.nrows; n++ ) for ( k = K + (n-N); k <= K + (n-N) + g; k++ ) if ( Dm < upper_bound(n,k) ) upper_bound(n,k) = Dm; } TEX( ![ {\tt exist}:\ Execute the procedure of the {\tt yes} command. The code is correct but probably trash. ]! ) index_method(exist) bool codetable::exist(int N, int K, int D, bool weak) { int n, k, n1, n2, k1, k2, a, b; // Resize lower_bound table if needed. if ( 2*N + 3 > lower_bound.nrows ) { int old_size = lower_bound.nrows, new_size = 3*N; lower_bound.resize( new_size, new_size ); for ( n = 1; n < new_size; n++ ) { for ( k = 1; k <= n; k++ ) { if ( k >= old_size || n >= old_size ) lower_bound(n, k) = 1; } } } // Propagate rules. bool something_changed; do { if ( D <= lower_bound(N,K) ) return true; something_changed = false; for ( n1 = 1; n1 <= N; n1++ ) for ( n2 = n1; n2 <= N; n2++ ) { int topk = min(n1, n2); if (weak) topk = min(topk, K); for ( k = 1; k <= topk; k++ ) something_changed = something_changed || update_lower_bound( n1 + n2, k, lower_bound(n1, k) + lower_bound(n2, k) ); } for ( n = 1; n <= N; n++ ) { int topk1 = n; if (weak) topk1 = min(topk1, K); for ( k1 = 1; k1 <= topk1; k1++ ) { int topk2 = k1; if (weak) topk2 = min(topk2, K - k1); for ( k2 = 1; k2 <= topk2; k2++ ) something_changed = something_changed || update_lower_bound( 2*n, k1 + k2, min( 2*lower_bound(n, k1), int( lower_bound(n, k2) ) ) ); } } for ( n = 1; n <= 2*N; n++ ) { int topk = n; if (weak) topk = min(topk, K); for ( k = 1; k <= topk; k++ ) for ( a = -1; a <= min(n-1,1); a++ ) for ( b = 0; b <= min(k-1,1); b++ ) { if ( n-a < k-b ) continue; int d = lower_bound(n,k) - max(a-b, 0); if ( d <= 0 ) continue; something_changed = something_changed || update_lower_bound( n-a, k-b, d ); } } for ( n = 1; n <= 2*N; n++ ) { int topk = n; if (weak) topk = min(topk, K); for ( k = 1; k <= topk; k++ ) if ( odd( int( lower_bound(n,k) ) ) ) something_changed = something_changed || update_lower_bound( n + 1, k, lower_bound(n,k) + 1 ); } } while(something_changed); return D <= lower_bound(N,K); } // I don't think this is giving the right values when the minimum distance // is odd. void codetable::recompute_lower_bound(int N, int K) { int n, k, n1, n2, k1, k2, a, b; // The increment to K (5, at present) has been chosen so that facts about // lower-dimensional codes are correctly deduced from higher-dimensional // codes, in the range of codes actually encountered so far. Zero is not // good enough; no other values have been tried. K += 5; // Resize lower_bound table if needed. if ( 2*N + 3 > lower_bound.nrows ) { int old_size = lower_bound.nrows, new_size = 3*N; lower_bound.resize( new_size, new_size ); for ( n = 1; n < new_size; n++ ) { for ( k = 1; k <= n; k++ ) { if ( k >= old_size || n >= old_size ) lower_bound(n, k) = 1; } } } // Propagate rules. bool something_changed; do { something_changed = false; for ( k = 1; k < K; k++ ) { if ( Ipow( 2, k - 1 ) > N ) break; int tk = Ipow( 2, k-1 ); for ( n = k; n + 2*tk <= N; n++ ) something_changed = update_lower_bound( n + 2*tk, k + 1, min( lower_bound(n,k) + tk, 2*tk ) ) || something_changed; } for ( n1 = 1; n1 <= N; n1++ ) { int topk = min(n1-1, K); for ( k = 1; k <= topk; k++ ) { if ( n1 >= 2 && lower_bound(n1-1,k) >= lower_bound(n1,k) ) continue; for ( n2 = n1; n2 <= N; n2++ ) something_changed = update_lower_bound( n1 + n2, k, lower_bound(n1, k) + lower_bound(n2, k) ) || something_changed; } } for ( n = 1; n <= N; n++ ) { int topk1 = min(n, K); for ( k1 = 1; k1 <= topk1; k1++ ) { int topk2 = min(k1, K - k1); for ( k2 = 1; k2 <= topk2; k2++ ) something_changed = update_lower_bound( 2*n, k1 + k2, min( 2*lower_bound(n, k1), int( lower_bound(n, k2) ) ) ) || something_changed; } } int np, kp; for ( n = 1; n <= 2*N; n++ ) { int topk = min(n, K); for ( k = 1; k <= topk; k++ ) { if ( n >= 2 && n-1 >= k && lower_bound(n-1,k) >= lower_bound(n,k) ) continue; if ( n+1 <= 2*N && k+1 <= topk && lower_bound(n+1,k+1) >= lower_bound(n,k) ) continue; if ( n+1 <= 2*N && lower_bound(n+1,k) > lower_bound(n,k) ) continue; for ( np = 1; np <= 2*N; np++ ) { int topkp = min(np, k); for ( kp = 1; kp <= topkp; kp++ ) { int d = lower_bound(n, k); int dp = np - n - (kp - k) + d; if ( dp > np ) dp = np; if ( dp > d + 1) dp = d + 1; if ( dp == d + 1 && even(d) ) dp = d; something_changed = update_lower_bound(np, kp, dp) || something_changed; } } } } } while(something_changed); } TEX( \verb|new_not_exist|:\ Execute the procedure of the ``{\tt no}'' command. The only allowed values for {\tt div} are $1$ and $4$. Be sure to set {\tt home = 0} after calling. ) index_method(new_not_exist) bool codetable::new_not_exist(int n, int k, int d, int div, codehome* home, String& code_label, int allowed_failures) { // First save the previous codehome, if there was one. if (home != 0) save( *home, code_label ); HIDE( ![ if (n == 0 || k == 0 || k > n || d == 0 || d > n || (div != 1 && div != 4)) INTERNAL_ERROR( "new_not_exist: bad arguments." ); ]! ) // Now deal with some silly cases. if ( k == n ) return d != 1; if ( k == 1 ) return false; if ( not_exist( n, k, d ) || not_exist( n-1, k, d-1 ) ) return true; if ( n >= 2 && k == n - 1 && d == 2 ) return false; if ( div == 4 && d % 4 != 0 ) return false; if ( div == 1 ) div = 2; int i, dual_min, wx; // Reduce to even case. if ( odd(d) ) { n++; d++; } // If you remove "= weightlist" from the following line, a parse // error results. This must be a compiler bug. weightlist w = weightlist(String(dec(d)) + String("_") + dec(div), n), wd; if ( not_exist( n, k, w ) || not_exist( n-1, k-1, w ) ) return true; w = intersection( w, possible_weights( n, k, d, true ) ); if ( w.length( ) == 1 ) return true; // 0 is only weight // Is Griesmer bound violated? if ( codebase( n, k, w ).griesmer( ) > n ) return true; // Get lower bound for minimum weight of dual code. dual_min = 1; for ( i = k-1; i >= 0; i-- ) if ( not_exist( n-i-1, k-i, d ) ) { dual_min = i + 2; break; } if ( not_exist( n, n - k, dual_min ) ) return true; TEX(![ \begin{quote} Now we have to do linear programming. If $k \geq n/2$, we will work with the dual code instead. The reason for this is that the numerical instability of the linear programming problem grows with $k$, so for $k > n/2$ the dual problem is more stable. A better way to handle this would be to have the {\tt split} routine do this automatically. \end{quote} ]!) int fail_count = 0; if ( 2*k <= n ) { weightlist w_full = weightlist( String(dec(d)) + String("_") + dec(div), n ); home = new codehome(n, k, w_full, *this); home->ww(home->base) = w; home->basic_joint_vars(&home->configs(home->base), *this); if ( home->configs(home->base).share->wjv.length == 0 ) { delete home; return true; } OSLList joint_maybe_nonzero; // The list "joint_maybe_nonzero" list causes some variables not // to be tested for zeroness. It is conceivable that such a variable // could actually be zero, and so the list could result in a // harmless "mistake". if ( home->contradiction(true, *this) ) { delete home; return true; } int last_weight_killed = 0; kill_weights: bool some_killed = false; fail_count = 0; weightlist wz = home->configs(home->base).share->ww; bool no_successes_yet = true; while(1) { wx = wz.Max( ); if ( wx == 0 ) break; if ( last_weight_killed > 0 && !some_killed && wx < last_weight_killed ) break; bool pretest = false; home->set_current(home->base); if ( home->configs(home->base). known( String("y") + dec(wx) + "!=0" ) ) { wz.del(wx); if (!no_successes_yet) cerr << ".\n"; no_successes_yet = true; if ( allowed_failures >= 1 && ++fail_count == allowed_failures ) break; cerr << "Weight " << wx << " may exist.\n"; continue; } if ( home->show( String("y") + dec(wx) + "=0", *this, true ) ) pretest = true; if (!pretest) { if ( n == wx ) home->set_config( String(dec(wx)) + ":{1}", *this ); else home->set_config( String(dec(wx)) + "," + dec(n - wx) + ":{10}", *this ); home->configs(home->current). check_secondary_residuals(*this); } wz.del(wx); bool win_flag = pretest || home->contradiction(true, *this); if (!win_flag && (limited_secondary_kill || full_secondary_kill)) { Pix yy, p = home->current; config& c = home->configs(p); SLList to_kill; if (full_secondary_kill) { for ( i = 1; i < home->active->vtable.length; i++ ) to_kill.append( home->active->vtable(i).maw ); } else if ( n != wx ) { for ( i = 0; i < 2; i++ ) { forPix( yy, home->ww(p) ) { weightlist& www = home->ww(p); if ( www(yy) == 0 ) continue; int first_part = www(yy), second_part = 0; if ( i == 1 ) swap(first_part, second_part); if ( first_part > c.part(0) || second_part > c.part(1) ) continue; wordtype wt(&c, String("x_")+dec(first_part) + "_" + dec(second_part) ); if ( home->active->vtable.mfind(wt) > 0 ) to_kill.append(wt); } } } else { forPix( yy, home->ww(p) ) { weightlist& www = home->ww(p); if ( www(yy) == 0 ) continue; wordtype wt(&c, String("x_") + dec(www(yy)) ); if ( home->active->vtable.mfind(wt) > 0 ) to_kill.append(wt); } } prevector to_kill_v(to_kill); for ( i = 0; i < to_kill_v.length; i++ ) c.make_minimal(to_kill_v(i)); to_kill_v.unique_sort(&wcmp); int success_count = 0; String var; for ( i = 0; i < to_kill_v.length; i++ ) { wordtype& wtt = to_kill_v(i); if ( wtt.length == 2 ) { int i1 = wx; int i2 = wtt(0) + wtt(1); int i3 = wx - wtt(0) + wtt(1); var = make_j_var(i1, i2, i3); if ( joint_maybe_nonzero.contains(var) ) continue; } Pix pi = subdivide( home->configs(home->current), wtt, *this ); home->set_current(pi); if (residual_check_for_kill) home->configs(home->current). check_secondary_residuals(*this); home->activate(true, *this); if ( secondary_kill_maxvars == 0 || secondary_kill_maxvars >= home->active->vtable.length ) { if ( home->contradiction(true, *this) ) { success_count++; cerr << "[" << wtt.variable( ) << " killed]"; home->configs(home->base).share->ycon.append( var + "=0" ); if ( wtt.length == 2 ) { prevector& vars = home->configs(home->current).share->wjv; int po = vars.pos( var, &String_cmp ); HIDE( ![ if ( po == -1 ) INTERNAL_ERROR("joint variable " << "already known to be " << "zero"); ]! ) prevector vars_new( vars.length - 1 ); for ( int j = 0; j < po; j++ ) vars_new(j) = vars(j); for ( int j = po + 1; j < vars.length; j++ ) vars_new(j-1) = vars(j); vars = vars_new; } home->configs(p).con.append( wtt.variable( ) + "=0" ); home->set_current(p); if ( home->contradiction(true, *this) ) { win_flag = true; break; } } else if ( wtt.length == 2 ) joint_maybe_nonzero.add(var); } if ( home->current != p ) home->set_current(p); home->activate(true, *this); } if ( !win_flag && success_count > 0 && home->contradiction(true, *this) ) win_flag = true; } if (win_flag) { some_killed = true; last_weight_killed = wx; if (no_successes_yet) cerr << "There are no words of weight: " << wx; else cerr << "," << wx; joint_maybe_nonzero.clear( ); no_successes_yet = false; fail_count = 0; home->set_current(home->base); bool nan; home->configs(home->base).add_constraint( String("y") + dec(wx) + "=0", *this, nan ); if ( home->contradiction(true, *this) ) { cerr << ".\n"; delete home; return true; } for ( i = 2; i <= 3; i++ ) { int divx = Ipow(2, i); if ( !wz.divisible(divx) && home->show( String("div") + dec(divx) + ">" + dec( (divx - 1) * Ipow(2, home->dim - i) ), *this, true ) ) { wz.make_divisible(divx); home->ww(home->base).make_divisible(divx); cerr << ",all weights not divisible by " << divx; home->deactivate( ); if ( home->contradiction(true, *this) ) { cerr << ".\n"; delete home; return true; } } else break; } } else { if (!no_successes_yet) cerr << ".\n"; no_successes_yet = true; cerr << "Weight " << wx << " may exist.\n"; if ( allowed_failures >= 1 && ++fail_count == allowed_failures ) break; } } if ( !no_successes_yet ) cerr << ".\n"; if ( repeat_loop && some_killed ) goto kill_weights; if ( 2*k != n ) goto joint_phase; // Perhaps we can show that the all 1's word is in the code. // (Not discussed in documentation for "no" command.) bool all_ones = false; if ( even(n) && home->ww(home->base).contains(n) ) { home->set_current(home->base); if ( home->show( String("y") + dec(n) + "!=0", *this, true ) ) { cerr << "The word of weight " << n << " is in the code.\n"; all_ones = true; } } fail_count = 0; bool a_fail_occurred = false; int dp = home->configs(home->base).share->dual_min_low; while(1) { if ( all_ones && odd(dp) && n != dp ) { dp++; continue; } if ( n == dp ) { config dd = config( home, String(dec(dp)) + "::{1}" ); home->set_config(dd, *this); } else { if ( !all_ones ) { config dd = config( home, String(dec(n - dp)) + "," + dec(dp) + "::{01}" ); home->set_config(dd, *this); } else { config dd = config( home, String(dec(n - dp)) + "," + dec(dp) + ":{11}:{01}" ); home->set_config(dd, *this); } } if ( home->contradiction(true, *this) ) { fail_count = 0; home->configs(home->base).share->ycon. append( String("mu") + dec(dp) + "=0" ); cerr << "There is no dual word of weight " << dp++ << ".\n"; if ( !a_fail_occurred && not_exist(n,n-k,dp) ) { delete home; return true; } home->set_current(home->base); if ( home->contradiction(true, *this) ) { delete home; return true; } } else { cerr << "There may be a dual word of weight " << dp << ".\n"; a_fail_occurred = true; if ( allowed_failures >= 1 && ++fail_count == allowed_failures || n == dp++ ) goto joint_phase; } } } else { wd.add(0); for ( i = dual_min; i <= n; i++ ) wd.add(i); home = new codehome(n, n-k, wd, *this); if ( home->configs(home->base).share->realizable == -1 ) { delete home; return true; } home->configs(home->base).share->dual_min_low = d; for ( i = d; i <= n; i += 2 ) if ( !w.contains(i) ) home->configs(home->base).share->ycon. append( String("mu") + dec(i) + "=0" ); home->set_config( String(dec(n)) + ":{1}", *this ); if ( home->contradiction(true, *this) ) { delete home; return true; } while(1) { wx = w.Max( ); if ( wx == 0 ) break; if ( home->n == wx ) home->set_config( String(dec(wx)) + ":{1}:{1}", *this ); else home->set_config( String(dec(wx)) + "," + dec(n - wx) + ":{11}:{10}", *this ); w.del(wx); if ( home->contradiction(true, *this) ) { cerr << "Weight " << wx << " does not exist.\n"; fail_count = 0; home->configs(home->base).share->ycon. append( String("mu") + dec(wx) + "=0" ); home->set_config( String(dec(n)) + ":{1}", *this ); if ( home->contradiction(true, *this) ) { delete home; return true; } } else { cerr << "Weight " << wx << " may exist.\n"; if ( allowed_failures >= 1 && ++fail_count == allowed_failures ) break; } } // Perhaps we can show that the all 1's word is in the code. // (Not discussed in documentation for "no" command.) if ( even(n) && w.contains(n) ) { home->set_current(home->base); if ( home->show( String("mu") + dec(n) + "!=0", *this, true ) ) { cerr << "The word of weight " << n << " is in the code.\n"; home->configs(home->base).share->ww.make_divisible(2); } } fail_count = 0; weightlist www = home->configs(home->base).share->ww; while(1) { wx = www.min( ); if ( wx == n ) { delete home; return false; } home->set_config( String(dec(wx)) + "," + dec(n - wx) + ":{10,01}", *this ); www.del(wx); if ( home->contradiction(true, *this) ) { cerr << "There is no dual word of weight " << wx << ".\n"; fail_count = 0; home->configs(home->base).share->ww.del(wx); if ( not_exist(n,n-k,home->ww(home->base)) ) { delete home; return true; } home->set_config( String(dec(n)) + ":{1}", *this ); if ( home->contradiction(true, *this) ) { delete home; return true; } } else { cerr << "There may be a dual word of weight " << wx << ".\n"; if ( allowed_failures >= 1 && ++fail_count == allowed_failures ) { delete home; return false; } } } } joint_phase: if (auto_joint_search > 0 || auto_joint_test > 0 ) { home->set_current(home->base); home->basic_joint_vars(&home->configs(home->base), *this); prevector& vars = home->configs(home->base).share->wjv; int njvars = vars.length; if ( auto_try_to_kill_jvars && 2 * njvars < 3 * max(auto_joint_search, auto_joint_test) ) try_to_kill_jvars( home, *this ); if ( njvars == 0 ) INTERNAL_ERROR( "wjv length = 0 in new_not_exist, joint_phase" ); if ( auto_joint_test == 1 || njvars <= auto_joint_test ) { home->set_current(home->base); if ( joint_infeasible(*home, *this) ) { delete home; return true; } } if ( njvars <= auto_joint_search ) { home->set_current(home->base); opt_table search(home); weightlist www = home->ww(home->base); www.del(0); forPixDef( ppp, www ) search.add( String("y") + dec( www(ppp) ) ); search.compute(*this, true); if ( search.feasible == false ) cerr << "It would " << "appear that this code type is unrealizable.\n"; else { forPix( ppp, search.data ) cerr << search.data(ppp); if (save_bounds) { cerr << "saving the following bounds for even codes:\n"; Rational eps(1,1000), low, high; constraint cc; config& cur = home->configs(home->base); forPix( ppp, search.data ) { low = search.data(ppp).min; high = search.data(ppp).max; Integer Ilow = ceil(low - eps); Integer Ihigh = floor(high + eps); cc.LHS = search.data(ppp).var; if ( Ilow > 0 ) { cc.sense = '>'; cc.RHS = Ilow; cerr << " " << cc << "\n"; cur.share->ycon.append(cc); } cc.sense = '<'; cc.RHS = Ihigh; cerr << " " << cc << "\n"; cur.share->ycon.append(cc); } save(*home, ""); home = 0; } } } } div2w.append(make_pair( make_triple(n,k,d), bitvec(home->ww(home->base)) )); delete home; home = 0; if (generate_noneven_bounds > 0) { w = weightlist( dec(d), n ); home = new codehome(n, k, w, *this); home->basic_joint_vars(&home->configs(home->base), *this); prevector& vars = home->configs(home->base).share->wjv; if ( vars.length == 0 ) INTERNAL_ERROR( "wjv length = 0 in new_not_exist, generate noneven bounds" ); if (vars.length <= generate_noneven_bounds) { opt_table search(home); weightlist www = home->ww(home->base); www.del(0); forPixDef( ppp, www ) search.add( String("y") + dec( www(ppp) ) ); search.compute(*this, true); if ( search.feasible == false ) cerr << "It would " << "appear that this code type is unrealizable.\n"; else { cerr << "saving the following bounds for all codes:\n"; Rational eps(1,1000), low, high; constraint cc; config& cur = home->configs(home->base); forPix( ppp, search.data ) { low = search.data(ppp).min; high = search.data(ppp).max; Integer Ilow = ceil(low - eps); Integer Ihigh = floor(high + eps); cc.LHS = search.data(ppp).var; if ( Ilow > 0 ) { cc.sense = '>'; cc.RHS = Ilow; cerr << " " << cc << "\n"; cur.share->ycon.append(cc); } cc.sense = '<'; cc.RHS = Ihigh; cerr << " " << cc << "\n"; cur.share->ycon.append(cc); } } save(*home, ""); home = 0; } } delete home; return false; } index_method(save) void codetable::save(codehome& home, String code_label) { if ( home.configs(home.base).share->realizable == -1 ) { kill(home, code_label); delete &home; } else { forPixDef( q, home.configs ) { if ( home.configs(q).share->realizable == 1 ) { update_lower_bound( home.n, home.dim, home.w.min( ) ); break; } } if (purge_joints_on_type_exit) { forPix( q, home.configs ) home.configs(q).share->wjv.set_size(0); } Pix p = open.append(&home); if ( code_label != "" ) olabels.append( make_pair( code_label, p ) ); if ( !home.assumed_cons.empty( ) || !home.opt.none_chosen( ) ) return; int d = home.w.min( ); if ( home.w.length( ) == home.n - d + 2 ) // all weights present div1w.append( make_pair( make_triple(home.n, home.dim, d), bitvec(home.ww(home.base)) ) ); else if ( even(d) && home.w.length( ) == (home.n - d)/2 + 2 ) { forPix( q, home.w ) // all even weights present? if ( !even( home.w(q) ) ) break; div2w.append( make_pair( make_triple(home.n, home.dim, d), bitvec(home.ww(home.base)) ) ); } } } set_compile_file(code.c) HIDE( ![ #include "codehome.h" #include "codetable.h" ]! ) TEX( \block{Miscellaneous methods} ) set_compile_file(config.cc) HIDE(![vector we_from_String( String, int, int ); extern int matrix_isomorphism_silent;]!) TEX( ![ \verb|known_globals|:\ Return the known global and joint constraints for a configuration {\tt c}, possibly excluding those known for the base configuration, but including those which are implicit in the working weight list and working joint variable list for {\tt c}. ]! ) index_method(known_globals) constraintlist known_globals( config& c ) { constraintlist u; forPixDef( p, c.assumed_cons ) if ( c.assumed_cons(p).joint( ) ) u.append( c.assumed_cons(p) ); u.merge( c.share->ycon ); weightlist& ww = c.home->ww(c.home->base); forPix( p, ww ) if ( !c.share->ww.contains( ww(p) ) ) u.append( String("y") + dec(ww(p)) + "=0" ); prevector& wjv = c.home->configs(c.home->base).share->wjv; for ( int i = 0; i < wjv.length; i++ ) if ( c.share->wjv.pos( wjv(i), &String_cmp ) == -1 ) { int i1, i2, i3; parse_j_var( wjv(i), i1, i2, i3 ); if ( c.share->ww.contains(i1) && c.share->ww.contains(i2) && c.share->ww.contains(i3) ) u.append( wjv(i) + "=0" ); } return u; } TEX(![ When the {\tt config} constructor is called, it automatically sets the share pointer to equal the share pointer for the base configuration. If the base pointer has not yet been defined (signified by {\tt base == 0}), this step is omitted. ]!) index_method(config constructor) config::config(codehome* h, const String& s) : home(h) { prevector args = unpack(s, ":"); if ( args.length < 2 || args.length > 4 ) ERROR( "The configuration |" << s << "| is mangled."); part = partition(args(0)); if ( part.n != h->n ) ERROR( "The sum of the partition elements does not equal the " << "length of the code type." ); small = code(part.length, args(1)); gen = matrix( part.length, args(1) ); if ( args.length >= 3 ) dualsmall = code(part.length, args(2)); else dualsmall = code(part.length, "{}"); leading1s = small.basis.leading_ones( ); if ( args.length == 4 ) { if ( args(3).length( ) == 0 || args(3)[0] != '{' || args(3)[args(3).length( )-1] != '}' ) ERROR("The constraintlist does not have the correct form."); args(3).gsub( "{", 0 ); args(3).gsub( "}", 0 ); if ( !args(3).contains( '^' ) && !args(3).contains( '[' ) ) assumed_cons = constraintlist( args(3) ); else { prevector cons = unpack( args(3) ); SLList newcons; for ( int i = 0; i < cons.length; i++ ) { if ( cons(i).contains( '^' ) ) { vector we = we_from_String( cons(i), h->n, h->dim ); for ( int j = 1; j <= h->n; j++ ) if ( h->w.contains(j) ) newcons.append( String("y") + dec(j) + "=" + dec(we(j)) ); } else if ( cons(i).contains( '[' ) ) { Pix cp; if ( cons(i) == "[current]" ) { if ( h->current == 0 ) { ERROR( "The current configuration " << "is undefined." ); } else cp = h->current; } else { forPixDef( p, h->labels ) if ( h->labels(p).first == cons(i) ) cp = h->labels(p).second; } newcons.append( known_globals( h->configs(cp) ) ); } else newcons.append( cons(i) ); } forPixDef( p, newcons ) assumed_cons.merge( constraintlist(newcons(p)) ); } } if ( h->base != 0 ) { share = new config_share; *share = *(h->configs(h->base).share); if ( assumed_cons.length( ) > 0 ) share->wjv.set_size(0); } aut.n = part.length; no_auto = false; } config::config(codehome* h, matrix m) : home(h) { part.set_all_ones(home->n); small.basis = m; leading1s = small.basis.leading_ones( ); dualsmall.basis.set_size(0, home->n); share = new config_share; *share = *(h->configs(h->base).share); aut.n = part.length; no_auto = false; } TEX(![ I don't know why the following copy constructor is needed. Without it, one gets a segmentation fault (or at least on did at one time). ]!) config::config(const config& c) { home = c.home; part = c.part; small = c.small; gen = c.gen; dualsmall = c.dualsmall; assumed_cons = c.assumed_cons; con = c.con; aut = c.aut; share = c.share; auto_labels = c.auto_labels; leading1s = c.leading1s; no_auto = c.no_auto; } ostream& operator<<(ostream& s, const config& c) BHIDE1( ![ if ( c.part.x == 0 ) INTERNAL_ERROR( "I'm trying to print out a configuration whose " << "partition was not defined." ); ]!, ![ s << " config "; ]! ) for ( int i = 0; i < c.part.length; i++ ) { s << c.part(i); if ( i < c.part.length - 1 ) s << ","; } s << " : " << c.small.basis << " : " << c.dualsmall.basis << " : {" << c.assumed_cons << "}\n"; HIDE( ![ if ( c.share == 0 ) INTERNAL_ERROR("Pointer to share is zero."); ]! ) if ( c.share->realizable == -1 ) return s << " unrealizable\n"; HIDE( ![ if ( c.share->ww.length( ) == 0 ) INTERNAL_ERROR("Weight list is empty."); ]! ) s << " working weight list is " << c.share->ww << "\n"; if ( c.con.length( ) != 0 ) s << " known constraints (local): " << c.con << "\n"; if ( c.share->ycon.length( ) != 0 ) s << " known constraints (global): " << c.share->ycon << "\n"; s << " minimum weight of dual code is between " << c.share->dual_min_low << " and " << c.share->dual_min_high << "\n"; if ( c.aut.length != 0 ) { s << " known automorphisms:\n"; for ( int i = 0; i < c.aut.length; i++ ) s << " " << c.aut(i) << "\n"; } if ( c.share->realizable == 1 ) s << " realizable\n"; return s; } TEX( Replace a \verb|term_sum| by one in which the only global variables which appear are {\tt y} variables (or {\tt x} variables, in the case where the partition has only one part.) ) index_method(simplify_global_vars) term_sum config_core::simplify_global_vars(const term_sum& in, const weightlist& w, int dim, bool verbatim) const { term_sum out; int i, j, k, n = part.n; Rational ycoeff[n + 1]; Pix p, q; for ( i = 0; i <= n; i++ ) ycoeff[i] = 0; forPix( p, in ) { // Evade const to avoid problems with "after". String& v = const_cast(in(p).var); const Rational& cf = in(p).coeff; if ( v[0] == 'y' || (v[0] == 'x' && part.length == 1) ) ycoeff[ yno(v) ] += cf; else if ( v[0] == 'd' ) { int divider = as_int( v.after("div") ); for ( j = 0; j <= n; j += divider ) ycoeff[j] += cf; } else if ( v[0] == 'm' ) { k = as_int( v.after("mu") ); Integer sum, total = Ipow(2, dim); forPix( q, w ) { sum = 0; for ( j = 0; j <= k; j++ ) if ( j <= w(q) && k - j <= n - w(q) ) sum += minus1_to_the(j) * choose( w(q), j ) * choose( n - w(q), k - j ); ycoeff[ w(q) ] += Rational(sum) * cf / total; } } else out.append( in(p) ); } if (!verbatim) { forPix( q, w ) { if ( ycoeff[ w(q) ] != Rational(0) ) out.append( term( ycoeff[ w(q) ], String("y") + dec(w(q)) ) ); } } else for ( i = 0; i <= n; i++ ) if ( ycoeff[ i ] != Rational(0) ) out.append( term( ycoeff[ i ], String("y") + dec(i) ) ); return out; } TEX( \verb|no_bad_weights|: Make sure that every word in the smallcode of the given configuration has weight in the working weightlist of the base configuration. ) index_method(no_bad_weights) bool config::no_bad_weights( ) const { vector y = smallcode_we( ); for ( int i = 0; i <= home->n; i++ ) if ( y(i) > 0 && !home->ww(home->base).contains(i) ) return false; return true; } TEX(![ {\tt evaluate(v, low, high):}\ Let {\tt v} be a variable. Search for known constraints whose \LHS\ is {\tt v}, to get integer lower and upper bounds for it. If no upper bound is found, {\tt high} is set to $-1$. (For a bona fide variable, we always return a nonnegative value.) The preexisting values for {\tt low} and {\tt high} are assumed to be known bounds, with the same convention regarding {\tt high} $= -1$. ]!) index_method(evaluate) void config::evaluate(const String& s, Integer& low, Integer& high) const { assumed_cons.evaluate( s, low, high ); share->ycon.evaluate( s, low, high ); con.evaluate( s, low, high ); home->assumed_cons.evaluate( s, low, high ); if ( share != home->configs(home->base).share ) home->configs(home->base).share->ycon.evaluate( s, low, high ); static Regex div_number_pattern("div" + number_pat); if ( s.matches( div_number_pattern ) ) { Integer h = Ipow( 2, home->dim ); if ( high == -1 || h < high ) high = h; } if ( high == -1 && !s.contains( '+' ) && !s.contains( '-' ) && isalpha( s[0] ) ) { if ( s[0] == 'j' ) high = Ipow(2, 2 * home->n); else if ( s[0] == 'c' || s[0] == 'y' ) high = Ipow(2, home->dim); else high = Ipow(2, home->n); } else if ( high == -1 && !s.contains( '-' ) ) { term_sum t(s); Rational sum = 0; forPixDef( p, t ) sum += t(p).coeff; high = floor(sum) * Ipow(2, 2 * home->n); } } TEX(![ {\tt known}, \verb|known_global|:\ Determine if a constraint is ``known'' for a configuration. In the current version, the constraint must either appear essentially verbatim (see {\tt constraintlist::known}) in one of the lists of known constraints, or must be of the form $\hbox{\tt y}_i$\ {\tt = 0}, where $i$ does not appear in the working weightlist for the configuration. ]!) index_method(known_global) bool known_global( codehome* home, config_share* cs, constraint f ) { if ( home->assumed_cons.known(f) || cs->ycon.known(f) ) return true; if ( cs != home->configs(home->base).share ) if ( home->configs(home->base).share->ycon.known(f) ) return true; if ( f.simple_global( ) && f.sense == '=' && f.RHS == 0 ) if ( !cs->ww.contains( yno(f.LHS.front( ).var) ) ) return true; return false; } index_method(known) bool config::known(const constraint& f) const { return assumed_cons.known(f) || con.known(f) || known_global(home, share, f); } index_method(known_cons) constraintlist config::known_cons( ) const { constraintlist u = home->assumed_cons; u.merge( assumed_cons ); u.merge( share->ycon ); u.merge( con ); if ( share != home->configs(home->base).share ) u.merge( home->configs(home->base).share->ycon ); if ( share->ww.divisible(4) && home->dim >= 3 ) u.merge( constraint(String("div8>=") + dec(Ipow(2, home->dim - 3))) ); return u; } index_method(activate_wjv) // I don't know why this is needed. void activate_wjv( config& c, codetable& results ) { if ( c.share->wjv.length == 0 && auto_joint_list ) c.home->basic_joint_vars( &c, results ); } index_method(del_weight) bool config::del_weight(int weight, codetable& results) { if ( !share->ww.contains(weight) ) return false; share->ww.del(weight); activate_wjv(*this, results); if ( share->wjv.length > 0 ) { prevector& vars = share->wjv; SLList vars_new; for ( int i = 0; i < vars.length; i++ ) { int i1, i2, i3; parse_j_var( vars(i), i1, i2, i3 ); if ( share->ww.contains(i1) && share->ww.contains(i2) && share->ww.contains(i3) ) vars_new.append( vars(i) ); } vars = vars_new; } forPixDef( p, share->ycon ) { constraint& c = share->ycon(p); static Regex basic_joint_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); if ( c.simple( ) && c.sense == '=' && c.RHS == 0 && c.LHS.front( ).var.matches( basic_joint_pattern ) ) { int i1, i2, i3; parse_j_var( c.LHS.front( ).var, i1, i2, i3 ); if ( !share->ww.contains(i1) || !share->ww.contains(i2) || !share->ww.contains(i3) ) share->ycon.del(p, -1); } } return true; } TEX(![ The following routine ``adjoins'' a constraint which has been proved by one of the constraint generation commands, such as {\tt show} or {\tt infer}. It is not always the case that a constraint is added to a constraintlist. Moreover, depending on what the constraint is, some additional action may be taken. The flag ``\verb|new_active_needed|'' is set if the \verb|config_active| object will need to be recomputed; this will be the case if either a basic global variable or a basic local variable is set to $0$. Otherwise, the flag is not modified. The given configuration must be {\tt current}, or else bad things will happen. This is a poor design feature which should be corrected. ]!) index_method(add_constraint) void config::add_constraint(constraint conx, codetable& results, bool& new_active_needed, bool no_create) { static Regex ynumber_pat( "y" + number_pat + orsign + "x_" + number_pat + orsign + "x[0-9]" ); static Regex basic_joint_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); if ( conx.LHS.empty( ) ) { share->ycon.merge(conx); return; } term term1 = conx.LHS.front( ); if (conx.simple( ) && conx.sense == '<' && conx.RHS == 0) conx.sense = '='; TEX( ![ \begin{quote} Does the constraint have the form ``variable = 0''? \end{quote} ]! ) if ( conx.simple( ) && conx.sense == '=' && conx.RHS == 0 ) { if ( term1.var[0] == 'x' && part.length == 1 ) { term1.var.del( '_' ); term1.var.gsub( 'x', 'y' ); } // Does the constraint set a basic global variable to 0? if ( term1.var.matches(ynumber_pat) ) { new_active_needed = del_weight( yno(term1.var), results ); return; } // Does the constraint set a basic joint variable to 0? activate_wjv(*this, results); if ( share->wjv.length > 0 && term1.var.matches(basic_joint_pattern) ) { int i1, i2, i3; parse_j_var( term1.var, i1, i2, i3 ); String var = make_j_var( i1, i2, i3 ); share->wjv.pos_del( var, &String_cmp ); } // Does it set a mu variable to 0? if_match( term1.var, "mu" + number_pat ) { int weight = as_int(term1.var.after("mu")); if ( share->dual_min_low == weight ) { share->dual_min_low += 1; share->ycon.merge(conx); new_active_needed = true; return; } } // Does it set a z_0_r variable equal to zero? This may imply // that a certain joint variable is zero. if ( term1.var[0] == 'z' ) { String vz = term1.var; vz[0] = 'x'; wordtype zz(this, vz); if ( zz.length == 2 && zz(0) == 0 ) { if ( assumed_cons.length( ) == 0 && dualsmall.basis.nrows == 0 && small.basis.nrows == 1 && small.basis(0,0) == 1 && small.basis(0,1) == 0 ) home->configs(home->base).share->ycon.merge( constraint( String("jy") + dec(part(0).x) + "d" + dec(zz(1).x) + "=0" ) ); } } // Does it set a basic local variable to 0? Probably we should // use the "orbit" routine instead. if ( term1.var.contains("x", 0) && assumed_cons.global( ) ) { // Note the inefficiency of the following. It may be that // the automorphism group has already been computed, and is // trivial. Then we recompute it needlessly. if ( aut.length == 0 ) { pair< Permutationlist, Integer > pp = find_automorphism_group( ); aut = pp.first; } OSLList orb; Pix yy, zz; orb.add( wordtype( this, term1.var ) ); int old_length; wordtype wt; do { old_length = orb.length( ); for( int ii = 0; ii < aut.length; ii++ ) { check_orb: forPix( yy, orb ) { wt = orb(yy); aut(ii).act(wt); forPix( zz, orb ) if ( equiv(part, small.basis, wt, orb(zz)) ) break; if ( zz == 0 ) { orb.add(wt); goto check_orb; } } } } while( old_length != orb.length( ) ); forPix( yy, orb ) con.merge( constraint( orb(yy).variable( ) + "=0" ) ); } if ( term1.var.contains("x", 0) ) new_active_needed = true; // Does it set a basic local variable to 0 in such a way that // one should deduce the zeroness of a joint variable for a basal // configuration (and for current)? if ( term1.var.contains("x", 0) && part.length <= 2 && small.basis.nrows == 1 && dualsmall.basis.nrows == 0 && ( part.length == 1 || small.basis(0,0) != small.basis(0,1) ) ) { wordtype w( this, term1.var ); int i1, i2, i3; if ( part.length == 1 ) { i1 = w(0); i2 = home->n; i3 = home->n - w(0); } else if ( small.basis(0,0).x == 0 ) { i1 = part(1); i2 = w(0) + w(1); i3 = w(0) + part(1) - w(1); } else { i1 = part(0); i2 = w(0) + w(1); i3 = w(1) + part(0) - w(0); } String varz = make_j_var( i1, i2, i3 ); activate_wjv(*this, results); if (share->wjv.length > 0) share->wjv.pos_del(varz, &String_cmp); forPixDef( p, home->configs ) { config& cf = home->configs(p); if ( cf.basal( ) && assumed_cons <= cf.assumed_cons ) { cf.share->ycon.merge( constraint( varz + "=0" ) ); if ( cf.share->wjv.length > 0 ) { cf.share->wjv.pos_del( varz, &String_cmp ); new_active_needed = true; } } } } } TEX( ![ \begin{quote} Does the constraint have the form ``$\verb|div|i = 2^k$'' (for some $i$) or ``{\tt div4 = }$2^{k-2}$'', where $k$ is the dimension of the code type? \end{quote} ]! ) if ( conx.simple( ) && conx.LHS.front( ).var.contains("div") && conx.sense == '=' && conx.RHS == Ipow(2, home->dim) ) { int div = as_int( conx.LHS.front( ).var.after("div") ); share->ww.make_divisible(div); new_active_needed = true; } if (conx.simple( ) && conx.LHS.front( ).var == "div4" && conx.sense != '>') { if ( conx.RHS == Ipow(2, home->dim - 2) ) new_active_needed = true; } TEX( ![ \begin{quote} Append the constraint. \end{quote} ]! ) if ( conx.joint( ) ) share->ycon.merge(conx); else con.merge(conx); TEX( ![ \begin{quote} If the constraint sets a basic global variable to a nonzero value, and this results in the weight enumerator being completely determined, we delete some weights from the working weightlist. Also, the nonzeroness of a basic global variable may force some other basic global variables to be zero. \end{quote} ]! ) if ( conx.simple_global( ) && conx.sense != '<' && conx.RHS > 0 ) { weightlist& w = home->ww(home->current); if ( w.length( ) != 1 ) { int d = w.min( ); int yn = yno( conx.LHS.front( ).var ); Pix p; int i, n = home->n; bool weight_deleted = false; begin_del: forPix( p, w ) { if ( w(p) != yn && 2 * n - w(p) - yn < d ) { del_weight( w(p), results ); weight_deleted = true; goto begin_del; } } Integer low, high; vector lowv(n+1); lowv.set_zero( ); lowv(0) = 1; forPix( p, w ) { if ( w(p) == 0 ) continue; low = 0; high = -1; evaluate( String("y") + dec(w(p)), low, high ); lowv( w(p) ) = low; } Integer sum = 0; for ( i = 0; i <= n; i++ ) sum += lowv(i); if ( sum == Ipow(2, home->dim) ) for ( i = 0; i <= n; i++ ) if ( lowv(i) == 0 ) { del_weight(i, results); weight_deleted = true; } if (weight_deleted) new_active_needed = true; } } TEX(![ \begin{quote} If the constraint tells us that a {\tt mu} variable is nonzero, and {\tt[current]} $\sim$ {\tt[base]}, we subdivide {\tt[base]} accordingly. \end{quote} ]!) if ( conx.simple( ) ) { String vb = term1.var; if ( vb[0] == 'm' && conx.sense != '<' && conx.RHS >= 1 && share == home->configs(home->base).share ) { int mu_no = as_int( vb.after("mu") ); config c( home, String( dec(home->n - mu_no) ) + "," + dec(mu_no) + "::{01}" ); Pix p = home->merge_config(c); home->configs.join( home->base, p ); } } TEX(![ \begin{quote} If the constraint tells us that the sum of one or more nontrivial basic local variables is nonzero, we subdivide and adjoin the corresponding logical data. (This feature is not adequately documented.) If one or more of the basic local variables are inadmissible, this will cause pointless but harmless things to happen. In the case where the partition has one part, we have to treat the variable {\tt y}$i$ like \verb|x_|$i$. Because we subdivide, this part of \verb|add_constraint| is a potential time sink. \end{quote} ]!) // Note!! The following line bypasses the subdivision step. Is it OK? if ( 1 == 1 ) return; if ( conx.sense == '<' || conx.RHS <= 0 || no_create ) return; SLList ws; forPixDef( ee, conx.LHS ) { if ( conx.LHS(ee).coeff != Rational(1) ) return; String vb = conx.LHS(ee).var; if ( vb[0] != 'x' && (vb[0] != 'y' || part.length != 1) ) return; wordtype w = wordtype(this, vb); word mm(part.length); int i; for ( i = 0; i < mm.length; i++ ) { if ( w(i) == 0 ) mm(i) = 0; else if ( w(i) == part(i) ) mm(i) = 1; else break; } if ( !( i == mm.length && small.basis.rowspace_member(mm) ) ) ws.append(w); } if ( ws.empty( ) ) return; home->activate(true, results); if ( ws.length( ) == 1 ) { Pix pi = subdivide( home->configs(home->current), ws.front( ), results ); home->configs.join( home->current, pi, ws.front( ) ); } else { SLList pxs; forPix( ee, ws ) pxs.append( subdivide( home->configs(home->current), ws(ee), results ) ); home->implications.append(make_pair( home->current, pxs )); } } void config::add_constraint(String conx_s, codetable& results, bool& new_active_needed) { constraint conx(conx_s); add_constraint( conx, results, new_active_needed ); } index_method(analyze_local_relations) void analyze_local_relations( config* c, codetable& results ) { c->home->activate( true, results ); mawhometable& vt = c->home->active->vtable; int nvars = vt.length; SLList aw; for ( int i = 0; i < vt.length; i++ ) { forPixDef( p, vt(i).w ) { wordtype alttype = vt(i).maw; alttype.act( vt(i).w(p) ); aw.append(alttype); } } prevector awv(aw); int np = c->part.length; int i, j; partition p = c->part; c->small.build( ); c->home->basic_joint_vars(c, results); prevector vars = c->share->wjv; prevector< prevector< prevector > > poss(awv.length); for ( int i1 = 0; i1 < awv.length; i1++ ) { poss(i1).set_size(nvars); for ( int i2 = 0; i2 < nvars; i2++) { poss(i1)(i2).set_size(nvars); for ( int i3 = 0; i3 < nvars; i3++ ) { poss(i1)(i2)(i3) = false; wordtype u = awv(i1); wordtype v = vt(i2).maw; wordtype w = vt(i3).maw; for ( i = 0; i < np; i++ ) { if ( (u(i) + v(i) + w(i)) % 2 != 0 ) break; if ( u(i) + v(i) + w(i) > 2*p(i) ) break; if ( w(i) < abs( u(i) - v(i) ) ) break; if ( u(i) < abs( w(i) - v(i) ) ) break; if ( v(i) < abs( w(i) - u(i) ) ) break; } if ( i < np ) continue; for ( i = 0; i < c->small.x.nrows; i++ ) { for ( j = 0; j < c->small.x.nrows; j++ ) { word up = c->small.x(i), vp = c->small.x(j); wordtype ux = u; wordtype vx = v; wordtype wx = w; ux.act( up, u ); vx.act( vp, v ); wx.act( up + vp, w ); String var = make_j_var( sum(ux), sum(vx), sum(wx) ); if ( !vars.member(var) ) break; } if ( j < c->small.x.nrows ) break; } if ( i < c->small.x.nrows ) continue; poss(i1)(i2)(i3) = true; } } } prevector jok( vars.length ); for ( i = 0; i < vars.length; i++ ) jok(i) = false; for ( int i1 = 0; i1 < awv.length; i1++ ) for ( int i2 = 0; i2 < nvars; i2++) for ( int i3 = 0; i3 < nvars; i3++ ) if ( poss(i1)(i2)(i3) ) { wordtype u = awv(i1); wordtype v = vt(i2).maw; wordtype w = vt(i3).maw; for ( i = 0; i < c->small.x.nrows; i++ ) { for ( j = 0; j < c->small.x.nrows; j++ ) { word up = c->small.x(i), vp = c->small.x(j); wordtype ux = u; wordtype vx = v; wordtype wx = w; ux.act( up, u ); vx.act( vp, v ); wx.act( up + vp, w ); String var = make_j_var( sum(ux), sum(vx), sum(wx) ); int pos = vars.find(var); if ( pos == -1 ) INTERNAL_ERROR( "analyze_local_relations" ); jok(pos) = true; } } } prevector& jvars = c->home->configs(c->home->current).share->wjv; for ( i = 0; i < vars.length; i++ ) { if ( !jok(i) ) { if (auto_analyze_local_relations_vocal) cerr << "NO: " << vars(i) << "\n"; jvars.pos_del( vars(i), &String_cmp ); } } } index_method(check_secondary_residuals) void config::check_secondary_residuals(codetable& results) { if ( share->realizable == -1 ) INTERNAL_ERROR( "check_secondary_residuals invoked on unrealizable configuration." ); if ( !secondary_plus || home->dim <= 2 ) return; bool nan = false; home->activate(true, results); SLList answer; small.build( ); int i, j, k, l, m, r, fl, dw, d = share->ww.min( ), n = home->n; mawhometable& vt = home->active->vtable; wordtype v(this); Pix p, q; config_core cc(*this); iterate: for ( i = 1; i < vt.length; i++ ) { forPix( q, answer ) if ( answer(q) == vt(i).maw ) break; if ( q != 0 ) continue; partition dpart = subdivide_partition( part, vt(i).maw ); code dsmall; dsmall.basis = subdivide_matrix( small.basis, part, vt(i).maw, true ); dsmall.build( ); TEX( ![ \begin{quotea} Make a list of all the admissible wordtypes for the subdivision of {\tt[current]} along its \th{i}\ wordtype. \end{quotea} ]! ) SLList vars; for ( k = 0; k < vt.length; k++ ) { forPix( q, answer ) if ( answer(q) == vt(k).maw ) break; if ( q != 0 ) continue; term_sum t = subdivide_basic_local_variable( dpart, dsmall.basis, *(home->active), vt(i).maw, vt(k).maw, false ); forPix( p, t ) { // Build the wordtype corresponding to t(p).var, // except that we don't actually have a // configuration, so we have to do some stupid // stuff. prevector args; if ( t(p).var[1] == '_' ) args = unpack(t(p).var.after("x_"), "_"); else args = unpack(t(p).var.after("x"), ""); wordtype wt(args.length); for ( l = 0; l < args.length; l++ ) wt(l) = as_int(args(l)); for ( l = 0; l < dsmall.x.nrows; l++ ) { wordtype wt2(args.length); for ( m = 0; m < dpart.length; m++ ) { if ( dsmall.x(l)(m).x == 0 ) wt2(m) = wt(m); else wt2(m) = dpart(m) - wt(m); } vars.append(wt2); } } } prevector varsv(vars); // We sort now, which is bad. Instead, we should not have generated // duplicate wordtypes in the first place. varsv.unique_sort(&wcmp); vector indx(dpart.length); while( indx.advance( ) ) { int iw = indx * dpart, Pn = dpart.n - iw, Pk, Pd = Pn; if ( Pn == 0 ) continue; int Sn = iw, Sk, Sd = Sn + 1; for ( l = 0; l < varsv.length; l++ ) { for ( m = 0; m < dpart.length; m++ ) if ( !indx(m) && varsv(l)(m) != 0 ) break; if ( m == dpart.length ) { int Sd_new = indx * varsv(l); if ( Sd_new != 0 ) Sd = min( Sd, Sd_new ); } int Pd_new = 0; for ( m = 0; m < dpart.length; m++ ) if ( !indx(m) ) Pd_new += varsv(l)(m); if ( Pd_new != 0 ) Pd = min( Pd, Pd_new ); } for ( Sk = 0; Sk <= min(Sn, home->dim) - 1; Sk++ ) if ( results.not_exist( Sn, Sk + 1, Sd ) ) break; if ( Sk != home->dim ) { if ( results.not_exist( Pn, home->dim - Sk, Pd ) ) { answer.append( vt(i).maw ); add_constraint( vt(i).maw.variable( ) + "=0", results, nan ); cerr << "appending " << vt(i).maw.variable( ) << " to answer\n"; goto iterate; } } } } if (nan) home->deactivate( ); } index_method(terminal) bool config::terminal( ) const { return small.basis.nrows == home->dim && dualsmall.basis.nrows == 0 && assumed_cons.global( ); } index_method(full) bool config::full( ) const { return small.basis.nrows == home->dim; } TEX(![ Test to see if a variable is valid, i.e.\ known to the language. Exit with error if not. Note that {\tt v} variables are not included, because they are not supposed to be entered by the user. ]!) index_method(check_global_variable) bool check_global_variable(String v, int n) { static Regex div_number_pattern("div" + number_pat); String rest; if ( v[0] == 'y' ) { rest = v.after("y"); if_no_match( rest, number_pat ) return false; return Integer(rest) <= n; } if ( v[0] == 'm' && v.length( ) >= 2 && v[1] == 'u' ) return Integer( String(v.after("mu")) ) <= n; if ( v.matches(div_number_pattern) ) { rest = v.after("div"); if ( Integer(rest) > n || Integer(rest) == 0 ) return false; int divi = as_int(rest); while( even(divi) ) divi /= 2; return divi == 1; } return false; } index_method(check_variable) void config::check_variable(String v) const { static Regex word_pattern( "[01]*" ); static Regex sub_pattern( "sub.*" ); static Regex dual_pattern( "q" + list_of( "_" + left + "z" + orsign + number_pat + right, "") + orsign + "q[0-9z]+" ); static Regex basic_joint_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); static Regex jdi_pattern( "jy" + number_pat + "d" + number_pat + "i" + number_pat ); static Regex jyd_pattern( "jy" + number_pat + "d" + number_pat ); static Regex jd_pattern( "jd" + number_pat + "d" + number_pat + "d" + number_pat ); static Regex number_pattern(number_pat); String rest; if ( check_global_variable( v, part.n ) ) return; if ( v[0] == 'x' || v[0] == 'z' ) { v[0] = 'x'; wordtype(this, v); return; } if ( v.matches( sub_pattern ) ) { rest = v.after("sub"); String wd = take( rest, word_pattern ); if ( wd.length( ) != part.length ) goto invalid_variable; if ( rest.length( ) == 0 ) return; if_no_match( rest, "_" + number_pat ) goto invalid_variable; rest = rest.after("_"); if ( Integer(rest) > part.n ) goto invalid_variable; return; } if ( v.matches( dual_pattern ) ) { prevector qs; if ( v[1] == '_' ) qs = unpack( v.after("q_"), "_"); else qs = unpack( v.after("q"), "" ); if ( qs.length != part.length ) goto invalid_variable; for ( int i = 0; i < qs.length; i++ ) if ( qs(i) != "z" && Integer( qs(i) ) > Integer(part(i)) ) goto invalid_variable; return; } if ( v == "jdiv2" || v == "jdiv4" ) return; if ( v.matches( basic_joint_pattern ) || v.matches( jdi_pattern ) || v.matches( jd_pattern ) || v.matches( jyd_pattern) ) { int r, s, t; parse_j_var( v, r, s, t ); if ( (v.matches(basic_joint_pattern) || v.matches(jd_pattern)) && r <= part.n && s <= part.n && t <= part.n && r + s >= t && r + t >= s && s + t >= r && r + s + t <= 2*part.n ) return; if ( v.matches(jdi_pattern) && t <= r && t <= s && r + s - t <= part.n ) return; if ( v.matches(jyd_pattern) && r + s <= part.n ) return; } if ( v.contains( "co", 0 ) ) { String v2 = v.after( "co" ); if ( v2.empty( ) ) return; if ( v2.matches(number_pattern) && as_int(v2) <= part.n ) return; } invalid_variable: ERROR("The variable \"" << v << "\" is not defined in the language."); } index_method(cmp_second) inline int cmp_second(const pair< vector, matrix >& a, const pair< vector, matrix >& b ) { return cmp( a.second, b.second ); } TEX(![ \verb|configuration_search(c1, c2)|: Let {\tt c1} be a terminal configuration, and let {\tt c2} be any configuration. Determine if the words defined by {\tt c2.small.basis} could be in the code $C$ defined by {\tt c1}. ]! ) index_method(configuration_search) bool configuration_search( const config& c1, const config& c2, String lab1, String lab2 ) { c1.small.build( ); bool example_printed = false; pair< Permutationlist, Integer > pp; if ( configuration_search_group_level > 0 ) pp = c1.find_automorphism_group( ); Permutationlist gp(c1.part.length); if ( configuration_search_group_level > 1 ) { Permutationlist gen(c1.part.length); int i; for ( i = 0; i < pp.first.length; i++ ) gen.append( pp.first(i) ); int cap = configuration_search_group_size_cap; if ( cap == 0 ) cap = -1; gp.generate(gen, cap); } matrix B2 = c2.small.basis; if ( c2.gen.x != 0 ) B2 = c2.gen; int r = B2.nrows; int M = c1.small.x.nrows; int k, l; int intersection_weight; SLList< vector > part[r+1]; SLList< matrix > red[r+1]; vector first(0); part[0].append( first ); bool group_not_used_yet = true; for ( int level = 1; level <= r; level++ ) { word subset0( level-1 ), subset( level ); subset( level-1 ) = 1; int nsubsets = Ipow( 2, level-1 ); prevector iw( nsubsets ); int count = 0; do { for ( l = 0; l < level-1; l++ ) subset(l) = subset0(l); intersection_weight = 0; for ( k = 0; k < c2.part.length; k++ ) { for ( l = 0; l < level; l++ ) { if ( !subset(l) ) continue; if ( !B2(l,k) ) break; } if ( l == level ) intersection_weight += c2.part(k); } iw( count++ ) = intersection_weight; } while( subset0.advance( ) ); int bw = B2(level-1) * c2.part; forPixDef( p, part[ level - 1 ] ) { vector next(level); for ( l = 0; l < level-1; l++ ) next(l) = part[ level - 1 ](p)(l); subset0.set_zero( ); count = 0; matrix piw( nsubsets, c1.part.length ); do { intersection_weight = 0; for ( k = 0; k < c1.part.length; k++ ) { for ( l = 0; l < level-1; l++ ) if ( subset0(l) && !next(l)(k) ) break; piw( count, k ) = ( l == level-1 ); } count++; } while( subset0.advance( ) ); for ( int J = 0; J < M; J++ ) { next( level-1 ) = c1.small.x(J); word nx = next( level-1 ); if ( nx.weight( ) != bw ) continue; TEX( \begin{quotec} The next loop cycles through subsets of the {\tt level} elements. The intersection of the words in the subset should have the same weight as the intersection of the corresponding words in {\tt c2}'s small code. \end{quotec} ) intersection_weight = 0; gf2* nxx = nx.x; number* c1px = c1.part.x; for ( count = 1; count < nsubsets; count++ ) { intersection_weight = iw(count); bool* piwc = piw(count).x; if ( c1.part.n == c1.part.length ) { for ( k = 0; k < c1.part.length; k++ ) { if ( nxx[k] && piwc[k] ) intersection_weight--; } } else { for ( k = 0; k < c1.part.length; k++ ) { if ( nxx[k] && piwc[k] ) intersection_weight -= c1px[k]; } } if ( intersection_weight != 0 ) break; } if ( intersection_weight == 0 ) { if ( level == r && configuration_search_show_example && !example_printed ) { cerr << "Example:\n"; for ( k = 0; k < r; k++ ) cerr << " " << next(k) << "\n"; example_printed = true; } if ( level == r && !configuration_search_to_end ) return true; if ( level == r ) { matrix C( level, c1.part.length ); for ( k = 0; k < level; k++ ) C(k) = next(k); C.reduce_nz( ); forPixDef( q, red[level] ) if ( red[level](q) == C ) break; if ( q == 0 ) { red[level].append(C); part[level].append(next); } } else part[level].append(next); } } } if ( level <= configuration_search_group_level ) { prevector< vector > oldpart( part[level] ); int old_length = oldpart.length; oldpart.sort( &cmp ); EquivRelIntList e( oldpart.length ); Permutationlist* G = (group_not_used_yet ? &(pp.first) : &gp); for ( int i = 0; i < (*G).length; i++ ) { for ( int j = 0; j < oldpart.length; j++ ) { if ( !group_not_used_yet && !e.minimal(j) ) continue; vector w = oldpart(j); for ( k = 0; k < level; k++ ) (*G)(i).act( w(k) ); k = oldpart.pos( w, cmp ); if ( k == -1 && group_not_used_yet ) INTERNAL_ERROR( "configuration_search" ); if ( k != -1 ) e.join( j, k ); } } part[level].clear( ); for ( int j = 0; j < oldpart.length; j++ ) if ( e.minimal(j) ) part[level].append( oldpart(j) ); int new_length = part[level].length( ); if ( new_length < old_length ) group_not_used_yet = false; } cerr << "level " << level << " has " << part[level].length( ) << " elements\n"; if ( level == r && configuration_search_expand_final_count && configuration_search_group_level > 0 ) { // First expand. bool something_changed; do { something_changed = false; forPixDef( q, part[r] ) { for ( int i = 0; i < pp.first.length; i++ ) { vector w = part[r](q); for ( k = 0; k < r; k++ ) pp.first(i).act( w(k) ); matrix C( r, c1.part.length ); for ( k = 0; k < r; k++ ) C(k) = w(k); C.reduce_nz( ); forPixDef( qr, red[r] ) if ( red[r](qr) == C ) break; if ( qr == 0 ) { something_changed = true; red[r].append(C); part[r].append(w); } } } } while( something_changed ); int expanded_count = part[r].length( ); // Then reduce. prevector< pair< vector, matrix > > oldpart( part[r].length( ) ); int i = 0; Pix qr = red[r].first( ); forPixDef( q, part[r] ) { oldpart(i++) = make_pair( part[r](q), red[r](qr) ); red[r].next(qr); } sort_by_secondz( oldpart ); EquivRelIntList e( oldpart.length ); for ( i = 0; i < pp.first.length; i++ ) { for ( int j = 0; j < oldpart.length; j++ ) { vector w = oldpart(j).first; for ( k = 0; k < r; k++ ) pp.first(i).act( w(k) ); matrix C( r, c1.part.length ); for ( k = 0; k < r; k++ ) C(k) = w(k); C.reduce_nz( ); k = oldpart.pos( make_pair(w, C), cmp_second ); if (k == -1) INTERNAL_ERROR( "configuration_search" ); e.join( j, k ); } } part[r].clear( ); for ( int j = 0; j < oldpart.length; j++ ) if ( e.minimal(j) ) part[r].append( oldpart(j).first ); int reduced_count = part[r].length( ); cerr << "The number of subcodes of " << lab1 << " which are " << "isomorphic to " << lab2 << " is " << expanded_count << ". Relative to the action of the " << "automorphism group of " << lab1 << ", these subcodes " << "occur in " << reduced_count << " orbits.\n"; } if ( level == r && configuration_search_print_final_list ) { int ct = 1; forPixDef( q, part[r] ) { cerr << "Number " << ct++ << ":\n"; for ( k = 0; k < r; k++ ) cerr << " " << part[r](q)(k) << "\n"; } } if ( level == r ) return part[r].length( ) != 0; } } TEX( \verb|expand_term_sum(t)|: Expand the sum of terms {\tt t} as a linear combination of {\tt v} variables. Return a vector {\tt v} whose \th{i}\ entry is the coefficient of $\hbox{\tt v}(i+1)$ in the expanded expression. ) index_method(expand_term_sum) void config_active::expand_term_sum(const term_sum& t, vector& v) const { static Regex zero_one_string( "[01]*" ); config_core core(*c); term_sum tg = core.simplify_global_vars(t, c->share->ww, c->home->dim); v.set_size(vtable.length); v.set_zero( ); HIDE( ![ if ( y_as_vsum.length != c->share->ww.length( ) ) INTERNAL_ERROR("expand_term_sum: ww modified without deactivation." << " The working weight list is " << c->share->ww << " but y_as_vsum has length " << y_as_vsum.length << "."); ]! ) forPixDef( i, tg ) { // There are many cases, corresponding to the many possible types // of variables. HIDE( ![ if ( joint_var( tg(i).var ) ) INTERNAL_ERROR( "Joint variable passed to expand_term_sum." ); ]! ) if ( tg(i).var[0] == 'v' ) { int var_no = as_int( tg(i).var.after("v") ); v(var_no - 1) += tg(i).coeff; } else if ( tg(i).var[0] == 'y' ) { int r = 0, weight = yno( tg(i).var ); forPixDef( j, c->share->ww ) { if ( weight == c->share->ww(j) ) break; r++; } if ( j == 0 ) continue; forPix( j, y_as_vsum(r) ) { term& tt = y_as_vsum(r)(j); int var_no = as_int( tt.var.after("v") ); v(var_no - 1) += tt.coeff * tg(i).coeff; } } else if ( tg(i).var[0] == 'x' ) { int var_no = x_to_v(tg(i).var); if ( var_no != 0 ) v(var_no - 1) += tg(i).coeff; } else if ( tg(i).var[0] == 's' ) { String rest = tg(i).var.after("sub"); word w( take( rest, zero_one_string ), 0 ); int mm = -1; if ( !rest.empty( ) ) mm = as_int( rest.after("_") ); wordtype z(c); for ( int l = 0; l < vtable.length; l++ ) { forPixDef( j, vtable(l).w ) { z.act( vtable(l).w(j), vtable(l).maw ); if ( w.complement( ) * z == 0 ) if ( mm == -1 || sum(z) == mm ) v(l) += tg(i).coeff; } } } else if ( tg(i).var[0] == 'z' || tg(i).var[0] == 'q' ) { prevector ss; char z_or_q = tg(i).var[0]; tg(i).var.del(z_or_q); if ( tg(i).var[0] == '_' ) ss = unpack( tg(i).var.after("_"), "_" ); else ss = unpack( tg(i).var, "" ); wordtype wt(c); word w(c->part.length); w = w.complement( ); int j, l; for ( l = 0; l < c->part.length; l++ ) { if ( ss(l) == "z" ) w(l) = 0; else wt(l) = as_int( ss(l) ); } Integer** binom = new Integer*[c->home->n + 1]; for ( l = 0; l <= c->home->n; l++ ) { binom[l] = new Integer[l+1]; binom[l][0] = 1; for ( j = 1; j < l; j++ ) binom[l][j] = binom[l-1][j] + binom[l-1][j-1]; binom[l][l] = 1; } vector vi(vtable.length); convert_dual_variable(w, wt, binom, vi); Integer code_size = Ipow(2, c->home->dim); for ( j = 0; j < vtable.length; j++ ) { if ( z_or_q == 'z' ) v(j) += tg(i).coeff * Rational( vi(j), code_size ); else v(j) += tg(i).coeff * Rational(vi(j)); } for ( l = 0; l <= c->home->n; l++ ) delete [ ] binom[l]; delete [ ] binom; } } } index_method(add_to_rational_constraint) void add_to_rational_constraint ( qvconstraint& qv, const vconstraint& vcon, Rational& multiplier ) { // We're building a <= constraint. If the contribution will // amount to a >= constraint, it can't be used. Ignore it. if ( vcon.sense == '<' && sign(multiplier) < 0 ) return; if ( vcon.sense == '>' && sign(multiplier) > 0 ) return; qv.RHS += Rational(vcon.RHS) * multiplier; for ( int i = 0; i < vcon.LHS.length; i++ ) qv.LHS(i) += vcon.LHS(i) * multiplier; } TEX( Two configurations are declared to be ``equal'' if their {\it defining\/} members are equal. ) bool operator==(const config& c1, const config& c2) { return (mostly_equal(c1,c2) && c1.assumed_cons == c2.assumed_cons); } TEX(![ The routine ``\verb|is_automorphism|'' does not do a good job with local variables in assumed constraints. Indeed, if $\cal T$ is the set of assumed constraints for the configuration, what is tested is not whether $\sigma(\cal T) \sim \cal T$, but rather whether $\sigma(f) \sim f$, for all $f \in \cal T$. Thus \verb|is_automorphism| will sometimes return {\tt false} when it should return {\tt true}. ]!) index_method(is_automorphism) bool config::is_automorphism(const Permutation& p, codetable& results) { // Check to see if the alleged permutation preserves the sizes // of the partition elements. int i; for ( i = 0; i < part.length; i++ ) if ( part(i) != part(p(i)-1) ) return false; // Does it preserve the basis and dual basis? matrix* b[ ] = { &small.basis, &dualsmall.basis }; for ( int k = 0; k < 2; k++ ) { Permutation* colfix = b[k]->column_fix( ); matrix permuted_basis = *(b[k]); Permutation colfix_i = colfix->inverse( ); permuted_basis.permute_columns( (*colfix) * p * colfix_i ); int rank = rank_of_rowspace_sum(*(b[k]), permuted_basis); b[k]->permute_columns(colfix_i); delete colfix; if ( rank != b[k]->nrows ) return false; } // Are assumed constraints preserved? forPixDef( q, assumed_cons ) { term_sum& ts = assumed_cons(q).LHS; term_sum local_part; // to be the local part of the given constraint forPixDef( r, ts ) { // Test for local variable. if ( local_var( ts(r).var ) ) local_part.append( ts(r) ); } if ( local_part.length( ) != 0 ) { home->activate(false, results); int nvars = home->active->vtable.length; vector vs(nvars), vs_new(nvars); home->active->expand_term_sum(local_part, vs); for ( i = 0; i < nvars; i++ ) { wordtype w = home->active->vtable(i).maw; p.act(w); int j = home->active->vtable.mfind(w); if ( vs(i) != vs(j) ) return false; } } } return true; } TEX( Return weight enumerator of the basic code associated to the small code of a configuration. ) index_method(smallcode_we) vector config_core::smallcode_we( ) const { time_used_by_smallcode_we -= time(0); vector y(part.n + 1); HIDE( ![ if (debug) { matrix m = smallbasis; m.reduce_nz( ); if ( m != smallbasis ) INTERNAL_ERROR( "smallcode_we: matrix not reduced" ); } ]! ) if ( 2 * smallbasis.nrows <= part.n || part.length != part.n ) { y.set_zero( ); if ( smallbasis.nrows <= 31 ) { unsigned long M = Ipow(2, smallbasis.nrows); if ( part.length != part.n ) { vector sum(smallbasis.ncols); y(0) = 1; for ( unsigned long i = 0; i < M - 1; i++ ) { sum += smallbasis.x[ gray(i) ]; ++y( sum * part ); } } else { bitmat A(smallbasis); bitvec sum(smallbasis.ncols); y(0) = 1; for ( unsigned long i = 0; i < M - 1; i++ ) { sum += A.x[ gray(i) ]; ++y( sum.weight( ) ); } } } else // This should be replaced! { vector indx(smallbasis.nrows), sum(smallbasis.ncols); do { mul( indx, smallbasis, sum ); ++y( sum * part ); } while( indx.advance( ) ); } } else { matrix D; basic_small( ).nullspace_equals(D); y = dual_of_we( D.enumerate_weights( ) ); } time_used_by_smallcode_we += time(0); return y; } vector config::smallcode_we( ) const { return config_core(*this).smallcode_we( ); } TEX( Return a generator matrix for the basic code associated to the small code of a configuration. ) index_method(basic_small) matrix config_core::basic_small( ) const { matrix M(smallbasis.nrows, part.n); int k = 0; // column index for M for ( int j = 0; j < smallbasis.ncols; j++ ) { for ( int l = 0; l < part(j); l++ ) for ( int i = 0; i < smallbasis.nrows; i++ ) M(i, k + l) = smallbasis(i,j); k += part(j); } return M; } matrix config::basic_small( ) const { return config_core(*this).basic_small( ); } index_method(basic_dualsmall) matrix config_core::basic_dualsmall( ) const { matrix M(dualsmallbasis.nrows, part.n); int k = 0; // column index for M for ( int j = 0; j < dualsmallbasis.ncols; j++ ) { for ( int l = 0; l < part(j); l++ ) for ( int i = 0; i < dualsmallbasis.nrows; i++ ) M(i, k + l) = dualsmallbasis(i,j); k += part(j); } return M; } HIDE( ![ template void sort_by_second( prevector< pair >& ); ]! ) TEX( ![ \verb|invariant_generating_set|:\ Given a matrix $M$ over $\F_2$ with linearly independent rows, and a partition $p$, with the length $\ell$ of $p$ equalling the number of columns of $M$, find a subset $S$ of the rowspace $V$ of $M$ with the following properties. First, $S$ generates $V$. Second, $S$ is invariant, meaning that if $\sigma \in S_{\ell}$ and $\sigma(p) = p$ and $\sigma(V) = V$, then $\sigma(S) = S$. Third, $S$ is relatively small. Fourth, the routine should be {\it canonical\/} in the sense that if the columns of $M$ are permuted by a permutation $\sigma$, the resulting $S$ will be the same, except that its columns will also be permuted by $\sigma$. The method is to divide $V$ into a collection $\cal C$ of invariant subsets, and then try to find a collection of those subsets whose union is small and yet generates $V$. There is quite a bit of room for improvement in the algorithm. ]! ) index_method(invariant_generating_set) prevector invariant_generating_set( const matrix& M, const partition& p ) BHIDE1( ![ if ( M.ncols != p.length ) INTERNAL_ERROR("invariant_generating_set: garbage input"); ]!, ![ if ( M.nrows == 0 ) return prevector(0); ]! ) time_used_by_igs -= time(0); int i, j, n = p.n, nparts = p.length; prevector< pair< SLList, matrix > > bag(n+1); TEX( ![ \begin{quote} Let $\verb|bag(|i\verb|).first|$ be the set of all coordinate vectors of words of weight $i$ in $V$, where the weights are computed relative to $p$. Let $\verb|bag(|i\verb|).second|$ be a basis for $\verb|bag(|i\verb|).first|$. We do a pass first in which we try to ignore the larger sets of words. \end{quote} ]! ) vector count(n+1); count.set_zero( ); word ind(M.nrows), x(M.ncols); int best_ct, best_ct_save; static int top(20); int pass = 1; if ( M.nrows <= 31 && n == nparts ) { bitmat A(M); unsigned long X = Ipow(2, M.nrows); bitvec sum( M.ncols ); restart0: sum.set_zero( ); if ( pass == 1 ) { ++count(0); bag(0).first.append(ind); } for ( unsigned long l = 0; l < X - 1; l++ ) { int g = gray(l); sum += A.x[g]; ind.x[g].x ^= 1; int ar = sum.weight( ); ++count(ar); if ( pass == 1 && ( count(ar) >= top || count(ar) > 8192 ) ) continue; if ( pass == 2 && ( count(ar) < top || count(ar) > 8192 ) ) continue; bag(ar).first.append(ind); } for ( i = 0; i <= n; i++ ) { if ( pass == 1 && count(i) >= top ) continue; if ( pass == 2 && count(i) < top ) continue; if ( bag(i).first.length( ) != 0 ) { bag(i).second = matrix(M.nrows, bag(i).first); bag(i).second.reduce_nz( ); } } best_ct = Ipow(2, M.nrows) + 1; best_ct_save = best_ct; for ( i = 0; i <= n; i++ ) { if ( pass == 1 && count(i) >= top ) continue; if ( pass == 2 && count(i) < top ) continue; if ( bag(i).first.length( ) != 0 && bag(i).second.nrows == M.nrows && bag(i).first.length( ) < best_ct ) best_ct = bag(i).first.length( ); } if ( best_ct == best_ct_save && pass == 1 ) { pass = 2; count.set_zero( ); ind.set_zero( ); goto restart0; } top = best_ct + 1; } else // This should be rewritten! { restart: do { mul( ind, M, x ); int ar = (n == nparts) ? x.weight( ) : (x * p); ++count(ar); if ( pass == 1 && count(ar) >= top ) continue; if ( pass == 2 && count(ar) < top ) continue; bag(ar).first.append(ind); } while ( ind.advance( ) != 0 ); for ( i = 0; i <= n; i++ ) { if ( pass == 1 && count(i) >= top ) continue; if ( pass == 2 && count(i) < top ) continue; if ( bag(i).first.length( ) != 0 ) { bag(i).second = matrix(M.nrows, bag(i).first); bag(i).second.reduce_nz( ); } } best_ct = Ipow(2, M.nrows) + 1; best_ct_save = best_ct; for ( i = 0; i <= n; i++ ) { if ( pass == 1 && count(i) >= top ) continue; if ( pass == 2 && count(i) < top ) continue; if ( bag(i).first.length( ) != 0 && bag(i).second.nrows == M.nrows && bag(i).first.length( ) < best_ct ) best_ct = bag(i).first.length( ); } if ( best_ct == best_ct_save && pass == 1 ) { pass = 2; count.set_zero( ); ind.set_zero( ); goto restart; } top = best_ct + 1; } TEX( ![ \begin{quote} Now we have ${\cal C} = \{\verb|bag(|i\verb|).first|\}_{0 \leq i \leq n}$. We would like to apply an algorithm which cycles through the subsets $D$ of $\cal C$ in increasing order according to the size of the union of the sets in $D$, and which does so in an efficient manner. In lieu of such an algorithm, we sort the elements of $\cal C$ by size, and then (using this order on $\cal C$) cycle through its full power set. When we encounter a $D$ which generates, we stop. There is no guarantee that the size of the union of the sets in $D$ is minimized. \end{quote} ]! ) SLList< pair< pair< matrix, int>, int> > cag; for ( i = 0; i <= n; i++ ) { if ( pass == 1 && count(i) >= top ) continue; int bifl = bag(i).first.length( ); if ( bifl != 0 && bifl <= best_ct ) cag.append( make_pair( make_pair( bag(i).second, i ), bifl ) ); } prevector< pair< pair< matrix, int>, int> > vag(cag); sort_by_second(vag); int k = vag.length; word indx(k), indxr(k); // indxr is indx with the bit order reversed do { int nrows = 0, row_ptr = 0; for ( i = 0; i < k; i++ ) indxr(i) = indx(k - i - 1); for ( i = 0; i < k; i++ ) if ( indxr(i) ) nrows += vag(i).first.first.nrows; matrix B( nrows, M.nrows ); for ( i = 0; i < k; i++ ) if ( indxr(i) ) for ( j = 0; j < vag(i).first.first.nrows; j++ ) B(row_ptr++) = vag(i).first.first(j); if ( B.reduce( ) == M.nrows ) break; } while( indx.advance( ) != 0 ); if ( indx.if_zero( ) ) ERROR( "I've encountered a code which I can't compute the " << "automorphism group of because the associated graph " << "will have more than 8192 vertices." ); int sz = 0, ans_ptr = 0; for ( i = 0; i < k; i++ ) if ( indxr(i) ) sz += bag(vag(i).first.second).first.length( ); prevector answer(sz); for ( i = 0; i < k; i++ ) if ( indxr(i) ) { j = vag(i).first.second; forPixDef( q, bag(j).first ) mul( bag(j).first(q), M, answer(ans_ptr++) ); } time_used_by_igs += time(0); return answer; } TEX( ![ Find generators for the automorphism group of a configuration and compute its size. The problem is rephrased in terms of finding the automorphism group of a vertex-colored graph. ]! ) index_method(find_automorphism_group) pair< Permutationlist, Integer > config::find_automorphism_group( ) const { int i, j, n = home->n, nparts = part.length; if ( !assumed_cons.global( ) ) ERROR("The routine find_automorphism_group can only" << " work with configurations having global assumed constraints."); matrix M; if ( 2 * small.basis.nrows <= part.n || part.length != part.n ) M = small.basis; else basic_small( ).nullspace_equals(M); prevector cd = invariant_generating_set( M, part ); prevector dcd = invariant_generating_set( dualsmall.basis, part ); vertex_colored_graph g(nparts + cd.length + dcd.length); for ( i = 0; i < nparts; i++ ) g.c(i) = part(i); for ( i = nparts; i < nparts + cd.length; i++ ) g.c(i) = n + 1; // a color different from the others for ( i = nparts + cd.length; i < g.n; i++ ) g.c(i) = n + 2; // another color for ( i = 0; i < cd.length; i++ ) for ( j = 0; j < nparts; j++ ) if ( cd(i)(j) ) { g.a(j).set(nparts + i); g.a(nparts + i).set(j); } for ( i = 0; i < dcd.length; i++ ) for ( j = 0; j < nparts; j++ ) if ( dcd(i)(j) ) { g.a(j).set(nparts + cd.length + i); g.a(nparts + cd.length + i).set(j); } pair< Permutationlist, Integer > ans0 = g.find_automorphism_group( ); Permutationlist pl(part.length); for ( i = 0; i < ans0.first.length; i++ ) { Permutation q(part.length); for ( j = 0; j < part.length; j++ ) q(j) = ans0.first(i)(j); pl.append(q); } return make_pair( pl, ans0.second ); } index_method(find_automorphism_group) pair< Permutationlist, Integer > find_automorphism_group(const matrix& M) { int i, j, n = M.ncols; if (!matrix_isomorphism_silent) { cerr << "computing the automorphism group of an " << M.nrows << " x " << M.ncols << " matrix; weight enumerator = " << as_poly(M.enumerate_weights( )) << "... "; } partition part(n); part.set_all_ones(n); prevector cd = invariant_generating_set( M, part ); vertex_colored_graph g(n + cd.length); for ( i = 0; i < n; i++ ) g.c(i) = part(i); for ( i = n; i < n + cd.length; i++ ) g.c(i) = n + 1; // a color different from the others for ( i = 0; i < cd.length; i++ ) for ( j = 0; j < n; j++ ) if ( cd(i)(j) ) { g.a(j).set(n + i); g.a(n + i).set(j); } pair< Permutationlist, Integer > ans0 = g.find_automorphism_group( ); Permutationlist pl(part.length); for ( i = 0; i < ans0.first.length; i++ ) { Permutation q(part.length); for ( j = 0; j < part.length; j++ ) q(j) = ans0.first(i)(j); pl.append(q); } if (!matrix_isomorphism_silent) cerr << "done\n"; return make_pair( pl, ans0.second ); } HIDE( ![ SLList< vector > dual_words_of_given_weight(matrix, int); ]! ) // For the following method, both M1 and M2 should be in reduced row-echelon // form. index_method(isomorphic) bool isomorphic( const matrix& M1, const matrix& M2, prevector igs1 ) { if ( M1.nrows != M2.nrows || M1.ncols != M2.ncols ) return false; vector y = M1.enumerate_weights( ); if ( y != M2.enumerate_weights( ) ) return false; int i, j, k, n = M1.ncols; prevector M1l(n), M2l(n); for ( i = 0; i < n; i++ ) { M1l(i) = M1.col(i); M2l(i) = M2.col(i); } M1l.sort(&cmp); M2l.sort(&cmp); if ( M1l == M2l ) return true; if (!matrix_isomorphism_silent) { cerr << "testing to see if two " << M1.nrows << " x " << M1.ncols << " matrices are isomorphic; weight enumerator = " << as_poly(M1.enumerate_weights( )) << "... "; } TEX( ![ \begin{quote} Test for codes with exactly one odd weight. These are extremely difficult for the automorphism tester, but can often be dealt with faster. \end{quote} ]! ) int odd_count = 0; for ( i = 0; i <= n; i++ ) if ( odd(i) && y(i) != 0 ) odd_count++; if (odd_count == 1) { matrix M[2], Me[2], Mh[2]; // code, even subcode, half of it M[0] = M1; M[1] = M2; int l; k = M1.nrows; for ( l = 0; l < 2; l++ ) { for ( i = 0; i < k; i++ ) if ( odd( M[l](i).weight( ) ) ) break; if ( !odd( M[l]( k-1 ).weight( ) ) ) M[l]( k-1 ) += M[l](i); for ( j = 0; j < k-1; j++ ) if ( odd( M[l](j).weight( ) ) ) M[l](j) += M[l]( k-1 ); Me[l] = M[l]; Me[l].resize( k-1, n ); SLList< vector > d2 = dual_words_of_given_weight( Me[l], 2 ); if ( d2.length( ) * 2 != n ) goto special_fails; forPixDef( p, d2 ) { forPixDef( q, d2 ) if ( intersection_size( d2(p), d2(q) ) == 1 ) goto special_fails; } forPix( p, d2 ) if ( int(M[l](k-1, d2(p)(0))) + int(M[l](k-1, d2(p)(1))) != 1 ) goto special_fails; Mh[l].set_size(k-1, n/2); i = 0; forPix( p, d2 ) { for ( j = 0; j < k-1; j++ ) Mh[l](j,i) = Me[l](j, d2(p)(0)); i++; } } if (!matrix_isomorphism_silent) cerr << "reformulating\n"; return isomorphic( Mh[0], Mh[1] ); } special_fails: partition part; part.set_all_ones(n); prevector cd[2]; if ( igs1.x == 0 ) cd[0] = invariant_generating_set( M1, part ); else cd[0] = igs1; cd[1] = invariant_generating_set( M2, part ); if ( cd[0].length != cd[1].length ) { if (!matrix_isomorphism_silent) cerr << "done (false)\n"; return false; } vertex_colored_graph g[2]; for ( j = 0; j < 2; j++ ) { g[j] = vertex_colored_graph(n + cd[j].length); for ( i = 0; i < n; i++ ) g[j].c(i) = 1; for ( i = n; i < n + cd[j].length; i++ ) g[j].c(i) = n + 1; // a color different from the others for ( i = 0; i < cd[j].length; i++ ) for ( k = 0; k < n; k++ ) if ( cd[j](i)(k) ) { g[j].a(k).set(n + i); g[j].a(n + i).set(k); } } bool answer = Isomorphic( g[0], g[1] ); if (!matrix_isomorphism_silent) { if (answer) cerr << "done (yes)\n"; else cerr << "done (no)\n"; } return answer; } TEX( ![ \verb|simple_isomorphic|:\ Determine if there exists a permutation of rows and columns which converts one matrix into another. ]! ) index_method(simple_isomorphic) bool simple_isomorphic( const matrix& M1, const matrix& M2 ) { if ( M1.nrows != M2.nrows || M1.ncols != M2.ncols ) return false; int i, j, l, n = M1.ncols, k = M1.nrows; vertex_colored_graph g[2]; for ( j = 0; j < 2; j++ ) { g[j] = vertex_colored_graph(n + k); for ( i = 0; i < n + k; i++ ) g[j].c(i) = (i < n) ? 1 : 2; for ( i = 0; i < k; i++ ) for ( l = 0; l < n; l++ ) { if ( j == 0 && M1(i,l) ) { g[0].a(l).set(n + i); g[0].a(n + i).set(l); } if ( j == 1 && M2(i,l) ) { g[1].a(l).set(n + i); g[1].a(n + i).set(l); } } } return Isomorphic( g[0], g[1] ); } index_method(iso_member) bool iso_member( const matrix& M, const SLList< matrix >& l ) { forPixDef( p, l ) if ( isomorphic( M, l(p) ) ) return true; return false; } index_method(isomorphic) bool codehome::isomorphic(const config_core& c1, const config_core& c2, bool fully_refined) const { int i, j, k; const config_core* c[ ] = { &c1, &c2 }; // Are the configurations blatantly non-isomorphic? if ( c1.smallbasis.nrows != c2.smallbasis.nrows || c1.dualsmallbasis.nrows != c2.dualsmallbasis.nrows || (!fully_refined && c1.part.length != c2.part.length) ) return false; if ( c1.smallcode_we( ) != c2.smallcode_we( ) ) return false; TEX( ![ \begin{quote} Find permutations $\sigma_i$ of {\tt part.length} ($i = 1,2$) which put the elements of {\tt ci.part} in increasing order. \end{quote} ]! ) partition part[2]; code small[2], dualsmall[2]; int nparts; Permutation p[2]; if ( !fully_refined ) { for ( i = 0; i < 2; i++ ) { part[i] = c[i]->part; small[i].basis = c[i]->smallbasis; dualsmall[i].basis = c[i]->dualsmallbasis; part[i].sort( rcmp, p[i] ); } nparts = c1.part.length; if ( part[0] != part[1] ) return false; for ( i = 0; i < 2; i++ ) { for ( j = 0; j < small[i].basis.nrows; j++ ) p[i].act( small[i].basis(j) ); for ( j = 0; j < dualsmall[i].basis.nrows; j++ ) p[i].act( dualsmall[i].basis(j) ); } } else { for ( j = 0; j < 2; j++ ) { part[j].set_all_ones(n); p[j] = Permutation(n); small[j].basis = c[j]->basic_small( ); dualsmall[j].basis = c[j]->basic_dualsmall( ); } nparts = n; } prevector cd[2], dcd[2]; for ( j = 0; j < 2; j++ ) cd[j] = invariant_generating_set( small[j].basis, part[j] ); if ( cd[0].length != cd[1].length ) return false; for ( j = 0; j < 2; j++ ) dcd[j] = invariant_generating_set( dualsmall[j].basis, part[j] ); if ( dcd[0].length != dcd[1].length ) return false; vertex_colored_graph g[2]; for ( j = 0; j < 2; j++ ) { g[j] = vertex_colored_graph(nparts + cd[j].length + dcd[j].length); for ( i = 0; i < nparts; i++ ) g[j].c(i) = part[0](i); for ( i = nparts; i < nparts + cd[j].length; i++ ) g[j].c(i) = n + 1; // a color different from the others for ( i = nparts + cd[j].length; i < g[j].n; i++ ) g[j].c(i) = n + 2; // another color for ( i = 0; i < cd[j].length; i++ ) for ( k = 0; k < nparts; k++ ) if ( cd[j](i)(k) ) { g[j].a(k).set(nparts + i); g[j].a(nparts + i).set(k); } for ( i = 0; i < dcd[j].length; i++ ) for ( k = 0; k < nparts; k++ ) if ( dcd[j](i)(k) ) { g[j].a(k).set(nparts + cd[j].length + i); g[j].a(nparts + cd[j].length + i).set(k); } } return Isomorphic( g[0], g[1] ); } TEX( ![ \verb|isomorphic|:\ Determine if two configurations are isomorphic. If the ``\verb|fully_refine|'' parameter is set, the configurations will be fully refined before testing. Beware about the way that assumed constraints are tested. ]! ) bool codehome::isomorphic(const config& c1, const config& c2, bool fully_refined) const BHIDE1( ![ if ( !c1.assumed_cons.global( ) || !c2.assumed_cons.global( ) ) INTERNAL_ERROR("The routine isomorphic can only" << " work with configurations having global assumed constraints."); ]!, ![ if ( c1.assumed_cons != c2.assumed_cons ) return false; ]! ) return isomorphic( config_core(c1), config_core(c2), fully_refined ); } TEX( ![ \verb|dual_words_of_given_weight|:\ Find all words of the given weight $w$ in $\F_2^n$ dual to the rowspace of the given matrix $D$. The method is to traverse lexicographically through all words of weight $w$ in $\F_2^n$. ]! ) index_method(dual_word) SLList< vector > dual_words_of_given_weight(matrix D, int w) { SLList< vector > answer; int i, j, k; vector bit_on(w); for ( i = 0; i < w; i++ ) bit_on(i) = i; gf2 dot; while(1) { for ( i = 0; i < D.nrows; i++ ) { dot = 0; for ( j = 0; j < w; j++ ) dot += D(i)(bit_on(j)); if (dot) break; } if ( i == D.nrows ) answer.append( bit_on ); if ( bit_on( w-1 ) < D.ncols - 1 ) ++bit_on( w-1 ); else { for ( i = w-1; i >= 0; i-- ) if ( bit_on(i) != D.ncols - w + i ) break; if ( i == -1 ) break; j = bit_on(i) - i + 1; for ( k = i; k < w; k++ ) bit_on(k) = j + k; } } return answer; } TEX( ![ \verb|core_design_test|:\ Implement the condition described on page \pageref{elaborate-design-condition}, using ($n,m,\kappa,A,B,C$) as inputs to the routine. Here $m$ is the dimension of the code and $\kappa$ is the block size. The implementation could no doubt be substantially speeded up. ]! ) index_method(core_design_test) bool core_design_test( int n, int m, int k, SLList< vector >& twos, SLList< vector >& dual_words, OSLList< vector >& contained_by_every_design ) { int i, j; Pix p, q; while(1) { SLList< vector > uniquely_covered_twos; forPix( p, twos ) { number count; forPix( q, dual_words ) if ( subset( twos(p), dual_words(q) ) ) ++count; if ( count == 0 ) return false; if ( count == 1 ) uniquely_covered_twos.append( twos(p) ); } if ( uniquely_covered_twos.empty( ) ) { int block_count = contained_by_every_design.length( ); if ( Integer(block_count) * choose(k,2) != choose(n,2) ) return true; matrix blocks(block_count, n); int block_ptr = 0; forPix( p, contained_by_every_design ) { vector block = contained_by_every_design(p); for ( i = 0; i < block.length; i++ ) blocks(block_ptr, block(i)) = 1; block_ptr++; } return (blocks.reduce( ) == n - m); } SLList< vector > special_dual_words; forPix( p, dual_words ) forPix( q, uniquely_covered_twos ) { if ( subset( uniquely_covered_twos(q), dual_words(p) ) ) { special_dual_words.append( dual_words(p) ); break; } } prevector< vector > sdw(special_dual_words); for ( i = 0; i < sdw.length; i++ ) { contained_by_every_design.add( sdw(i) ); for ( j = i+1; j < sdw.length; j++ ) if ( intersection_size( sdw(i), sdw(j) ) >= 2 ) return false; } SLList< vector > saved_twos, deleted_twos, saved_dual_words; forPix( p, twos ) { forPix( q, special_dual_words ) if ( subset( twos(p), special_dual_words(q) ) ) break; if ( q == 0 ) saved_twos.append( twos(p) ); else deleted_twos.append( twos(p) ); } forPix( p, dual_words ) { vector& ww = dual_words(p); forPix( q, deleted_twos ) if ( subset( deleted_twos(q), ww ) ) break; if ( q == 0 ) saved_dual_words.append( ww ); } twos = saved_twos; dual_words = saved_dual_words; } } index_method(options_satisfied) bool codehome::options_satisfied(const config_core& d) { matrix D = d.basic_small( ); SLList< vector > dual_words, dual_words_save, uniquely_contained; SLList< vector > all_twos; prevector< SLList< prevector< vector > > > covers; int i, j, k; Pix p, q; if ( opt.partition_of_word_by_dual_words ) { dual_words = dual_words_of_given_weight(D, opt.d); dual_words_save = dual_words; SLList containers; code dc; dc.basis = D; dc.build( ); for ( i = 0; i < dc.x.nrows; i++ ) if ( dc.x(i).weight( ) == opt.w ) containers.append( dc.x(i) ); prevector tw(containers); covers.set_size( tw.length ); vector ii(opt.w/opt.d), ii_save(opt.w/opt.d); for ( i = 0; i < tw.length; i++ ) { TEX( ![ \begin{quotebneg} Find all dual words of weight {\tt opt.d} contained in the given word of weight {\tt opt.w}. \end{quotebneg} ]! ) SLList< vector > in_it; forPix( p, dual_words) { vector& dw = dual_words(p); for ( j = 0; j < dw.length; j++ ) if ( !(tw(i)(dw(j))) ) break; if ( j == dw.length ) in_it.append(dw); } prevector< vector > in_itv(in_it); TEX( ![ \begin{quoteb} At any given point, the first $\verb|ii_ptr| + 1$ elements of {\tt ii} are to be an increasing sequence of elements between $0$ and $\verb|in_itv.length| - 1$. \end{quoteb} ]! ) int ii_ptr = 0; ii(0) = 0; if ( in_itv.length < ii.length ) return false; int twicount = 0; while(1) { for ( j = 0; j < ii_ptr; j++ ) if ( intersection_size( in_itv( ii(ii_ptr) ), in_itv( ii(j) ) ) > 0 ) break; if ( j == ii_ptr && ii_ptr == opt.w/opt.d - 1 ) { twicount++; prevector< vector > a_cover(opt.w/opt.d); for ( k = 0; k < a_cover.length; k++ ) a_cover(k) = in_itv( ii(k) ); covers(i).append( a_cover ); ii_save = ii; } if ( j == ii_ptr && ii_ptr != opt.w/opt.d - 1 ) { ii_ptr++; ii(ii_ptr) = ii(ii_ptr-1) + 1; } else { // Work backwards to find element of ii that can // be incremented. for ( j = ii_ptr; j >= 0; j-- ) if ( ii(j) < in_itv.length - 1 - (opt.w/opt.d - 1 - j) ) break; if ( j < 0 ) break; ii_ptr = j; ++ii(j); } } if ( twicount == 1 ) { for ( j = 0; j < ii_save.length; j++ ) uniquely_contained.append( in_itv(ii_save(j)) ); } if ( twicount == 0 ) return false; } dc.unbuild( ); } if ( opt.dual_may_be_code_of_design ) { matrix cover(D.ncols, D.ncols); cover.set_zero( ); if ( !opt.partition_of_word_by_dual_words || opt.d != opt.k ) dual_words = dual_words_of_given_weight(D, opt.k); forPix( p, dual_words ) for ( i = 0; i < opt.k; i++ ) for ( j = i+1; j < opt.k; j++ ) ++cover( dual_words(p)(i), dual_words(p)(j) ); for ( i = 0; i < D.ncols; i++ ) for ( j = i+1; j < D.ncols; j++ ) if ( cover(i,j) < opt.lambda ) return false; if ( opt.lambda == 1 ) { for ( i = 0; i < D.ncols; i++ ) for ( j = i+1; j < D.ncols; j++ ) { vector x(2); x(0) = i; x(1) = j; all_twos.append(x); } } } if ( opt.dual_may_be_code_of_design && opt.lambda == 1 && opt.partition_of_word_by_dual_words && opt.d == opt.k ) { SLList< vector > twos; OSLList< vector > duals_in_cover; prevector< prevector< prevector< vector > > > coversv; coversv.set_size(covers.length); for ( i = 0; i < coversv.length; i++ ) coversv(i) = covers(i); prevector which(coversv.length); int level = 0; while(1) { prevector< vector > a = coversv(level)(which(level)); for ( i = 0; i < level; i++ ) { prevector< vector > b = coversv(i)(which(i)); for ( j = 0; j < a.length; j++ ) for ( k = 0; k < b.length; k++ ) { int isize = intersection_size( a(j), b(k) ); if ( isize > 1 && isize < opt.d ) goto bad_cover; } } if ( level == coversv.length - 1 ) { duals_in_cover.clear( ); for ( i = 0; i < which.length; i++ ) { prevector< vector > cw; // cover of a word cw = coversv(i)(which(i)); for ( j = 0; j < cw.length; j++ ) duals_in_cover.add( cw(j) ); } dual_words.clear( ); forPix( q, dual_words_save ) { forPixDef( qq, duals_in_cover ) { int is = intersection_size( dual_words_save(q), duals_in_cover(qq) ); if ( is > 1 ) break; } if ( qq == 0 ) dual_words.append( dual_words_save(q) ); } twos.clear( ); forPix( q, all_twos ) { forPixDef( qq, duals_in_cover ) { if ( subset( all_twos(q), duals_in_cover(qq) ) ) break; } if ( qq == 0 ) twos.append( all_twos(q) ); } if ( core_design_test( n, dim, opt.k, twos, dual_words, duals_in_cover ) ) goto next_test; goto bad_cover; } which(++level) = 0; continue; bad_cover: for ( i = level; i >= 0; i-- ) if ( which(i) < coversv(i).length - 1 ) break; if ( i == -1 ) return false; level = i; ++which(level); } } next_test: if ( opt.dual_may_be_code_of_design && opt.lambda == 1 ) { OSLList< vector< number> > cb; if ( core_design_test(n, dim, opt.k, all_twos, dual_words, cb) ) return true; } if ( opt.dual_radius > 0 ) { if ( opt.dual_radius_length == n ) { if (!sub_to_dual_radius( opt.dual_radius, d.part, d.smallbasis, opt.dual_radius_dim ) ) return false; } else { partition dp( d.part.length + 1 ); for ( i = 0; i < d.part.length; i++ ) dp(i) = d.part(i); dp(d.part.length) = opt.dual_radius_length - n; matrix ds( d.smallbasis ); ds.resize( ds.nrows, ds.ncols + 1 ); if ( !sub_to_dual_radius( opt.dual_radius, dp, ds, opt.dual_radius_dim ) ) return false; } } if ( opt.doubly_even_part_is_subcode ) { SLList de; code dc; dc.basis = D; dc.build( ); for ( i = 0; i < dc.x.nrows; i++ ) if ( dc.x(i).weight( ) % 4 == 0 ) de.append( dc.x(i) ); matrix dem(n, de); if ( Ipow( 2, dem.reduce( ) ) != dem.nrows ) return false; } return true; } TEX( ![ A lot of time gets spent in the following routine. This time shows up as time spent in the routine ``{\tt subdivide}''. ]! ) index_method(equiv) bool equiv(const partition& part, const matrix& smallbasis, const wordtype& wt1, const wordtype& wt2) { word wd(part.length); SLList ambiguous_positions; for ( int j = 0; j < part.length; j++ ) { if ( wt1(j) == wt2(j) ) { if ( 2 * wt1(j) == part(j) ) ambiguous_positions.append(j); else wd(j) = 0; } else if ( wt2(j) == part(j) - wt1(j) ) wd(j) = 1; else return false; } if ( ambiguous_positions.empty( ) ) return smallbasis.rowspace_member(wd); vector amb(ambiguous_positions); vector indx( amb.length ), wdx( wd.length ); do { wdx = wd; for ( int k = 0; k < indx.length; k++ ) wdx( amb(k) ) += indx(k); if ( smallbasis.rowspace_member(wdx) ) return true; } while( indx.advance( ) != 0 ); return false; } index_method(subdivide_partition) partition subdivide_partition( const partition& cp, const wordtype& w ) { int i, r = cp.length, k = 0; for ( i = 0; i < cp.length; i++ ) if ( 1 <= w(i) && w(i) < cp(i) ) r++; partition p(r); p.n = cp.n; for ( i = 0; i < cp.length; i++ ) { if ( 1 <= w(i) && w(i) < cp(i) ) { p(k++) = w(i); p(k++) = cp(i) - w(i); } else p(k++) = cp(i); } return p; } TEX(![ This routine and the way it gets invoked is inefficient, but it probably doesn't matter. ]!) index_method(subdivide_word) word subdivide_word( const partition& cp, const wordtype& w, const word& wo ) { partition p = subdivide_partition(cp, w); word w_new = word(p.length); int k = 0; for ( int i = 0; i < cp.length; i++ ) { if ( 1 <= w(i) && w(i) < cp(i) ) w_new(k++) = w_new(k++) = wo(i); else w_new(k++) = wo(i); } return w_new; } index_method(subdivide_matrix) matrix subdivide_matrix( const matrix& m0, const partition& p0, const wordtype& w, bool extra, bool reduce ) { partition p = subdivide_partition( p0, w ); matrix m( m0.nrows + extra, p.length ); for ( int j = 0; j < m0.nrows; j++ ) m(j) = subdivide_word( p0, w, m0(j) ); if (extra) { int k = 0; for ( int i = 0; i < p0.length; i++ ) { m( m.nrows - 1, k++ ) = (w(i) > 0); if ( 1 <= w(i) && w(i) < p0(i) ) m( m.nrows - 1, k++ ) = 0; } if (reduce) m.reduce( ); } return m; } index_method(reduce_wordtype_list) prevector reduce_wordtype_list(const SLList& l1, const config& d) { prevector l2(l1); l2.unique_sort(&String_cmp); prevector l3(l2.length); for ( int i = 0; i < l2.length; i++ ) { wordtype w( &d, l2(i) ); d.make_minimal(w); l3(i) = w.variable( ); } l3.unique_sort(&String_cmp); return l3; } index_method(subdivide) Pix subdivide( const config& c, const wordtype& w, codetable& results ) { time_used_by_subdivide -= time(0); c.small.build( ); int i, j, k = 0; // Check for bogus subdivision. word mm(c.part.length); for ( i = 0; i < mm.length; i++ ) { if ( w(i) == c.part(i) ) mm(i) = 1; else if ( w(i) != 0 ) break; } if ( i == mm.length && c.small.basis.rowspace_member(mm) ) ERROR( "An attempt has been made to subdivide a configuration " << "along the wordtype corresponding to a small code member." ); config d; d.home = c.home; d.part = subdivide_partition(c.part, w); int r = d.part.length; d.small.basis = subdivide_matrix( c.small.basis, c.part, w, true ); d.dualsmall.basis = subdivide_matrix(c.dualsmall.basis, c.part, w, false); d.leading1s = d.small.basis.leading_ones( ); // Create the new constraints. forPixDef( p, c.assumed_cons ) { constraint q = subdivide_constraint( d, c, w, c.assumed_cons(p), results ); d.assumed_cons.append(q); } forPix( p, c.con ) { if ( c.con(p).simple_local_zero( ) ) continue; if ( c.con(p).simple_local( ) && c.con(p).sense == '>' && c.con(p).RHS == 1 && c.con(p).LHS.front( ).var == w.variable( ) ) continue; constraint q = subdivide_constraint( d, c, w, c.con(p), results ); d.con.append(q); } TEX( ![ \begin{quote} If the parent configuration has any constraints of the form $v = 0$, where $v$ is a basic local variable, this is communicated to the child configuration. \end{quote} ]! ) SLList must_be_zero; forPix( p, c.con ) { if ( c.con(p).simple_local_zero( ) ) { wordtype wt( &c, c.con(p).LHS.front( ).var ); c.home->activate(true, results); config_active& a = *(c.home->active); term_sum dead_stuff = subdivide_basic_local_variable( d.part, d.small.basis, a, w, wt, true ); forPixDef( pp, dead_stuff ) must_be_zero.append( dead_stuff(pp).var ); } } prevector mbz = reduce_wordtype_list(must_be_zero, d); for ( i = 0; i < mbz.length; i++ ) d.con.append( constraint( mbz(i) + "=0" ) ); d.aut.n = r; d.share = new config_share( *(c.share) ); if ( d.share->realizable == 1 ) d.share->realizable = 0; Pix tttt = c.home->merge_config(d); time_used_by_subdivide += time(0); return tttt; } HIDE( ![ prevector< triple< int, int, prevector< pair > > > sblv_triple_maker(const partition&, const partition&, const wordtype&, wordtype&, int = 0); ]! ) index_method(subdivide_constraint) constraint subdivide_constraint( const config& d, const config& c, const wordtype& w, constraint con, codetable& results ) { constraint ans( con.sense, con.RHS ); if ( con.global( ) ) return con; c.home->activate(true, results); config_active& a = *(c.home->active); forPixDef( p, con.LHS ) { String va = con.LHS(p).var; if ( global_var(va) || joint_var(va) ) ans.LHS.append( con.LHS(p) ); else if ( va[0] == 'x' ) { wordtype v( &c, va ); if ( !a.vtable.admissible(v) ) continue; // inadmissible variable term_sum ts = subdivide_basic_local_variable( d.part, d.small.basis, a, w, v, false ); forPixDef( q, ts ) { ts(q).coeff = con.LHS(p).coeff; ans.LHS.append( ts(q) ); } } else if ( va[0] == 's' ) { String subw = va.after("sub"), tail = ""; if ( subw.contains("_") ) { tail = "_" + subw.after("_"); subw = subw.before("_"); } word wd = subdivide_word( c.part, w, word( subw, 0 ) ); subw = "sub" + String(wd) + tail; ans.LHS.append( term( con.LHS(p).coeff, subw ) ); } else if ( va[0] == 'z' || va[0] == 'q' ) { String vax = va; char z_or_q = va[0]; vax[0] = 'x'; vax.gsub( "z", "0" ); wordtype v( &c, vax ); prevector sv; va.del(z_or_q); if ( va[0] == '_' ) sv = unpack( va.after("_"), "_" ); else sv = unpack( va, "" ); wordtype vnew = vector(d.part.length); prevector< triple< int, int, prevector< pair > > > t = sblv_triple_maker( d.part, c.part, v, vnew ); int i, j; vector indx(t.length); while(1) { for ( i = 0; i < t.length; i++ ) { vnew( t(i).first ) = t(i).third(indx(i)).first; vnew( t(i).first + 1 ) = t(i).third(indx(i)).second; } if ( d.small.basis.orthogonal_to(vnew) ) { String newv = z_or_q; j = 0; for ( i = 0; i < c.part.length; i++ ) { if ( 1 <= w(i) && w(i) < c.part(i) ) { if ( sv(i) == "z" ) newv += "_z_z"; else newv += String("_") + dec(int(vnew(j))) + "_" + dec(int(vnew(j + 1))); j += 2; } else { if ( sv(i) == "z" ) newv += "_z"; else newv += String("_") + dec(int(vnew(j))); j++; } } ans.LHS.append( term( con.LHS(p).coeff, newv ) ); } for ( i = t.length - 1; i >= 0; i-- ) if ( indx(i) < t(i).third.length - 1 ) break; if ( i < 0 ) break; for ( j = t.length - 1; j > i; j-- ) indx(j) = 0; ++indx(i); } } } if ( ans.LHS.length( ) > 1000 ) WARNING( "The process of subdivision has lead to a very large " << "constraint -- it has " << ans.LHS.length( ) << " terms." << " It is possible that a string-related abortion will result." ); return ans; } index_method(sblv_triple_maker) prevector< triple< int, int, prevector< pair > > > sblv_triple_maker( const partition& p, const partition& cp, const wordtype& v, wordtype& vnew, int pmax = 0 ) { prevector< triple< int, int, prevector< pair > > > t(p.length - cp.length); int i, j, k = 0, t_ptr = 0; for ( i = 0; i < p.length; i++ ) { if ( p(i) == cp(k) ) vnew(i) = v(k++); // Set the fixed entries. else // Determine range of values for variable entries. { SLList< pair > t_entry; // Note: cp(k) = p(i) + p(i+1). Split v(k). for ( j = 0; j <= v(k); j++ ) { if ( j > p(i) || v(k) - j > p(i+1) ) continue; if ( pmax != 0 && (j > pmax || v(k) - j > pmax) ) continue; t_entry.append( make_pair( j, v(k) - j ) ); } t(t_ptr++) = make_triple( i++, k++, prevector< pair >(t_entry) ); } } return t; } TEX(![ \verb|subdivide_basic_local_variable(|% \verb|d.part, d.small.basis, c, w, v, weak)|: Let $c$ be a configuration, and let $w$ be a wordtype for it. Let $d$ be the subdivision of $c$ along $w$, which has dimension $\dim(c) + 1$. Let $v$ be another wordtype for $c$, thought of as a basic local variable. Let {\tt weak} be {\tt true} or {\tt false}. If {\tt weak} = {\tt false}, assume that $v$ is admissible. Then $v$ induces a sum of (generally) admissible basic local variables of $d$. Return this sum. If {\tt weak} = {\tt true}, it is not assumed that $v$ is admissible, and the variables returned in the sum are admissible only in the weak sense that adding an element of the small code yields a basic local variable whose weight is in {\tt rww}, and the dot product with each word in the dual small code is even. Also, only one representative from each equivalence class is returned. Presumably a variant of this routine (with {\tt weak} = {\tt false}) could be used as a tool for computing the {\tt mawhometable} of $d$, and presumably it would be much faster. ]!) index_method(subdivide_basic_local_variable) term_sum subdivide_basic_local_variable( const partition& dpart, const matrix& dsmallbasis, const config_active& a, const wordtype& w, const wordtype& v, bool weak ) { const partition& p = dpart; // silly? TEX( ![ \begin{quote} Each new wordtype will be called {\tt vnew}. Some of its entries are fixed, whereas others will vary in adjacent pairs. The object {\tt t} keeps track of these pairs. \end{quote} ]! ) wordtype vnew2(p.length), vnew(p.length); prevector< triple< int, int, prevector< pair > > > t = sblv_triple_maker( p, a.c->part, v, vnew ); int i, j; vector indx(t.length); wordtype vup = v; for ( i = 0; i < v.length; i++ ) if ( w(i) == a.c->part(i) ) vup(i) = w(i) - v(i); SLList vnew_list; while(1) { // Make vnew. for ( i = 0; i < t.length; i++ ) { vnew( t(i).first ) = t(i).third(indx(i)).first; vnew( t(i).first + 1 ) = t(i).third(indx(i)).second; } TEX(![ \begin{quotea} Is {\tt vnew} admissible? To answer this, add to {\tt vnew} the smallword in $d$ induced by w, and lift back to a wordtype vup of $c$. If vup is admissible (in $c$), then {\tt vnew} is admissible in $d$. For efficiency, it would make sense to only cycle through ``minimal'' {\tt vnew}'s. Perhaps the definition of {\tt minimal} would have to be changed to make this work well. \end{quotea} ]!) for ( i = 0; i < t.length; i++ ) vup( t(i).second ) = p(t(i).first) - vnew(t(i).first) + vnew(t(i).first + 1); if (!weak) { if ( a.vtable.admissible(vup) ) vnew_list.append(vnew); } else { wordtype alttype = vup; for ( i = 0; i < a.c->small.x.nrows; i++ ) { alttype.act( a.c->small.x(i), vup ); if ( !a.rww.contains( sum(alttype) ) ) break; } if ( i == a.c->small.x.nrows ) { if ( a.c->dualsmall.basis.orthogonal_to(vup) ) { forPixDef( aaa, vnew_list ) if ( equiv( dpart, dsmallbasis, vnew_list(aaa), vnew ) ) break; if ( aaa == 0 ) vnew_list.append(vnew); } } } // Advance "indx" so that we will be ready to build the next vnew. for ( i = t.length - 1; i >= 0; i-- ) if ( indx(i) < t(i).third.length - 1 ) break; if ( i < 0 ) break; for ( j = t.length - 1; j > i; j-- ) indx(j) = 0; ++indx(i); } // Build the answer. term_sum ts; forPixDef( pp, vnew_list ) ts.append( term( 1, vnew_list(pp).variable( ) ) ); return ts; } index_method(operator+(config_share, config_share)) config_share* operator+(const config_share& c1, const config_share& c2) { config_share* c = new config_share; HIDE( ![ if ( c1.realizable * c2.realizable == -1 ) INTERNAL_ERROR( "Two configurations are logically equivalent," << " but one is realizable and one is unrealizable." ); ]! ) if ( c1.realizable == 1 || c2.realizable == 1 ) c->realizable = 1; else if ( c1.realizable == -1 || c2.realizable == -1 ) c->realizable = -1; else c->realizable = 0; c->ww = intersection( c1.ww, c2.ww ); c->dual_min_low = max( c1.dual_min_low, c2.dual_min_low ); c->dual_min_high = min( c1.dual_min_high, c2.dual_min_high ); c->ycon.merge(c1.ycon); c->ycon.merge(c2.ycon); if ( c1.wjv.length != 0 && c2.wjv.length == 0 ) c->wjv = c1.wjv; else if ( c1.wjv.length == 0 && c2.wjv.length != 0 ) c->wjv = c2.wjv; else if ( c1.wjv.length != 0 && c2.wjv.length != 0 ) { SLList vars; for ( int i = 0; i < c1.wjv.length; i++ ) if ( c2.wjv.member( c1.wjv(i) ) ) vars.append( c1.wjv(i) ); c->wjv = vars; } return c; } TEX( ![ \verb|x_to_v|: convert an {\tt x} variable to a {\tt v} variable, returning the number of the {\tt v} variable, or $0$ if it is not admissible. The code overlaps with {\tt mawhometable::find}. ]! ) index_method(x_to_v) int config_active::x_to_v(const String& xvar) const { wordtype w(c, xvar); c->make_minimal(w); for ( int i = 0; i < vtable.length; i++ ) if ( w == vtable(i).maw ) return i + 1; return 0; } TEX( ![ If the {\tt weak} option is chosen, the {\tt w} member of the mawhome entries will not be computed. Also \verb|y_as_vsum| will not be computed. Use with caution! ]! ) index_method(config_active constructor) config_active::config_active(config* c, codetable& results, bool quiet, bool weak) : c(c), bound(c->part.length), dual_bound(c->part.length), file_status(0) { if ( c->share->realizable == -1 ) INTERNAL_ERROR( "Attempt to activate unrealizable configuration." ); int i, j; c->small.build( ); c->dualsmall.build( ); weightlist& w = c->share->ww; TEX(![ \begin{quote} Build \verb|global_bound|. \end{quote} ]!) int n = c->home->n; Integer low, high; global_bound.set_size(n + 1); global_bound(0) = make_pair(Integer(1), Integer(1)); for ( i = 1; i <= n; i++ ) global_bound(i) = make_pair(Integer(0), Integer(0)); forPixDef( p, w ) { if ( w(p) == 0 ) continue; low = 0; high = -1; c->evaluate( String("y") + dec(w(p)), low, high ); global_bound( w(p) ) = make_pair( low, high ); } TEX(![ \begin{quote} Build {\tt rww}, the restricted working weightlist. \end{quote} ]!) small_we = c->smallcode_we( ); forPix( p, w ) { if ( w(p) == 0 ) continue; low = global_bound( w(p) ).first; high = global_bound( w(p) ).second; if ( high == -1 || high > small_we( w(p) ) ) rww.add( w(p) ); // The following line may be dangerous, because the calling routine // may not expect the configuration to be unrealizable. In addition, // we then proceed to carry out a pointless activation. else if ( high < small_we( w(p) ) ) { c->share->realizable = -1; rww.clear( ); break; } } // Set up dualsmall_working. SLList< vector > dsmw_temp; for ( i = 0; i < c->dualsmall.basis.nrows; i++ ) dsmw_temp.append( c->dualsmall.basis(i) ); if ( w.divisible(2) ) { vector v(c->part.length); for ( i = 0; i < c->part.length; i++ ) v(i) = 1; dsmw_temp.append(v); if ( w.divisible(4) ) for ( i = 0; i < c->small.basis.nrows; i++ ) dsmw_temp.append( c->small.basis(i) ); } if ( c->home->dim > 1 && ( c->home->opt.doubly_even_part_is_subcode || ( w.divisible(2) && c->known( "div4=" + String(dec(Ipow(2, c->home->dim - 2))) ) ) ) ) { for ( i = 0; i < c->small.basis.nrows; i++ ) { if ( (c->small.basis(i) * c->part) % 4 == 0 ) dsmw_temp.append( c->small.basis(i) ); } } // Now convert dsmw_temp to dualsmall_working. matrix dsmw2(c->part.length, dsmw_temp); dsmw2.reduce_nz( ); dualsmall_working.basis = dsmw2; dualsmall_working.build( ); // Set up dual_leading1s. dual_leading1s = dualsmall_working.basis.leading_ones( ); for ( i = 0; i < c->part.length; i++ ) bound(i) = dual_bound(i) = c->part(i); for ( i = 0; i < c->small.basis.nrows; i++ ) bound(c->leading1s(i)) /= 2; for ( i = 0; i < dualsmall_working.basis.nrows; i++ ) dual_bound(dual_leading1s(i)) /= 2; TEX(![ \begin{quote} We build the table of mawhomes, by cycling through all wordtypes, testing each for admissibility and minimality. \end{quote} ]!) ofstream var_def( calculations_dir + "/variable_definitions" ); SLList vtable0; wordtype wu(c), alt(c); int vcount = 1; if (!weak) { wordtype types[c->small.x.nrows]; do { mawhome m; m.maw = wu; int wordcount = 0; for ( i = 0; i < c->small.x.nrows; i++ ) { alt.act( c->small.x(i), wu ); for ( j = 0; j < wordcount; j++ ) if ( types[j] == alt ) break; if ( j == wordcount ) { types[wordcount++] = alt; m.w.append( c->small.x(i) ); } } if (show_variables) cerr << "v" << vcount++ << " = " << wu.variable( ) << "\n"; vtable0.append(m); } while( wu.advance(this, results) != 0 ); } else { do { mawhome m; m.maw = wu; if (show_variables) cerr << "v" << vcount++ << " = " << wu.variable( ) << "\n"; vtable0.append(m); } while( wu.advance(this, results) != 0 ); } vtable = mawhometable(vtable0); for ( i = 0; i < vtable.length; i++ ) var_def << "v" << i + 1 << " = " << vtable(i).maw.variable( ) << "\n"; var_def.close( ); TEX( ![ \begin{quote} Compute \verb|y_as_vsum|, which expresses each \verb|y_i| as a sum of \verb|v|'s. Note that this must be recomputed if \verb|c->share->ww| is changed. \end{quote} ]! ) if (!weak) { int count, wt_no = 0; y_as_vsum.set_size( w.length( ) ); forPix( p, w ) { for ( i = 0; i < vtable.length; i++ ) { count = 0; SLList& words = vtable(i).w; forPixDef( q, words ) { alt.act( words(q), vtable(i).maw ); if ( sum(alt) == w(p) ) count++; } y_as_vsum(wt_no).append( term(count, String("v") + (i+1) )); } wt_no++; } } } TEX( \verb|make_minimal(w)|: make a given wordtype {\tt w} minimal. ) index_method(make_minimal) void config::make_minimal(wordtype& w) const { static vector border_rows; border_rows.set_size(small.basis.nrows); int border_count = 0, diff, i, col; for ( i = 0; i < leading1s.length; i++ ) { col = leading1s(i); diff = 2 * w(col) - part(col); if ( diff > 0 ) w.act(small.basis(i)); else if ( diff == 0 ) border_rows(border_count++) = i; } if ( border_count == 0 ) return; TEX(![ \begin{quote} Now we have to deal with the borderline cases, where $2 * $\verb|w(i)| = \verb|part(i)| for some \verb|i|. Form the subcode of the small code generated by the ``borderline rows'' of the associated matrix. One by one let these act on \verb|w|, to see if it can be made smaller. This method can no doubt be much improved. \end{quote} ]!) vector indx(border_count); wordtype v(w), best(w); do { v = w; for ( int j = 0; j < border_count; j++ ) if ( indx(j) ) v.act( small.basis(border_rows(j))); if ( v < best ) best = v; } while ( indx.advance( ) != 0 ); w = best; } TEX( The following routine determines the equivalence relation on the admissible basic local variables induced by the known automorphisms of the configuration. ) index_method(auto_equiv) EquivRelIntList config_active::auto_equiv( ) const { EquivRelIntList e(vtable.length); wordtype w(c); for ( int i = 0; i < c->aut.length; i++ ) for ( int j = 0; j < vtable.length; j++ ) { w = vtable(j).maw; c->aut(i).act(w); int k = vtable.mfind(w); if ( k == -1 ) ERROR("The admissible basic local variable " << vtable(j).maw.variable( ) << " is carried by the automorphism\n" << c->aut(i) << "\nto the inadmissible basic local" << " variable " << w.variable( ) << ". The current " << "version of the language is not smart enough to " << "handle this. You can work around the problem " << "by using the \"reduce variable set\" command."); e.join(j, k); } return e; } qvconstraint::qvconstraint(const constraint& con, codehome* home) : sense( con.sense ), RHS( con.RHS ) { home->active->expand_term_sum( con.LHS, LHS ); } set_include_file(homedefs.h) HIDE( ![ #include "basedefs.h" class config; class config_active; class config_share; class codebase; class codehome; class codetable; #include "share.h" #include "multiedge.h" #include "vconstraint.h" #include "code.h" #include "partition.h" #include "wordtype.h" #include "weightlist.h" #include "config.h" #include "codehome.h" ]! ) set_compile_file(code.c) TEX(![ \block{Linear programming methods} We describe the structure of the {\it constraint file}. This is modelled roughly on the ``LP format'' of CPLEX. In particular, we impose various quirky conditions because they are imposed by CPLEX; other conditions are imposed for our convenience. We have already described the syntax of constraints, but their use here is slightly more restrictive. A variable name ({\it var}) starts with a letter, may include letters, numbers, and underscores, and has at most $16$ characters in it. Let {\it int\/} denote any integer, {\it pos\/} any positive integer. A {\it constraint\/} has the form {\it [{\tt-}]pos var $\pm \cdots \pm$ pos var op int\/}, where {\it [{\tt-}]\/} denotes an optional minus sign and {\it op\/} is one of {\tt =}, {\tt >=}, or {\tt <=}. White space may appear anywhere, except within a {\tt var}, within a sequence of digits, within {\tt >=}, or within {\tt <=}. A newline may not occur between {\it op\/} and {\it int}. At most $255$ characters may occur between newlines. A {\it constraint file\/} is a file which starts with the single line ``maximize 0 subject to'' and which is followed by zero or more constraints, each beginning on a new line. CPLEX prefers that the last line of the file is ``{\tt end}'', but we do not follow this convention. ]! ) set_compile_file(process.cc) HIDE( ![ extern char* PATH_PREFIX; #include "homedefs.h" #include #include void eat_constraint(istream&); extern int homebrew, warnings_are_fatal; extern int cplex_verification_failure_accepted; extern String homebrew_status; pair lp_crunch(const prevector&, int, const vconstraint&, bool = false); void add_to_rational_constraint(qvconstraint&, const vconstraint&, Rational&); int take_int(String&, const Regex&); void parse_j_var(String, int&, int&, int&); String make_j_var(int, int, int); ]! ) index_class(int_item) class int_item { public: union { char c[sizeof(int)]; int x; }; friend istream& operator>>(istream& s, int_item& l) { for ( int i = 0; i < sizeof(int); i++ ) s.get( l.c[i] ); return s; } }; index_class(double_item) class double_item { public: union { char c[sizeof(double)]; double x; }; friend istream& operator>>(istream& s, double_item& l) { for ( int i = 0; i < sizeof(double); i++ ) s.get( l.c[i] ); return s; } }; index_method(skip_record) void skip_record( istream& s ) { int_item l_start, l_stop; s >> l_start; for ( int i = 0; i < l_start.x; i++ ) s.get( ); s >> l_stop; if ( !s || l_start.x != l_stop.x ) INTERNAL_ERROR( "error reading CPLEX record" ); } TEX(![ \par\noindent\verb|process_cplex_report( |{\it report file}\verb|, |% {\it status indicator}\verb| )|:\ The report file is supposed to have been generated with the CPLEX write command, e.g.\ \verb|w solution.bin|. First determine the status, $1$ for feasible, $0$ for infeasible. Then determine the dual activity for each constraint, which is a double precision number. This dual activity is rounded to a rational, and put into a list, which is returned to the caller. Remove the report file when done. This routine is perilously dependent on the exact structure of the CPLEX report file. Any deviance will cause this routine to produce an error and exit. It is conceivable that a different version of CPLEX or an implementation of the same version on another machine could produce slightly different report files. In that case, this routine would have to be appropriately modified. ]!) index_method(process_cplex_report) SLList process_cplex_report( String report_file, int& status ) { ifstream report( report_file ); if (!report) ERROR( "The CPLEX report file \"" << report_file << "\" was not written. It is " << "possible that CPLEX ran out of memory. (If so, try increasing " << "swap space.) If you look at the file cplex_output, you will " << "probably be able to figure out what happened." ); int i; int_item l; for ( i = 0; i < 4; i++ ) // skip 4 records skip_record(report); // extract status from solution record for ( i = 0; i < 112 + sizeof(int); i++ ) report.get( ); char status_string[4]; for ( i = 0; i < 4; i++ ) report.get( status_string[i] ); for ( i = 0; i < 84 + sizeof(int); i++ ) report.get( ); for ( i = 0; i < 5; i++ ) // skip 5 records skip_record(report); double_item d[8]; SLList dual_activity_rational; while(1) BHIDE2( ![ if (!report) INTERNAL_ERROR( "error reading CPLEX row records" ); ]!, ![ report >> l; // read length ]! ) for ( i = 0; i < 8; i++ ) report >> d[i]; if ( String(d[0].c).contains("$ENDSEC$", 0) ) break; dual_activity_rational.append(d[4].x); report >> l; } if ( status_string[0] == 'N' && status_string[1] == 'F' ) status = 0; else status = 1; report.close( ); remove( report_file ); return dual_activity_rational; } bool infeasible_core(const prevector&, const vconstraint&); TEX(![ \verb|infeasible(codehome)|:\ Use CPLEX to determine if the system given by the constraint files \verb|cplex_in| and \verb|cplex_in2| (built if need be) is infeasible. Return true if we know (with certainty) that the system is infeasible. Otherwise, return false. However, if CPLEX reports infeasible, but it can't be verified, issue an error. ]!) index_method(infeasible) bool infeasible( codehome& home, codetable& results, bool quiet ) { home.activate(quiet, results); home.active->split(quiet, results, constraintlist( )); prevector files(2); files(0) = "cplex_in"; files(1) = "cplex_in2"; vconstraint tot(home.active->vtable.length); tot.sense = '='; tot.RHS = Ipow( 2, home.dim ); for ( int i = 0; i < tot.LHS.length; i++ ) tot.LHS(i) = home.active->vtable(i).w.length( ); lp_crunch(files, home.active->vtable.length, tot); return infeasible_core( files, tot ); } index_method(map_constraint) void map_constraint( vconstraint& v, vconstraint& w, prevector& vars, prevector& mp ) { w.sense = v.sense; w.RHS = v.RHS; w.LHS.set_zero( ); for ( int i = 0; i < vars.length; i++ ) w.LHS( mp(i) ) += v.LHS(i); } index_method(qmap_constraint) void qmap_constraint( qvconstraint& v, qvconstraint& w, prevector& vars, prevector& mp ) { w.sense = v.sense; w.RHS = v.RHS; w.LHS.set_zero( ); for ( int i = 0; i < vars.length; i++ ) w.LHS( mp(i) ) += v.LHS(i); } TEX( ![ If a code is known to contain the all ones word, then many of its joint variables are equal. The following routine utilizes this to shrink the size of the constraint file. Of course a more efficient approach to this would be to utilize this information at the start, in which case a much smaller constraint file would be directly generated. ]! ) index_method(reduce_joint_in) prevector reduce_joint_in( codehome& home, prevector& vars ) { if ( home.configs(home.current).known(String("y") + dec(home.n) + ">=1") ) { EquivRelIntList e( vars.length ); int i, j, r, s, t, f, g, h, n = home.n; for ( i = 0; i < e.length; i++ ) { if ( e.minimal(i) ) { parse_j_var( vars(i), r, s, t ); f = vars.find( make_j_var( n-r, n-s, t ) ); g = vars.find( make_j_var( n-r, s, n-t ) ); h = vars.find( make_j_var( r, n-s, n-t ) ); if ( f == -1 || g == -1 || h == -1 ) ERROR( "A joint variable is equivalent to an " << "inadmissible joint variable. I am not " << "programmed to deal with this situation." ); e.join(i, f); e.join(i, g); e.join(i, h); } } prevector m( e.length ), u( e.length ), mp( e.length ); for ( i = 0; i < e.length; i++ ) m(i) = e.min_in_class(i); j = 0; for ( i = 0; i < e.length; i++ ) if ( e.minimal(i) ) u(i) = j++; for ( i = 0; i < e.length; i++ ) mp(i) = u(m(i)); ifstream jin( calculations_dir + "/joint_in" ); ofstream jout( "/tmp/joint_in" ); vconstraint v( vars.length ), w( e.orbit_count( ) ); bool cplex_header = false; if ( jin.peek( ) == 'm' ) { cplex_header = true; for ( i = 0; i < 22; i++ ) // skip over "maximize 0" jin.get( ); } // "subject to" while( jin.peek( ) != EOF ) { jin >> v; map_constraint( v, w, vars, mp ); if ( w.LHS.if_zero( ) && ( (w.sense == '=' && w.RHS == 0) || (w.sense == '<' && w.RHS >= 0) || (w.sense == '>' && w.RHS <= 0) ) ) continue; jout << w; } jin.close( ); jout.close( ); system( "sort -u -T calculations/tmp < /tmp/joint_in > /tmp/joint_in2" ); ifstream jin2( "/tmp/joint_in2" ); String pipe_command0 = "fold -s > " + calculations_dir + "/joint_in"; procbuf jout2p( pipe_command0, ios::out ); ostream jout2( &jout2p ); if (cplex_header) jout2 << "maximize 0\nsubject to\n"; // Look for constraint pairs of the form f >= 0, f <= 0, and // replace them by f = 0. vconstraint v1( e.orbit_count( ) ), v2( e.orbit_count( ) ); jin2 >> v1; while( jin2.peek( ) != EOF ) { jin2 >> v2; if ( v1.sense == '<' && v2.sense == '>' && v1.RHS == 0 && v2.RHS == 0 && v1.LHS == v2.LHS ) { v1.sense = '='; jout2 << v1; if ( jin2.peek( ) == EOF ) goto end_of_cons; jin2 >> v1; } else { jout2 << v1; v1 = v2; } } jout2 << v1; end_of_cons: jin2.close( ); jout2p.close( ); prevector newvars( e.orbit_count( ) ); j = 0; for ( i = 0; i < e.length; i++ ) if ( e.minimal(i) ) { parse_j_var( vars(i), r, s, t ); if ( s > t ) swap( s, t ); if ( r > s ) swap( r, s ); if ( s > t ) swap( s, t ); if ( n - s <= s && n - t <= t ) { s = n - s; t = n - t; } String var = make_j_var( r, s, t ); newvars(j++) = var; } vars = newvars; ofstream vardef( calculations_dir + "/joint_variable_definitions_short"); for ( i = 0; i < vars.length; i++ ) vardef << "v" << dec(i+1) << " = " << vars(i) << "\n"; vardef.close( ); return mp; } return prevector(0); } index_method(joint_infeasible) bool joint_infeasible( codehome& home, codetable& results, constraintlist forced ) { accommodate( choose( home.n, home.dim ) ); home.generate_joint_constraints(results, false, forced); home.basic_joint_vars(&home.configs(home.current), results); prevector vars = home.configs(home.current).share->wjv; if ( vars.length == 0 ) INTERNAL_ERROR( "wjv length = 0 in joint_infeasible" ); int nvars = vars.length; prevector files(1); files(0) = "joint_in"; vconstraint tot(nvars); tot.sense = '='; tot.RHS = Ipow( 2, 2 * home.dim ); for ( int i = 0; i < nvars; i++ ) { int r, s, t; parse_j_var( vars(i), r, s, t ); if ( r != s && r != t && s != t ) tot.LHS(i) = 6; else if ( r == s && s == t ) tot.LHS(i) = 1; else tot.LHS(i) = 3; } prevector vars_old = vars; prevector mp = reduce_joint_in( home, vars ); if ( mp.length != 0 ) { nvars = vars.length; vconstraint tot_new(nvars); map_constraint( tot, tot_new, vars_old, mp ); tot = tot_new; } lp_crunch( files, nvars, tot ); return infeasible_core( files, tot ); } index_method(infeasible_core) bool infeasible_core( const prevector& files, const vconstraint& tot ) { int nvars = tot.LHS.length; if (homebrew) { if ( homebrew_status == "infeasible" ) return true; if ( homebrew_status == "confused" ) WARNING("Homebrew calculation failed."); return false; } int status; SLList dual_activity = process_cplex_report( calculations_dir + "/cplex.bin", status ); if ( status != 0 ) return false; // system appears to be feasible TEX(![ \begin{quote} Multiply each constraint (from \verb|cplex_in| and \verb|cplex_in2|) by the corresponding dual activity. Add it up, to get a ![$<=$]! inequality. \end{quote} ]!) ifstream conf( calculations_dir + "/" + files(0) ); char c; for ( int j = 1; j <= 2; j++ ) // skip over "maximize 0 subject to" { do { conf.get(c); } while ( c != '\n' ); } qvconstraint qv(nvars); vconstraint vcx(nvars); qv.RHS = 0; Pix d = dual_activity.first( ); bool first_file = true; while(1) { if ( conf.peek( ) == EOF ) { if (first_file) { first_file = false; conf.close( ); if ( files.length == 1 ) break; conf.open( calculations_dir + "/" + files(1) ); if ( conf.peek( ) == EOF ) break; } else break; } HIDE( ![ if ( d == 0 ) INTERNAL_ERROR("infeasible: not enough dual activity numbers"); ]! ) // If dual activity is nonzero, read a constraint, multiply by // dual activity, and add to sum. Otherwise, skip over constraint. if ( sign(dual_activity(d)) != 0 ) { conf >> vcx; add_to_rational_constraint( qv, vcx, dual_activity(d) ); } else eat_constraint(conf); dual_activity.next(d); } HIDE( ![ if (d != 0) INTERNAL_ERROR("infeasible: too many dual activity numbers"); ]! ) conf.close( ); TEX(![ \begin{quote} Now decide if there's a contradiction. The idea is that if $k$ is the dimension of the code, and we write $(*):$ $2^k = \sum_i a_i v_i$ $(a_i > 0$), then if the summed constraint is feasible, there will be a point where the constraint holds, with all but one of the $v$'s zero, and the remaining $v$ equal to whatever makes $(*)$ work. \end{quote} ]!) if ( sign(qv.RHS) >= 0 ) { if (cplex_verification_failure_accepted) cerr << "(CPLEX claim of infeasibility was not verified.)\n"; else WARNING( "CPLEX claim of infeasibility was not verified" ); return false; } for ( int i = 0; i < nvars; i++ ) if ( qv.LHS(i) < Rational(0) ) { if ( qv.LHS(i) * Rational(tot.RHS) <= Rational(tot.LHS(i)) * qv.RHS ) { if (cplex_verification_failure_accepted) cerr << "(CPLEX claim of infeasibility was not verified.)\n"; else WARNING( "CPLEX claim of infeasibility was not verified" ); return false; } } return true; } set_include_file(opt.h) index_class(opt_card) class opt_card { public: term_sum var; // what is to be minimized or maximized String request; // can be "min", "max", "minmax" double min; // computed minimum double max; // computed maximum opt_card( const term_sum& var, const String& request ) : var(var), request(request) { } opt_card( ) { } HIDE( ![ friend ostream& operator<<(ostream&, const opt_card&); ]! ) }; index_method(add) index_class(opt_table) class opt_table { public: codehome* home; bool feasible; SLList data; opt_table( codehome* home ) : home(home) { } void compute( codetable&, bool joint = false, constraintlist = constraintlist( ) ); void add( const term_sum& var, const String& request = String("minmax") ) { data.append( opt_card( var, request ) ); } }; set_compile_file(opt.cc) HIDE(![ #include "homedefs.h" #include "simplex.h" extern int homebrew; extern int vars, create_con_file_only; extern char* PATH_PREFIX; extern "C" int srandomx(unsigned); ifelse(UNAME,Openstep,,![extern "C" double floor(double);]!) #include "opt.h" pair lp_crunch(const prevector&, int, const vconstraint&, bool = false); void joint_to_qv(constraint, qvconstraint&, const prevector&, Pix, codehome&, Integer ***); Integer*** make_krawtchouk(int); extern String homebrew_status; void qmap_constraint(qvconstraint&, qvconstraint&, prevector&, prevector&); prevector reduce_joint_in(codehome&, prevector&); ]!) index_method(intish_double_to_String) String intish_double_to_String( double x ) { String sign; if ( x < 0 ) { sign = "-"; x = -x; } Integer int_part = floor(Rational(x)); String ans = dec(int_part); double tail = x - double(int_part); int itail = (int) floor(10000 * tail); if ( itail == 0 && ans == "0" ) return ans; if ( itail == 0 ) return sign + ans; if ( itail == 9999 ) return sign + dec( int_part + 1 ); if ( itail > 999 ) return sign + ans + "." + dec(itail); if ( itail > 99 ) return sign + ans + ".0" + dec(itail); if ( itail > 9 ) return sign + ans + ".00" + dec(itail); return sign + ans + ".000" + dec(itail); } ostream& operator<<(ostream& s, const opt_card& o) { if ( o.request == "minmax" ) { String low = intish_double_to_String(o.min); String high = intish_double_to_String(o.max); if ( low == high ) return s << o.var << " = " << low << "\n"; if ( low == "0" ) return s << o.var << " <= " << high << "\n"; return s << low << " <= " << o.var << " <= " << high << "\n"; } if ( o.request == "min" ) cerr << intish_double_to_String(o.min) << " <= "; s << o.var; if ( o.request == "max" ) s << " <= " << intish_double_to_String(o.max); if ( o.max >= 0 && o.min >= 0 && o.max < 0.99999 * o.min ) s << " (doesn't look reliable)"; return s << "\n"; } HIDE( ![ inline void Set_precision(Big& x, int n) { x.set_precision(n); } ]! ) index_method(compute) void opt_table::compute( codetable& results, bool joint, constraintlist forced ) { if ( home->ww(home->current).length( ) == 1 && home->dim < home->n ) { feasible = false; return; } remove( calculations_dir + "/homebrew.log" ); accommodate( choose( home->n, home->dim ) ); prevector jvars, jvars_old; Integer*** combo; prevector mp; if (joint) { home->basic_joint_vars(&home->configs(home->current), results); jvars = home->configs(home->current).share->wjv; if ( jvars.length == 0 ) INTERNAL_ERROR( "wjv length = 0 in opt_table::compute" ); jvars_old = jvars; home->generate_joint_constraints(results, homebrew, forced); combo = make_krawtchouk(home->n); } if (homebrew) { home->deactivate( ); home->activate(true, results); prevector files; vconstraint tot; create_con_file_only = 1; int nvars; if ( !joint ) { home->active->split(false, results, forced); nvars = home->active->vtable.length; files.set_size(2); files(0) = "cplex_in"; files(1) = "cplex_in2"; tot.LHS.set_size( home->active->vtable.length ); tot.sense = '='; tot.RHS = Ipow( 2, home->dim ); for ( int ii = 0; ii < tot.LHS.length; ii++ ) tot.LHS(ii) = home->active->vtable(ii).w.length( ); } else { nvars = jvars.length; files.set_size(1); files(0) = "joint_in"; // We create tot, but this seems pointless. tot.LHS.set_size(0); tot.sense = '='; tot.RHS = 0; mp = reduce_joint_in( *home, jvars ); nvars = jvars.length; } accommodate( choose( home->n, home->dim ) ); pair rep = lp_crunch( files, nvars, tot ); if ( homebrew_status == "infeasible" ) { feasible = false; return; } int total_constraints = rep.first; int eq_constraints = rep.second; create_con_file_only = 0; ifstream homebrew_in( calculations_dir + "/homebrew_in" ); int n = vars, m = total_constraints, m_eq = eq_constraints; srandomx(1); bool confused; int ii; constraint cc( '=', 0 ); // sense and RHS are dummies bool use_dual_simplex = true; if (use_dual_simplex) { exact_lp_problem ex; ex.n = vars; ex.m = total_constraints; ex.m_eq = eq_constraints; ex.known_to_be_infeasible = false; ex.con_file = calculations_dir + "/homebrew_in"; accommodate( ex.presolve( ) ); if ( ex.known_to_be_infeasible ) { feasible = false; home->deactivate( ); return; } forPixDef( i, data ) { cc.LHS = data(i).var; qvconstraint qv; if (!joint) qv = qvconstraint( cc, home ); else { joint_to_qv( cc, qv, jvars_old, home->current, *home, combo ); if ( mp.length != 0 ) { qvconstraint qvn( jvars.length ); qmap_constraint( qv, qvn, jvars_old, mp ); qv = qvn; } } ex.obj.set_size(1); if ( data(i).request != "min" ) { ex.obj(0) = make_triple( Rational(0), qv.LHS, String("max") ); extend ans = ex.bound_by_primal_simplex_on_dual( ); if ( ans.PlusInfinity( ) ) { feasible = false; home->deactivate( ); return; } if ( ans.MinusInfinity( ) ) ERROR( "Unbounded objective function." ); data(i).max = double(ans.x); } if ( data(i).request != "max" ) { ex.obj(0) = make_triple( Rational(0), qv.LHS, String("min") ); extend ans = ex.bound_by_primal_simplex_on_dual( ); if ( ans.MinusInfinity( ) ) { feasible = false; home->deactivate( ); return; } if ( ans.PlusInfinity( ) ) ERROR( "Unbounded objective function." ); data(i).min = double(ans.x); } } feasible = true; home->deactivate( ); return; } else { if ( current_precision == 1 ) { canonical_lp_problem prob(m, n + m - m_eq); prob.slacks = m - m_eq; homebrew_in >> prob; homebrew_in.seekg(0, ios::beg); vector cost(n), improve; extend obj; forPixDef( i, data ) { cc.LHS = data(i).var; qvconstraint qv; if (!joint) qv = qvconstraint( cc, home ); else { joint_to_qv( cc, qv, jvars_old, home->current, *home, combo ); if ( mp.length != 0 ) { qvconstraint qvn( jvars.length ); qmap_constraint( qv, qvn, jvars_old, mp ); qv = qvn; } } for ( ii = 0; ii < qv.LHS.length; ii++ ) assign( prob.c(ii), qv.LHS(ii) ); if ( data(i).request != "max" ) { obj = prob.simple_simplex( cost, improve, confused, false ); if (confused) ERROR( "Simplex calculation failed." << " Retry using precision level 2." ); if ( obj.PlusInfinity( ) ) { feasible = false; home->deactivate( ); return; } assign( data(i).min, double(obj) ); if ( data(i).request != "min" ) { for ( ii = 0; ii < prob.c.length; ii++ ) prob.c(ii) = -prob.c(ii); obj = prob.simple_simplex( cost, improve, confused, false ); if (confused) ERROR( "Simplex calculation failed." << "Retry using precision level 2." ); if ( obj.PlusInfinity( ) ) { feasible = false; home->deactivate( ); return; } assign( data(i).max, -double(obj) ); } } } } if ( current_precision == 2 ) { canonical_lp_problem prob(m, n + m - m_eq); prob.slacks = m - m_eq; homebrew_in >> prob; homebrew_in.seekg(0, ios::beg); vector cost(n), improve; extend obj; forPixDef( i, data ) { cc.LHS = data(i).var; qvconstraint qv; if (!joint) qv = qvconstraint( cc, home ); else { joint_to_qv( cc, qv, jvars_old, home->current, *home, combo ); if ( mp.length != 0 ) { qvconstraint qvn( jvars.length ); qmap_constraint( qv, qvn, jvars_old, mp ); qv = qvn; } } for ( ii = 0; ii < qv.LHS.length; ii++ ) assign( prob.c(ii), qv.LHS(ii) ); if ( data(i).request != "max" ) { obj = prob.simple_simplex( cost, improve, confused, false ); if (confused) ERROR( "Simplex calculation failed " << "at precision level 2. " << "Retry using precision level 3." ); if ( obj.PlusInfinity( ) ) { feasible = false; home->deactivate( ); return; } assign( data(i).min, doubledouble(obj) ); if ( data(i).request != "min" ) { for ( ii = 0; ii < prob.c.length; ii++ ) prob.c(ii) = -prob.c(ii); obj = prob.simple_simplex( cost, improve, confused, false ); if (confused) ERROR( "Simplex calculation failed " << "at precision level 2. " << "Retry using precision level 3." ); if ( obj.PlusInfinity( ) ) { feasible = false; home->deactivate( ); return; } assign( data(i).max, -doubledouble(obj) ); } } } } if ( current_precision >= 3 ) { canonical_lp_problem prob(m, n + m - m_eq); { int i, j; for ( i = 0; i < prob.At.nrows; i++ ) for ( j = 0; j < prob.At.ncols; j++ ) Set_precision( prob.At(i,j), current_precision ); for ( i = 0; i < prob.b.length; i++ ) Set_precision( prob.b(i), current_precision ); for ( i = 0; i < prob.c.length; i++ ) Set_precision( prob.c(i), current_precision ); for ( i = 0; i < prob.x.length; i++ ) Set_precision( prob.x(i), current_precision ); for ( i = 0; i < prob.LU.nrows; i++ ) for ( j = 0; j < prob.LU.ncols; j++ ) Set_precision( prob.LU(i,j), current_precision ); for ( i = 0; i < prob.A_B.nrows; i++ ) for ( j = 0; j < prob.A_B.ncols; j++ ) Set_precision( prob.A_B(i,j), current_precision ); for ( i = 0; i < prob.x_B.length; i++ ) Set_precision( prob.x_B(i), current_precision ); for ( i = 0; i < prob.b_minus.length; i++ ) Set_precision( prob.b_minus(i), current_precision ); Set_precision( prob.tolx, current_precision ); for ( i = 0; i < prob.l.length; i++ ) Set_precision( prob.l(i).x, current_precision ); for ( i = 0; i < prob.u.length; i++ ) Set_precision( prob.u(i).x, current_precision ); } prob.slacks = m - m_eq; homebrew_in >> prob; homebrew_in.seekg(0, ios::beg); vector cost(n), improve; extend obj; forPixDef( i, data ) { cc.LHS = data(i).var; qvconstraint qv; if (!joint) qv = qvconstraint( cc, home ); else { joint_to_qv( cc, qv, jvars_old, home->current, *home, combo ); if ( mp.length != 0 ) { qvconstraint qvn( jvars.length ); qmap_constraint( qv, qvn, jvars_old, mp ); qv = qvn; } } for ( ii = 0; ii < qv.LHS.length; ii++ ) assign( prob.c(ii), qv.LHS(ii) ); if ( data(i).request != "max" ) { obj = prob.simple_simplex( cost, improve, confused, false ); if (confused) ERROR("Simplex calculation failed " << "at precision level " << current_precision << ". Retry using higher precision level."); if ( obj.PlusInfinity( ) ) { feasible = false; home->deactivate( ); return; } assign( data(i).min, Big(obj) ); if ( data(i).request != "min" ) { for ( ii = 0; ii < prob.c.length; ii++ ) prob.c(ii) = -prob.c(ii); obj = prob.simple_simplex( cost, improve, confused, false ); if (confused) ERROR("Simplex calculation failed " << "at precision level " << current_precision << ". Retry using higher precision level."); if ( obj.PlusInfinity( ) ) { feasible = false; home->deactivate( ); return; } assign( data(i).max, -Big(obj) ); } } } } feasible = true; home->deactivate( ); return; } } home->activate(true, results); ofstream command_file( calculations_dir + "/cplex_commands0" ); command_file << "set logfile *\n"; if ( CPLEX_VERSION[0] <= '2' ) { command_file << "set presolve n\n"; command_file << "set aggregate n\n"; } else { command_file << "set preprocessing presolve n\n"; command_file << "set preprocessing aggregator n\n"; } SLList multipliers; int j; int nvars = jvars.length; if (joint) mp = reduce_joint_in( *home, jvars ); nvars = jvars.length; forPixDef( i, data ) { // Convert the term_sum to be optimized to a linear combination of v // variables, with rational coefficients. Clear the denominators by // multiplying through by a number "multiplier". We'll have to // divide by this later. constraint cc( '=', 0 ); // sense and RHS are dummies cc.LHS = data(i).var; vconstraint vc(joint ? nvars : home->active->vtable.length); Rational multiplier; qvconstraint qv; if (!joint) qv = qvconstraint( cc, home ); else { joint_to_qv( cc, qv, jvars_old, home->current, *home, combo ); if ( mp.length != 0 ) { qvconstraint qvn( jvars.length ); qmap_constraint( qv, qvn, jvars_old, mp ); qv = qvn; } } multiplier = clear_denom( qv, vc ); multipliers.append(multiplier); if ( multiplier == Rational(0) ) // we're trying to optimize 0 { // Issue a warning of sorts. We could bypass optimization but // it would complicate the flow of the routine. cerr << "The expression " << data(i).var << " is identically " << "zero, but I'll optimize it anyway.\n"; } // Turn off CPLEX's echoing of "change coeff..." commands. The // double newline is needed to prevent the next command from being // gobbled up. command_file << "set output results n\n\n"; for ( j = 0; j < vc.LHS.length; j++ ) command_file << "change coeff obj v" << j + 1 << " " << vc.LHS(j) << "\n"; command_file << "set output results y\n\n"; // Load optimization instructions. if ( data(i).request != "max" ) command_file << "change sense obj min\n" << "opt\n"; if ( data(i).request == "max" || data(i).request == "minmax" ) command_file << "change sense obj max\n" << "opt\n"; } command_file.close( ); prevector files; if (!joint) { home->active->split(false, results, forced); if (homebrew) INTERNAL_ERROR("compute - homebrew"); files.set_size(2); files(0) = "cplex_in"; files(1) = "cplex_in2"; vconstraint tot(home->active->vtable.length); tot.sense = '='; tot.RHS = Ipow( 2, home->dim ); for ( int ii = 0; ii < tot.LHS.length; ii++ ) tot.LHS(ii) = home->active->vtable(ii).w.length( ); accommodate( choose( home->n, home->dim ) ); lp_crunch( files, home->active->vtable.length, tot, true ); remove( calculations_dir + "/cplex_in2" ); } else { files.set_size(1); files(0) = "joint_in"; if ( CPLEX_VERSION[0] <= '2' ) system( "echo set sizes nonzeros 2000000 5000 > " + calculations_dir + "/cplex_commands" ); else { system( "echo set read nonzeros 2000000 100000 > " + calculations_dir + "/cplex_commands" ); system( "echo set read constraints 50000 1000 >> " + calculations_dir + "/cplex_commands"); } system( String("echo r ") + PATH_PREFIX + calculations_dir + "/joint_in lp >> " + calculations_dir + "/cplex_commands" ); system( "cat " + calculations_dir + "/cplex_commands0 >> " + calculations_dir + "/cplex_commands" ); remove( calculations_dir + "/cplex_commands0" ); remove("cplex.log"); system( String(CPLEX) + " < " + calculations_dir + "/cplex_commands > " + calculations_dir + "/cplex_output" ); } ifstream infile ( calculations_dir + "/cplex_output" ); double optimum; String infile_piece; Pix mpix = multipliers.first( ); forPix( i, data ) { for ( j = 1; j <= 2; j++ ) { while(1) { infile >> infile_piece; if (!infile) goto error_exit; if ( infile_piece == "infeasible," || infile_piece == "Infeasible:" ) goto infeasible_exit; if ( infile_piece == "Optimal:" ) { infile >> infile_piece; if ( infile_piece != "Objective" ) goto error_exit; infile >> infile_piece; if ( infile_piece != "=" ) goto error_exit; infile >> optimum; break; } } if ( j == 2 ) { if ( multipliers(mpix) != Rational(0) ) data(i).max = Rational(optimum)/multipliers(mpix); else data(i).max = 0; break; } if ( data(i).request == "min" || data(i).request == "minmax" ) { if ( multipliers(mpix) != Rational(0) ) data(i).min = Rational(optimum)/multipliers(mpix); else data(i).min = 0; if ( data(i).request == "min" ) break; } if ( data(i).request == "max" ) { if ( multipliers(mpix) != Rational(0) ) data(i).max = Rational(optimum)/multipliers(mpix); else data(i).max = 0; break; } } multipliers.next(mpix); } infile.close( ); feasible = true; return; infeasible_exit: if ( i == data.first( ) ) { feasible = false; return; } ERROR("The optimization status has changed from feasible to" << " infeasible. The explanation for this is presumably" << " that the problem is numerically unstable. Under the" << " current version, there is nothing that can be done" << " about this. Try looking at codes which have smaller" << " length and/or dimension."); error_exit: ERROR( "opt_table::compute got confused while" << " scanning output of CPLEX. This could conceivably be an " << "\"internal error\", but other causes are more likely. For " << "example, CPLEX could have run out of memory. (Check the file " << "\"" << calculations_dir << "/cplex_output\" for confirmation. Consider using " << "the homebrew option.) Interrupting " << "a process can also result in this error message." ); } TEX(![ \block{The split linear programming routine} The procedure {\tt split} temporarily has two modes, depending on whether {\tt homebrew} is set. If {\tt homebrew} is not set, we proceed as follows. If \verb|file_status| $= 0$, the procedure \verb|split| first builds the file \verb|cplex_in|, which contains the main constraints coming from the split linear programming method. If \verb|file_status| $ = 1$, it will be assumed that the file \verb|cplex_in| is already built and current. The construction of \verb|cplex_in| can be very time-consuming. Next the procedure prepares a file \verb|cplex_commands|. This file tells CPLEX to read the file \verb|cplex_in|, and it also tells it to add all auxiliary constraints, which are placed in the file \verb|cplex_in2|. The file \verb|cplex_commands0| (which should exist prior to calling \verb|split|) is then appended to \verb|cplex_commands|. Then CPLEX is invoked from the file \verb|cplex_commands|. Output is written to the file \verb|cplex_output|. If {\tt homebrew} is set, the behavior is different, primarily because the built-in simplex solver is used in place of CPLEX. But there is another fundamental difference, namely that we will always try to show that the system is infeasible. The outcome of this attempt is reported via the global variable \verb|homebrew_status|, which is set to {\tt infeasible} if the system has been proved infeasible, {\tt feasible} if the system {\it appears\/} to be feasible, and {\tt confused} if the simplex calculation terminated abnormally. There is no provision yet for multiple objective functions as would be appropriate e.g.\ if one were simultaneously trying to prove several inequalities. ]! ) set_compile_file(split.cc) HIDE( ![ extern char* PATH_PREFIX; #include "homedefs.h" #include #include #include extern int sort_flag; extern long time_used_by_CPLEX; extern long time_used_generating_Krawtchouk_table; extern long time_used_generating_constraints; extern int homebrew, dual_constraint_bound, total_dual_constraint_bound; extern int smart_dual, silent, dcb_depth_limit, auto_projection, load_limit; extern int auto_projection_show_constraints; extern int auto_projection_show_parameters; extern int vars, total_constraints, eq_constraints, create_con_file_only; extern int adjoin_extra_brouwer_constraints; extern String homebrew_status; Integer choose(int, int); extern "C" int srandomx(unsigned); constraintlist known_globals(config&); void parse_j_var(String, int&, int&, int&); #include "simplex.h" #include "bitvec.h" #include "codetable.h" ]! ) TEX( ![ \verb|convert_dual_variable|:\ Given $w \in \F_2^r$ and a multi-index $J = \verb|dualw|$, let $D$ be the subcode of $C$ supported on $w$. Compute $\abs{D} \cdot \abs{\setofh{$J$-words in $D^\perp$}}$, by expressing it as a $\Z$-linear combination of basic local variables, with coefficients given in the vector {\tt vi}. Upon entry {\tt binom} should be an array of binomial coefficients. Compare with the implementation of {\tt split}. ]! ) index_method(convert_dual_variable) void config_active::convert_dual_variable( const word& w, const wordtype& dualw, Integer** binom, vector& vi ) const { int i, j, k, a, r, jj, sumx, n = c->home->n; word w_comp = w.complement( ); bool all_ones = w_comp.if_zero( ); Pix p; vi.set_size(vtable.length); Integer coeff, S; for ( j = 0; j < vtable.length; j++ ) { wordtype& v = vtable(j).maw; sumx = 0; forPix( p, vtable(j).w ) { if (!all_ones) { wordtype alt = v; alt.act( vtable(j).w(p) ); if ( w_comp * alt != 0 ) continue; } if ( even( vtable(j).w(p) * dualw ) ) sumx++; else sumx--; } if ( sumx != 0 ) { coeff = 1; for ( k = 0; k < c->part.length; k++ ) { S = 0; r = dualw(k); i = c->part(k) - v(k); jj = v(k); TEX(![ \begin{quotec} We compute the coefficient of $x^r$ in $(1+x)^i (1-x)^j$, according to the formula $\displaystyle{\sum_{a = \max(0,r-j)}^{\min(r,i)} {i \choose a} {j \choose r-a} (-1)^{r-a}}$. \end{quotec} ]!) for ( a = max(0,r-jj); a <= min(r,i); a++ ) { if ( even(r-a) ) S += binom[i][a] * binom[jj][r-a]; else S -= binom[i][a] * binom[jj][r-a]; } coeff *= S; } coeff *= sumx; vi(j) = coeff; } else vi(j) = 0; } } index_method(make_krawtchouk) Integer*** make_krawtchouk( int mp ) { static int last_mp(-1); static Integer*** last_combo; int i, j, k; if ( mp <= last_mp ) return last_combo; if ( last_mp >= 0 ) { // Delete last_combo. There is some reason to believe that // sometimes this does not work. for ( k = 0; k <= last_mp; k++ ) for ( i = (k+1)/2; i <= last_mp; i++ ) delete [ ] last_combo[k][i]; for ( k = 0; k <= last_mp; k++ ) delete [ ] last_combo[k]; delete [ ] last_combo; } Integer ***combo = new Integer**[mp+1]; last_mp = mp; last_combo = combo; for ( k = 0; k <= mp; k++ ) { combo[k] = new Integer*[mp+1]; for ( i = (k+1)/2; i <= mp; i++ ) combo[k][i] = new Integer[ min(i, mp-i) + 1 ]; } for( i = 0; i <= mp; i++ ) { // Warning! The following two lines were // combo[0][i][0] = combo[i][i][0] = 1; // but spurious errors resulted. combo[0][i][0] = 1; combo[i][i][0] = 1; for( k = 1; k <= i-1; k++ ) combo[k][i][0] = combo[k-1][i-1][0] + combo[k][i-1][0]; for( j = 1; j <= min(i, mp - i); j++ ) { combo[0][i][j] = 1; for( k = 1; k <= i+j-1; k++ ) combo[k][i][j] = combo[k][i][j-1] - combo[k-1][i][j-1]; combo[i+j][i][j] = -combo[i+j-1][i][j-1]; } } return combo; } index_method(generate_shared_constraints) constraintlist generate_shared_constraints( config* c, codetable& results ) { constraintlist ans; TEX( ![ \begin{quote} If the code is even and exactly one quarter of its codewords are doubly even, then the doubly even words comprise a subcode. Search for information about doubly even codes of dimension $k-2$ from which we can make deductions. \end{quote} ]! ) HIDE( ![ static Regex basic_joint_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); ]! ) weightlist www = c->home->ww(c->home->current); if ( c->home->dim > 1 && www.divisible(2) && c->known( String("div4<=") + dec(Ipow(2,c->home->dim-2)) ) ) { www.make_divisible(4); constraintlist knowns = known_globals(*c); forPixDef( p, results.open ) { codehome* h = results.open(p); if ( h->n == c->home->n && h->dim == c->home->dim - 2 && h->ww(h->base).divisible(4) && www <= h->w && h->opt.none_chosen( ) && h->assumed_cons <= knowns ) { constraintlist plus = h->configs(h->base).share->ycon; forPixDef( q, plus ) { // Only constraints which concern y_r (4|r) are // imported. constraint cc = plus(q); forPixDef( r, cc.LHS ) { String var = cc.LHS(r).var; if ( var[0] == 'y' ) { if ( yno(var) % 4 != 0 ) goto bad_var; } else if ( var[0] == 'd' ) { if ( var == "div2" ) goto bad_var; } else if ( var.matches( basic_joint_pattern ) ) { int i1, i2, i3; parse_j_var( var, i1, i2, i3 ); if ( i1 % 4 != 0 || i2 % 4 != 0 || i3 % 4 != 0 ) goto bad_var; } else goto bad_var; } ans.append(cc); bad_var: continue; } } } } return ans; } index_method(split) void config_active::split(bool quiet, codetable& results, constraintlist forced) { accommodate( choose( c->home->n, c->home->dim ) ); ofstream dump( calculations_dir + "/current" ); dump << "current configuration (for some calculations):\n\n" << *c; dump.close( ); prevector vars = c->share->wjv; ofstream vardef( calculations_dir + "/joint_variable_definitions" ); for ( int i = 0; i < vars.length; i++ ) vardef << "v" << dec(i+1) << " = " << vars(i) << "\n"; vardef.close( ); // Test to see if the first line of cplex_in is "maximize 0". if ( file_status == 1 ) { ifstream cpin( calculations_dir + "/cplex_in" ); if ( cpin.peek( ) == 'm' ) file_status = !homebrew; cpin.close( ); } if ( file_status == 1 ) { time_used_generating_constraints -= time(0); goto build_cplex_in2; } remove( calculations_dir + "/cplex_in" ); { int i, j, k, l, n = c->home->n; Pix p, q; TEX(![ \begin{quote} We will need to know the coefficient of $x^k$ in $(1+x)^i (1-x)^j$, for many triples $(k,i,j)$. Sometimes it is better to build a complete table in advance, and sometimes it is better to compute the coefficients one by one as needed, building only a table of binomial coefficients in advance. We have not yet thought carefully about how this choice should be made. In general, how to proceed should depend on the partition of $n$ belonging to the current partition. Let $mp$ be the maximum size of a part in the partition of the current configuration. For the time being, we build the complete table whenever $mp < 60$, building an array {\tt combo} whose $\hbox{\tt [k][i][j]}^{\operatoratfont th}$ entry is the coefficient of $x^k$ in $(1+x)^i (1-x)^j$, for $0 \leq j \leq i$ and $0 \leq k \leq i+j \leq mp$. \end{quote} ]!) Integer ***combo, **binom; number mp = c->part(0); for ( i = 1; i < c->part.length; i++ ) mp = max( mp, c->part(i) ); bool complete_table = (mp < 60); if (complete_table) { time_used_generating_Krawtchouk_table -= time(0); combo = make_krawtchouk(mp); time_used_generating_Krawtchouk_table += time(0); } else { binom = new Integer*[n+1]; for ( i = 0; i <= n; i++ ) { binom[i] = new Integer[i+1]; binom[i][0] = 1; for ( j = 1; j < i; j++ ) binom[i][j] = binom[i-1][j] + binom[i-1][j-1]; binom[i][i] = 1; } } TEX( \begin{quote} Now generate the main constraints. \end{quote} ) time_used_generating_constraints -= time(0); ofstream cplexin1( calculations_dir + "/cplex_in" ); if (!homebrew) cplexin1 << "maximize 0\nsubject to\n"; cplexin1.close( ); String pipe_command; if (sort_flag) { if (!homebrew) pipe_command = "sort -u -T calculations/tmp | fold -s >> " + calculations_dir + "/cplex_in"; else pipe_command = "sort -u -T calculations/tmp >> " + calculations_dir + "/cplex_in"; } else { if (!homebrew) pipe_command = "fold -s - >> " + calculations_dir + "/cplex_in"; else ERROR("Bad idea... sort before using homebrew lp."); } procbuf cplexin2p( pipe_command, ios::out ); ostream cplexin2( &cplexin2p ); if (!quiet && !silent) cerr << "[setting up linear program with " << vtable.length << " variables and "; int constraint_count = 0, sumx, sign_error; wordtype dualw(c); dualw.dual_advance(true); // initialize vconstraint vc(vtable.length); bool non_zero; vc.RHS = 0; Integer coeff; word all_ones(c->part.length); for ( i = 0; i < all_ones.length; i++ ) all_ones(i) = 1; do { if ( dual_constraint_bound >= 0 && dualw(0) > dual_constraint_bound && (dcb_depth_limit == 0 || c->part.length <= dcb_depth_limit) ) continue; for ( i = 0; i < dualw.length; i++ ) if ( total_dual_constraint_bound >= 0 && dualw(i) > total_dual_constraint_bound ) break; if ( i < dualw.length ) continue; non_zero = false; if (!complete_table) { convert_dual_variable(all_ones, dualw, binom, vc.LHS); if ( !vc.LHS.if_zero( ) ) non_zero = true; goto constraint_computed; } for ( j = 0; j < vtable.length; j++ ) { wordtype& v = vtable(j).maw; TEX(![ \begin{quoteb} Let $w_p$ range over a collection of words in the smallcode such that $w_p + {\tt v}$ gives all basic local variables equivalent to {\tt v}, without repetition. Set\\ \ \ \ \ \ \ $\displaystyle{\hbox{\tt sum} \ =\ \sum_p (-1)^{w_p \hbox{$\cdot$}\kern2pt \hbox{\tt\small dualw}}}$. \end{quoteb} ]!) sumx = 0; forPix( p, vtable(j).w ) { if ( even( vtable(j).w(p) * dualw ) ) sumx++; else sumx--; } if ( sumx != 0 ) { TEX( ![ \begin{quotec} We set {\tt coeff} $=$\\[0.05in] $\prod_{i = 0}^{\hbox{\small c-$>$part.length} - 1} \hbox{\tt combo[dualw(}i\hbox{\tt)][c->part(}i\hbox{\tt) - v(}i \hbox{\tt)][v(}i\hbox{\tt)]}$, except that things are complicated by the fact that we've only defined $\hbox{\tt combo[}k\hbox{\tt][}i\hbox{\tt][}j\hbox{\tt]}$ when $i \geq j$. \end{quotec} ]! ) sign_error = 0; if ( c->part(0) - v(0) >= v(0) ) coeff = combo[ dualw(0) ] [ c->part(0) - v(0) ] [ v(0) ]; else { coeff = combo[ dualw(0) ] [ v(0) ] [ c->part(0) - v(0) ]; sign_error += dualw(0); } for ( i = 1; i < c->part.length; i++ ) { if ( c->part(i) - v(i) >= v(i) ) coeff *= combo[ dualw(i) ] [ c->part(i) - v(i) ] [ v(i) ]; else { coeff *= combo[ dualw(i) ] [ v(i)] [ c->part(i) - v(i) ]; sign_error += dualw(i); } } if ( odd(sign_error) ) sumx = -sumx; coeff *= sumx; vc.LHS(j) = coeff; if ( coeff != 0 ) non_zero = true; } else vc.LHS(j) = 0; } constraint_computed: if ( !non_zero ) continue; // constraint is identically zero constraint_count++; if ( Integer(constraint_count) * Integer(vtable.length) > Integer(load_limit) * Integer(1000000) ) ERROR( "The number of basic local variables times the number of " << "constraints generated thusfar exceeds " << load_limit << ",000,000. Increase the parameter \"load limit\" if " << "you really want to carry out this calculation." ); TEX( ![ \begin{quotea} Determine if {\tt dualw} is dual-equivalent to a word of an inadmissible weight. \end{quotea} ]! ) bool must_be_zero = false; wordtype altz(c); for( i = 0; i < dualsmall_working.x.nrows; i++ ) { altz.act( dualsmall_working.x(i), dualw ); int dualweight = sum(altz); if ( 1 <= dualweight && dualweight < c->share->dual_min_low ) { must_be_zero = true; break; } } if (smart_dual && !must_be_zero) { int su = 0; for ( i = 0; i < c->part.length; i++ ) su += min( int(dualw(i)), c->part(i) - dualw(i) ); if ( 2 * su < c->share->dual_min_low ) { vc.sense = '<'; vc.RHS = Ipow( 2, c->home->dim ); cplexin2 << vc; vc.RHS = 0; } } vc.reduce( ); vc.sense = ( must_be_zero ? '=' : '>' ); cplexin2 << vc; } while( dualw.dual_advance(false) != 0 ); if (!quiet && !silent) cerr << constraint_count << " main constraints]\n"; cplexin2 << "v1 = 1\n"; if (!homebrew) { vconstraint tot(vtable.length); tot.sense = '='; tot.RHS = Ipow( 2, c->home->dim ); for ( i = 0; i < tot.LHS.length; i++ ) tot.LHS(i) = vtable(i).w.length( ); cplexin2 << tot; } cplexin2p.close( ); TEX( \begin{quote} Release space occupied by {\tt binom}. This is to avoid hogging memory. \end{quote} ) if ( !complete_table ) { for ( i = 0; i <= n; i++ ) delete [ ] binom[i]; delete [ ] binom; } file_status = 1; } build_cplex_in2: TEX(![ \begin{quote} Build the auxiliary constraintlist. Adjoin constraints as in the former command ``{\tt projection onto}'', which was as follows. {\tt projection onto}\kern5pt$w$\kern5pt{\tt is}\kern5pt\clabel{\tt;} ``Let $w$ be a small word, and let $\loW$ be its complement. The value $m$ of {\tt sub}$\loW$ must be known. Consider the projection $P$ of a code in ${\cal R}(\hbox{\tt current})$ onto the bits defined by the $1$'s in $w$. Let \clabel\ be a code type and suppose its length equals the weight of the basic word associated to $w$, it has dimension $k - \log_2(m)$, and it has no assumed constraints. Assume moreover that if $x_I$ is an admissible basic local variable for the current configuration, then $w \cdot I$ (dot product) lies in the assumed weight list of \clabel. If \clabel\ is known to be unrealizable, we conclude that {\tt[current]} is unrealizable. Otherwise, each known constraint for the base configuration of \clabel\ which involves only global variables is translated into a constraint for the current configuration, which is appended to the list of known constraints. This translation is accomplished by replacing each occurrence of $y_i$ by $1/m$ times the sum of all admissible basic local variables $x_I$ such that $w \cdot I = i$.'' Then print it out in terms of {\tt v} variables, to the file \verb|cplex_in2|. \end{quote} ]!) constraintlist aux = c->known_cons( ); aux.merge(forced); if (auto_projection) { c->small.build( ); int j, d = c->home->ww(c->home->current).min( ); for ( j = 0; j < c->small.x.nrows; j++ ) { word& wd = c->small.x(j); int dw = wd * c->part; if ( dw < d || dw >= 2*d ) continue; if ( results.not_exist(c->home->n - dw, c->home->dim - 1, d - dw/2) ) continue; weightlist residues; wordtype v(c); for ( int i = 0; i < vtable.length; i++ ) { SLList& words = vtable(i).w; forPixDef( q, words ) { v.act( words(q), vtable(i).maw ); int r = wd.complement( ) * v; residues.add(r); } } if (auto_projection_show_parameters) cerr << "checking for info on [" << c->home->n - dw << "," << c->home->dim - 1 << "," << residues << "]\n"; term_sum tr[c->home->n - dw + 1]; wordtype wt(c), wtm(c); vtable.first(wt); do { int s = wd.complement( ) * wt; wtm = wt; c->make_minimal(wtm); tr[s].merge( term( 1, wtm.variable( ) ) ); } while( vtable.advance(wt) ); forPixDef( p, results.open ) { codehome* h = results.open(p); if ( h->n != c->home->n - dw || h->dim != c->home->dim - 1 || !h->opt.none_chosen( ) || !(residues <= h->w) ) continue; if ( !h->assumed_cons.empty( ) ) { int low = c->share->dual_min_low; if ( c->known( String("jy") + dec(dw) + "d" + dec(low) + "=0" ) ) ++low; forPixDef( pp, h->assumed_cons ) { constraint co = h->assumed_cons(pp); if ( !co.simple( ) ) break; if ( co.RHS != 0 || co.sense != '=' ) break; String var = co.LHS.front( ).var; static Regex mu_pat( "mu" + pos_number ); static Regex y_pat( "y" + pos_number ); if ( var.matches(mu_pat) ) { if( as_int( var.after("mu") ) >= low ) break; } else if ( var.matches(y_pat) ) { if ( residues.contains( yno(var) ) ) break; } else break; } if ( pp != 0 ) continue; } config_core core( h->configs( h->base) ); constraintlist cl = h->configs(h->base).share->ycon; forPixDef( qq, residues ) { int rw = residues(qq); if ( !h->configs(h->base).share->ww.contains(rw) ) { constraint yc( String("y") + dec(rw) + "=0" ); cl.append(yc); } } forPixDef( q, cl ) { if ( !cl(q).global( ) ) continue; constraint cnew( cl(q).sense, cl(q).RHS * 2 ); term_sum ts = cl(q).LHS; forPix( qq, ts ) if ( ts(qq).var[0] != 'y' ) break; if ( qq != 0 ) ts = core.simplify_global_vars( cl(q).LHS, h->ww(h->base), h->dim ); forPixDef( t, ts ) { term_sum tr2 = tr[ yno( ts(t).var ) ]; forPixDef( xxx, tr2 ) tr2(xxx).coeff *= ts(t).coeff; cnew.adjoin(tr2); } if ( cnew.LHS.length( ) == 0 && cnew.sense == '=' && cnew.RHS == 0 ) continue; forPix( t, cnew.LHS ) if ( cnew.LHS(t).coeff < Rational(0) ) break; if ( t == 0 && cnew.sense == '>' && cnew.RHS == 0 ) continue; if ( !aux.known(cnew) ) { if (auto_projection_show_constraints) { cerr << "merging constraint " << cnew << " (from constraint " << cl(q); String hn = results.get_codehome_name(h); if ( hn != "" ) cerr << " for code type " << hn; cerr << ")\n"; } aux.append(cnew); } } } } } TEX( ![ \begin{quote} Adjoin constraints coming from constraints of the form $\verb|co|_m = 0$. \end{quote} ]! ) c->small.build( ); Integer dlow = 0, dhigh = -1; c->evaluate( "div4", dlow, dhigh ); int k = c->home->dim; bool dnot = dlow > Ipow(2, k-1) || dhigh < Ipow(2, k-1); bool even = c->home->ww(c->home->current).divisible(2); for ( int j = 1; j < c->small.x.nrows; j++ ) { word v = c->small.x(j); int m = v * c->part; if ( c->known( String("co") + dec(m) + "=0" ) || c->known( String("co=1") ) || ( dnot && even && odd(m/2) ) ) { constraint ev; ev.sense = '='; ev.RHS = Ipow(2, k - 1); for ( int i = 0; i < vtable.length; i++ ) { forPixDef( p, vtable(i).w ) { wordtype w = vtable(i).maw; w.act( vtable(i).w(p) ); if ( (v * w) % 2 == 0 ) ev.addterm( 1, w.variable( ) ); } } aux.append(ev); } } c->small.unbuild( ); aux.merge( generate_shared_constraints( c, results ) ); TEX( ![ \begin{quote} Adjoin constraints coming from Brouwer lower bound on the number of words divisible by a given power of $2$. \end{quote} ]! ) if ( !adjoin_extra_brouwer_constraints ) goto skip_brouwer; { word indx(c->part.length); indx.advance( ); // Don't do the code itself. do { SLList z; // Find variables which are zero where indx is one. for ( int i = 0; i < vtable.length; i++ ) { forPixDef( p, vtable(i).w ) { wordtype w = vtable(i).maw; w.act( vtable(i).w(p) ); if ( indx * w == 0 ) z.append(w); } } if ( z.length( ) > 1 ) { weightlist zw; forPixDef( p, z ) zw.add( sum( z(p) ) ); int divider = 2; while( zw.divisible(divider) ) divider *= 2; String dcon; forPix( p, z ) if ( sum( z(p) ) % divider == 0 ) { if ( dcon.length( ) != 0 ) dcon += "+"; dcon += dec(divider) + z(p).variable( ); } forPix( p, z ) dcon += "-" + z(p).variable( ); dcon += ">=0"; aux.append(dcon); } } while( indx.advance( ) ); TEX( ![ \begin{quote} Do the same for residual codes. \end{quote} ]! ) indx.set_zero( ); indx.advance( ); // Get a list of all variables. SLList z; for ( int i = 0; i < vtable.length; i++ ) { forPixDef( p, vtable(i).w ) { wordtype w = vtable(i).maw; w.act( vtable(i).w(p) ); z.append(w); } } do { word indxc = indx.complement( ); if ( indxc.if_zero( ) ) break; weightlist zw; forPixDef( p, z ) zw.add( indx * z(p) ); if ( zw.length( ) == 1 ) continue; int divider = 2; while( zw.divisible(divider) ) divider *= 2; String dcon; forPix( p, z ) if ( ( indx * z(p) ) % divider == 0 ) { if ( dcon.length( ) != 0 ) dcon += "+"; dcon += dec(divider) + z(p).variable( ); } dcon += String(">=") + dec( Ipow( 2, c->home->dim ) ); aux.append(dcon); } while( indx.advance( ) ); } skip_brouwer: String to_do; if (!homebrew) to_do = "fold -s > " + calculations_dir + "/cplex_in2"; else to_do = "cat > " + calculations_dir + "/cplex_in2"; procbuf cplex_in2p( to_do, ios::out ); ostream cplex_in2( &cplex_in2p ); vconstraint vc(vtable.length); forPixDef( ii, aux ) { if ( !aux(ii).local( ) ) continue; Rational mult = clear_denom( qvconstraint( aux(ii), c->home ), vc ); if ( mult != Rational(0) ) cplex_in2 << vc; } cplex_in2p.close( ); time_used_generating_constraints += time(0); } // Return (total constraints, number of equality constraints). // Always call accommodate first to set precision. index_method(lp_crunch) pair lp_crunch( const prevector& files, int nvars, const vconstraint& tot, bool skip_setup = false ) { int i, j; remove( calculations_dir + "/homebrew.log" ); TEX(![ \begin{quote} Make the CPLEX command file. We turn off the CPLEX presolver and aggregator, because sometimes these processors find that the system is infeasible, and then CPLEX won't allow us to write a file (via ``\verb|w|'') so that we may verify CPLEX's conclusion. \end{quote} ]!) if ( !skip_setup ) { remove( calculations_dir + "/cplex_commands0" ); ofstream command_file( calculations_dir + "/cplex_commands0" ); command_file << "set logfile *\n"; if ( CPLEX_VERSION[0] <= '2' ) { command_file << "set presolve n\n"; command_file << "set aggregate n\n"; } else { command_file << "set preprocessing presolve n\n"; command_file << "set preprocessing aggregator n\n"; } command_file << "opt\n"; remove( calculations_dir + "/cplex.bin" ); command_file << "w " << PATH_PREFIX << calculations_dir << "/cplex.bin\n"; command_file.close( ); } TEX(![ \begin{quote} On most machines one has to give an upper bound on the number of nonzero coefficients, using the ``\verb|set sizes nonzeros|'' command. It was set to 100,000,000, but I lowered it. At one time I also added a line\\ ``\verb|set read constraints 2000000 100000|'' to the CPLEX commands file, for some reason, but I noticed subsequently that this slowed down most calculations. It may need to be added back under certain conditions. [11/98: changed read constraints from $20000$ to $50000$] \end{quote} ]!) if (!homebrew) { if ( CPLEX_VERSION[0] <= '2' ) system( "echo set sizes nonzeros 2000000 5000 > " + calculations_dir + "/cplex_commands" ); else { system( "echo set read nonzeros 2000000 100000 > " + calculations_dir + "/cplex_commands" ); system( "echo set read constraints 50000 1000 >> " + calculations_dir + "/cplex_commands" ); } system( String("echo r ") + PATH_PREFIX + calculations_dir + "/" + files(0) + " lp >> " + calculations_dir + "/cplex_commands" ); for ( i = 1; i < files.length; i++ ) system(String("echo add ") + PATH_PREFIX + calculations_dir + "/" + files(i) + " >> " + calculations_dir + "/cplex_commands" ); system( "cat " + calculations_dir + "/cplex_commands0 >> " + calculations_dir + "/cplex_commands" ); remove( calculations_dir + "/cplex_commands0" ); remove("cplex.log"); time_used_by_CPLEX -= time(0); system( String(CPLEX) + " < " + calculations_dir + "/cplex_commands > " + calculations_dir + "/cplex_output" ); time_used_by_CPLEX += time(0); } else { // Compute number of constraints and their types. Merge constraint // files to form homebrew_in. vars = nvars; ofstream homebrew_in( calculations_dir + "/homebrew_in" ); vconstraint vvv(vars); homebrew_in << tot; int total_constraints = 1, eq_constraints = 1; for ( i = 0; i < files.length; i++ ) { ifstream cpin1( calculations_dir + "/" + files(i) ); while( cpin1.peek( ) != EOF ) { cpin1 >> vvv; if ( vvv.sense == '=' ) eq_constraints++; total_constraints++; homebrew_in << vvv; } cpin1.close( ); } homebrew_in.close( ); ofstream homebrew_log( calculations_dir + "/homebrew.log", ios::app ); homebrew_log << total_constraints << " constraints, of which " << eq_constraints << " are equalities\n"; homebrew_log << vars << " variables\n"; homebrew_log.close( ); exact_lp_problem ex; ex.n = vars; ex.m = total_constraints; ex.m_eq = eq_constraints; ex.known_to_be_infeasible = false; ex.con_file = calculations_dir + "/homebrew_in"; accommodate( ex.presolve( ) ); if ( ex.known_to_be_infeasible ) { homebrew_status = "infeasible"; return make_pair(ex.m, ex.m_eq); } if ( create_con_file_only ) { homebrew_status = ""; return make_pair(ex.m, ex.m_eq); } TEX( ![ \begin{quotea} Reset random number generator. This makes it easier to replicate problems. \end{quotea} ]! ) srandomx(1); homebrew_status = ex.show_infeasible_by_primal_simplex_on_dual(tot); return make_pair(ex.m, ex.m_eq); } } set_compile_file(code.c) HIDE(![#include "opt.h"]!) TEX(![ \block{Analyze code extensions} This section contains the \verb|list_extensions| routine, which is invoked only by the\\ \verb|via extension| command. The code in this section is written to the file {\tt extensions.cc}. \vspace{0.1in} \par\noindent {\tt minimal}: Let a group $G = \langle\VEC g1n\rangle$ act on an ordered set $S$. Let $x \in S$. Return {\tt true} if $x \leq gx$ for all $g \in G$, else {\tt false}. The method is to construct the orbit $Gx$, or part of it, in the {\tt false} case. Space may run out in the process, in which case execution will terminate abnormally. \vspace{0.1in} \par\noindent{\bf Outline of method} \vspace{0.1in} If an element of $Gx$ is expressible in the form $g_{\alpha_1} \cdots g_{\alpha_r} x$ $(1 \leq \VEC\alpha1r \leq n)$, we say that it has {\it length\/} $r$. If moreover it does not have length $s$ for any $0 \leq s < r$, we say it has {\it pure length\/} $r$. \vspace{0.1in} \par\noindent $Q := \setof{\VEC g1n}$\\ $X_{-1} := \emptyset$\\ $X_0 := \setof{x}$\\ $i := 1$\\ \begin{tabular}{lll} \kern-6pt repeat \{\ \ \ \ & $X_i := Q X_{i-1}$\ &(list of $\abs{Q} \cdot \abs{X_{i-1}}$ elements)\\ & \multicolumn{2}{l}{(As we go through the above, test for minimality, and if violated, return {\tt false}.)}\\ & $X_i := $ unique sort of $X_i$\\ & \multicolumn{2}{l}{(At this point $X_i = Q \cdot \setofh{elements of pure length $i-1$}$.)}\\ & $X_{i-1} := X_{i-2} \cup X_{i-1}$\ &(merge of nonoverlapping unique-sorted\\ && sets, to form a new unique-sorted set)\\ & \multicolumn{2}{l}{(At this point $X_{i-1}$ consists of all elements of length $\leq i-1$.)}\\ & delete $X_{i-2}$\\ & $X_i := X_i - X_{i-1}$ & (still a unique-sorted set)\\ & \multicolumn{2}{l}{(At this point $X_i$ consists of all elements having pure length $i$.)}\\ & if ( $X_i = \emptyset$ ) return {\tt true}\\ & $i${\tt++}\ \ \ \ \ \ \ \} \end{tabular} \mindex{minimal} ]!) set_compile_file(extensions.cc) HIDE( ![ #include "homedefs.h" ifelse(UNAME,Openstep, ![#include ]!, ![#include ]!) #include vector pack(matrix); matrix canonical_form(matrix); #include "uniq.h" extern long time_used_by_list_extensions; template void sort_by_second( prevector< pair >& ); bool sub_to_dual_radius(int, partition, matrix, int); bool realizable(config_core&, constraintlist&, codehome*, codetable&); void mul( const vector&, const matrix&, vector&); ]! ) TEX(\label{bool-minimal}) template bool minimal( const prevector& Q, const S& x, int (*cmp)(const S&, const S&), void (*act)(const G&, const S&, S&) ) { prevector Xa(0), Xb(1), Xc, Xt; Xb(0) = x; int i, j, k, c, n = Q.length; while(1) { Xc.set_size( n * Xb.length ); for ( i = 0; i < Q.length; i++ ) for ( j = 0; j < Xb.length; j++ ) { act( Q(i), Xb(j), Xc( i + n * j ) ); if ( (*cmp)(Xc( i + n * j ), x) < 0 ) return false; } Xc.unique_sort(cmp); merge( Xa, Xb, Xt, cmp ); // Merge Xa and Xb to get Xa = Xt; // new Xa, then set Xb = Xc - Xa. diff( Xc, Xa, Xb, cmp ); if ( Xb.length == 0 ) return true; } } HIDE(![int rcmp(const number&, const number&);]!) index_method(yact) void yact(const Permutation& p, const vector& v, vector& v_new) { v_new.set_size(v.length); for ( int i = 0; i < v.length; i++ ) v_new(i) = p( v(i) - 1 ); v_new.sort(rcmp); } index_method(ycmp) int ycmp(const vector& a, const vector& b) { register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i).x > b(i).x ) return 1; if ( a(i).x < b(i).x ) return -1; } return 0; } index_method(list_extensions) SLList< matrix > codehome::list_extensions(bool alternate_extension_method, bool enumerators_only, codetable& results) { time_used_by_list_extensions -= time(0); config& c = configs(current); config_core core = configs(base); Pix q, l; int i, j, k, wt; int s = c.small.basis.nrows; // dimension of code we start with int r = dim - s; // number of extension steps if ( r == 0 ) ERROR( "This is silly." ); int rg = c.part(c.part.length-1); // room to grow // Check the current configuration to see if it meets the // requirements of the "via extension" command. for ( i = 0; i < c.part.length - 1; i++ ) if ( c.part(i) != 1 ) ERROR("The partition of the configuration must have the " << "form 1,1,...,r for some r."); for ( i = 0; i < s; i++ ) if ( c.small.basis(i,c.part.length-1).x != 0 ) ERROR("Configuration not of correct type: " << "last entry of each small code element must be 0."); if ( rg < r ) ERROR("Configuration not of correct type."); // Find the generator matrix of the code D to be extended. matrix B(s, n - r); for ( i = 0; i < B.nrows; i++ ) { for ( j = 0; j < n - rg; j++ ) B(i,j) = c.small.basis(i,j); } if ( !c.no_bad_weights( ) ) ERROR("There is a word of illegal weight."); // Compute the automorphism group. if ( c.assumed_cons.joint( ) ) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; } // Form the list of permutations which are known to act on D. Permutationlist genset(n-r); Permutation p(n-r); for ( int ii = 0; ii < c.aut.length; ii++ ) { Permutation p0 = c.aut(ii); if ( p0(p0.length-1) == c.part.length ) { for ( i = 0; i < p0.length - 1; i++ ) p(i) = p0(i); for ( i = p0.length; i < p.length; i++ ) p(i) = i + 1; genset.append(p); } } TEX( ![ \begin{quote} Determine the minimum weight and if we are working with even codes. Also determine if there are other weights to be excluded. \end{quote} ]! ) weightlist& wl = c.share->ww; int min_weight = wl.min( ); bool w_is_even = wl.divisible(2); OSLList bad_weights; int incre = ( w_is_even ? 2 : 1 ); for ( i = min_weight; i <= n; i += ( w_is_even ? 2 : 1 ) ) bad_weights.append(i); forPix( q, wl ) bad_weights.del( wl(q) ); OSLList bw_curr = bad_weights; forPix( q, bad_weights ) if ( bad_weights(q) > n - r + 1 ) bw_curr.del( bad_weights(q) ); vector bw_curr_v(bw_curr); prevector bwcv(n+1); for ( i = 0; i <= n; i++ ) bwcv(i) = false; for ( i = 0; i < bw_curr_v.length; i++ ) bwcv( bw_curr_v(i) ) = true; vector bwv(n+1); for ( i = 0; i <= n; i++ ) bwv(i) = true; forPix( q, wl ) if ( wl(q) ) bwv( wl(q) ) = false; TEX( ![ \begin{quote} Determine if the dual small code has a dual word corresponding to the last bit of the partition. \end{quote} ]! ) vector lastbit(c.part.length); lastbit( lastbit.length - 1 ) = 1; bool last_dual = c.dualsmall.basis.rowspace_member( lastbit ); TEX( ![ \begin{quote} Form a matrix {\tt M} in \RREF\ whose rows form a basis for the nullspace of {\tt B}. Let {\tt M1} be obtained by adding a ``blank'' column to {\tt M}. The rows of the matrix {\tt D} will form a basis for the nullspace of {\tt M1}. \end{quote} ]! ) matrix M; B.nullspace_equals(M); M.reduce( ); matrix M1, a_col( M.nrows, 1 ), D(s + 1, n - r + 1); hcat( M, a_col, M1 ); // Find the admissible elements of V := F_2^{n-r-s}. matrix DE; partition Dp; if ( opt.dual_radius > 0 ) { DE.set_size( D.nrows, opt.dual_radius_length ); Dp.set_all_ones(opt.dual_radius_length); } SLList< vector > adm; vector v(n-r-s), test(n-r+1); do { TEX( ![ \begin{quoteaneg} If the code is even, and you add together all the rows of the generator matrix for the dual code, you will get the all $1$'s word. Hence the columns of the dual code generator matrix should have odd weight. \end{quoteaneg} ]! ) if ( w_is_even && even( v.weight( ) ) ) continue; M1.set_col( n-r, v ); M1.nullspace_equals(D); if ( s <= 31 ) { unsigned long X = Ipow(2, s); for ( j = 0; j < test.length; j++ ) test(j) = D(s,j); for ( unsigned long I = 0; I < X; I++ ) { wt = test.weight( ); if ( wt < min_weight || bwcv(wt) ) goto inadmissible; int g = gray(I); for ( j = 0; j < test.length; j++ ) test(j).x ^= D(g,j).x; } } else { vector indx(s); do { for ( j = 0; j < test.length; j++ ) test(j) = D(s,j); for ( i = 0; i < indx.length; i++ ) if ( indx(i).x ) for ( j = 0; j < test.length; j++ ) test(j).x ^= D(i,j).x; wt = test.weight( ); if ( wt < min_weight || bwcv(wt) ) goto inadmissible; } while( indx.advance( ) != 0 ); } if ( opt.dual_radius > 0 ) { for ( i = 0; i < D.nrows; i++ ) for ( j = 0; j < D.ncols; j++ ) DE(i, j) = D(i, j); if ( !sub_to_dual_radius( opt.dual_radius, Dp, DE, opt.dual_radius_dim ) ) goto inadmissible; } if ( v.length == MAXSHORT ) ERROR("There are > " << MAXSHORT << " admissible elements," << " which is too many for the language to handle."); adm.append(v); inadmissible: continue; } while( v.advance( ) != 0 ); cerr << "There are " << adm.length( ) << " admissible elements.\n"; vector< vector > admv(adm); admv.sort(&cmp); int count = admv.length; // genset2 will act on the admissible elements. We compute its action. Permutationlist genset2(count); genset2.set_size( genset.length ); matrix Mc, Q; vector rx; Permutation pp(count); for ( k = 0; k < genset.length; k++ ) { Mc = M; Mc.permute_columns( genset(k) ); Mc.reduce_i(Q); for ( i = 0; i < count; i++ ) { mul( Q, admv(i), rx ); int xp = admv.pos( rx, cmp ); HIDE( ![ if ( xp == -1 ) INTERNAL_ERROR("computation of genset2"); ]! ) pp(i) = xp + 1; } genset2(k) = pp; } // Make a list of 200 group elements. Permutationlist genset2v(count); genset2v.generate( genset2, 200 ); // Delete identity if present in list. for ( i = 0; i < genset2v.length; i++ ) { if ( genset2v(i) == Permutation(count) ) { Permutationlist genset2vx(count); genset2vx.set_size( genset2v.length - 1 ); for ( j = 0; j < genset2v.length; j++ ) { if ( j < i ) genset2vx(j) = genset2v(j); if ( j > i ) genset2vx(j-1) = genset2v(j); } genset2v = genset2vx; break; } } SLList< vector > level[r+1]; SLList< matrix > answer; // Compute level 1. vector one(1); uniq_mat_list levelr(n); for ( i = 1; i <= count; i++ ) { one(0) = i; if ( minimal( prevector(genset2), one, ycmp, yact ) ) { if ( r != 1 ) level[1].append(one); else { M1.set_col( n-r, admv(i-1) ); M1.nullspace_equals(D); config_core dcore; dcore.part.set_all_ones(D.ncols); dcore.smallbasis = D; dcore.dualsmallbasis.set_size(0, D.ncols); if ( realizable( dcore, assumed_cons, this, results ) ) { vector weights(0); if (enumerators_only) { weights = D.enumerate_weights( ); forPixDef( qr, answer ) if (weights == answer(qr).enumerate_weights( ) ) break; if ( qr != 0 ) continue; } else if ( !levelr.add(D) ) continue; if ( weights.length == 0 ) weights = D.enumerate_weights( ); level[1].append(one); answer.append(D); cerr << "Extension " << answer.length( ) << ": " << D << "\n" << "weight enumerator: " << as_poly(weights) << "\n"; } } } } cerr << "level 1 has " << level[1].length( ) << " elements\n"; // Compute levels 2,...,r. int lev; for ( lev = 2; lev <= r; lev++ ) { bw_curr = bad_weights; forPix( q, bad_weights ) if ( bad_weights(q) > n-r + lev ) bw_curr.del( bad_weights(q) ); bw_curr_v = vector( bw_curr ); vector curr(lev); matrix M2, lev_cols( M.nrows, lev ), D2(s + lev, n - r + lev); hcat( M, lev_cols, M2 ); codehome lrhome( D2.ncols, D2.nrows, weightlist("1", D2.ncols), results ); vector test(n-r+lev), indx(s+lev-1); forPix( q, level[lev-1] ) { for ( i = 0; i < lev-1; i++ ) curr(i) = level[lev-1](q)(i); for ( j = 0; j < lev - 1; j++ ) M2.set_col( M.ncols+j, admv(curr(j) - 1) ); TEX( ![ \begin{quoteb} We have a matrix {\tt M2}. For each iteration of the main loop (below), its last column changes (or at least it would, if we did not use the faster methods to be described here). We would then determine if there could exist an ``illegal weight'' vector having one in its last position and orthogonal to the rows of {\tt M2}. However, it is faster to first make some computations which apply to each {\tt M2}. For this, we actually set the last column of {\tt M2} to zero. First perform elementary row operations and then column permutations on {\tt M2} to yield a matrix {\tt M2f} of the form $[I|*]$. \end{quoteb} ]! ) matrix M2f = M2, D2f, QQ; for ( i = 0; i < M2f.nrows; i++ ) // Make sure last col is zero. M2f( i, M2f.ncols - 1 ) = 0; M2f.reduce_i(QQ); bool QQ_is_identity = false; for ( i = 0; i < QQ.nrows; i++ ) for ( j = 0; j < QQ.ncols; j++ ) if ( QQ(i,j).x != (i == j) ) goto not_identity; QQ_is_identity = true; not_identity: for ( i = 0; i < M2f.ncols; i++ ) if ( M2f( M2f.nrows - 1, i ) ) break; if ( i == M2f.ncols ) INTERNAL_ERROR( "Matrix should have full row rank." ); Permutation* colfix = M2f.column_fix( ); delete colfix; // Create a matrix kerM2f whose rows are the vectors which // (1) are orthogonal to the rows of M2f and // (2) have one in their last position. M2f.nullspace_equals(D2f); matrix kerM2f( (int) Ipow(2, D2f.nrows-1), M2f.ncols ); word indxf( D2f.nrows ), kv( D2f.ncols ); i = 0; do { mul( indxf, D2f, kv ); if ( kv( kv.length - 1 ) ) kerM2f( i++ ) = kv; } while ( indxf.advance( ) ); // Set kerM2f1 to the first M2f.nrows columns of kerM2f. // Then set wkerM2f2 to the vector whose i'th entry is the weight // of the part of the i'th row of kerM2f to the right of the // first M2f.nrows columns. matrix kerM2f1 = kerM2f; kerM2f1.resize( kerM2f.nrows, M2f.nrows ); vector wkerM2f2( kerM2f.nrows ); for ( i = 0; i < wkerM2f2.length; i++ ) { int sum = 0; for ( j = M2f.nrows+1; j < kerM2f.ncols; j++ ) if ( kerM2f(i,j) ) sum++; wkerM2f2(i) = sum; } for ( i = curr(lev-2) + 1; i <= count; i++ ) { curr(lev-1) = i; TEX( ![ \begin{quotec} Test for $G$-minimality, where $G$ is the $200$ (or less) element subset of the automorphism group constructed above. If the parameter \verb|alternate_extension_method| is set, we use the entire known automorphism group. \end{quotec} ]! ) if ( alternate_extension_method ) { if ( !minimal( prevector(genset2), curr, ycmp, yact ) ) continue; } else if ( genset2v.length > 0 && !genset2v.minimal(curr) ) continue; // Test for admissibility. if ( w_is_even ) { word ka ( QQ.nrows ); if ( QQ_is_identity ) ka = admv(i-1); else mul( QQ, admv(i-1), ka ); static int targ(0); register gf2* r2 = ka.x; for ( j = 0; j < kerM2f.nrows; j++ ) { register gf2* r1 = kerM2f1.x[j].x; register int sum = wkerM2f2(j); for ( register int jj = 0; jj < ka.length; jj++ ) sum += r1[jj] ^ r2[jj]; if ( odd(sum) ) sum++; if ( bwv.x[sum] ) #define TOP_QUEUE 6 { if ( j >= TOP_QUEUE ) { swap( kerM2f1(j), kerM2f1(targ) ); swap( wkerM2f2(j), wkerM2f2(targ) ); targ++; targ %= TOP_QUEUE; } goto inadmissible2; } } } else { M2.set_col( M.ncols+lev-1, admv(i-1) ); M2.nullspace_equals(D2); if ( s + lev - 1 <= 31 ) { unsigned long X = Ipow(2, s + lev - 1); for ( j = 0; j < test.length; j++ ) test(j) = D2(s + lev - 1,j); for ( unsigned long I = 0; I < X; I++ ) { wt = test.weight( ); if ( wt < min_weight || bwcv(wt) ) goto inadmissible2; gf2* D2g = D2.x[ gray(I) ].x; for ( j = 0; j < test.length; j++ ) test(j).x ^= D2g[j].x; } } else { register gf2* D2k; register int tl; indx.set_zero( ); do { // Set test = // (indx(0), ..., indx(last),1) * D2. register int j, k; for ( j = 0; j < test.length; j++ ) test(j) = D2(s+lev-1,j); for ( k = 0; k < indx.length; k++ ) if ( indx(k).x ) { D2k = D2.x[k].x; tl = test.length; for ( j = 0; j < tl; j++ ) test(j).x ^= D2k[j].x; } wt = test.weight( ); if (wt < min_weight || bw_curr_v.member(wt)) goto inadmissible2; } while( indx.advance( ) != 0 ); } } if ( opt.dual_radius > 0 ) { M2.set_col( M.ncols+lev-1, admv(i-1) ); M2.nullspace_equals(D2); matrix DE = D2; DE.resize( D2.nrows, opt.dual_radius_length ); partition Dp(opt.dual_radius_length); Dp.set_all_ones(opt.dual_radius_length); if ( !sub_to_dual_radius( opt.dual_radius, Dp, DE, opt.dual_radius_dim ) ) goto inadmissible2; } if (last_dual) { M2.set_col( M.ncols+lev-1, admv(i-1) ); M2.nullspace_equals(D2); for ( j = 0; j < D2.nrows; j++ ) { char sum = 0; for ( k = n-rg; k < D2.ncols; k++ ) sum ^= D2(j,k); if ( sum != 0 ) break; } if ( j != D2.nrows ) continue; } if ( lev != r ) level[lev].append(curr); if ( lev == r ) { M2.set_col( M.ncols+lev-1, admv(i-1) ); M2.nullspace_equals(D2); D2.reduce( ); config_core dcore; dcore.part.set_all_ones(D2.ncols); dcore.smallbasis = D2; dcore.dualsmallbasis.set_size(0, D2.ncols); if ( realizable( dcore, assumed_cons, this, results ) ) { vector weights(0); if (enumerators_only) { weights = D2.enumerate_weights( ); forPixDef( qr, answer ) if (weights == answer(qr).enumerate_weights( ) ) break; if ( qr != 0 ) continue; } else if ( !levelr.add(D2) ) continue; if ( weights.length == 0 ) weights = D2.enumerate_weights( ); level[lev].append(curr); answer.append(D2); cerr << "Extension " << answer.length( ) << ": " << D2 << "\n" << "weight enumerator: " << as_poly(weights) << "\n"; } } inadmissible2: continue; } } cerr << "level " << lev << " has " << level[lev].length( ) << " elements\n"; } time_used_by_list_extensions += time(0); return answer; } set_compile_file(code.c) TEX(![ \block{Command parser} The parser is invoked by: \vspace{0.05in} \par\noindent\kern0.5in\verb|parse( s, &( |$\hbox{\it item}_1$\verb|, |% $\ldots$\verb|, |$\hbox{\it item}_r$\verb| ) )| \vspace{0.05in} \par\noindent where \verb|s| is a pre-existing string and the given items each have one of the following forms: \begin{itemize} \item \verb|parse_text(|{\it required text}\verb|)|, where {\it required text\/} must occur; \item \verb|parse_pat(|{\it pattern}\verb|, |{\it string-name}\verb| )|\\ where {\it pattern\/} points to a regular expression, and {\it string-name\/} is the name of a \verb|String| object to be filled with whatever matches {\it pattern}; \item \verb|parse_pos(|{\it Integer-name}\verb|,|\kern5pt% {\it lowest allowed value (default $1$)}\verb|,|\kern5pt% {\it highest allowed value (default $\infty$)}\verb|)|, where {\it Integer-name} is the name of a \verb|Integer| object to be filled. \item \verb|parse_pos_list(|{\tt number} {\it vector}\verb|,|\kern5pt% {\it low}\verb|,|\kern5pt{\it high}\verb|)|, where {\it low}, {\it high} are as in the \verb|parse_pos| form; \item \verb|parse_short(|{\it short int-name}\verb|,|\kern5pt% {\it lowest allowed value (default $1$)}\verb|,|\kern5pt% {\it highest allowed value (default $\infty$)}\verb|)|, where {\it short int-name} is the name of a \verb|short int| object to be filled. \item \verb|parse_word(|{\it word}\verb|)| \item \verb|parse_open_code_type(|{\it codetable}\verb|, | {\it string-name}\verb|, |{\it pix-name}\verb| )| \item \verb|parse_constraint(|{\it constraint-name}\verb|)| \item \verb|parse_constraint_list(|{\it constraintlist-name}\verb|)| \item \verb|parse_known_config(results, |{\it pointer to\/} {\tt codehome}% \verb|, |{\it string-name}\verb|, |{\it pix-name}\verb| )| \end{itemize} The routine {\tt parse} returns {\tt true} if there is a successful match (with all the items, in order), and otherwise {\tt false}. ]!) index_class(parse_base) index_method(create) class parse_base { public: static String in; static parse_base* first; static parse_base* last; parse_base* next; parse_base( ); virtual bool create( ) = 0; }; parse_base::parse_base( ) { if ( first == 0 ) first = this; else last->next = this; last = this; next = 0; } String parse_base::in; parse_base* parse_base::first = 0; parse_base* parse_base::last; index_class(parse_pos) class parse_pos : public parse_base { public: Integer* n; Integer low, high; bool create( ); parse_pos(Integer& r, const Integer& low = 1, const Integer& high = -1) : low(low), high(high) { n = &r; } }; Regex pos_number_pattern(pos_number); bool parse_pos::create( ) { if ( !in.contains( pos_number_pattern, 0 ) ) return false; *n = Integer( take( in, pos_number_pattern ) ); if ( *n < low ) ERROR("The number " << *n << " is too small. It should be at " << "least " << low << "."); if ( high != -1 && *n > high ) ERROR("The number " << *n << " is too large. It should be no " << "greater than " << high << "."); return true; } index_class(parse_small) class parse_short : public parse_base { public: short int* n; int low, high; bool create( ); parse_short(short int& r, const int& low = 1, const int& high = MAXSHORT) : low(low), high(high) { n = &r; } }; bool parse_short::create( ) { if ( !in.contains( pos_number_pattern, 0 ) ) return false; Integer N = Integer( take( in, pos_number_pattern ) ); if ( N < low ) ERROR("The number " << N << " is too small. It should be at " << "least " << low << "."); if ( high != -1 && N > high ) ERROR("The number " << N << " is too large. It should be no " << "greater than " << high << "."); *n = int(N); return true; } index_class(parse_pos_list) class parse_pos_list : public parse_base { public: vector* v; Integer low; Integer high; bool create( ); parse_pos_list( vector& vv, const Integer& low = 1, const Integer& high = MAXSHORT ) : low(low), high(high) { v = &vv; } }; bool parse_pos_list::create( ) { static Regex pos_list_pattern(pos_list); if ( in.empty( ) || !isdigit(in[0]) ) return false; String matching_piece = take( in, pos_list_pattern ); prevector args = unpack( matching_piece ); v->set_size( args.length ); for ( int i = 0; i < args.length; i++ ) { Integer n = Integer(args(i)); if ( n < low ) ERROR("The number " << n << " is too small. It should be " << "at least " << low << "."); if ( high != -1 && n > high ) ERROR("The number " << n << " is too large. It should be " << "no greater than " << high << "."); (*v)(i) = int(n); } return true; } index_class(parse_word) class parse_word : public parse_base { public: word* w; bool create( ); parse_word( word& wd ) { w = &wd; } }; bool parse_word::create( ) { static Regex zero_one_pat( "[01]+" ); if ( !in.contains( zero_one_pat, 0 ) ) return false; *w = word( take( in, zero_one_pat ), 0 ); return true; } index_class(parse_pat) class parse_pat : public parse_base { public: Regex* pat; String* s; bool create( ) { if ( !in.contains( *pat, 0 ) ) return false; *s = take( in, *pat ); return true; } parse_pat( Regex* r, String& st ) : pat(r) { s = &st; } }; index_class(parse_test) class parse_test : public parse_base { public: String s; bool* test; bool create( ); parse_test( const String& st, bool& t ) : s(st) { test = &t; } }; bool parse_test::create( ) { if ( !in.contains( s, 0 ) ) *test = false; else { *test = true; in.del(s); } return true; } index_class(parse_known_config) class parse_known_config : public parse_base { public: codetable* results; codehome* home; String* label; Pix* p; bool create( ); parse_known_config( codetable& c, codehome& h, String& l, Pix& pr ) { results = &c, home = &h, label = &l, p = ≺ } }; bool parse_known_config::create( ) { static Regex gen_label_pattern( gen_label_pat ); if ( !in.contains( gen_label_pattern, 0 ) ) return false; *label = take( in, gen_label_pattern ); // The following line is dangerous because there could be a command which // starts with a label pattern, but the label is not supposed to // be a preexisting configuration. *p = home->label_to_Pix(*label, *results); return true; } index_class(parse_open_code_type) class parse_open_code_type : public parse_base { public: const codetable* results; String* label; Pix* px; bool create( ); parse_open_code_type( const codetable& c, String& l, Pix& p ) { results = &c, label = &l, px = &p; } }; bool parse_open_code_type::create( ) { static Regex label_pattern(label_pat); if ( !in.contains( label_pattern, 0 ) ) return false; *label = take( in, label_pattern ); forPixDef( p, results->olabels ) { if ( results->olabels(p).first == *label ) { *px = results->olabels(p).second; break; } } if ( p == 0 ) ERROR("Code type " << *label << " is not a known open type."); return true; } index_class(parse_code_type) class parse_code_type : public parse_base { public: const codetable* results; String* label; Pix* px; int* status; // -1 if dead, else 0 bool create( ); parse_code_type( const codetable& c, String& l, Pix& p, int& st ) { results = &c, label = &l, px = &p, status = &st; } }; bool parse_code_type::create( ) { static Regex label_pattern(label_pat); if ( !in.contains( label_pattern, 0 ) ) return false; *label = take( in, label_pattern ); forPixDef( p, results->olabels ) { if ( results->olabels(p).first == *label ) { *px = results->olabels(p).second; *status = 0; return true; } } forPix( p, results->dlabels ) { if ( results->dlabels(p).first == *label ) { *px = results->dlabels(p).second; *status = -1; return true; } } ERROR("Code type " << *label << " is not a known code type."); } index_class(parse_constraint) class parse_constraint : public parse_base { public: constraint* con; bool create( ); parse_constraint( constraint& c ) { con = &c; } }; bool parse_constraint::create( ) { static Regex gen_constraint_pattern(constraint_pat + orsign + var + "!=0"); // Check for fake constraints (kludge). if ( in.contains("dual",0) || in.contains("by",0) || in.contains("from",0) || in.contains("kill",0) ) return false; if ( !in.contains( gen_constraint_pattern, 0 ) ) return false; *con = take( in, gen_constraint_pattern ); return true; } index_class(parse_constraint_list) class parse_constraint_list : public parse_base { public: constraintlist* con; bool create( ); parse_constraint_list( constraintlist& c ) { con = &c; } }; bool parse_constraint_list::create( ) { static String less_op = left + "<" + orsign + "<=" + right; static String compound_constraint_pat = "[-]?" + number_pat + less_op + LHS_pat + less_op + "[-]?" + number_pat; static Regex constraint_list_pat( list_of( constraint_pat + orsign + var + "!=0" + orsign + compound_constraint_pat) ); if ( !in.contains( constraint_list_pat, 0 ) ) return false; *con = take( in, constraint_list_pat ); return true; } index_class(parse_text) class parse_text : public parse_base { public: String require; bool create( ); parse_text(const String& s) : require(s) { } }; bool parse_text::create( ) { if ( !in.contains( require, 0 ) ) return false; in.del(require); return true; } bool parse( const String& parse_me ... ) { parse_base::in = parse_me; parse_base* current = parse_base::first; parse_base::first = 0; while ( current != 0 ) { if ( !(*current).create( ) ) return false; current = current->next; } return parse_base::in.empty( ); } set_compile_file(op0.cc) HIDE( ![ #include "homedefs.h" #include "bitvec.h" #include "codetable.h" int take_int(String&, const Regex&); extern String pos_number, left, right, orsign, gen_label_pat, pos_list; extern String config_list_piece; extern int debug; extern matrix BCH(int, int, int, int); typedef vector polyF2; polyF2 primitive_poly(int); int divides(const polyF2&, polyF2); matrix BCH(polyF2, int, vector); String list_of(const String&, const String& = ","); String nontrivial_list_of(const String&, const String& = ","); prevector< vector > tuple_orbits(matrix, int); int min_distance(const matrix&, int); prevector expand_config_list(codehome*, String); SLList< matrix > enlarge_by_dual_word(const matrix&, int); SLList< vector > dual_words_of_given_weight(matrix, int); vector pack(matrix); matrix canonical_form(matrix); OSLList int_set(String); bool iso_member(const matrix&, const SLList< matrix >&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); SLList< vector > iso_dual_words_of_given_weight(matrix, int); pair< Permutationlist, Integer > find_automorphism_group(const matrix&); prevector invariant_generating_set(const matrix&, const partition&); matrix unpack(char*, int, int); prevector bal_unpack(String); #include "uniq.h" extern "C" int isalpha(int); typedef triple< int, int, OSLList< vector > > packed_matrix_list; #include "generic.h" bool simple_isomorphic(const matrix&, const matrix&); bool contains_zero_one_matrix(const String&, int); typedef vector polyF2; polyF2 remainder(polyF2, const polyF2&); vector unpack_poly(String); matrix fetch_known_matrix(String, const codetable&, codehome*, String&); int operator>(const vector&, const vector&); ]! ) TEX( ![ Many routines with names \verb|pmd_|$\ldots$ follow. These are pieces of \verb|evaluate_expression| which have been separated from it to reduce compilation time. ]! ) index_method(pmd_subs) void pmd_subs( String& s ) { while( s.contains( "Sub({" ) ) { String first = s.before( "Sub({" ); String ml = s.after( "Sub({" ); String last, defs, body; int i, j, k, paren_count = 1, brack_count = 1; for ( i = 0; i < ml.length( ); i++ ) { if ( ml[i] == '(' ) paren_count++; else if ( ml[i] == ')' ) paren_count--; else if ( ml[i] == '{' ) brack_count++; else if ( ml[i] == '}' ) brack_count--; if ( paren_count == 1 && brack_count == 0 && defs == "" ) defs = ml.at( 0, i ); if ( paren_count == 0 && brack_count == 0 ) { last = ml.after(i); body = ml.at( int(defs.length( ) + 2), int(i-defs.length( ) - 2) ); break; } } if ( i == ml.length( ) ) ERROR( "(#1) Illegal Sub expression." ); prevector defsv = bal_unpack(defs); if ( defsv.length == 0 ) ERROR( "(#2) Illegal Sub expression." ); prevector defname(defsv.length), defbody(defsv.length); prevector argcount(defsv.length); HIDE( ![ static Regex var_pattern(var); ]! ) for ( i = 0; i < defsv.length; i++ ) { if ( !defsv(i).contains( ":=" ) ) ERROR( "(#3) Illegal Sub expression." ); defname(i) = defsv(i).before( ":=" ); if ( defname(i).matches( var_pattern ) ) argcount(i) = 0; else { String rest = defname(i).after( var_pattern ); defname(i) = defname(i).at( var_pattern ); static Regex rest_pat( "(" + list_of( "%" + pos_number ) + ")" ); if ( !rest.matches( rest_pat ) ) ERROR( "(#4) Illegal Sub expression." ); rest.del( "(" ); rest.del( ")" ); rest.gsub( ",", 0 ); rest.del( "%" ); prevector restv( rest, '%' ); for ( j = 0; j < restv.length; j++ ) if ( restv(j) != j + 1 ) ERROR( "(#5) Illegal Sub expression." ); argcount(i) = restv.length; if ( argcount(i) > 9 ) ERROR( "Sub -- too many arguments." ); } defbody(i) = defsv(i).after( ":=" ); // The following is not quite correct. for ( j = 0; j < defbody(i).length( ); j++ ) { if ( isalpha( defbody(i)[j] ) && ( j == 0 || !isalpha( defbody(i)[j-1] ) ) ) { if ( defname(i) == defbody(i).at( var_pattern, j ) ) ERROR( "Sub -- definition appears to be " << "recursive." ); } } } String newbody; bool something_changed; do { something_changed = false; newbody = ""; for ( i = 0; i < body.length( ); i++ ) { // The following line is not quite correct. if ( isalpha( body[i] ) && ( i == 0 || !isalpha( body[i-1] ) ) ) { String name = body.at( var_pattern, i ); for ( j = 0; j < defname.length; j++ ) { if ( name == defname(j) ) { something_changed = true; if ( argcount(j) == 0 ) { newbody += "(" + defbody(j) + ")"; i += name.length( ) - 1; break; } String postname = body.after(var_pattern, i); if ( !postname.contains( "(", 0 ) ) ERROR( "(#6) Illegal Sub expression." ); paren_count = 1; for ( k = 1; k < postname.length( ); k++ ) { if ( postname[k] == '(' ) paren_count++; if ( postname[k] == ')' ) paren_count--; if ( paren_count == 0 ) break; } if ( k == postname.length( ) ) ERROR( "(#7) Illegal Sub expression." ); String pn = postname.at( 1, k - 1 ); prevector args = bal_unpack( pn ); if ( args.length != argcount(j) ) ERROR( "(#8) Illegal Sub expression." ); String obj = defbody(j); for ( int l = 0; l < args.length; l++ ) obj.gsub( String("%") + dec(l+1), args(l) ); newbody += "(" + obj + ")"; i += name.length( ) + k; break; } } if ( j == defname.length ) newbody += body[i]; } else newbody += body[i]; } body = newbody; } while( something_changed ); s = first + body + last; continue; } } void pmd_col0( String& s, String first, String middle, String last, prevector& at_codes, int& at_count ) { middle.del('@'); HIDE( ![ static Regex number_pattern( number_pat ); ]! ) int jj = take_int( middle, number_pattern ); at_codes(jj).convert( "List(MatF2){homogeneous}" ); packed_matrix_list start = at_codes(jj); int i, j, k = start.first, n = start.second; if ( start.third.length( ) == 0 ) ERROR( "- column applied to empty list of matrices." ); OSLList< vector > Ms; uniq_mat_list Ms_can(n-1); forPixDef( p, start.third ) { matrix M = unpack( start.third(p).x, k, n ); EquivRelIntList e( M.ncols ); pair< Permutationlist, Integer > pp = find_automorphism_group(M); for ( i = 0; i < pp.first.length; i++ ) for ( j = 0; j < e.length; j++ ) e.join( j, pp.first(i)(j) - 1 ); for ( i = 0; i < M.ncols; i++ ) { if ( !e.minimal(i) ) continue; matrix P = M; P.delete_column(i); matrix P_save = P; P.reduce_nz( ); if ( P.nrows < k ) ERROR( "When applying the - column operator, " << "the rank of the matrix " << "dropped. This is not allowed." ); if ( Ms_can.add(P) ) Ms.append( pack(P_save) ); } } at_codes(at_count) = generic_object( "List(MatF2{reduced}){homogeneous}", make_triple( k, n - 1, Ms ) ); s = first + "(@" + dec(at_count++) + ")" + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); } index_method(pmd_tilde_dual) void pmd_tilde_dual( String& s, String first, String middle, String last, prevector& at_codes, int& at_count ) { middle.del('@'); HIDE( ![ static Regex number_pattern( number_pat ); ]! ) int jj = take_int( middle, number_pattern ); at_codes(jj).convert( "List(MatF2){homogeneous}" ); prevector< matrix > Bs = at_codes(jj); jj = take_int( middle, number_pattern ); at_codes(jj).convert( "Int" ); int r = at_codes(jj); SLList< matrix > Ms1, Ms2; for ( int pp = 0; pp < Bs.length; pp++ ) { matrix B = Bs(pp); B.reduce_nz( ); if ( r >= B.ncols ) ERROR( "Illegal dual word weight." ); SLList< vector > L = iso_dual_words_of_given_weight(B,r); forPixDef( p, L ) { matrix M, C( B.ncols, B.ncols ); int i; for ( i = 0; i < B.ncols; i++ ) C(i,i) = 1; for ( i = 0; i < r; i++ ) C( L(p)(i), L(p)(i) ) = 0; rowspace_intersection( B, C, M ); M.delete_columns( L(p) ); M.reduce_nz( ); matrix Mc = canonical_form(M); forPixDef( q, Ms1 ) if ( Mc == Ms1(q) ) break; if ( q == 0 ) { Ms1.append(Mc); Ms2.append(M); } } } at_codes(at_count) = generic_object( "List(MatF2)", Ms2 ); s = first + "(@" + dec(at_count++) + ")" + last; if (at_count >= at_codes.length) at_codes.resize(at_codes.length + 1000); } index_method(ATT) #define ATT(mat) \ at_codes(at_count) = generic_object( "MatF2", mat ); \ s_new += String("@") + dec(at_count++); \ if ( at_count >= at_codes.length ) \ at_codes.resize( at_codes.length + 1000 ); \ i += t.length( ) - 1; index_method(PreInt_at) bool PreInt_at( const String& s, int i ) { if ( !isdigit( s[i] ) ) return false; if ( i >= 1 && isdigit( s[i-1] ) ) return false; int j, k; if ( i >= 1 ) { static String before( "-({,:+*!$%^&=~|:<>.?/" ); for ( j = 0; j < before.length( ); j++ ) if ( s[i-1] == before[j] ) break; if ( j == before.length( ) ) return false; } for ( j = i; j < s.length( ); j++ ) if ( !isdigit( s[j] ) ) break; if ( j == s.length( ) ) return true; static String after( "_-)},:+*!$%^&=~|:<>.?/" ); for ( k = 0; k < after.length( ); k++ ) if ( s[j] == after[k] ) return true; return false; } index_method(pmd_atom) bool pmd_atom(String& s, prevector& at_codes, int& at_count, const codetable& results, codehome* home, String& code_label) { String s_new; HIDE( ![ static Regex number_pattern( number_pat ); static Regex pos_number_pattern( pos_number ); ]! ) int i, j, k; for ( i = 0; i < s.length( ); i++ ) { static Regex BCH_pat( "BCH(" + pos_number + "," + pos_number + "," + pos_number + ".." + pos_number + ")" ); static Regex Coset_pat( "Coset(2^" + pos_number + "," + pos_number + ",n=" + pos_number + ")" ); static Regex Col_pat( "Col(" + nontrivial_list_of("@" + number_pat) + ")" ); static Regex MulMod_pat( String("MulMod(") + "[^),]+" + "," + "[^)]+" + ")" ); static Regex Perm_pat( nontrivial_list_of( "(" + list_of( pos_number ) + ")", "" ) ); static Regex digits_pat( "[0-9]+" ); static Regex pdp( String("[0-9]+") + "[_-)},:+*!$%^&=~|:<>.?/]" ); static Regex before_digits_pat( "[-({,:+*!$%^&=~|:<>.?/]" ); // Test for PreInt at position i. // The following code doesn't work: // if ( s.contains( digits_pat, i ) && // ( i == 0 || s.contains( before_digits_pat, i-1 ) ) && // ( s.length( ) == i+1 || s.contains( pdp, i ) ) ) if ( PreInt_at( s, i ) ) { for ( j = i + 1; j < s.length( ); j++ ) if ( !isdigit( s[j] ) ) break; String I = s.at( i, j-i ); at_codes(at_count) = generic_object( "PreInt", I ); s_new += String("@") + dec(at_count++); if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); i = j-1; } // Bug forces next complicated contains: else if ( s.contains( Perm_pat, i ) && s[i+1] != '(' ) { String t = s.at( Perm_pat, i ); Permutation p( t ); matrix B( p.length, p.length ); for ( k = 0; k < p.length; k++ ) for ( j = 0; j < p.length; j++ ) B(j, k) = ( (p(k) - 1) == j ); ATT(B); } else if ( s.contains("c", i) && s.contains(Coset_pat, i) ) { String t = s.at( Coset_pat, i ); String t2 = t.after( "Coset(2^" ); int m = take_int( t2, pos_number_pattern ); t2.del( "," ); int r = take_int( t2, pos_number_pattern ); t2.del( ",n=" ); int n = take_int( t2, pos_number_pattern ); int two_m = Ipow( 2, m ); OSLList pows; pows.add(0); while(1) { if ( pows.contains(r) ) break; pows.add(r); r *= 2; r %= two_m - 1; } at_codes(at_count) = generic_object( "MatF2", BCH( primitive_poly(m), n, vector(pows) ) ); s_new += String("@") + dec(at_count++); if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); i += t.length( ) - 1; } else if ( s.contains("Col", i) && s.contains(Col_pat, i) ) { String t = s.at( Col_pat, i ); String t2 = t; prevector pos( t2.freq(",") + 1 ); int i1, i2; for ( i1 = 0; i1 < pos.length; i1++ ) { i2 = take_int( t2, number_pattern ); at_codes(i2).convert( "Int" ); Integer I = at_codes(i2); pos(i1) = I; } for ( i1 = 0; i1 < pos.length; i1++ ) for ( i2 = i1 + 1; i2 < pos.length; i2++ ) if ( pos(i1) == pos(i2 ) ) ERROR( "Illegal use of Col operator." ); Integer m = 0; for ( i1 = 0; i1 < pos.length; i1++ ) m = max( m, pos(i1) ); matrix B( m, 1 ); for ( i1 = 0; i1 < pos.length; i1++ ) B( pos(i1) - 1, 0 ) = 1; ATT(B); } else if ( s.contains( "Mu", i ) && s.contains( MulMod_pat, i ) ) { String t = s.at( MulMod_pat, i ); String t2 = s.after( MulMod_pat, i ); String ts = t.after( "MulMod(" ); String polys = ts.before( "," ); String multipliers = ts.after( "," ); multipliers.del( ")", -1 ); vector poly = unpack_poly( polys ); vector multiplier = unpack_poly( multipliers ); int d, m, l, j; for ( d = poly.length - 1; d >= 0; d-- ) if ( odd( poly(d) ) ) break; if (d <= 0) ERROR( polys << " (mod 2) has degree <= 0." ); polyF2 poly2(d + 1); for ( l = 0; l <= d; l++ ) poly2(l) = int( poly(l) ) % 2; for ( m = multiplier.length - 1; m >= 0; m-- ) if ( odd( multiplier(m) ) ) break; polyF2 multiplier2(m + 1); for ( l = 0; l <= m; l++ ) multiplier2(l) = int( multiplier(l) ) % 2; matrix M( d, d ); polyF2 mult_red = remainder( multiplier2, poly2 ); polyF2 x = mult_red; for ( l = 0; l < d; l++ ) { // Set the l'th column of M to x. for ( j = 0; j < min(d, x.length); j++ ) M( j, l ) = x(j); // Multiply x by t. x.resize( x.length + 1 ); for ( j = x.length - 2; j >= 0; j-- ) x(j + 1) = x(j); x(0) = 0; x = remainder(x, poly2); } ATT(M); } else if ( s.contains("B", i) && s.contains(BCH_pat, i) ) { String t = s.at( BCH_pat, i ); String t2 = t.after( "BCH(" ); int r = take_int( t2, pos_number_pattern ); t2.del( "," ); int n = take_int( t2, pos_number_pattern ); t2.del( "," ); int first = take_int( t2, pos_number_pattern ); t2.del( ".." ); int last = take_int( t2, pos_number_pattern ); if ( last < first ) ERROR( "BCH operator doesn't make sense." ); at_codes(at_count) = generic_object( "MatF2", BCH( r, n, first, last ) ); s_new += String("@") + dec(at_count++); if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); i += t.length( ) - 1; } else s_new += s[i]; } bool something_changed = (s != s_new); s = s_new; return something_changed; } set_compile_file(op.cc) HIDE( ![ #include "homedefs.h" #include "bitvec.h" #include "codetable.h" int take_int(String&, const Regex&); extern String pos_number, left, right, orsign, gen_label_pat, pos_list; extern int debug; extern matrix BCH(int, int, int, int); typedef vector polyF2; polyF2 primitive_poly(int); int divides(const polyF2&, polyF2); matrix BCH(polyF2, int, vector); String list_of(const String&, const String& = ","); String nontrivial_list_of(const String&, const String& = ","); prevector< vector > tuple_orbits(matrix, int); int min_distance(const matrix&, int); prevector expand_config_list(codehome*, String); SLList< matrix > enlarge_by_dual_word(const matrix&, int); SLList< vector > dual_words_of_given_weight(matrix, int); vector pack(matrix); matrix canonical_form(matrix); OSLList int_set(String); bool iso_member(const matrix&, const SLList< matrix >&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); SLList< vector > iso_dual_words_of_given_weight(matrix, int); pair< Permutationlist, Integer > find_automorphism_group(const matrix&); prevector invariant_generating_set(const matrix&, const partition&); matrix unpack(char*, int, int); ]! ) TEX( \block{Process expressions} ) TEX( ![ The following class maintains a list of matrices over $\F_2$, no two isomorphic. At present this is handled by tracking the matrices, their weight enumerators, and their invariant generating sets. ]! ) set_include_file(uniq.h) index_class(uniq_matrix_list) class uniq_matrix_list { private: SLList< triple< matrix, vector, prevector > > core; public: uniq_matrix_list( ) { } bool add( const matrix& ); SLList< matrix > list( ); }; index_class(uniq_mat_list) class uniq_mat_list { private: prevector< OSLList< vector > > Ms_can; int n; int log2_npiles; public: uniq_mat_list(int n) : n(n) { log2_npiles = min(12, n); int npiles = Ipow(2, log2_npiles); Ms_can.set_size(npiles); } bool add( const matrix& M ) { matrix MC = canonical_form(M); int loc = 0; int mult = 1; for ( int j = n - log2_npiles; j < n; j++ ) { loc += mult * MC(0)(j).x; mult *= 2; } vector MCp = pack( MC ); forPixDef( q, Ms_can(loc) ) if ( Ms_can(loc)(q) == MCp ) return false; Ms_can(loc).append( MCp ); return true; } }; set_compile_file(op.cc) TEX( ![ Add a matrix, in \RREF, and having no zero rows. ]! ) HIDE( ![ #include "uniq.h" extern "C" int isalpha(int); bool simple_isomorphic(const matrix&, const matrix&); extern int ingredient_tracking; vector dual_of_we(vector, bool = false); extern String juxt(String, String); #include "generic.h" extern String scope; extern DLList< triple< String, String, generic_object > > globals; void ee_main(String&, prevector&, int&, codetable&, codehome*, String&); void pmd_subs(String&); static Regex alphanumericu( "[a-zA-Z0-9_]*" ); ]! ) TEX( ![ \verb|bal_unpack|:\ Unpack a given string into comma-separated pieces, each of which is balanced \WRT\ commas and curly brackets. If this is not possible, the last piece will be bad. ]! ) index_method(bal_unpack) prevector bal_unpack( String s ) { int paren_count = 0, brack_count = 0; SLList pieces; String piece; for ( int i = 0; i < s.length( ); i++ ) { if ( paren_count == 0 && brack_count == 0 && s[i] == ',' ) { pieces.append( piece ); piece = ""; continue; } if ( s[i] == '(' ) paren_count++; else if ( s[i] == ')' ) paren_count--; else if ( s[i] == '{' ) brack_count++; else if ( s[i] == '}' ) brack_count--; piece += s[i]; } pieces.append( piece ); return pieces; } index_method(add) bool uniq_matrix_list::add( const matrix& M ) { vector y = M.enumerate_weights( ); partition part; part.set_all_ones(M.ncols); prevector igs = invariant_generating_set( M, part ); forPixDef( p, core ) { matrix& M2 = core(p).first; if ( M2.nrows != M.nrows || M2.ncols != M.ncols ) continue; if ( core(p).second != y ) continue; if ( isomorphic( M, M2, igs ) ) return false; } core.append( make_triple( M, y, igs ) ); return true; } index_method(list) SLList< matrix > uniq_matrix_list::list( ) { SLList< matrix > answer; forPixDef( p, core ) answer.append( core(p).first ); return answer; } TEX( ![ \verb|max_li|:\ Given a list of elements of $\F_2^n$, find a maximal linearly independent subset, giving preference to those elements in the list which appear earlier. ]! ) index_method(max_li) SLList max_li( SLList l ) { SLList answer; if ( l.length( ) == 0 ) return answer; matrix answerm( 0, l.front( ).length ); forPixDef( p, l ) { if ( !answerm.rowspace_member( l(p) ) ) { answer.append( l(p) ); answerm.resize( answerm.nrows + 1, answerm.ncols ); answerm( answerm.nrows - 1 ) = l(p); answerm.reduce_nz( ); } } return answer; } index_method(punctured_codes) SLList< pair< int, matrix > > punctured_codes( const matrix& M ) { SLList< matrix > cans; SLList< pair< int, matrix > > answer; int i, j, k; EquivRelIntList e( M.ncols ); pair< Permutationlist, Integer > pp = find_automorphism_group(M); for ( i = 0; i < pp.first.length; i++ ) for ( j = 0; j < e.length; j++ ) e.join( j, pp.first(i)(j) - 1 ); for ( i = 0; i < M.ncols; i++ ) { if ( !e.minimal(i) ) continue; matrix P = M; P.delete_column(i); P.reduce_nz( ); matrix Pc = canonical_form(P); forPixDef( q, cans ) if ( cans(q) == Pc ) break; if ( q == 0 ) { answer.append( make_pair( i+1, P ) ); cans.append( Pc ); } } return answer; } index_method(fetch_known_matrix) matrix fetch_known_matrix( String t, const codetable& results, codehome* home, String& code_label ) { String t2 = t.after("["); HIDE( ![ static Regex pos_number_pattern( pos_number ); static Regex gen_label_pattern( gen_label_pat ); ]! ) String clabel = "[" + take( t2, alphanumericu ) + "]"; codehome* xhome; if (home != 0 && clabel == code_label) xhome = home; else { xhome = results.get_home(clabel); if (xhome == 0) return matrix( ); } t2.del("."); t2 = "[" + t2; int del_co = 0; String ll = t2.before("]"); if ( ll.contains("-") ) { String cx1 = t2.before("-"); String cx2 = t2.after("-"); del_co = take_int( cx2, pos_number_pattern ); t2 = cx1 + cx2; } // Note that the following code is copied (with minor modification) // from label_to_Pix. static Regex alpha_pat( "[a-zA-Z_0-9]+" ); static Regex labelx_pat( "\\[[a-zA-Z_0-9]+:.*\\]" ); Pix pix1; matrix A; String label = take(t2, gen_label_pattern); if ( label == "[current]" ) { pix1 = xhome->current; goto pix_found; } forPixDef( i, xhome->labels ) if ( xhome->labels(i).first == label ) { pix1 = xhome->labels(i).second; goto pix_found; } if ( label.matches( labelx_pat ) ) { String new_config_name = label; String labelx = label.after("["); String codehome_name = "[" + take(labelx, alpha_pat) + "]"; String config_name = labelx.after(":"); if ( config_name[ config_name.length( ) - 1 ] = ']' ) { config_name = "[" + config_name; forPixDef( p, results.olabels ) { if ( codehome_name == results.olabels(p).first ) { codehome* h = results.open(results.olabels(p).second); if (h->n != xhome->n) ERROR("Code length descrepancy."); forPix( i, h->labels ) if ( h->labels(i).first == config_name ) { A = h->configs(h->labels(i).second). small.basis; goto matrix_found; } } } } } forPix( i, xhome->config_lists ) { int r = xhome->config_lists(i).member(label); if ( r != 0 ) { A = xhome->config_lists(i).fetch(r); A.reduce_nz( ); goto matrix_found; } } pix1 = 0; pix_found: // End code copied from label_to_Pix. if ( pix1 == 0 ) return matrix( ); A = xhome->configs(pix1).basic_small( ); matrix_found: if ( del_co > 0 ) A.delete_column( del_co - 1 ); A.reduce_nz( ); return(A); } index_method(contains_zero_one_matrix) bool contains_zero_one_matrix( const String& s, int i ) { int n = s.length( ) - i; if ( n <= 1 || s[i] != '{' || s[i+1] == '}' ) return false; for ( int j = 1; j < n; j++ ) { if ( s[i + j] == '}' ) return true; if ( s[i + j] != '0' && s[i + j] != '1' && s[i + j] != ',' ) return false; } return false; } index_class(packed_matrix_list) typedef triple< int, int, OSLList< vector > > packed_matrix_list; set_include_file(generic.h) TEX( ![ A {\tt Word} is a sequence of nonnegative integers, representing a word in the alphabet consisting of $0, 1, 2, \ldots$. However, in practice we only allow values up to $255$. ]! ) index_class(Word) index_method(pos) index_method(cmp) index_method(cat) class Word { public: prevector x; Word( ) { x.set_size(0); } friend bool operator==(const Word& W1, const Word& W2) { return W1.x == W2.x; } friend bool operator!=(const Word& W1, const Word& W2) { return W1.x != W2.x; } friend int cmp(const Word& a, const Word& b) { register int i, n = min(a.x.length, b.x.length); for ( i = 0; i < n; i++ ) { if ( a.x(i) > b.x(i) ) return 1; if ( a.x(i) < b.x(i) ) return -1; } return a.x.length - b.x.length; } friend int operator<(const Word& a, const Word& b) { return cmp(b, a) > 0; } friend int operator>(const Word& a, const Word& b) { return cmp(a, b) > 0; } friend Word cat(const Word& a, const Word& b) { Word w; w.x.set_size( a.x.length + b.x.length ); for ( int i = 0; i < a.x.length; i++ ) w.x(i) = a.x(i); for ( int i = 0; i < b.x.length; i++ ) w.x( i + a.x.length ) = b.x(i); return w; } // pos: if w is contained in this, return the index in w for the first // place it occurs. Otherwise return -1. int pos( const Word& w ) { int i, j; for ( i = 0; i < x.length - w.x.length + 1; i++ ) { for ( j = 0; j < w.x.length; j++ ) if ( x(i + j) != w.x(j) ) break; if ( j == w.x.length ) return i; } return -1; } // ostream: note junk comes out if x >= 26. friend ostream& operator<<(ostream& s, const Word& W) { for ( int i = 0; i < W.x.length; i++ ) s << char('a' + W.x(i)); return s; } }; index_class(Group) class Group { public: int n; // number of generators prevector< pair > rel; // relations // (actually transformation rules) Group( ) { rel.set_size(0); } friend bool operator==(const Group& G1, const Group& G2) { return (G1.n == G2.n) && (G1.rel == G2.rel); } friend ostream& operator<<(ostream& s, const Group& G) { if ( G.n > 26 ) { s << "(There are " << G.n << " letters. I can't " << "print out the relations. Sorry.)\n"; return s; } s << "( "; for ( int i = 0; i < G.n; i++ ) { s << char('a' + i); if ( i < G.n - 1 ) s << ", "; } s << " : "; for ( int i = 0; i < G.rel.length; i++ ) { s << G.rel(i).first << " -> " << G.rel(i).second; if ( i < G.rel.length - 1 ) s << ", "; } s << " )"; return s; } }; index_class(lp_prog) typedef pair< prevector, String > lp_prog; index_class(generic_object) index_method(apply_gen1) index_method(apply_gen2) index_method(to_type) TEX( ![ The \verb|generic_object| class is based on the types described at the beginning of \S\ref{matrix-descriptor-section}. The attributes described in that section are stored in the {\tt flags} member of a \verb|generic_object|. As an example, \verb|List(MatF2{reduced}){homogeneous}| would parse to {\tt name} = \verb|List(MatF2)|, {\tt flags} = \verb|homogeneous1, reduced2|. This is done by the routine \verb|parse_type|. A given type can (in principle) be represented in more than one way as a {\tt C++} object. The standard way (whatever that is) is encoded by setting the {\tt storage} member to the null string. There are at present only two nonstandard representations. An object of type \verb|List(MatF2)| with flag {\tt homogeneous1} may be represented by a \verb|packed_matrix_list|, and an object of type \verb|List(List(MatF2))| with flag {\tt homogeneous2} may be represented by a \verb|prevector|. Both of these special representations are encoded by setting {\tt storage} to {\tt packed}. ]! ) class generic_object { public: String name; OSLList flags; String storage; void* loc; // Utilities. friend void parse_type(String, String&, OSLList&); friend String expand_type(const String&, const OSLList&); // Definitions of types and their standard representations. Each time // a new type is added, very careful changes must be made to what follows! #define apply_gen1(FUN) \ FUN( F2, gf2 ) \ FUN( List(F2), vector ) \ FUN( MatF2, matrix ) \ FUN( List(MatF2), prevector< matrix > ) \ FUN( List(List(MatF2)), prevector< prevector< matrix > > ) \ FUN( Int, Integer ) \ FUN( List(Int), vector ) \ FUN( List(List(Int)), prevector< vector > ) \ FUN( MatInt, matrix ) \ FUN( Rat, Rational ) \ FUN( List(Rat), vector ) \ FUN( MatRat, matrix ) \ FUN( PVSF2, prevector< prevector< vector > > ) \ FUN( List(PVSF2), prevector< prevector< prevector< vector > > > ) \ FUN( Bool, bool ) \ FUN( List(Bool), prevector ) \ FUN( Group, Group ) \ FUN( LinearProgram, lp_prog ) \ FUN( List(List(PreInt)), prevector< prevector > ) #define apply_gen2(FUN) \ FUN( PreInt, String ) \ FUN( List(PreInt), prevector ) \ FUN( String, String ) \ FUN( List(String), prevector ) // Constructors. Note that these do very little checking. generic_object( ) { } generic_object(const generic_object&); #define from_base(NAME, TYPE) \ generic_object( String t, const TYPE& x ) \ { parse_type( t, name, flags ); \ if ( name != #NAME ) \ INTERNAL_ERROR( "gen object constructor:" #NAME ); \ loc = new TYPE(x); } apply_gen1(from_base) generic_object( String t, const String& x ) { parse_type( t, name, flags ); if ( name != "PreInt" && name != "String" ) INTERNAL_ERROR( "gen object constructor: PreInt/String" ); \ loc = new String(x); } generic_object( String t, const prevector& x ) { parse_type( t, name, flags ); if ( name != "List(PreInt)" && name != "List(String)" ) INTERNAL_ERROR( "gen object constructor: List(PreInt/String)" );\ loc = new prevector(x); } generic_object(String, const packed_matrix_list&); generic_object(String, const SLList< matrix >&); // Construct a generic object from a list of generic objects. generic_object(int, const generic_object*); // Destructor. ~generic_object( ); // Change the type of a generic object. Note that extra flags are not // deleted. For example, converting from List(MatF2){homogeneous} to // List(MatF2) does not discard the homogeneous flag. void convert(const String&); // Assignment operator. generic_object& operator=(const generic_object&); // Comparison. friend bool operator==(const generic_object&, const generic_object&); friend bool operator!=(const generic_object& g1, const generic_object& g2) { return !(g1 == g2); } // Convert a generic_object to some other type. // I used to have "operator TYPE&( ) const", but this sort of type // conversion operator does not work correctly. // Try to restore at a later date! #define to_type(NAME, TYPE) \ operator TYPE( ) const \ { if ( name != #NAME ) \ ERROR( "An object of type " << name << " was encountered " \ << "where a " << #NAME << " was expected." ); \ return *(TYPE*) loc; } to_type( F2, gf2 ) to_type( List(F2), vector ) to_type( MatF2, matrix ) to_type( Int, Integer ) to_type( MatInt, matrix ) to_type( List(Int), vector ) to_type( List(List(Int)), prevector< vector > ) to_type( Rat, Rational ) to_type( List(Rat), vector ) to_type( MatRat, matrix ) to_type( PVSF2, prevector< prevector< vector > > ) to_type( List(PVSF2), prevector< prevector< prevector< vector > > > ) to_type( Bool, bool ) to_type( List(Bool), prevector ) to_type( Group, Group ) to_type( LinearProgram, lp_prog ) to_type( List(List(PreInt)), prevector< prevector > ) operator String( ) const { if ( name != "PreInt" && name != "String" ) ERROR( "An object of type " << name << " was encountered " << "where a " << "Preint or String" << " was expected." ); return *(String*) loc; } operator prevector( ) const { if ( name != "List(PreInt)" && name != "List(String)" ) ERROR( "An object of type " << name << " was encountered " << "where a List(Preint) or List(String) was expected." ); return *(prevector*) loc; } operator prevector< matrix >( ) const; operator prevector< prevector< matrix > >( ) const; operator packed_matrix_list( ) const; operator prevector( ) const; // Output routine. // Should be "const generic_object&": friend ostream& operator<<(ostream&, generic_object&); }; set_compile_file(generic.cc) HIDE( ![ #include "basedefs.h" matrix unpack(char*, int, int); vector pack(matrix); typedef triple< int, int, OSLList< vector > > packed_matrix_list; #include "generic.h" int take_int(String&, const Regex&); extern int input_form; ostream& operator<<(ostream&, const prevector&); ]! ) index_method(transpose) generic_object transpose( const generic_object& g ) { if ( !g.name.contains( "List(List(", 0 ) ) ERROR( "Attempt to transpose generic_object which does not have the " << "form List(List(...))." ); generic_object x; x.name = g.name; if ( g.name == "List(List(Int))" ) { prevector< vector > L = g; int i, j, r = L(0).length, n = L.length; for ( i = 1; i < n; i++ ) if ( L(i).length != r ) ERROR( "Transpose fails." ); prevector< vector >* ans = new prevector< vector >(r); for ( i = 0; i < r; i++ ) { (*ans)(i).set_size(n); for ( j = 0; j < n; j++ ) (*ans)(i)(j) = L(j)(i); } x.loc = ans; } else if ( g.name == "List(List(MatF2))" ) { prevector< prevector< matrix > > L = g; int i, j, r = L(0).length, n = L.length; for ( i = 1; i < n; i++ ) if ( L(i).length != r ) ERROR( "Transpose fails." ); prevector< prevector< matrix > >* ans = new prevector< prevector< matrix > >(r); for ( i = 0; i < r; i++ ) { (*ans)(i).set_size(n); for ( j = 0; j < n; j++ ) (*ans)(i)(j) = L(j)(i); } x.loc = ans; x.flags = g.flags; x.flags.del( "homogeneous2" ); } else ERROR( "Transpose can't handle type " << g.name << "." ); return x; } index_method(UNLIST) #define UNLIST(NAME, TYPE, HOLDER) \ else if ( g.name == "List(" #NAME ")" ) \ { HOLDER< TYPE > L = g.operator HOLDER< TYPE >( ); \ v.set_size(L.length); \ for ( int i = 0; i < v.length; i++ ) \ v(i) = generic_object( #NAME, L(i) ); } index_method(unlist) prevector unlist( const generic_object& g ) { if ( !g.name.contains( "List(", 0 ) ) ERROR( "List of something expected, but " << g.name << " encountered." ); HIDE( ![ static Regex number_pattern( number_pat ); ]! ) prevector v; if (0); UNLIST( F2, gf2, vector ) UNLIST( Int, Integer, vector ) UNLIST( List(Int), vector, prevector ) UNLIST( PVSF2, prevector< prevector< vector > >, prevector ) UNLIST( MatF2, matrix, prevector ) UNLIST( List(MatF2), prevector< matrix >, prevector ) UNLIST( Bool, bool, prevector ) for ( int i = 0; i < v.length; i++ ) { forPixDef( p, g.flags ) { String fl = g.flags(p); int j = take_int( fl, number_pattern ); if ( j >= 2 ) v(i).flags.add( g.flags(p) + dec(j - 1) ); } } return v; } generic_object::operator prevector< matrix >( ) const { if ( name != "List(MatF2)" ) ERROR( "An object of type " << name << " was encountered " << "where a " << "List(MatF2)" << " was expected." ); if ( storage == "" ) return *(prevector< matrix >*) loc; // Otherwise storage must be packed. const packed_matrix_list& l = *(packed_matrix_list*) loc; prevector< matrix > ans( l.third.length( ) ); int i = 0; forPixDef( p, l.third ) ans(i++) = unpack( l.third(p).x, l.first, l.second ); return ans; } generic_object::operator prevector< prevector< matrix > >( ) const { if ( name != "List(List(MatF2))" ) ERROR( "An object of type " << name << " was encountered " << "where a " << "List(List(MatF2))" << " was expected." ); if ( storage == "" ) return *(prevector< prevector< matrix > >*) loc; // Otherwise storage must be packed. const prevector& l = *(prevector*) loc; prevector< prevector< matrix > > ans( l.length ); for ( int j = 0; j < l.length; j++ ) { ans(j).set_size( l(j).third.length( ) ); int i = 0; forPixDef( p, l(j).third ) ans(j)(i++) = unpack( l(j).third(p).x, l(j).first, l(j).second ); } return ans; } generic_object::operator packed_matrix_list( ) const { if ( name == "List(MatF2)" && storage == "packed" ) return *(packed_matrix_list*) loc; else if ( name == "List(MatF2)" && flags.contains( "homogeneous1" ) ) { prevector< matrix >& L = *(prevector< matrix >*) loc; OSLList< vector > l; for ( int i = 0; i < L.length; i++ ) l.append( pack( L(i) ) ); return make_triple(L(0).nrows, L(0).ncols, l); } INTERNAL_ERROR( "Conversion from generic_object to " << "packed_matrix_list failed." ); } generic_object::operator prevector( ) const { if ( name == "List(List(MatF2))" && storage == "packed" ) return *(prevector*) loc; else if ( name == "List(List(MatF2))" && flags.contains( "homogeneous2" ) ) { prevector< prevector< matrix > >& L = *(prevector< prevector< matrix > >*) loc; prevector ans( L.length ); for ( int i = 0; i < L.length; i++ ) { OSLList< vector > l; for ( int j = 0; j < L(i).length; j++ ) l.append( pack( L(i)(j) ) ); ans(i) = make_triple(L(i)(0).nrows, L(i)(0).ncols, l); } return ans; } INTERNAL_ERROR( "Conversion from generic_object to " << "prevector failed." ); } generic_object::generic_object( String type, const packed_matrix_list& x ) { parse_type( type, name, flags ); if ( name != "List(MatF2)" ) INTERNAL_ERROR( "gen obj error: pml" ); storage = "packed"; loc = new packed_matrix_list(x); } generic_object::generic_object( String type, const SLList< matrix >& x ) { parse_type( type, name, flags ); if ( name != "List(MatF2)" ) INTERNAL_ERROR( "gen obj error: SL" ); if ( flags.contains( "homogeneous2" ) ) { OSLList< vector > l; forPixDef( p, x ) l.append( pack( x(p) ) ); matrix M = x.front( ); loc = new packed_matrix_list(make_triple(M.nrows, M.ncols, l)); storage = "packed"; } else loc = new prevector< matrix >(x); } index_method(parse_type) void parse_type( String type, String& name, OSLList& flags ) { // No checking of the arguments is done! name = ""; flags.clear( ); int i, j, paren_level = 0; for ( i = 0; i < type.length( ); i++ ) { if ( type[i] == '(' ) paren_level++; else if ( type[i] == ')' ) paren_level--; if ( type[i] == '{' ) { String args; for ( i = i + 1; type[i] != '}'; i++ ) args += type[i]; prevector argsv = unpack(args); for ( j = 0; j < argsv.length; j++ ) flags.add( argsv(j) + dec( paren_level + 1 ) ); } else name += type[i]; } } index_method(expand_type) String expand_type( const String& name, const OSLList& flags ) { String answer; HIDE( ![ static Regex number_pattern( number_pat ); ]! ) int paren_count = 0; for ( int i = 0; i <= name.length( ); i++ ) { if ( i == name.length( ) || name[i] == ')' ) { bool first_flag = true; forPixDef( p, flags ) { String f = flags(p); if ( as_int(f.at(number_pattern)) == paren_count+1 ) { f.del( number_pattern ); answer += (first_flag ? String("{") : String(",")) + f; first_flag = false; } } if ( !first_flag ) answer += '}'; if ( i != name.length( ) ) answer += ')'; } else answer += name[i]; if ( i != name.length( ) ) { if ( name[i] == '(' ) paren_count++; else if ( name[i] == ')' ) paren_count--; } } return answer; } index_method(make_genlist) #define make_genlist( NAME, TYPE, HOLDER ) \ if ( v[0].name == #NAME ) \ { OSLList new_flags = v[0].flags; \ for ( i = 1; i < r; i++ ) \ new_flags = intersection( new_flags, v[i].flags ); \ forPixDef( p, new_flags ) \ { i = take_int( new_flags(p), number_pattern ); \ flags.add( new_flags(p) + dec(i + 1) ); } \ name = "List(" #NAME ")"; \ HOLDER< TYPE >* ans = new HOLDER< TYPE >; \ (*ans).set_size( r ); \ for ( i = 0; i < r; i++ ) \ (*ans)(i) = *(TYPE*) v[i].loc; \ loc = ans; \ return; } generic_object::generic_object( int r, const generic_object* v ) { if ( r == 0 ) ERROR( "Empty list of generic objects encountered." ); HIDE( ![ static Regex number_pattern( number_pat ); ]! ) int i, j; for ( i = 1; i < r; i++ ) if ( v[i].name != v[0].name ) { for ( j = 0; j < r; j++ ) if ( !v[j].name.contains( "PreInt" ) ) break; if ( j == r ) ERROR( "Inhomogeneous list of generic objects encountered." ); name = "List(" + v[j].name + ")"; if ( v[j].name == "Int" ) { vector* ans = new vector; (*ans).set_size(r); for ( i = 0; i < r; i++ ) { generic_object g = v[i]; g.convert( v[j].name ); (*ans)(i) = *(Integer*) g.loc; } loc = ans; return; } if ( v[j].name == "F2" ) { vector* ans = new vector; (*ans).set_size(r); for ( i = 0; i < r; i++ ) { generic_object g = v[i]; g.convert( v[j].name ); (*ans)(i) = *(gf2*) g.loc; } loc = ans; return; } if ( v[j].name == "List(Int)" ) { prevector< vector >* ans = new prevector< vector >; (*ans).set_size(r); for ( i = 0; i < r; i++ ) { generic_object g = v[i]; g.convert( v[j].name ); (*ans)(i) = *(vector*) g.loc; } loc = ans; return; } if ( v[j].name == "List(F2)" ) { matrix* ans = new matrix; for ( i = 0; i < r; i++ ) { generic_object g = v[i]; g.convert( v[j].name ); vector x = g; if ( i == 0 ) (*ans).set_size(r, x.length); else if ( x.length != (*ans).ncols ) ERROR( "MatF2 has rows of different lengths." ); (*ans)(i) = x; } loc = ans; return; } ERROR( "Inhomogeneous conversion to " << name << " failed." ); } make_genlist( F2, gf2, vector ) make_genlist( MatF2, matrix, prevector ) make_genlist( PreInt, String, prevector ) make_genlist( List(PreInt), prevector, prevector ) make_genlist( Int, Integer, vector ) make_genlist( MatInt, matrix, prevector ) make_genlist( List(Int), vector, prevector ) make_genlist( Rat, Rational, vector ) make_genlist( List(Rat), vector, prevector ) make_genlist( MatRat, matrix, prevector ) make_genlist( PVSF2, prevector< prevector< vector > >, prevector ) make_genlist( Bool, bool, prevector ) make_genlist( String, String, prevector ) if ( v[0].name == "List(MatF2)" ) { OSLList new_flags = v[0].flags; for ( i = 1; i < r; i++ ) new_flags = intersection( new_flags, v[i].flags ); forPixDef( p, new_flags ) { i = take_int( new_flags(p), number_pattern ); flags.add( new_flags(p) + dec(i + 1) ); } name = "List(" "List(MatF2)" ")"; if ( storage == "" ) { prevector< prevector< matrix > >* ans = new prevector< prevector< matrix > >; for ( i = 0; i < r; i++ ) { prevector< matrix > xx = v[i]; (*ans)(i) = xx; } loc = ans; return; } else if ( storage == "packed" ) { prevector< packed_matrix_list >* ans = new prevector< packed_matrix_list >; (*ans).set_size(r); for ( i = 0; i < r; i++ ) (*ans)(i) = *(packed_matrix_list*) v[i].loc; loc = ans; return; } } ERROR( "The type List(" << v[0].name << ") is not defined." ); } index_method(copy_unit) #define copy_unit(NAME, TYPE) \ else if (name == #NAME && storage == "") loc = new TYPE( *(TYPE*) g.loc ); generic_object::generic_object(const generic_object& g) { name = g.name; flags = g.flags; storage = g.storage; if ( name == "List(MatF2)" && storage == "packed" ) loc = new packed_matrix_list( *(packed_matrix_list*) g.loc ); else if ( name == "List(List(MatF2))" && storage == "packed" ) loc = new prevector ( *(prevector*) g.loc ); apply_gen1(copy_unit) apply_gen2(copy_unit); } index_method(kill_type) #define kill_type(NAME, TYPE) \ else if ( name == #NAME && storage == "" ) delete (TYPE*) loc; generic_object& generic_object::operator=(const generic_object& g) { if ( name == "List(MatF2)" && storage == "packed" ) delete (packed_matrix_list*) loc; else if ( name == "List(List(MatF2))" && storage == "packed" ) delete (prevector*) loc; apply_gen1(kill_type) apply_gen2(kill_type); name = g.name; storage = g.storage; flags = g.flags; if ( name == "List(MatF2)" && storage == "packed" ) loc = new packed_matrix_list( *(packed_matrix_list*) g.loc ); else if ( name == "List(List(MatF2))" && storage == "packed" ) loc = new prevector ( *(prevector*) g.loc ); apply_gen1(copy_unit) apply_gen2(copy_unit); } generic_object::~generic_object( ) { if ( name == "List(MatF2)" && storage == "packed" ) delete (packed_matrix_list*) loc; else if ( name == "List(List(MatF2))" && storage == "packed" ) delete (prevector*) loc; apply_gen1(kill_type) apply_gen2(kill_type); } index_method(eq_obj) #define eq_obj(NAME, TYPE) \ if ( g1.name == #NAME ) return *(TYPE*) g1.loc == *(TYPE*) g2.loc; bool operator==(const generic_object& g1, const generic_object& g2) { if ( g1.name != g2.name ) return false; if ( g1.name == "" ) return true; if ( g1.storage == "" && g2.storage == "" ) { if (1); apply_gen1(eq_obj) apply_gen2(eq_obj); } if ( g1.storage == "packed" && g2.storage == "packed" ) { if ( g1.name == "List(MatF2)" ) return *(packed_matrix_list*) g1.loc == *(packed_matrix_list*) g2.loc; if ( g1.name == "List(List(MatF2))" ) return *(prevector*) g1.loc == *(prevector*) g2.loc; } if ( g1.storage == "packed" || g2.storage == "packed" ) { prevector< matrix > L1 = g1; prevector< matrix > L2 = g2; return L1 == L2; } INTERNAL_ERROR( "generic_object operator==" ); } index_method(convert) void generic_object::convert( const String& s ) { static Regex number_pattern( number_pat ); String new_name; OSLList new_flags; parse_type( s, new_name, new_flags ); OSLList extra_flags = diff( new_flags, flags ); if ( name == new_name && extra_flags.length( ) == 0 ) return; if ( name == "MatF2" && new_name == "MatF2" ) { if ( extra_flags.contains( "invertible1" ) ) { matrix& M = *(matrix*) loc; if ( !M.invertible( ) ) goto conversion_failed; } if ( extra_flags.contains( "reduced1" ) ) { matrix& M = *(matrix*) loc; if ( !M.reduced( ) ) goto conversion_failed; } goto add_flags; } if ( name == "List(MatF2)" && new_name == "List(MatF2)" ) { if ( extra_flags.contains( "homogeneous1" ) ) { prevector< matrix >& L = *(prevector< matrix >*) loc; if ( L.length == 0 ) goto conversion_failed; for ( int i = 1; i < L.length; i++ ) if ( L(i).nrows != L(0).nrows || L(i).ncols != L(0).ncols ) goto conversion_failed; } if ( storage == "packed" ) { packed_matrix_list& L = *(packed_matrix_list*) loc; forPixDef( p, L.third ) { matrix M = unpack( L.third(p).x, L.first, L.second ); if (extra_flags.contains("invertible2") && !M.invertible( )) goto conversion_failed; if ( extra_flags.contains( "reduced2" ) && !M.reduced( ) ) goto conversion_failed; } } else { prevector< matrix >& L = *(prevector< matrix >*) loc; for ( int i = 0; i < L.length; i++ ) { if ( extra_flags.contains( "invertible2" ) ) if ( !L(i).invertible( ) ) goto conversion_failed; if ( extra_flags.contains( "reduced2" ) ) if ( !L(i).reduced( ) ) goto conversion_failed; } } goto add_flags; } if ( name == "PreInt" && new_name == "Int" ) { String s = *(String*) loc; if ( !s.matches(number_pattern) ) goto conversion_failed; delete (String*) loc; Integer* l = new Integer; loc = l; (*l) = s; name = new_name; if ( new_flags.length( ) > 0 ) ERROR( "Flags not implemented for PreInt --> Int conversion." ); return; } if ( name == "PreInt" && new_name == "F2" ) { String s = *(String*) loc; if ( s != "0" && s != "1" ) goto conversion_failed; delete (String*) loc; gf2* l = new gf2; loc = l; (*l) = s; name = new_name; if ( new_flags.length( ) > 0 ) ERROR( "Flags not implemented for PreInt --> F2 conversion." ); return; } if ( name == "PreInt" && new_name == "List(F2)" ) { String s = *(String*) loc; static Regex zero_one_pat( "[01]+" ); if ( !s.matches(zero_one_pat) ) goto conversion_failed; delete (String*) loc; vector* l = new vector; loc = l; (*l) = vector( s, 0 ); name = new_name; if ( new_flags.length( ) > 0 ) ERROR( "Flags not implemented for PreInt --> List(F2) conversion." ); return; } if ( name == "List(PreInt)" && new_name == "List(Int)" ) { prevector s = *(prevector*) loc; for ( int i = 0; i < s.length; i++ ) if ( !s(i).matches(number_pattern) ) goto conversion_failed; delete (prevector*) loc; vector* l = new vector; l->set_size( s.length ); loc = l; for ( int i = 0; i < s.length; i++ ) (*l)(i) = s(i); name = new_name; if ( new_flags.length( ) > 0 ) ERROR( "Flags not implemented for " << "List(PreInt) --> List(Int) conversion." ); return; } if ( name == "List(PreInt)" && new_name == "List(F2)" ) { prevector s = *(prevector*) loc; for ( int i = 0; i < s.length; i++ ) if ( s(i) != "0" && s(i) != "1" ) goto conversion_failed; delete (prevector*) loc; prevector* l = new prevector; l->set_size( s.length ); loc = l; for ( int i = 0; i < s.length; i++ ) (*l)(i) = s(i); name = new_name; if ( new_flags.length( ) > 0 ) ERROR( "Flags not implemented for " << "List(PreInt) --> List(F2) conversion." ); return; } if ( name == "List(PreInt)" && new_name == "MatF2" ) { prevector s = *(prevector*) loc; static Regex zero_one_pat( "[01]+" ); for ( int i = 0; i < s.length; i++ ) if ( !s(i).matches(zero_one_pat) ) goto conversion_failed; if ( s.length == 0 ) goto conversion_failed; for ( int i = 1; i < s.length; i++ ) if ( s(i).length( ) != s(i-1).length( ) ) goto conversion_failed; delete (prevector*) loc; matrix* l = new matrix( s.length, s(0).length( ) ); loc = l; for ( int i = 0; i < s.length; i++ ) (*l)(i) = vector( s(i), 0 ); name = new_name; if ( new_flags.length( ) > 0 ) ERROR( "Flags not implemented for " << "List(PreInt) --> MatF2 conversion." ); return; } if ( name == "List(PreInt)" && new_name == "List(MatF2)" ) { prevector s = *(prevector*) loc; static Regex zero_one_pat( "[01]+" ); for ( int i = 0; i < s.length; i++ ) if ( !s(i).matches(zero_one_pat) ) goto conversion_failed; if ( s.length == 0 ) goto conversion_failed; for ( int i = 1; i < s.length; i++ ) if ( s(i).length( ) != s(i-1).length( ) ) goto conversion_failed; delete (prevector*) loc; matrix M( s.length, s(0).length( ) ); for ( int i = 0; i < s.length; i++ ) M(i) = vector( s(i), 0 ); prevector< matrix >* l = new prevector< matrix >; l->set_size(1); (*l)(0) = M; loc = l; name = new_name; if (new_flags.length( ) == 1 && new_flags.front( ) == "homogeneous1") goto add_flags; if ( new_flags.length( ) > 0 ) ERROR( "Most Flags not implemented " << "for List(PreInt) --> List(MatF2) conversion." ); return; } if ( name == "List(List(PreInt))" && new_name == "List(List(Int))" ) { prevector< prevector > s = *(prevector< prevector >*) loc; for ( int i = 0; i < s.length; i++ ) for ( int j = 0; j < s(i).length; j++ ) if ( !s(i)(j).matches(number_pattern) ) goto conversion_failed; delete (prevector< prevector >*) loc; prevector< vector >* l = new prevector< vector >; l->set_size( s.length ); loc = l; for ( int i = 0; i < s.length; i++ ) { (*l)(i).set_size( s(i).length ); for ( int j = 0; j < s(i).length; j++ ) (*l)(i)(j) = s(i)(j); } name = new_name; if ( new_flags.length( ) > 0 ) ERROR( "Flags not implemented for " << "List(List(PreInt)) --> List(List(Int)) conversion." ); return; } if ( name == "MatF2" && new_name == "List(MatF2)" ) { matrix M = *(matrix*) loc; delete (matrix*) loc; prevector< matrix >* l = new prevector< matrix >(1); loc = l; (*l)(0) = M; name = new_name; if ( new_flags.contains( "invertible2" ) && !flags.contains( "invertible1" ) && !M.invertible( ) ) goto conversion_failed; if ( new_flags.contains( "reduced2" ) && !flags.contains( "reduced1" ) && !M.reduced( ) ) goto conversion_failed; new_flags.add( "homogeneous1" ); if ( flags.contains( "reduced1" ) ) new_flags.add( "reduced2" ); if ( flags.contains( "invertible1" ) ) new_flags.add( "invertible2" ); flags = new_flags; return; } if ( name == "List(MatF2)" && new_name == "MatF2" ) { matrix A; if ( storage == "" ) { prevector< matrix >& p = *(prevector< matrix >*) loc; if ( p.length != 1 ) goto conversion_failed; A = p(0); delete (prevector< matrix >*) loc; } else { packed_matrix_list& L = *(packed_matrix_list*) loc; if ( L.third.length( ) != 1 ) goto conversion_failed; A = unpack( L.third.front( ).x, L.first, L.second); delete (packed_matrix_list*) loc; } matrix* M = new matrix(A); loc = M; name = new_name; if ( new_flags.contains( "invertible1" ) && !flags.contains( "invertible2" ) && !M->invertible( ) ) goto conversion_failed; if ( new_flags.contains( "reduced1" ) && !flags.contains( "reduced2" ) && !M->reduced( ) ) goto conversion_failed; if ( flags.contains( "reduced2" ) ) new_flags.add( "reduced1" ); if ( flags.contains( "invertible2" ) ) new_flags.add( "invertible1" ); flags = new_flags; return; } if ( name == "List(List(MatF2))" && new_name == "List(List(MatF2))" ) { if ( extra_flags.contains( "homogeneous2" ) ) { prevector< prevector< matrix > >& L = *(prevector< prevector< matrix > >*) loc; for ( int j = 0; j < L.length; j++ ) { if ( L(j).length == 0 ) goto conversion_failed; for ( int i = 1; i < L(j).length; i++ ) if ( L(j)(i).nrows != L(j)(0).nrows || L(j)(i).ncols != L(j)(0).ncols ) goto conversion_failed; } } if ( storage == "packed" ) { prevector& L = *(prevector*) loc; for ( int i = 0; i < L.length; i++ ) { forPixDef( p, L(i).third ) { matrix M = unpack(L(i).third(p).x, L(i).first, L(i).second); if ( extra_flags.contains( "invertible3" ) && !M.invertible( ) ) goto conversion_failed; if ( extra_flags.contains( "reduced3" ) && !M.reduced( ) ) goto conversion_failed; } } } else { prevector< prevector< matrix > >& L = *(prevector< prevector< matrix > >*) loc; for ( int j = 0; j < L.length; j++ ) { for ( int i = 0; i < L(j).length; i++ ) { if ( extra_flags.contains( "invertible2" ) ) if ( !L(j)(i).invertible( ) ) goto conversion_failed; if ( extra_flags.contains( "reduced2" ) ) if ( !L(j)(i).reduced( ) ) goto conversion_failed; } } } goto add_flags; } conversion_failed: ERROR( "Conversion from " << expand_type(name, flags) << " to " << expand_type(new_name, new_flags) << " failed." ); add_flags: forPixDef( p, extra_flags ) flags.add( extra_flags(p) ); return; } // Should be "const generic_object&": ostream& operator<<(ostream& s, generic_object& g) { if ( g.name == "F2" ) { // Should be ref: gf2 x = g; s << "a element of F_2: " << x << "\n"; } else if ( g.name == "List(MatF2)" && g.storage == "packed" ) { // Should be ref: packed_matrix_list Ms = g; s << Ms.third.length( ) << ( Ms.third.length( ) == 1 ? " matrix" : " matrices" ) << " of the same size over F_2:\n"; forPixDef( p, Ms.third ) s << unpack(Ms.third(p).x, Ms.first, Ms.second) << "\n"; } else if ( g.name == "List(MatF2)" ) { prevector< matrix > x = g; s << x.length << ( x.length == 1 ? " matrix" : " matrices" ) << " over F_2:\n"; for ( int i = 0; i < x.length; i++ ) s << x(i) << "\n"; } else if ( g.name == "List(List(MatF2))" && g.storage == "packed" ) { // Should be ref: prevector v = g; if (input_form) s << "{\n"; else s << v.length << " lists of matrices:\n"; for ( int i = 0; i < v.length; i++ ) { packed_matrix_list& Ms = v(i); if (input_form) s << " {\n"; else s << Ms.third.length( ) << ( Ms.third.length( ) == 1 ? " matrix" : " matrices" ) << " of the same size over F_2:\n"; forPixDef( p, Ms.third ) { if (input_form && p != Ms.third.first( ) ) s << "\n,"; s << " " << unpack(Ms.third(p).x, Ms.first, Ms.second); } if (input_form) { s << "\n }"; if ( i < v.length - 1 ) s << ","; s << "\n"; } } if (input_form) s << "}\n"; } else if ( g.name == "List(List(MatF2))" ) { prevector< prevector< matrix > > x = g; if (input_form) s << "{\n"; else s << x.length << " lists of matrices:\n"; for ( int j = 0; j < x.length; j++ ) { if (input_form) s << " {\n"; else s << x(j).length << ( x(j).length == 1 ? " matrix" : " matrices" ) << " over F_2:\n"; for ( int i = 0; i < x(j).length; i++ ) { s << " " << x(j)(i); if ( input_form && i < x(j).length - 1 ) s << ","; s << "\n"; } if (input_form) { s << " }"; if ( j < x.length - 1 ) s << ","; s << "\n"; } } if (input_form) s << "}\n"; } else if ( g.name == "MatF2" ) { // Should be ref: matrix M = g; s << M.nrows << " x " << M.ncols << " matrix over F_2:\n" << M << "\n"; } else if ( g.name == "List(F2)" ) { // Should be ref: vector v = g; s << "vector over gf2:\n" << v << "\n"; } else if ( g.name == "PVSF2" ) { // Should be ref: prevector< prevector< vector > > p = g; int n = p(0)(0).length; s << "partition of F_2^" << n << ":\n"; for ( int i = 0; i < p.length; i++ ) s << p(i) << "\n"; } else if ( g.name == "List(PVSF2)" ) { // Should be ref: prevector< prevector< prevector< vector > > > q = g; s << "list of " << q.length << " partitioned vector spaces " << "over F_2:\n"; for ( int j = 0; j < q.length; j++ ) { prevector< prevector< vector > > p = q(j); int n = p(0)(0).length; s << "partition of F_2^" << n << ":\n"; for ( int i = 0; i < p.length; i++ ) s << p(i) << "\n"; } } else if ( g.name == "PreInt" ) { String x = g; s << "pre-integer: " << x << "\n"; } else if ( g.name == "List(PreInt)" ) { prevector x = g; s << "list of " << x.length << " pre-integers:"; for ( int i = 0; i < x.length; i++ ) s << " " << x(i); s << "\n"; } else if ( g.name == "List(List(PreInt))" ) { // Should be ref: prevector< prevector > v = g; s << v.length << " lists of pre-integers:\n"; for ( int i = 0; i < v.length; i++ ) s << "list " << i + 1 << ": " << v(i) << "\n"; } else if ( g.name == "Int" ) { // Should be ref: Integer i = g; s << "integer: " << i << "\n"; } else if ( g.name == "MatInt" ) { matrix m = g; s << "matrix of integers: " << m << "\n"; } else if ( g.name == "Rat" ) { // Should be ref: Rational i = g; s << "rational: " << i << "\n"; } else if ( g.name == "MatRat" ) { matrix m = g; s << "matrix of rationals: " << m << "\n"; } else if ( g.name == "List(Int)" ) { // Should be ref: vector v = g; String out = String(dec(v.length)) + " integers: "; for ( int i = 0; i < v.length; i++ ) { if ( out.length( ) + String(dec(v(i))).length( ) + 1 > 80 ) { s << out << "\n"; out = ""; out = String(dec(v(i))) + " "; } else out += String(dec(v(i))) + " "; } s << out << "\n"; } else if ( g.name == "List(Rat)" ) { // Should be ref: vector v = g; s << v.length << " rationals:\n"; for ( int i = 0; i < v.length; i++ ) s << v(i) << "\n"; } else if ( g.name == "List(List(Int))" ) { // Should be ref: prevector< vector > v = g; s << v.length << " lists of integers:\n"; for ( int i = 0; i < v.length; i++ ) s << "list " << i + 1 << ": " << v(i) << "\n"; } else if ( g.name == "Bool" ) { // Should be ref: bool b = g; s << "boolean: " << ( b ? "true\n" : "false\n" ); } else if ( g.name == "List(Bool)" ) { // Should be ref: prevector b = g; s << "list of booleans: {"; for ( int i = 0; i < b.length; i++ ) { if ( b(i) ) s << "true"; else s << "false"; if ( i < b.length - 1 ) s << ", "; } s << "}\n"; } else if ( g.name == "Group" ) { // Should be ref: Group G = g; s << "group: " << G << "\n"; } else if ( g.name == "LinearProgram" ) { pair< prevector, String > p = g; s << "linear program:\n"; s << "variables = " << p.first << "\n"; s << "program =\n"; ifstream in( calculations_dir + "/" + p.second ); while( in.peek( ) != EOF ) { char* line; in.gets(&line, '\n'); s << line << "\n"; delete line; } } else if ( g.name == "String" ) { String S = g; s << "string: " << S << "\n"; } else if ( g.name == "List(String)" ) { prevector Ss = g; s << "list of " << Ss.length << " strings:\n"; for ( int i = 0; i < Ss.length; i++ ) s << Ss(i) << "\n"; } else INTERNAL_ERROR( "Attempt to print object of unknown type." ); return s; } set_compile_file(op1.cc) HIDE( ![ #include #include "homedefs.h" #include "bitvec.h" #include "codetable.h" extern "C" int isalpha(int); int take_int(String&, const Regex&); extern String pos_number, left, right, orsign, label_pat, gen_label_pat, pos_list, constraint_pat, LHS_pat; extern int debug; extern matrix BCH(int, int, int, int); typedef vector polyF2; polyF2 primitive_poly(int); int divides(const polyF2&, polyF2); matrix BCH(polyF2, int, vector); String list_of(const String&, const String& = ","); String nontrivial_list_of(const String&, const String& = ","); prevector< vector > tuple_orbits(matrix, int); int min_distance(const matrix&, int); prevector expand_config_list(codehome*, String); SLList< matrix > enlarge_by_dual_word(const matrix&, int); SLList< vector > dual_words_of_given_weight(matrix, int); vector pack(matrix); matrix canonical_form(matrix); OSLList int_set(String); bool iso_member(const matrix&, const SLList< matrix >&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); SLList< vector > iso_dual_words_of_given_weight(matrix, int); pair< Permutationlist, Integer > find_automorphism_group(const matrix&); prevector invariant_generating_set(const matrix&, const partition&); matrix unpack(char*, int, int); typedef triple< int, int, OSLList< vector > > packed_matrix_list; #include "generic.h" void pmd_col0(String&, String, String, String, prevector&, int&); void pmd_tilde_dual(String&, String, String, String, prevector&, int&); #include "uniq.h" vector dual_of_we(vector, bool = false); SLList max_li(SLList); #include "NTL/BBFactoring.h" #include "NTL/mat_poly_zz_p.h" bool isomorphic( prevector< prevector >* ); prevector< prevector > orbits(prevector< matrix >); matrix direct_sum(prevector< matrix >); void decompose_rep(int, prevector< matrix >, prevector< prevector< matrix > >&, matrix&); bool isomorphic(prevector< matrix >, prevector< matrix >, bool = false); prevector unlist( const generic_object&); generic_object transpose(const generic_object&); int String_cmp(const String&, const String&); matrix End(int, prevector< matrix >); prevector< matrix > Aut(int, prevector< matrix >); bool pmd_atom(String&, prevector&, int&, const codetable&, codehome*, String&); int mcmp(const matrix&, const matrix&); void mmul(const matrix&, const matrix&, matrix&); bool ee_main1(String&, prevector&, int&); bool ee_main2(String&, prevector&, int&); bool ee_main3(String&, prevector&, int&, codehome*, String&, codetable&); bool ee_mainAI(String&, prevector&, int&, codehome*, String&, codetable&); bool ee_mainJZ(String&, prevector&, int&, codehome*, String&, codetable&); bool check(const constraint&, const vector&, const config_core&, int, const weightlist&); bool check_global_variable(String, int); bool realizable(config_core&, constraintlist&, codehome*, codetable&); void mul( const vector&, const matrix&, vector&); ]! ) index_method(FETCH) #define FETCH(OBJ, TYPE) \ i = take_int( middle, number_pattern ); \ at_codes(i).convert( #TYPE ); \ OBJ = at_codes(i); index_method(evaluate_Pert) void evaluate_Pert( String middle, prevector& at_codes, int& at_count ) { HIDE( ![ static Regex number_pattern( number_pat ); ]! ) middle.del( "Pert(@" ); middle.del( ")", -1 ); prevector pieces = unpack( middle ); int jj = as_int( pieces(0) ); at_codes(jj).convert( "List(MatF2){homogeneous}" ); packed_matrix_list start = at_codes(jj); bool mu_filter = false; int i, j, k = start.first, n = start.second; for ( i = 1; i < pieces.length; i++ ) { String pi = pieces(i); while(1) { if ( pi.length( ) >= 2 && pi[0] == '(' && pi[ pi.length( )-1 ] == ')' ) { pi.del( '(', 0 ); pi.del( ')', -1 ); } else break; } if ( pi == "mufilter" ) mu_filter = true; else ERROR( "Illegal Pert option." ); } uniq_mat_list Ms_can(n); OSLList< vector > Ms; int k_new; forPixDef( p, start.third ) { matrix M = unpack( start.third(p).x, k, n ); M.reduce_nz( ); if ( p == start.third.first( ) ) k_new = M.nrows; else if ( k_new != M.nrows ) ERROR("After reducing, not all the matrices in a " "list for Pert have the same number of rows."); if ( Ms_can.add(M) ) Ms.append( pack(M) ); } int d = min_distance( unpack( Ms.front( ).x, k_new, n ), 0 ); int count = Ms.length( ) + 1, pcount = 1, min_rows; p = Ms.first( ); do { cerr << "processing code #" << pcount++ << "\n"; matrix A = unpack( Ms(p).x, k_new, n ); // Find a basis which has as many words of minimum weight as possible. SLList min_words, min_words_coord; word indx(A.nrows); do { word v(A.ncols); mul(indx, A, v); if ( v.weight( ) == d ) min_words.append(v); } while( indx.advance( ) ); for ( i = 0; i < A.nrows; i++ ) min_words.append( A(i) ); SLList mw = max_li( min_words ); matrix C( A.ncols, mw ); for ( min_rows = 0; min_rows < C.nrows; min_rows++ ) if ( C(min_rows).weight( ) != d ) break; indx.set_zero( ); do { word v(C.ncols); mul(indx, C, v); if ( v.weight( ) == d ) min_words_coord.append(indx); } while( indx.advance( ) ); prevector< vector > cols = tuple_orbits(C, 1); for ( int ix = 0; ix < cols.length; ix++ ) { i = cols(ix)(0); indx.set_zero( ); word current_col = C.col(i); SLList mwcc; forPixDef( q, min_words_coord ) if ( min_words_coord(q) * current_col ) mwcc.append( min_words_coord(q) ); do { if ( indx == current_col ) continue; for ( j = 0; j < min_rows; j++ ) if ( !indx(j) && current_col(j) ) break; if ( j < min_rows ) continue; forPix( q, mwcc ) if ( !(mwcc(q) * indx) ) break; if ( q != 0 ) continue; matrix B = C; B.set_col( i, indx ); if (mu_filter) { bool mu_1_2nz = false; for ( int l = 0; l < n; l++ ) if ( B.col(l).if_zero( ) ) { mu_1_2nz = true; break; } if ( !mu_1_2nz ) { for ( int l = 0; l < n; l++ ) for ( j = l + 1; j < n; j++ ) if ( B.col(l) == B.col(j) ) { mu_1_2nz = true; goto mu; } } mu: if ( !mu_1_2nz ) continue; } if ( Ms_can.add(B) ) { B.reduce_nz( ); vector Mp = B.enumerate_weights( ); vector dMp = dual_of_we( Mp, true ); pair< Permutationlist, Integer > pp = find_automorphism_group(B); for ( j = 1; j <= B.ncols; j++ ) if ( dMp(j) != 0 ) break; cerr << "found code #" << count++ << ", enumerator = " << as_poly( Mp ) << ", dual code has minimum distance " << j << ", |G| = " << pp.second << "\n"; if (j == 1) cerr << B << "\n"; Ms.append( pack(B) ); } } while( indx.advance( ) ); } Ms.next(p); } while ( p != 0 ); at_codes(at_count) = generic_object( "List(MatF2{reduced}){homogeneous}", make_triple( k_new, n, Ms ) ); if ( at_count + 1 >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); } index_method(evaluate_PertTwo) void evaluate_PertTwo( String middle, prevector& at_codes, int& at_count ) { middle.del( "PertTwo(@" ); middle.del( ")", -1 ); prevector pieces = unpack( middle ); int stop_count = 0, start_count = 1; int jj = as_int( pieces(0) ); at_codes(jj).convert( "List(MatF2){homogeneous}" ); packed_matrix_list start = at_codes(jj); bool ex_triples = false, mu_filter = false; static Regex stop_option( "stopafter" + pos_number + "codes" ); static Regex start_option( "start=" + pos_number ); int i, j, k; for ( i = 1; i < pieces.length; i++ ) { String pi = pieces(i); while(1) { if ( pi.length( ) >= 2 && pi[0] == '(' && pi[ pi.length( )-1 ] == ')' ) { pi.del( '(', 0 ); pi.del( ')', -1 ); } else break; } if ( pi == "extriples" ) ex_triples = true; else if ( pi == "mufilter" ) mu_filter = true; else if ( pi.contains( stop_option, 0 ) ) { pi = pi.after( "stopafter" ); pi = pi.before( "codes" ); stop_count = as_int(pi); } else if ( pi.contains( start_option, 0 ) ) { pi = pi.after( "start=" ); start_count = as_int(pi); } else ERROR( "Illegal PertTwo option." ); } k = start.first; int n = start.second; if ( start_count > start.third.length( ) ) ERROR( "PertTwo: start count is too large." ); uniq_mat_list Ms_can(n); OSLList< vector > Ms; int k_new; forPixDef( p, start.third ) { matrix M = unpack( start.third(p).x, k, n ); M.reduce_nz( ); if ( p == start.third.first( ) ) k_new = M.nrows; else if ( k_new != M.nrows ) ERROR("After reducing, not all the matrices in a " "list for PertTwo have the same number of rows."); if ( Ms_can.add(M) ) Ms.append( pack(M) ); } int d = min_distance( unpack( Ms.front( ).x, k_new, n ), 0 ); int count = Ms.length( ) + 1, pcount = 1; p = Ms.first( ); do { if ( start_count > 1 ) { start_count--; pcount++; Ms.next(p); continue; } cerr << "processing code #" << pcount++ << "\n"; matrix A = unpack( Ms(p).x, k_new, n ); prevector< vector > cols = tuple_orbits(A, 2); SLList min_words, min_words_coord; word indx(A.nrows); do { word v(A.ncols); mul(indx, A, v); if ( v.weight( ) == d || v.weight( ) == d+1 ) { min_words_coord.append(indx); min_words.append(v); } } while( indx.advance( ) ); prevector mw(min_words), mwc(min_words_coord); for ( i = 0; i < cols.length; i++ ) { int i1 = cols(i)(0), i2 = cols(i)(1); word colsum = A.col(i1) + A.col(i2); if ( ex_triples ) { for ( j = 0; j < n; j++ ) if ( colsum == A.col(j) ) break; if ( j != n ) continue; } SLList mwc0; for ( j = 0; j < mw.length; j++ ) if ( mw(j)(i1) && mw(j)(i2) ) mwc0.append(mwc(j)); prevector mwc0v(mwc0); indx.set_zero( ); do { if ( colsum + indx < indx ) continue; for ( j = 0; j < mwc0v.length; j++ ) if ( mwc0v(j) * indx ) break; if ( j < mwc0v.length ) continue; matrix B(A); B.set_col( i1, B.col(i1) + indx ); B.set_col( i2, B.col(i2) + indx ); if (mu_filter) { bool mu_1_2nz = false; for ( int l = 0; l < n; l++ ) if ( B.col(l).if_zero( ) ) { mu_1_2nz = true; break; } if ( !mu_1_2nz ) { for ( int l = 0; l < n; l++ ) for ( j = l + 1; j < n; j++ ) if ( B.col(l) == B.col(j) ) { mu_1_2nz = true; goto mu; } } mu: if ( !mu_1_2nz ) continue; } if ( Ms_can.add(B) ) { B.reduce_nz( ); vector Mp = B.enumerate_weights( ); vector dMp = dual_of_we( Mp, true ); pair< Permutationlist, Integer > pp = find_automorphism_group(B); for ( j = 1; j <= B.ncols; j++ ) if ( dMp(j) != 0 ) break; cerr << "found code #" << count++ << ", enumerator = " << as_poly( Mp ) << ", dual code has minimum distance " << j << ", |G| = " << pp.second << "\n"; if (j == 1) cerr << B << "\n"; Ms.append( pack(B) ); if ( stop_count != 0 && count > stop_count ) goto bail_out; } } while( indx.advance( ) ); } Ms.next(p); } while ( p != 0 ); bail_out: at_codes(at_count) = generic_object( "List(MatF2{reduced}){homogeneous}", make_triple( k_new, n, Ms ) ); if ( at_count + 1 >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); } index_method(FML) #define FML(pat) \ something_changed = true; \ String first = s.before( pat ); \ String middle = s.at( pat ); \ String last = s.after( pat ); index_method(FIN) #define FIN(name, object) \ at_codes(at_count) = generic_object(#name, object); \ s = first + "@" + dec(at_count++) + last; \ if ( at_count >= at_codes.length ) \ at_codes.resize( at_codes.length + 1000 ); \ continue; index_method(simple_fun) #define simple_fun( name, type, decl ) \ static Regex name ## _pat( #name "(@" + number_pat + ")" ); \ if ( s.contains( name ## _pat ) ) \ { FML( name ##_pat ); \ j = take_int( middle, number_pattern ); \ at_codes(j).convert( #type ); \ decl = at_codes(j); index_method(apply_P) matrix apply_P( matrix A ) { A.reduce_nz( ); int i, j, k, k2 = Ipow(2, A.nrows); matrix B( A.nrows + 1, k2 + A.ncols ); for ( i = 0; i < A.nrows; i++ ) for ( j = 0; j < A.ncols; j++ ) B( i+1, j + k2 ) = A(i, j); for ( j = 0; j < k2; j++ ) B(0, j) = 1; i = 0; word indx(A.nrows); do { for ( k = 0; k < A.nrows; k++ ) B( k + 1, i ) = indx(k); i++; } while( indx.advance( ) ); B.reduce_nz( ); return B; } index_method(evaluate_transforms) void evaluate_transforms( String middle, prevector& at_codes, int& at_count ) { middle.del("@"); HIDE( ![ static Regex number_pattern( number_pat ); ]! ) int i, j, jj = take_int( middle, number_pattern ); at_codes(jj).convert( "MatF2" ); matrix A = at_codes(jj); A.reduce_nz( ); middle.del( "^Tusing{" ); middle.del( "}", -1 ); SLList cols; if ( !middle.contains( ":" ) ) // "dual transform" { prevector ms = unpack(middle); SLList< pair< Integer, vector > > w; for ( j = 0; j < ms.length; j++ ) { i = take_int( ms(j), number_pattern ); at_codes(i).convert( "Int" ); Integer r = at_codes(i); if ( ms(j).contains( "_" ) ) { i = take_int( ms(j), number_pattern ); at_codes(i).convert( "List(Int)" ); vector s = at_codes(i); w.append( make_pair( r, s ) ); } else w.append( make_pair( r, vector(0) ) ); } word indx(A.nrows), wd(A.ncols); do { mul( indx, A, wd ); int wt = wd.weight( ); forPixDef( p, w ) { if (w(p).first > A.ncols) ERROR( "Garbage weight for dual transform." ); if ( wt == w(p).first ) { for ( jj = 0; jj < w(p).second.length; jj++ ) { Integer k = w(p).second(jj); if ( k == 0 || k < -A.ncols || k > A.ncols ) ERROR( "Column numbers don't make sense." ); if ( k > 0 && !wd(int(k-1)) ) break; if ( k < 0 && wd(int(-k-1)) ) break; } if (jj == w(p).second.length) cols.append(indx); } } } while( indx.advance( ) != 0 ); } else // "dual orbit code" { prevector gs = unpack( middle.before(":") ); prevector gsi( gs.length ); Permutationlist aut = find_automorphism_group(A).first; for ( i = 0; i < gs.length; i++ ) { j = take_int( gs(i), number_pattern ); at_codes(j).convert( "Int" ); Integer r = at_codes(j); if ( r > aut.length ) ERROR( gs(i) << " does not make sense " << "because there are only " << aut.length << " generators." ); gsi(i) = aut(r-1); } prevector xx = unpack( middle.after( ":" ) ); prevector vv( xx.length ); for ( i = 0; i < vv.length; i++ ) { j = take_int( xx(i), number_pattern ); at_codes(j).convert( "List(F2)" ); word v = at_codes(j); if ( v.length != A.nrows ) ERROR( "Illegal vector length in dual transform." ); vv(i) = v; } matrix cs( vv.length, vv(0).length ); for ( i = 0; i < vv.length; i++ ) cs(i) = vv(i); word w( A.ncols ); OSLList gwi; for ( i = 0; i < cs.nrows; i++ ) { mul( cs(i), A, w ); gwi.add(w); } int old_length; do { old_length = gwi.length( ); forPixDef( q, gwi ) { for ( j = 0; j < gsi.length; j++ ) { w = gwi(q); gsi(j).act(w); gwi.add(w); } } } while ( gwi.length( ) > old_length ); forPixDef( q, gwi ) cols.append( A.coord_vector( gwi(q) ) ); } prevector colsv = cols; colsv.sort( &cmp ); matrix B(A.nrows, colsv.length); for ( j = 0; j < colsv.length; j++ ) B.set_col( j, colsv(j) ); B.reduce_nz( ); at_codes(at_count) = generic_object( "MatF2", B ); if ( at_count + 1 >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); } index_method(reduce) void reduce( Word& el, prevector< pair > ft ) { bool changed; int sub_count = 0; do { changed = false; if ( sub_count > 1000 ) ERROR( "Group substitutions seem to be diverging." ); for ( int k = 0; k < ft.length; k++ ) { int p = el.pos( ft(k).first ); if ( p >= 0 ) { changed = true; sub_count++; Word el_new; el_new.x.set_size( el.x.length - ft(k).first.x.length + ft(k).second.x.length ); for ( int i = 0; i < p; i++ ) el_new.x(i) = el.x(i); for ( int i = 0; i < ft(k).second.x.length; i++ ) el_new.x(p + i) = ft(k).second.x(i); for (int i = 0; i < el.x.length - ft(k).first.x.length - p; i++) el_new.x(p + ft(k).second.x.length + i) = el.x( p + ft(k).first.x.length + i ); el = el_new; break; } } } while( changed ); } index_method(evaluate_RegularRep) void evaluate_RegularRep( Group G, prevector& at_codes, int& at_count ) { int i, j; OSLList group; Word w; group.add(w); bool new_element; do { new_element = false; forPixDef( p, group ) { for ( j = 0; j < G.n; j++ ) { for ( i = 0; i < 2; i++ ) { Word el = group(p); w.x.set_size(1); w.x(0) = j; el = (i == 0) ? cat( el, w ) : cat( w, el ); reduce( el, G.rel ); if ( !group.contains(el) ) { group.add(el); if ( group.length( ) > 1000 ) ERROR( "RegularRep: group is too big." ); new_element = true; goto end_loop; } } } } end_loop: continue; } while( new_element ); prevector groupv(group); groupv.sort( &cmp ); int g = groupv.length; prevector< matrix > Ms( G.n ); for ( i = 0; i < G.n; i++ ) { Ms(i).set_size(g, g); for ( j = 0; j < g; j++ ) { w.x.set_size(1); w.x(0) = i; Word el = cat( w, groupv(j) ); reduce( el, G.rel ); int k = groupv.pos(el, &cmp); Ms(i)( k, j ) = 1; } } at_codes(at_count) = generic_object( "List(MatF2{invertible}){homogeneous}", Ms ); if ( at_count + 1 >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); } index_method(evaluate_Group) void evaluate_Group( String middle, prevector& at_codes, int& at_count ) { middle.del( "Group(" ); HIDE( ![ static Regex number_pattern( number_pat ); ]! ) middle.del( ")", -1 ); if ( !middle.contains( ":" ) ) ERROR("Missing : in Group."); prevector vars = unpack( middle.before( ":" ) ); static Regex letter_pat( "[A-Za-z]" ); int i, j, k, l; for ( i = 0; i < vars.length; i++ ) if ( !vars(i).matches( letter_pat ) ) ERROR( "In Group, the generators must be letters." ); for ( i = 0; i < vars.length; i++ ) for ( j = i + 1; j < vars.length; j++ ) if ( vars(i) == vars(j) ) ERROR( "Group: repetition of generators." ); prevector rels = unpack( middle.after( ":" ) ); prevector exp( vars.length ); if (rels.length < vars.length) ERROR("Group: not enough relations."); prevector from_to[2]; for ( i = 0; i < 2; i++ ) from_to[i].set_size( rels.length ); for ( i = 0; i < vars.length; i++ ) { String t = rels(i); if ( !t.contains(vars(i), 0) ) ERROR("Group: illegal relation."); t.del( vars(i) ); static Regex exp_pat( "\\^" + pos_number ); if ( !t.matches( exp_pat ) ) ERROR( "Group: illegal relation." ); t.del( "^" ); exp(i) = take_int( t, number_pattern ); for ( j = 0; j < exp(i); j++ ) from_to[0](i) += vars(i); } for ( i = vars.length; i < rels.length; i++ ) { if ( !rels(i).contains("->") ) ERROR("Group: illegal relation."); String ft[2]; ft[0] = rels(i).before( "->" ); ft[1] = rels(i).after( "->" ); static Regex signed_number_pat(signed_number); for ( j = 0; j < 2; j++ ) { String rel = ft[j]; String last_var; int lv; for ( k = 0; k < rel.length( ); k++ ) { char c = rel[k]; if ( c == '^' && last_var != "" ) { if ( !rel.contains( signed_number_pat, k+1 ) ) ERROR("Group: illegal relation."); String e = rel.at( signed_number_pat, k + 1 ); k += e.length( ); int en = as_int(e); while ( en < 0 ) en += exp(lv); for ( l = 0; l < en; l++ ) from_to[j](i) += last_var; last_var = ""; continue; } for ( l = 0; l < vars.length; l++ ) if ( String(c) == vars(l) ) break; if ( l == vars.length ) ERROR( "Group: illegal relation." ); from_to[j](i) += last_var; last_var = c; lv = l; } from_to[j](i) += last_var; } } Group G; G.n = vars.length; prevector< pair > r( rels.length ); for ( i = 0; i < r.length; i++ ) { Word w[2]; for ( l = 0; l < 2; l++ ) { w[l].x.set_size( from_to[l](i).length( ) ); for ( j = 0; j < w[l].x.length; j++ ) for ( k = 0; k < vars.length; k++ ) if ( String(from_to[l](i)[j]) == vars(k) ) { w[l].x(j) = k; break; } } r(i) = make_pair(w[0], w[1]); } G.rel = r; at_codes(at_count) = generic_object( "Group", G ); if ( at_count + 1 >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); } set_compile_file(op2.cc) HIDE( ![ #include #include "homedefs.h" #include "bitvec.h" #include "codetable.h" #include "simplex.h" int take_int(String&, const Regex&); extern String pos_number, left, right, orsign, gen_label_pat, pos_list, LHS_pat, constraint_pat; extern int homebrew, force_homebrew; vector pack(matrix); typedef triple< int, int, OSLList< vector > > packed_matrix_list; extern String homebrew_status; #include "generic.h" void pmd_col0(String&, String, String, String, prevector&, int&); void pmd_tilde_dual(String&, String, String, String, prevector&, int&); extern int warnings_are_fatal; prevector< prevector > orbits(prevector< matrix >); matrix direct_sum(prevector< matrix >); void decompose_rep(int, prevector< matrix >, prevector< prevector< matrix > >&, matrix&); bool check_global_variable(String, int); bool check(const constraint&, const vector&, const config_core&, int, const weightlist&); prevector unlist( const generic_object&); generic_object transpose(const generic_object&); pair lp_crunch(const prevector&, int, const vconstraint&, bool = false); bool infeasible_core(const prevector&, const vconstraint&); matrix End(int, prevector< matrix >); prevector< matrix > Aut(int, prevector< matrix >); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); bool isomorphic( prevector< prevector >* ); bool isomorphic(prevector< matrix >, prevector< matrix >, bool = false); String list_of(const String&, const String& = ","); Integer*** make_krawtchouk(int); int mcmp(const matrix&, const matrix&); void mmul(const matrix&, const matrix&, matrix&); void mul( const vector&, const matrix&, vector&); extern "C" long randomx( ); void evaluate_RegularRep(Group, prevector&, int&); void evaluate_Group(String, prevector&, int&); void evaluate_PertTwo(String, prevector&, int&); void evaluate_Pert(String, prevector&, int&); #define FML(pat) \ something_changed = true; \ String first = s.before( pat ); \ String middle = s.at( pat ); \ String last = s.after( pat ); #define simple_fun( name, type, decl ) \ static Regex name ## _pat( #name "(@" + number_pat + ")" ); \ if ( s.contains( name ## _pat ) ) \ { FML( name ##_pat ); \ j = take_int( middle, number_pattern ); \ at_codes(j).convert( #type ); \ decl = at_codes(j); ]! ) index_method(lex_G_minimal) inline bool lex_G_minimal( int& n, const prevector< matrix >& G, word& x ) { register matrix* Gx = G.x; register gf2* xx = x.x; for ( register int i = 1; i < G.length; i++ ) // assume G(0) = I { register word* Gxix = Gx[i].x; for ( register int j = 0; j < n; j++ ) { register gf2* Gxixj = Gxix[j].x; register gf2 mxj = 0; for ( register int l = 0; l < n; l++ ) mxj += Gxixj[l] * xx[l]; register gf2 xj = xx[j]; if ( mxj && !xj ) break; if ( !mxj && xj ) return false; } } return true; } index_class(mapgf2) index_method(apply) class mapgf2 { public: int inbits; int outbits; unsigned char kind; void* loc; mapgf2( ) { kind = 0; } mapgf2( const matrix& M, String op, String how ) { if ( op == "x|->xM" && how == "direct" ) { loc = new matrix(M); inbits = M.ncols; outbits = M.nrows; kind = 1; } else if ( op == "x|->xM" && how == "table" ) { inbits = M.ncols; outbits = M.nrows; word* table = new word[ int( Ipow(2,inbits) ) ]; loc = table; word x(inbits); int i = 0; do { word v; mul( x, M, v ); table[i++] = v; } while( x.advance( ) ); kind = 2; } else if ( op == "x|->xM" && how == "halftable" ) { inbits = M.ncols; outbits = M.nrows; if ( !even(inbits) || !even(outbits) ) INTERNAL_ERROR( "mapgf2 -- halftable use illegal" ); mapgf2* h = new mapgf2[4]; loc = h; matrix A = M.submatrix( inbits/2, outbits/2, 0, 0 ); h[0] = mapgf2( A, "x|->xM", "table" ); A = M.submatrix( inbits/2, outbits/2, inbits/2, 0 ); h[1] = mapgf2( A, "x|->xM", "table" ); A = M.submatrix( inbits/2, outbits/2, 0, outbits/2 ); h[2] = mapgf2( A, "x|->xM", "table" ); A = M.submatrix( inbits/2, outbits/2, inbits/2, outbits/2 ); h[3] = mapgf2( A, "x|->xM", "table" ); kind = 3; } else INTERNAL_ERROR( "Illegal construction of mapgf2." ); } mapgf2& operator=(const mapgf2& m) { if ( kind != 0 ) { if ( kind == 1 ) delete (matrix*) loc; else if ( kind == 2 ) delete (word[ ]) loc; else if ( kind == 3 ) delete (mapgf2[ ]) loc; } if ( m.kind != 0 ) { if ( m.kind == 1 ) loc = new matrix( *(matrix*) loc ); else if ( m.kind == 2 ) { int len = Ipow(2, m.inbits); word* v = (word*) m.loc; word* w = new word[len]; loc = w; for ( int i = 0; i < len; i++ ) w[i] = v[i]; } else if ( m.kind == 3 ) { mapgf2* t = new mapgf2[4]; mapgf2* u = (mapgf2*) m.loc; loc = t; for ( int i = 0; i < 4; i++ ) t[i] = u[i]; } kind = m.kind; inbits = m.inbits; outbits = m.outbits; } } ~mapgf2( ) { if ( kind == 1 ) delete (matrix*) loc; else if ( kind == 2 ) delete (word[ ]) loc; else if ( kind == 3 ) delete (mapgf2[ ]) loc; } void apply( const word& x, word& y ) { if ( kind == 1 ) { matrix& M = *(matrix*) loc; mul( x, M, y ); } else if ( kind == 2 ) { word* table = (word*) loc; register int indx = 0, two_pow = 1; register gf2* xx = x.x; for ( register int i = 0; i < inbits; i++ ) { if ( xx[i] ) indx += two_pow; two_pow += two_pow; } y = table[indx]; } else if ( kind == 3 ) { register int i, h = inbits >> 1, k = outbits >> 1; mapgf2* m = (mapgf2*) loc; y.set_size(outbits); register int indx1 = 0, indx2 = 0, two_pow = 1; register gf2* xx1 = x.x; register gf2* xx2 = xx1 + h; for ( i = 0; i < h; i++ ) { if ( xx1[i] ) indx1 += two_pow; if ( xx2[i] ) indx2 += two_pow; two_pow += two_pow; } word* table1 = (word*) m[0].loc; word* table2 = (word*) m[1].loc; word* table3 = (word*) m[2].loc; word* table4 = (word*) m[3].loc; for ( i = 0; i < k; i++ ) { y(i) = table1[indx1].x[i] + table3[indx2].x[i]; y(i + k) = table2[indx1].x[i] + table4[indx2].x[i]; } } } }; index_method(perm_enumerator) vector perm_enumerator( const matrix& B ) { int sz = min( B.nrows, B.ncols ); vector perm_we(sz+1); perm_we.set_zero( ); word indx(B.nrows); do { word indy(B.ncols); int r = indx.weight( ); if ( r == 0 ) { ++perm_we(0); continue; } matrix P(r,r); do { if ( r != indy.weight( ) ) continue; if ( B.select(indx, indy).invertible( ) ) ++perm_we(r); } while( indy.advance( ) ); } while( indx.advance( ) ); return perm_we; } index_method(ee_main1) bool ee_main1( String& s, prevector& at_codes, int& at_count ) { int i, j, k; HIDE( ![ static Regex number_pattern( number_pat ); ]! ) bool something_changed; // not really used // Test for For. static Regex For_head( "For(\\[" + var + "\\],@" + number_pat + "," ); if ( s.contains( For_head ) ) { i = s.index( For_head ); int paren_count = 1; for ( j = i + 4; j < s.length( ); j++ ) { if ( s[j] == '(' ) paren_count++; else if ( s[j] == ')' ) paren_count--; if ( paren_count == 0 ) break; } if ( j == s.length( ) ) INTERNAL_ERROR( "For paren failure." ); String first = s.before(i); String middle = s.at( i, j - i + 1 ); String last = s.after(j); middle.del( "For(" ); static Regex brack_var( "[" + var + "]" ); String indeterm = take( middle, brack_var ); middle.del( ",@" ); j = take_int( middle, number_pattern ); prevector L = unlist( at_codes(j) ); middle.del( "," ); middle.del( ")", -1 ); s = first + "{"; for ( k = 0; k < L.length; k++ ) { at_codes(at_count) = L(k); if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); String x = middle; x.gsub( indeterm, String("@") + dec(at_count) ); s += x; if ( k != L.length - 1 ) s += ","; at_count++; } s += "}" + last; return true; } // Test for RegularRep. simple_fun( RegularRep, Group, Group G ) { evaluate_RegularRep( G, at_codes, at_count ); s = first + "@" + dec(at_count++) + last; return true; } } // Test for Group. if ( s.contains( "Group(" ) ) { i = s.index( "Group(" ); if ( s.length( ) < i + 7 ) ERROR( "Group doesn't make sense." ); int paren_count = 1; for ( j = i + 11; j < s.length( ); j++ ) { if ( s[j] == '(' ) paren_count++; else if ( s[j] == ')' ) paren_count--; if ( paren_count == 0 ) break; } if ( j == s.length( ) ) INTERNAL_ERROR( "Group paren failure." ); String first = s.before(i); String middle = s.at( i, j - i + 1 ); String last = s.after(j); evaluate_Group(middle, at_codes, at_count ); s = first + "@" + dec(at_count++) + last; return true; } // Test for Transpose. static Regex Transpose_pat( "Transpose(@" + number_pat + ")" ); if ( s.contains( Transpose_pat ) ) { FML( Transpose_pat ); j = take_int( middle, number_pattern ); at_codes(at_count) = transpose( at_codes(j) ); s = first + "@" + dec(at_count++) + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); return true; } // Test for Select. static String at_pat( "@" + number_pat ); static String less_op = left + "<" + orsign + "<=" + right; static String compound_constraint_patx = "[-]?" + at_pat + less_op + LHS_pat + less_op + "[-]?" + at_pat; static String constraint_patx = left + LHS_pat + op + "[-]?" + at_pat + orsign + op + "[-]?" + at_pat + right; static Regex constraint_list_patx( list_of( constraint_patx + orsign + var + "!=" + at_pat + orsign + compound_constraint_patx) ); static Regex Select_pat( "Select(@" + number_pat + "," + left + constraint_patx + orsign + "{" + list_of( constraint_patx + orsign + var + "!=" + at_pat + orsign + compound_constraint_patx ) + "}" + right + ")" ); if ( s.contains( Select_pat ) ) { FML( Select_pat ); middle.del( "Select(@" ); j = take_int( middle, number_pattern ); at_codes(j).convert( "List(MatF2)" ); prevector< matrix > L = at_codes(j); SLList< matrix > answer; middle.del( "," ); middle.del( ")", -1 ); if ( middle.contains( "{", 0 ) ) { middle.del( "{", 0 ); middle.del( "}", -1); } String mx; while( middle.length( ) > 0 ) { if ( middle[0] != '@' ) { mx += middle[0]; middle.del( middle[0] ); } else { middle.del( '@' ); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer mm = at_codes(j); mx += dec(mm); } } constraintlist c(mx); for ( i = 0; i < L.length; i++ ) { matrix M = L(i); M.reduce_nz( ); forPixDef( q, c ) { constraint f = c(q); forPixDef( p, f.LHS ) if (!check_global_variable(f.LHS(p).var, M.ncols)) ERROR( "Illegal variable in Select " << "constraint." ); weightlist w( "1", M.ncols ); vector y = M.enumerate_weights( ); if ( !check( f, y, M, M.nrows, w ) ) break; } if ( q == 0 ) answer.append( L(i) ); } at_codes(at_count) = generic_object( "List(MatF2)", answer ); s = first + "@" + dec(at_count++) + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); return true; } // Test for DelsartePair. #define COMBO(A,I,J) ((J <= I) ? combo[A][I][J] : \ (even(A) ? combo[A][J][I] : -combo[A][J][I])) HIDE(![ String set_pat( "{" + list_of( pos_number + orsign + pos_number + "\\.\\." + pos_number ) + "}" ); ]!) String constraint_list_s( "{" + left + list_of( constraint_patx + orsign + var + "!=" + at_pat + orsign + compound_constraint_patx) + right + "}" ); static Regex constraint_list_pat( constraint_list_s ); static Regex DelsartePair_pat( "DelsartePair(" + at_pat + "," + at_pat + "," + at_pat + "," + at_pat + "," + constraint_list_s + ")" ); if ( s.contains( DelsartePair_pat ) ) { FML( DelsartePair_pat ); middle.del( "DelsartePair(" ); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer n = at_codes(j); middle.del( "," ); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer k = at_codes(j); middle.del( "," ); j = take_int( middle, number_pattern ); at_codes(j).convert( "List(Int)" ); prevector w = at_codes(j); middle.del( "," ); j = take_int( middle, number_pattern ); at_codes(j).convert( "List(Int)" ); prevector r = at_codes(j); if ( !subset( w, r ) ) ERROR( "The second weightlist must contain the first." ); middle.del( "," ); String conx = take( middle, constraint_list_pat ); conx.del( "{" ); conx.del( "}", -1 ); String mx; while( conx.length( ) > 0 ) { if ( conx[0] != '@' ) { mx += conx[0]; conx.del( conx[0] ); } else { conx.del( '@' ); j = take_int( conx, number_pattern ); at_codes(j).convert( "Int" ); Integer mm = at_codes(j); mx += dec(mm); } } constraintlist cons(mx); SLList vars; for ( i = 0; i < w.length; i++ ) vars.append( String("y") + dec(w(i)) ); for ( i = 0; i < r.length; i++ ) vars.append( String("Y") + dec(r(i)) ); prevector varsv(vars); // Create a file name. String fn; while(1) { fn = String("DL") + dec( randomx( ) % 100000 ); ifstream in( calculations_dir + "/" + fn ); if ( in.peek( ) == EOF ) break; in.close( ); } ofstream out( calculations_dir + "/" + fn ); vconstraint v( varsv.length ); // Process the given constraints. forPixDef( p, cons ) { constraint c = cons(p); qvconstraint qv( varsv.length ); qv.LHS.set_zero( ); forPixDef( q, c.LHS ) { term t = c.LHS(q); Rational coeff = t.coeff; String var = t.var; for ( i = 0; i < varsv.length; i++ ) if ( var == varsv(i) ) break; if ( i < varsv.length ) qv.LHS(i) += coeff; // else if ( var[0] == 'y' || var[0] == 'Y' ); // { // Should check for valid variable! } // Should allow mu, MU! } qv.sense = c.sense; qv.RHS = c.RHS; clear_denom( qv, v ); out << v; } // Adjoin constraints Y_i >= y_i. for ( i = 0; i < varsv.length; i++ ) { if ( varsv(i)[0] == 'Y' ) break; v.LHS.set_zero( ); v.LHS(i) = -1; String vup = upcase( varsv(i) ); for ( j = i + 1; j < varsv.length; j++ ) if ( varsv(j) == vup ) { v.LHS(j) = 1; break; } v.sense = '>'; v.RHS = 0; if ( j == varsv.length ) INTERNAL_ERROR( "Delsarte." ); out << v; } Integer ***combo = make_krawtchouk(n); v.sense = '>'; v.RHS = 0; for ( int kk = 0; kk <= n; kk++ ) { // Create constraint Y_kk^perp >= 0. v.LHS.set_zero( ); int l = w.length; for ( j = 0; j < r.length; j++ ) { i = r(j); v.LHS(l++) = COMBO(kk,n-i,i); } out << v; // Create constraint y_kk^perp >= Y_kk^perp. v.LHS.set_zero( ); l = 0; for ( j = 0; j < w.length; j++ ) { i = w(j); v.LHS(l++) = 2 * COMBO(kk,n-i,i); } for ( j = 0; j < r.length; j++ ) { i = r(j); v.LHS(l++) = -COMBO(kk,n-i,i); } out << v; } v.sense = '='; v.RHS = 1; v.LHS.set_zero( ); v.LHS(0) = 1; out << v; v.LHS(0) = 0; v.LHS( w.length ) = 1; out << v; v.LHS.set_zero( ); v.RHS = Ipow(2, k); for ( i = 0; i < w.length; i++ ) v.LHS(i) = 1; out << v; for ( j = i; j < v.LHS.length; j++ ) v.LHS(j) = 1; v.RHS = Ipow(2, k) + Ipow(2, k+1); out << v; out.close( ); at_codes(at_count) = generic_object( "LinearProgram", make_pair( varsv, fn ) ); s = first + "@" + dec(at_count++) + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); return true; } // Test for Infeasible. static Regex Infeasible_pat( "Infeasible(" + at_pat + "," + at_pat + ")" ); if ( s.contains( Infeasible_pat ) ) { FML( Infeasible_pat ); j = take_int( middle, number_pattern ); if ( at_codes(j).name != "LinearProgram" ) ERROR( "Illegal use of Infeasible." ); pair< prevector, String > lp = at_codes(j); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer precision = at_codes(j); vconstraint v( lp.first.length ); bool tot_found = false; ifstream in( calculations_dir + "/" + lp.second ); while( in.peek( ) != EOF ) { in >> v; if ( v.sense == '>' ) continue; for ( i = 0; i < v.LHS.length; i++ ) if ( v.LHS(i) <= 0 ) break; if ( i == v.LHS.length ) { tot_found = true; break; } } if ( !tot_found ) ERROR( "I can't test the feasibility of a linear program " << "unless it has a constraint with all positive " << "coefficients and sense = or <=." ); in.close( ); prevector files(1); files(0) = lp.second; current_precision = precision; if ( precision == 1 ) homebrew = force_homebrew; else homebrew = 1; lp_crunch(files, lp.first.length, v); bool answer = infeasible_core(files, v); at_codes(at_count) = generic_object( "Bool", answer ); s = first + "@" + dec(at_count++) + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); return true; } // Test for PertTwo. static Regex PertTwo_pat( "PertTwo(@" + number_pat + left + ")" + orsign + ",[^()]*)" + right ); if ( s.contains( PertTwo_pat ) ) { FML(PertTwo_pat); evaluate_PertTwo(middle, at_codes, at_count ); s = first + "(@" + dec(at_count++) + ")" + last; return true; } // Test for Pert(@n). static Regex Pert_pat( "Pert(@" + number_pat + left + ")" + orsign + ",[^()]*)" + right ); if ( s.contains( Pert_pat ) ) { FML( Pert_pat ); evaluate_Pert(middle, at_codes, at_count ); s = first + "(@" + dec(at_count++) + ")" + last; return true; } // Test for Stratify. static Regex Stratify_pat( "Stratify(@" + number_pat + ")" ); if ( s.contains( Stratify_pat ) ) { FML( Stratify_pat ); j = take_int( middle, number_pattern ); at_codes(j).convert( "MatF2" ); matrix M = at_codes(j); int l, sz; for ( sz = 1; sz < 100; sz++ ) if ( M.ncols == sz * sz ) break; if ( sz == 100 ) ERROR( "Stratify failed." ); prevector< triple< matrix, vector, vector > > d(M.nrows); for ( l = 0; l < M.nrows; l++ ) { matrix B(sz, sz); for ( i = 0; i < sz; i++ ) for ( j = 0; j < sz; j++ ) B(i, j) = M(l)( j + sz * i ); vector row_we(sz+1), col_we(sz+1); vector perm_we = perm_enumerator(B); matrix BP(B); BP.resize( B.nrows+1, B.ncols ); for ( i = 0; i < B.ncols; i++ ) BP( B.nrows, i ) = 1; vector perm_we2 = perm_enumerator(BP); row_we.set_zero( ); col_we.set_zero( ); for ( i = 0; i < sz; i++ ) { ++row_we( B(i).weight( ) ); ++col_we( B.col(i).weight( ) ); } vector row_col_we( row_we, col_we ); vector perm_we_comb( perm_we, perm_we2 ); d(l) = make_triple( B, row_col_we, perm_we_comb ); } EquivRelIntList e( M.nrows ); for ( int l1 = 0; l1 < M.nrows; l1++ ) for ( int l2 = 0; l2 < M.nrows; l2++ ) if ( d(l1).second == d(l2).second && d(l1).third == d(l2).third ) e.join( l1, l2 ); SLList< prevector< matrix > > Ms; for ( l = 0; l < M.nrows; l++ ) if ( e.minimal(l) ) { int r = e.size(l); if ( r > 1 ) { SLList el = e.orbit(l); prevector< matrix > X( el.length( ) ); j = 0; forPixDef( p, el ) X(j++) = d(el(p)).first; Ms.append(X); } } at_codes(at_count) = generic_object( "List(List(MatF2))", prevector< prevector< matrix > >(Ms) ); s = first + "@" + dec(at_count++) + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); return true; } // Test for OrbitCount and OrbitReps. static Regex OrbitCountReps_pat( left + "OrbitCount(@" + orsign + "OrbitReps(@" + right + number_pat + ")" ); if ( s.contains( OrbitCountReps_pat ) ) { FML( OrbitCountReps_pat ); bool find_reps = middle.contains( "Reps" ); SLList answer; j = take_int( middle, number_pattern ); at_codes(j).convert( "List(MatF2{invertible}){homogeneous}" ); prevector< matrix > Ms = at_codes(j); int n = Ms(0).nrows; // Warning!! There are a number of lines in the following code that // used to look something like // "if ( K(0) != I ) swap( K( K.find(I) ), K(0) );". // These resulted in difficult-to-track anomalies, or so I thought. // Now I am not so sure. // Try to find a subspace of F_2^n on which Ms acts trivially. prevector< prevector< matrix > > summands; matrix Q; decompose_rep( n, Ms, summands, Q ); if ( summands.length == 0 ) { summands.set_size(1); summands(0) = Ms; Q.set_identity(n); } int triv_count = 0; for ( i = 0; i < summands.length; i++ ) if ( summands(i)(0).nrows == 1 ) triv_count++; // Swap the first nontrivial summand with the last summand. if ( summands.length >= triv_count + 2 ) { int a = summands(triv_count)(0).nrows; int b = summands(summands.length-1)(0).nrows; swap( summands(triv_count), summands(summands.length-1) ); matrix Q1 = Q, Q2(a, n), Q3(n-a-b-triv_count, n), Q4(b, n); Q1.resize( triv_count, n ); for ( i = 0; i < a; i++ ) Q2(i) = Q( i + triv_count ); for ( i = 0; i < n - a - b - triv_count; i++ ) Q3(i) = Q( i + triv_count + a ); for ( i = 0; i < b; i++ ) Q4(i) = Q( i + n - b ); matrix T1, T2; vcat( Q1, Q4, T1 ); vcat( T1, Q3, T2 ); vcat( T2, Q2, Q ); } String how = even(n) ? "halftable" : "direct"; mapgf2 Qmul( Q, "x|->xM", how ); // Compute the action on the nontrivial part. prevector< matrix > Ms_nt( Ms.length ); for ( i = 0; i < Ms.length; i++ ) { prevector< matrix > D( summands.length - triv_count ); for ( j = 0; j < D.length; j++ ) D(j) = summands( triv_count + j )(i); Ms_nt(i) = direct_sum( D ); } int nt = n - triv_count; matrix I; I.set_identity(nt); prevector< matrix > G; orbit( Ms_nt, I, G, mcmp, mmul ); int gf = G.find(I); if ( gf != 0 ) swap( G(gf), G(0) ); Integer count = 0; if ( summands.length == triv_count ) { word indx(n); do { if (find_reps) answer.append(indx); ++count; } while( indx.advance( ) ); } else if ( summands.length == triv_count + 1 ) { word indx_nt(nt); do { if ( lex_G_minimal( nt, G, indx_nt ) ) { if ( triv_count == 0 ) { word v2; Qmul.apply( indx_nt, v2 ); if (find_reps) answer.append(v2); ++count; } else { word indx_t( n - nt ); do { ++count; word v, w( indx_t, indx_nt ); Qmul.apply( w, v ); if (find_reps) answer.append(v); } while( indx_t.advance( ) ); } } } while( indx_nt.advance( ) ); } else if ( summands.length == triv_count + 2 ) { prevector< matrix > H_gen = summands(triv_count), H; int ny = H_gen(0).nrows; I.set_identity(ny); orbit( H_gen, I, H, mcmp, mmul ); int hf = H.find(I); if ( hf != 0 ) swap( H(hf), H(0) ); int nr = nt - ny; word y(ny); do { if ( !lex_G_minimal( ny, H, y ) ) continue; // Compute the stabilizer K of y (in G). SLList< matrix > stab; for ( i = 0; i < G.length; i++ ) { matrix G1 = G(i); G1.resize( ny, ny ); if ( G1.fixes(y) ) stab.append( G(i) ); } prevector< matrix > K0( stab ); prevector< matrix > K( K0.length ); for ( i = 0; i < K.length; i++ ) { K(i).set_size( nr, nr ); for ( j = 0; j < nr; j++ ) for ( int l = 0; l < nr; l++ ) K(i)(j, l) = K0(i)( ny + j, ny + l ); } K.unique_sort( &cmp ); I.set_identity( nr ); int kf = K.find(I); if ( kf != 0 ) swap( K(kf), K(0) ); word r(nr), v; do { if ( !lex_G_minimal( nr, K, r ) ) continue; word indx_nt( y, r ); if ( triv_count == 0 ) { Qmul.apply( indx_nt, v ); if (find_reps) answer.append(v); ++count; } else { word indx_t( n - nt ), w(n); for ( i = 0; i < indx_nt.length; i++ ) w(i + n - nt) = indx_nt(i); count += Ipow(2, n - nt); do { for ( i = 0; i < indx_t.length; i++ ) w(i) = indx_t(i); Qmul.apply( w, v ); if (find_reps) answer.append( v ); } while( indx_t.advance( ) ); } } while( r.advance( ) ); } while( y.advance( ) ); } else { // Set H equal to the group generated by summands(triv_count), // which will consist of matrices having size ny x ny. Make // sure that the first element of H is the identity. prevector< matrix > H_gen = summands(triv_count), H; int ny = H_gen(0).nrows; I.set_identity(ny); orbit( H_gen, I, H, mcmp, mmul ); int hf = H.find(I); if ( hf != 0 ) swap( H(hf), H(0) ); // Let ns x ns be the size of the matrices in // summands(triv_count+1). int ns = summands(triv_count+1)(0).nrows; int nr = nt - ny - ns; word y(ny); do { if ( !lex_G_minimal( ny, H, y ) ) continue; // Compute the stabilizer K of y (in G). SLList< matrix > stab; for ( i = 0; i < G.length; i++ ) { matrix G1 = G(i).submatrix( ny, ny, 0, 0 ); if ( G1.fixes(y) ) stab.append( G(i) ); } prevector< matrix > K0( stab ); prevector< matrix > K( K0.length ); for ( i = 0; i < K.length; i++ ) K(i) = K0(i).submatrix( ns, ns, ny, ny ); K.unique_sort( &cmp ); I.set_identity( ns ); int kf = K.find(I); if ( kf != 0 ) swap( K(kf), K(0) ); word s(ns); prevector< matrix > subG( G.length ); for ( i = 0; i < G.length; i++ ) subG(i) = G(i).submatrix( ny + ns, ny + ns, 0, 0 ); do { if ( !lex_G_minimal( ns, K, s ) ) continue; word ys( y, s ); // Compute the stabilizer L of ys (in G). SLList< matrix > stabys; for ( i = 0; i < subG.length; i++ ) if ( subG(i).fixes(ys) ) stabys.append( G(i) ); prevector< matrix > L0( stabys ); prevector< matrix > L( L0.length ); for ( i = 0; i < L.length; i++ ) L(i) = L0(i).submatrix( nr, nr, ny+ns, ny+ns ); L.unique_sort( &cmp ); word v(n), w(n); int nys = ny + ns; if ( L.length > 1 ) { I.set_identity( nr ); int lf = L.find(I); if ( lf != 0 ) swap( L(lf), L(0) ); } word r(nr); do { if ( L.length > 1 && !lex_G_minimal( nr, L, r ) ) continue; // Form all length n words of the form // w = *|y|s|r, where * is arbitrary. Append Qw. word indx_nt( ys, r ); if ( triv_count == 0 ) { Qmul.apply( indx_nt, v ); if (find_reps) answer.append(v); ++count; } else { word indx_t( n - nt ); for ( i = 0; i < indx_nt.length; i++ ) w(i + n - nt) = indx_nt(i); count += Ipow(2, n - nt); do { for ( i = 0; i < n - nt; i++ ) w(i) = indx_t(i); Qmul.apply( w, v ); if (find_reps) answer.append(v); } while( indx_t.advance( ) ); } } while( r.advance( ) ); } while( s.advance( ) ); } while( y.advance( ) ); } if (find_reps) at_codes(at_count) = generic_object( "MatF2", matrix( n, answer ) ); else at_codes(at_count) = generic_object( "Int", count ); s = first + "@" + dec(at_count++) + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); return true; } return false; } index_method(FINX) #define FINX(name, object) \ { at_codes(at_count) = generic_object(String(#name), object); \ s = first + "@" + dec(at_count++) + last; \ if ( at_count >= at_codes.length ) \ at_codes.resize( at_codes.length + 1000 ); \ return true; } index_method(ee_main2) bool ee_main2( String& s, prevector& at_codes, int& at_count ) { int i, j, k; HIDE( ![ static Regex number_pattern( number_pat ); ]! ) bool something_changed; // not really used // Test for Reduce. static Regex Reduce_pat( "Reduce(@" + number_pat + ")" ); if ( s.contains( Reduce_pat ) ) { FML( Reduce_pat ); j = take_int( middle, number_pattern ); if ( at_codes(j).name == "MatF2" && at_codes(j).flags.contains( "reduced1" ) ) { s = first + "@" + dec(j) + last; return true; } if ( at_codes(j).name == "MatF2" ) { matrix M = at_codes(j); M.reduce_nz( ); FINX( MatF2{reduced}, M ); } if ( at_codes(j).name == "List(PreInt)" ) { at_codes(j).convert( "MatF2" ); matrix M = at_codes(j); M.reduce_nz( ); FINX( MatF2{reduced}, M ); } if ( at_codes(j).name == "List(MatF2)" && at_codes(j).flags.contains( "reduced2" ) ) { s = first + "@" + dec(j) + last; return true; } if ( at_codes(j).name == "List(MatF2)" ) { prevector< matrix > L = at_codes(j); for ( i = 0; i < L.length; i++ ) L(i).reduce_nz( ); FINX( List(MatF2{reduced}), L ); } ERROR( "Illegal use of Reduce." ); } static String at_pat( "@" + number_pat ); // Test for LinearProgram. static Regex LinearProgram_pat( "LinearProgram(" + var + ")" ); if ( s.contains( LinearProgram_pat ) ) { FML( LinearProgram_pat ); middle.del( "LinearProgram(" ); middle.del( ")", -1 ); ifstream lp(middle); // Stage 1: Make filename. String fn; while(1) { fn = String("LP") + dec( randomx( ) % 100000 ); ifstream in( calculations_dir + "/" + fn ); if ( in.peek( ) == EOF ) break; in.close( ); } ofstream out( calculations_dir + "/" + fn ); // Stage 2: Get list of variables. SLList vars; while( lp.peek( ) != EOF ) { constraint c; lp >> c; forPixDef( p, c.LHS ) { String v = c.LHS(p).var; forPixDef( q, vars ) if ( vars(q) == v ) break; if ( q == 0 ) vars.append(v); } } prevector varsv(vars); lp.close( ); // Stage 3: Create constraint file. ifstream lp2(middle); vconstraint v(varsv.length); while( lp2.peek( ) != EOF ) { constraint c; lp2 >> c; v.LHS.set_zero( ); forPixDef( p, c.LHS ) { term t = c.LHS(p); for ( i = 0; i < varsv.length; i++ ) if ( varsv(i) == t.var ) break; v.LHS(i) += floor( t.coeff ); } v.RHS = c.RHS; v.sense = c.sense; out << v; } FINX( LinearProgram, make_pair(varsv, fn) ); } // Test for Bound. static Regex Bound_pat( "Bound(" + at_pat + "," + var + ")" ); if ( s.contains( Bound_pat ) ) { FML( Bound_pat ); middle.del( "Bound(@" ); j = take_int( middle, number_pattern ); if ( at_codes(j).name != "LinearProgram" ) ERROR( "Illegal use of Infeasible." ); pair< prevector, String > lp = at_codes(j); middle.del( "," ); middle.del( ")", -1 ); int var; for ( var = 0; var < lp.first.length; var++ ) if ( lp.first(var) == middle ) break; if ( var == lp.first.length ) ERROR( "The variable " << middle << " does not appear in the given linear program." ); exact_lp_problem ex; ex.n = lp.first.length; ex.m = 0; ex.m_eq = 0; ifstream in( calculations_dir + "/" + lp.second ); vconstraint v( lp.first.length ); Integer max_entry; while( in.peek( ) != EOF ) { in >> v; ++ex.m; if ( v.sense == '=' ) ++ex.m_eq; for ( j = 0; j < v.LHS.length; j++ ) max_entry = max( max_entry, abs(v.LHS(j)) ); } in.close( ); accommodate( max_entry * max_entry ); ex.known_to_be_infeasible = false; ex.con_file = calculations_dir + "/" + lp.second; accommodate( ex.presolve( ) ); if ( ex.known_to_be_infeasible ) ERROR( "At would appear that the given linear program " << "is infeasible." ); vector obj(lp.first.length); obj.set_zero( ); obj(var) = 1; ex.obj.set_size(1); ex.obj(0) = make_triple( Rational(0), obj, String("max") ); extend ans_max = ex.bound_by_primal_simplex_on_dual( ); if ( ans_max.PlusInfinity( ) ) ERROR( "It would appear that the given" << " linear program is infeasible." ); if ( ans_max.MinusInfinity( ) ) ERROR( "Unbounded objective function." ); ex.obj(0) = make_triple( Rational(0), obj, String("min") ); extend ans_min = ex.bound_by_primal_simplex_on_dual( ); if ( ans_min.MinusInfinity( ) ) ERROR( "It would appear that the " << "given linear program is infeasible." ); if ( ans_min.PlusInfinity( ) ) ERROR( "Unbounded objective function." ); vector ans(2); assign( ans(0), ans_min.x ); assign( ans(1), ans_max.x ); FINX( List(Rat), ans ); } // Test for Identity. static Regex Identity_pat( "Identity(" + pos_number + ")" ); if ( s.contains( Identity_pat ) ) { FML( Identity_pat ); int n = take_int(middle, number_pattern); matrix I; I.set_identity(n); FINX( MatF2, I ); } // Test for Isomorphic. static Regex Isomorphic_pat( "Isomorphic(@" + number_pat + ",@" + number_pat + ")" ); if ( s.contains( Isomorphic_pat ) ) { FML( Isomorphic_pat ); int a = take_int(middle, number_pattern); int b = take_int(middle, number_pattern); bool agroup = at_codes(a).name == "List(MatF2)" && at_codes(a).flags.contains( "invertible2" ) && at_codes(a).flags.contains( "homogeneous1" ); if ( at_codes(a).name != "PVSF2" && !agroup ) { at_codes(a).convert( "MatF2" ); at_codes(b).convert( "MatF2" ); matrix A = at_codes(a), B = at_codes(b); A.reduce_nz( ); B.reduce_nz( ); FINX( Bool, isomorphic(A, B) ); } else if ( at_codes(a).name == "PVSF2" ) { prevector< prevector > A[2]; A[0] = at_codes(a); A[1] = at_codes(b); FINX( Bool, isomorphic(A) ); } else if ( agroup ) { prevector< matrix > G, H; G = at_codes(a); H = at_codes(b); FINX( Bool, isomorphic(G, H) ); } ERROR( "Illegal types for Isomorphic." ); } // Test for Classify. static Regex Classify_pat( "Classify(@" + number_pat + ")" ); if ( s.contains( Classify_pat ) ) { FML( Classify_pat ); int jj = take_int(middle, number_pattern); SLList ans; if ( at_codes(jj).name == "List(PVSF2)" ) { prevector< prevector< prevector > > pvss = at_codes(jj); int n = pvss.length; EquivRelIntList e(n); for ( i = 0; i < n; i++ ) for ( j = i + 1; j < n; j++ ) if ( e.minimal(i) && e.minimal(j) ) { prevector< prevector > arg[2]; arg[0] = pvss(i); arg[1] = pvss(j); if ( isomorphic( arg ) ) e.join( i, j ); } for ( i = 0; i < n; i++ ) if ( e.minimal(i) ) ans.append( i + 1 ); } else if ( at_codes(jj).name == "List(List(MatF2))" ) { at_codes(jj).convert( "List(List(MatF2{invertible}){homogeneous})" ); prevector< prevector< matrix > > L = at_codes(jj); int n = L.length; EquivRelIntList e(n); for ( i = 0; i < n; i++ ) for ( j = i + 1; j < n; j++ ) if ( e.minimal(i) && e.minimal(j) ) if ( isomorphic( L(i), L(j) ) ) e.join(i, j); for ( i = 0; i < n; i++ ) if ( e.minimal(i) ) ans.append( i + 1 ); } else ERROR( "Illegal type for Classify." ); FINX( List(Int), vector(ans) ); } return false; } set_compile_file(op3.cc) HIDE( ![ #include "homedefs.h" #include "bitvec.h" #include "codetable.h" #include "generic.h" vector pack(matrix); matrix canonical_form(matrix); #include "uniq.h" extern String pos_number, left, right, orsign, gen_label_pat, pos_list, LHS_pat, constraint_pat, label_pat; extern int show_terminals, show_all_configs, via_building_show_extra_info, depth_first; String list_of(const String&, const String& = ","); String zero_or_more(const String&, const String& = ","); int take_int(String&, const Regex&); matrix direct_sum(prevector< matrix >); bool check_global_variable(String, int); bool check(const constraint&, const vector&, const config_core&, int, const weightlist&); bool realizable(config_core&, constraintlist&, codehome*, codetable&); pair< Permutationlist, Integer > find_automorphism_group(const matrix&); bool iso_member(const matrix&, const SLList< matrix >&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); void mul( const vector&, const matrix&, vector&); prevector< matrix > extend_residual_code(codehome*, String, matrix, codetable&, Integer); void solve(const matrix&, vector&, const vector&, int); void execute_via_building(codehome*, int, int, bool, String, prevector, bool, bool, codetable&, String, int&, SLList< matrix >& ); Permutation isomorphism(matrix, matrix); extern "C" int isdigit(int); extern "C" int srandomx(unsigned); extern "C" long randomx( ); #define FINX(name, object) \ { at_codes(at_count) = generic_object(String(#name), object); \ s = first + "@" + dec(at_count++) + last; \ if ( at_count >= at_codes.length ) \ at_codes.resize( at_codes.length + 1000 ); \ return true; } #define FML(pat) \ something_changed = true; \ String first = s.before( pat ); \ String middle = s.at( pat ); \ String last = s.after( pat ); #define FETCH(OBJ, TYPE) \ i = take_int( middle, number_pattern ); \ at_codes(i).convert( #TYPE ); \ OBJ = at_codes(i); ]! ) index_method(ee_main3) bool ee_main3( String& s, prevector& at_codes, int& at_count, codehome* home, String& code_label, codetable& results ) { int i, j, k; HIDE( ![ static Regex number_pattern( number_pat ); ]! ) bool something_changed; // not really used // Test for Cyclic. static Regex Cyclic_pat( "Cyclic(@" + number_pat + ",@" + number_pat + ",@" + number_pat + ",@" + number_pat + left + ")" + orsign + ",@" + number_pat + ")" + right ); if ( s.contains( Cyclic_pat ) ) { FML( Cyclic_pat ); bool extra_given = ( middle.freq(',') == 4 ); i = take_int( middle, number_pattern ); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer n = at_codes(j); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer k = at_codes(j); if ( k > n ) ERROR( "Use of Cyclic doesn't make sense." ); vector p; if ( at_codes(i).name == "PreInt" || at_codes(i).name == "Int" ) { at_codes(i).convert( "Int" ); Integer q = at_codes(i); if (n % q != 0) ERROR(q << " does not divide " << n << "."); p.set_size(q); for ( i = 0; i < q; i++ ) p(i) = n/q; } else { at_codes(i).convert( "List(Int)" ); p = at_codes(i); } Permutation sigma(n); int pos = 0; for ( i = 0; i < p.length; i++ ) { if ( pos + p(i) > n ) ERROR("Illegal permutation."); for ( j = 0; j < p(i)-1; j++ ) sigma(pos + j) = pos + j + 2; sigma(pos + p(i) - 1) = pos + 1; pos = pos + p(i); } j = take_int( middle, number_pattern ); at_codes(j).convert( "List(F2)" ); word gen = at_codes(j), extra(0); if (extra_given) { j = take_int( middle, number_pattern ); at_codes(j).convert( "List(F2)" ); extra = at_codes(j); } if ( gen.length > n || extra.length > n ) ERROR( "A zero-one vector is too long." ); if (gen.length == 0) ERROR( "A zero-one vector is too short." ); matrix M(k, n); for ( i = 0; i < gen.length; i++ ) M(0, i) = gen(i); for ( i = 1; i < k - extra_given; i++ ) { M(i) = M(i-1); sigma.act( M(i) ); } if (extra_given) { for ( j = 0; j < extra.length; j++ ) M( k - 1, j ) = extra(j); } M.reduce_nz( ); FINX( MatF2, M ); } // Test for A_inverse_b. static Regex A_inverse_b_pat( "A_inverse_b(@" + number_pat + ",@" + number_pat + "," + number_pat + ")" ); if ( s.contains( A_inverse_b_pat ) ) { FML( A_inverse_b_pat ); j = take_int( middle, number_pattern ); at_codes(j).convert( "MatInt" ); matrix A = at_codes(j); j = take_int( middle, number_pattern ); at_codes(j).convert( "List(Int)" ); vector b = at_codes(j); j = take_int( middle, number_pattern ); vector x; solve( A, x, b, j ); FINX( List(Rat), x ); } // Test for WE. static Regex WE_pat( "WE(@" + number_pat + ")" ); if ( s.contains( WE_pat ) ) { FML( WE_pat ); j = take_int( middle, number_pattern ); s = first + "AsPoly(WeightEnumerator(@" + dec(j) + "))" + last; return true; } // Test for AsPoly. static Regex AsPoly_pat( "AsPoly(@" + number_pat + ")" ); if ( s.contains( AsPoly_pat ) ) { FML( AsPoly_pat ); j = take_int( middle, number_pattern ); if ( at_codes(j).name == "List(Int)" ) { at_codes(j).convert( "List(Int)" ); vector Ps = at_codes(j); FINX( String, as_poly(Ps, true) ); } at_codes(j).convert( "List(List(Int))" ); prevector< vector > Ps = at_codes(j); prevector ans( Ps.length ); for ( i = 0; i < Ps.length; i++ ) ans(i) = as_poly( Ps(i), true ); FINX( List(String), ans ) } // Test for AsConfig. static Regex AsConfig_pat( "AsConfig(@" + number_pat + ")" ); if ( s.contains( AsConfig_pat ) ) { FML( AsConfig_pat ); j = take_int( middle, number_pattern ); s = first + "AsConfig0(Sort(@" + dec(j) + "))" + last; return true; } static Regex AsConfig0_pat( "AsConfig0(@" + number_pat + ")" ); if ( s.contains( AsConfig0_pat ) ) { FML( AsConfig0_pat ); middle.del( "AsConfig0(" ); j = take_int( middle, number_pattern ); at_codes(j).convert( "MatF2" ); matrix A = at_codes(j); matrix At = transpose_of(A); if ( At.nrows == 0 ) FINX( String, "" ); SLList cols; SLList parts; int count = 1; for ( i = 1; i < At.nrows; i++ ) { if ( At(i) == At(i-1) ) count++; else { cols.append( At(i-1) ); parts.append(count); count = 1; } } cols.append( At(i-1) ); parts.append(count); matrix B(At.ncols, cols); String ans; forPixDef( p, parts ) { if ( p != parts.first( ) ) ans += ","; ans += dec( parts(p) ); } ans += " : " + String( transpose_of(B) ); FINX( String, ans ); } // Test for WeightEnumerator. static Regex WeightEnumerator_pat( "WeightEnumerator(@" + number_pat + ")" ); if ( s.contains( WeightEnumerator_pat ) ) { FML( WeightEnumerator_pat ); j = take_int( middle, number_pattern ); bool single = ( at_codes(j).name == "MatF2" ); at_codes(j).convert( "List(MatF2)" ); prevector< matrix > Ms = at_codes(j); prevector< vector > wes( Ms.length ); for ( i = 0; i < Ms.length; i++ ) { config_core c( Ms(i) ); wes(i) = c.smallcode_we( ); } if (single) FINX( List(Int), wes(0) ) else FINX( List(List(Int)), wes ) } // Test for Build. static Regex Build_pat( "Build(" + label_pat + "," + label_pat + ")" ); if ( s.contains( Build_pat ) ) { FML( Build_pat ); middle.del( "Build(" ); middle.del( ")", -1 ); String hlabel = middle.before( "," ); String clabel = middle.after( "," ); codehome* h; if ( home != 0 && (hlabel == code_label || hlabel == "[current]") ) h = home; else h = results.get_home( hlabel, false ); prevector labels(0); SLList< matrix > terminals; int pound_label_ctr = 1; execute_via_building( h, show_terminals, show_all_configs, false, clabel, labels, via_building_show_extra_info, depth_first, results, "$", pound_label_ctr, terminals ); prevector< matrix > terminalsv(terminals); FINX( List(MatF2{reduced}){homogeneous}, terminalsv ); } // Test for Random. static Regex Random_pat( "Random(List(Int)," + number_pat + "," + number_pat + "," + number_pat + "," + number_pat + ")" + orsign + "Random(MatInt," + number_pat + "," + number_pat + "," + number_pat + "," + number_pat + "," + number_pat + ")" ); if ( s.contains( Random_pat ) ) { FML( Random_pat ); middle.del( "Random(" ); String type = middle.before( "," ); if ( type == "List(Int)" ) { int size = take_int( middle, number_pattern ); if ( size < 0 ) ERROR( "Illegal size for Random." ); int range1 = take_int( middle, number_pattern ); int range2 = take_int( middle, number_pattern ); int seed = take_int( middle, number_pattern ); srandomx(seed); vector v(size); for ( i = 0; i < size; i++ ) v(i) = ( randomx( ) % (range2 - range1) ) + range1; FINX( List(Int), v ); } else if ( type == "MatInt" ) { int size1 = take_int( middle, number_pattern ); int size2 = take_int( middle, number_pattern ); if ( size1 < 0 || size2 < 0 ) ERROR("Illegal size for Random."); int range1 = take_int( middle, number_pattern ); int range2 = take_int( middle, number_pattern ); if ( range2 < range1 ) ERROR( "Range for Random doesn't make sense." ); int seed = take_int( middle, number_pattern ); srandomx(seed); matrix m(size1, size2); for ( i = 0; i < size1; i++ ) for ( j = 0; j < size2; j++ ) m(i,j) = ( randomx( ) % (range2 - range1) ) + range1; FINX( MatInt, m ); } else ERROR( "Illegal type for Random." ); } // Test for Read. static Regex Read_pat( "Read(List(Int),[^)]*)" + orsign + "Read(MatInt,[^)]*)" ); if ( s.contains( Read_pat ) ) { FML( Read_pat ); middle.del( "Read(" ); middle.del( ")", -1 ); String type = middle.before( "," ); String filename = middle.after( "," ); ifstream source(filename); if ( type == "List(Int)" ) { vector v; source >> v; source.close( ); FINX( List(Int), v ); } else if ( type == "MatInt" ) { matrix m; source >> m; source.close( ); FINX( MatInt, m ); } else ERROR( "Illegal type request for Read." ); } static Regex Read_pat2( "Read(List(Rat),[^)]*)" + orsign + "Read(MatRat,[^)]*)" ); if ( s.contains( Read_pat2 ) ) { FML( Read_pat2 ); middle.del( "Read(" ); middle.del( ")", -1 ); String type = middle.before( "," ); String filename = middle.after( "," ); ifstream source(filename); if ( type == "List(Rat)" ) { vector v; source >> v; source.close( ); FINX( List(Rat), v ); } else if ( type == "MatRat" ) { matrix m; source >> m; source.close( ); FINX( MatRat, m ); } else ERROR( "Illegal type request for Read." ); } // Test for dotdot. static Regex dotdot_pat( "@" + number_pat + "[" + "." + "][" + "." + "]@" + number_pat ); if ( s.contains( dotdot_pat ) ) { FML( dotdot_pat ); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer a = at_codes(j); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer b = at_codes(j); if ( a > b ) ERROR( "Illegal use of \"..\"." ); s = first; for ( Integer l = a; l <= b; ++l ) { if ( l > a ) s += ","; at_codes(at_count) = generic_object( "Int", l ); s += String("@") + dec(at_count++); if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); } s += last; return true; } // Test for AntiCode. static Regex AntiCode_pat( "AntiCode(@" + number_pat + "," + list_of( "@" + number_pat ) + ")" ); if ( s.contains( AntiCode_pat ) ) { FML( AntiCode_pat ); j = take_int( middle, number_pattern ); at_codes(j).convert( "Int" ); Integer kk = at_codes(j); SLList cols; int pc = middle.freq( ',' ); for ( i = 0; i < pc; i++ ) { j = take_int( middle, number_pattern ); at_codes(j).convert( "List(List(Int))" ); prevector< vector > v = at_codes(j); SLList masks; for ( j = 0; j < v.length; j++ ) { word mask(kk); for ( int l = 0; l < kk; l++ ) mask(l) = 1; for ( int l = 0; l < v(j).length; l++ ) { if ( v(j)(l) <= 0 || v(j)(l) > kk ) ERROR("Illegal use of AntiCode."); mask( v(j)(l)-1 ) = 0; } masks.append(mask); } word indx(kk); indx.advance( ); do { forPixDef( q, masks ) if ( idot( indx, masks(q) ) == 0 ) break; if (q == 0) cols.append(indx); } while( indx.advance( ) ); } FINX( MatF2, transpose_of( matrix( kk, cols ) ) ); } // Test for CharPoly2. // (Code adopted from code in Victor Shoup's NTL, which is more efficient.) static Regex CharPoly2_pat( "CharPoly2(@" + number_pat + ")" ); if ( s.contains( CharPoly2_pat ) ) { FML( CharPoly2_pat ); middle = middle.after( "CharPoly2" ); j = take_int( middle, number_pattern ); at_codes(j).convert( "MatRat" ); matrix M = at_codes(j); if ( M.nrows != M.ncols ) ERROR( "CharPoly2 can only be " << "applied to a square matrix." ); int n = M.nrows; prevector< vector > F(n+1); for ( i = 0; i <= n; i++ ) { F(i).set_size(i+1); F(i).set_zero( ); } F(0)(0) = 1; for ( j = 1; j <= n; j++ ) { for ( i = 0; i <= j-1; i++ ) { F(j)(i+1) = F(j-1)(i); F(j)(i) -= F(j-1)(i) * M(j-1,j-1); } Rational t = 1; for ( i = 1; i <= j-1; i++ ) { t *= M( j-i, j-i-1 ); Rational x = t * M(j-i-1, j-1); if ( x != Rational(0) ) { for ( k = 0; k <= j-i-1; k++ ) F(j)(k) -= F(j-i-1)(k) * x; } } } FINX( List(Rat), F(n) ); } // Test for Diag. static Regex Diag_pat( "Diag(" + list_of( "@" + number_pat ) + ")" ); if ( s.contains( Diag_pat ) ) { FML( Diag_pat ); middle.del( "Diag(" ); middle.del( ")" ); prevector vs = unpack(middle); int n = vs.length; prevector< prevector< matrix > > L(n); for ( i = 0; i < n; i++ ) { int jj = take_int( vs(i), number_pattern ); at_codes(jj).convert( "List(MatF2)" ); L(i) = at_codes(jj); } int r = L(0).length; for ( i = 1; i < n; i++ ) if ( L(i).length != r ) ERROR( "For Diag, each list of matrices must " << "have the same length." ); SLList< matrix > answer; for ( i = 0; i < r; i++ ) { prevector< matrix > in(n); for ( j = 0; j < n; j++ ) in(j) = L(j)(i); answer.append( direct_sum(in) ); } FINX( List(MatF2), answer ); } // Test for Realizable. static String at_pat( "@" + number_pat ); static Regex Realizable_pat( "Realizable(" + label_pat + ",@" + number_pat + ")" ); if ( s.contains( Realizable_pat ) ) { FML( Realizable_pat ); middle.del( "Realizable(" ); static Regex label_pattern(label_pat); String lab = take( middle, label_pattern ); codehome* h; if ( home != 0 && (lab == code_label || lab == "[current]") ) h = home; else h = results.get_home( lab, false ); j = take_int( middle, number_pattern ); at_codes(j).convert( "List(MatF2)" ); prevector< matrix > L = at_codes(j); SLList< matrix > answer; for ( i = 0; i < L.length; i++ ) { matrix M = L(i); M.reduce_nz( ); config_core cc(M); constraintlist nc; if ( M.nrows == h->dim && M.ncols == h->n && realizable( cc, nc, h, results ) ) answer.append( L(i) ); } FINX( List(MatF2), answer ); } // Test for Unresidue. static Regex Unresidue_pat( "Unresidue(" + label_pat + "," + label_pat + "," + at_pat + ")" + orsign + "Unresidue(" + label_pat + "," + label_pat + "," + at_pat + "," + at_pat + ")" ); if ( s.contains( Unresidue_pat ) ) { FML( Unresidue_pat ); middle.del( "Unresidue(" ); static Regex label_pattern(label_pat); String hlab = take( middle, label_pattern ); middle.del( "," ); String clab = take( middle, label_pattern ); middle.del( ",@" ); codehome* h; if ( home != 0 && (hlab == code_label || hlab == "[current]") ) h = home; else h = results.get_home( hlab, false ); j = take_int( middle, number_pattern ); at_codes(j).convert( "List(MatF2){homogeneous}" ); prevector< matrix > Rs = at_codes(j); Integer stop_after = 0; if ( middle.contains( "," ) ) { FETCH( Integer sa, Int ); stop_after = sa; } SLList< matrix > answer; if ( Rs.length == 0 ) FINX( List(MatF2), answer ); uniq_mat_list Ms_can( Rs(0).ncols ); for ( j = 0; j < Rs.length; j++ ) { cerr << "processing matrix " << j+1 << "\n"; prevector< matrix > Ms = extend_residual_code( home, clab, Rs(j), results, stop_after ); for ( i = 0; i < Ms.length; i++ ) if ( Ms_can.add( Ms(i) ) ) answer.append( Ms(i) ); } FINX( List(MatF2), answer ); } // Test for And. static Regex And_pat( "And(" + list_of( "@" + number_pat ) + ")" ); if ( s.contains( And_pat ) ) { FML( And_pat ); middle.del( "And(" ); middle.del( ")", -1 ); prevector args = unpack(middle); prevector vals; if ( args.length > 1 ) { vals.set_size( args.length ); for ( i = 0; i < args.length; i++ ) { j = as_int( args(i).after( "@" ) ); at_codes(j).convert( "Bool" ); vals(i) = at_codes(j); } } else { j = as_int( args(0).after( "@" ) ); at_codes(j).convert( "List(Bool)" ); vals = at_codes(j); } bool answer = true; for ( i = 0; i < vals.length; i++ ) answer &= vals(i); FINX( Bool, answer ); } return false; } set_compile_file(op1.cc) index_method(ee_main) void ee_main( String& s, prevector& at_codes, int& at_count, codetable& results, codehome* home, String& code_label ) { int i, j, k, paren_count; HIDE( ![ static Regex number_pattern( number_pat ); ]! ) bool something_changed = true; while(something_changed) { something_changed = false; if (debug) { cerr << "analyzing expression " << s << "\n"; OSLList printed; for ( i = 0; i < s.length( ); i++ ) if ( s[i] == '@' ) { j = as_int( s.at( number_pattern, i+1 ) ); if ( !printed.contains(j) ) { cerr << "@" << j << " has type " << expand_type( at_codes(j).name, at_codes(j).flags); printed.add(j); if ( at_codes(j).name == "MatF2" ) { matrix M = at_codes(j); cerr << " (" << M.nrows << " x " << M.ncols << ")"; } cerr << "\n"; } } } if ( pmd_atom( s, at_codes, at_count, results, home, code_label ) ) { something_changed = true; continue; } // Test for transforms. (Put here as part of a Bad Kluge.) static String at_pat( "@" + number_pat ); static Regex transform_pat( at_pat + "^Tusing{" + left + list_of( at_pat + orsign + at_pat + "_" + at_pat ) + orsign + list_of( "$" + at_pat ) + ":" + list_of(at_pat) + right + "}" ); if ( s.contains( transform_pat ) ) { FML( transform_pat ); evaluate_transforms( middle, at_codes, at_count ); s = first + "@" + dec(at_count++) + last; continue; } if ( ee_main1( s, at_codes, at_count ) || ee_main2( s, at_codes, at_count ) || ee_main3( s, at_codes, at_count, home, code_label, results ) || ee_mainAI( s, at_codes, at_count, home, code_label, results ) || ee_mainJZ( s, at_codes, at_count, home, code_label, results ) ) { something_changed = true; continue; } // Test for -Int. static Regex minus_int_pat( "-" + at_pat ); if ( s.contains( minus_int_pat ) ) { FML( minus_int_pat ); j = take_int( middle, number_pattern ); if ( at_codes(j).name == "Int" || at_codes(j).name == "PreInt" ) { at_codes(j).convert( "Int" ); Integer I = at_codes(j); FIN( Int, -I ); } else something_changed = false; } // Test for a contractible column complement expression. static Regex minus_pat( "@" + number_pat + "-@" + number_pat ); if ( s.contains( minus_pat ) ) { FML( minus_pat ); FETCH( matrix A1, MatF2 ); FETCH( matrix A2, MatF2 ); if ( A1.nrows != A2.nrows ) ERROR( "Illegal use of column complement operator." ); word w( A1.ncols ); for ( i = 0; i < A1.ncols; i++ ) { for ( j = 0; j < A2.ncols; j++ ) if ( A1.col(i) == A2.col(j) ) break; w(i) = (j == A2.ncols); } FIN( MatF2, A1.select_col(w) ); } // Test for a contractible sharp expression. static Regex sharp_pat( at_pat + "#" + at_pat ); if ( s.contains( sharp_pat ) ) { FML( sharp_pat ); FETCH( matrix A1, MatF2 ); FETCH( matrix A2, MatF2 ); matrix B( A1.nrows + A2.nrows, A1.ncols * A2.ncols ); for ( i = 0; i < A1.nrows; i++ ) for ( j = 0; j < A1.ncols; j++ ) for ( k = 0; k < A2.ncols; k++ ) B( i, A2.ncols * j + k ) = A1(i, j); for ( i = 0; i < A2.nrows; i++ ) for ( j = 0; j < A2.ncols; j++ ) for ( k = 0; k < A1.ncols; k++ ) B( i + A1.nrows, A2.ncols * k + j ) = A2(i, j); FIN( MatF2, B ); } // Test for Length. static Regex Length_pat( "Length(" + at_pat + ")" ); if ( s.contains( Length_pat ) ) { FML( Length_pat ); j = take_int( middle, number_pattern ); prevector L = unlist( at_codes(j) ); FIN( Int, Integer( L.length ) ); } // Test for Orbits. static Regex Orbits_pat( "Orbits(" + at_pat + ")" ); if ( s.contains( Orbits_pat ) ) { FML( Orbits_pat ); int jj = take_int( middle, number_pattern ); bool grouplist = at_codes(jj).name == "List(List(MatF2))" && at_codes(jj).flags.contains( "invertible3" ) && at_codes(jj).flags.contains( "homogeneous2" ); if (grouplist) { prevector< prevector< matrix > > L = at_codes(jj); prevector< prevector< prevector > > ans( L.length ); for ( i = 0; i < L.length; i++ ) ans(i) = orbits( L(i) ); FIN(PVSF2, ans); } else at_codes(jj).convert( "List(MatF2{invertible}){homogeneous}" ); prevector< matrix > L = at_codes(jj); FIN( PVSF2, orbits(L) ); } // Test for P. static Regex P_pat( "P(" + at_pat + ")" ); if ( s.contains( P_pat ) ) { FML( P_pat ); j = take_int( middle, number_pattern ); if ( at_codes(j).name == "MatF2" ) { matrix M = at_codes(j); FIN( MatF2{reduced}, apply_P(M) ); } else if ( at_codes(j).name == "List(MatF2)" ) { prevector< matrix > L = at_codes(j); for ( i = 0; i < L.length; i++ ) L(i) = apply_P( L(i) ); FIN( List(MatF2{reduced}), L ); } else ERROR( "Illegal use of P." ); } // Test for list expression. static Regex list_pat( "{" + list_of(at_pat) + "}" ); if ( s.contains( list_pat ) ) { FML( list_pat ); int r = middle.freq( "@" ); generic_object g[r]; for ( i = 0; i < r; i++ ) g[i] = at_codes( take_int( middle, number_pattern ) ); at_codes(at_count) = generic_object(r, g); s = first + "@" + dec(at_count++) + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); continue; } // Test for deletable parentheses. static Regex paren_pat( "(" + at_pat + ")" ); if ( s.contains( paren_pat ) ) { FML( paren_pat ); middle.del("("); s = first + middle.before( ")" ) + last; continue; } // Test for a "+ check" operator. static Regex check_pat( at_pat + "\\+check" ); if ( s.contains( check_pat ) ) { FML( check_pat ); // What follows is a kluge. We should never allow at_pat // to match if a letter comes before it. if ( first.length( ) > 0 && isalpha(first[first.length( ) - 1]) ) goto not_plus_check; FETCH( matrix B, MatF2 ); matrix Bp = B; Bp.resize( B.nrows, B.ncols+1 ); bool found_odd = false; for ( j = 0; j < B.nrows; j++ ) { if ( odd( B(j).weight( ) ) ) { Bp( j, B.ncols ) = 1; found_odd = true; } } if ( !found_odd ) ERROR( "You are adding a parity check " << "to an even code." ); FIN( MatF2, Bp ); } not_plus_check: // Test for a "- columns" operator. static Regex micols_pat( at_pat + "-columns" + at_pat ); if ( s.contains( micols_pat ) ) { FML( micols_pat ); FETCH( matrix B, MatF2 ); FETCH( vector delsi, List(Int) ); prevector dels(delsi.length); for ( i = 0; i < dels.length; i++ ) dels(i) = int( delsi(i) ); for ( i = 0; i < dels.length; i++ ) { if ( dels(i) > B.ncols ) ERROR( "Illegal use of \"- columns\" operator." ); for ( j = i+1; j < dels.length; j++ ) if ( dels(i) == dels(j) ) ERROR( "Illegal use of \"- columns\" operator." ); } B.delete_columns( dels - number(1) ); FIN( MatF2, B ); } // Test for a "- column" operator. static Regex micol_pat( at_pat + "-column" + number_pat ); if ( s.contains( micol_pat ) ) { FML( micol_pat ); FETCH( matrix B, MatF2 ); int r = take_int( middle, number_pattern ) - 1; if ( r >= B.ncols ) ERROR( "Illegal column number." ); B.delete_column(r); FIN( MatF2, B ); } // Test for a "- column" operator (without column number). static Regex micol_pat0( at_pat + "-column" ); if ( s.contains( micol_pat0 ) ) { FML( micol_pat0 ); pmd_col0( s, first, middle, last, at_codes, at_count ); continue; } // Test for a "~ column" operator. static Regex ticol_pat( at_pat + "~column" + number_pat ); if ( s.contains( ticol_pat ) ) { FML( ticol_pat ); FETCH( matrix B, MatF2 ); int r = take_int( middle, number_pattern ) - 1; if ( r >= B.ncols ) ERROR( "Illegal column number." ); for ( i = 0; i < B.nrows; i++ ) if ( B(i,r) ) break; if ( i == B.nrows ) B.delete_column(r); else { if ( i != B.nrows-1 && !B(B.nrows-1, r) ) B(B.nrows-1) += B(i); for ( i = 0; i < B.nrows-1; i++ ) if ( B(i,r) ) B(i) += B(B.nrows-1); B.resize( B.nrows-1, B.ncols ); B.delete_column(r); } B.reduce_nz( ); FIN( MatF2, B ); } // Test for a "~ column" operator (without column number). static Regex ticoln_pat( at_pat + "~column" ); if ( s.contains( ticoln_pat ) ) { FML( ticoln_pat ); FETCH( prevector< matrix > L, List(MatF2) ); SLList< matrix > Bs; for ( k = 0; k < L.length; k++ ) { matrix B = L(k); for ( int r = 0; r < B.ncols; r++ ) { matrix M = B; for ( i = 0; i < M.nrows; i++ ) if ( M(i,r) ) break; if ( i == M.nrows ) M.delete_column(r); else { if ( i != M.nrows-1 && !M(M.nrows-1, r) ) M(M.nrows-1) += M(i); for ( i = 0; i < M.nrows-1; i++ ) if ( M(i,r) ) M(i) += M(M.nrows-1); M.resize( M.nrows-1, M.ncols ); M.delete_column(r); } M.reduce_nz( ); matrix Bc = canonical_form(M); forPixDef( p, Bs ) if ( Bc == Bs(p) ) break; if ( p == 0 ) Bs.append(Bc); } } FIN( List(MatF2), Bs ); } // Test for a "- dual word of weight" operator. static Regex dualdel_pat( at_pat + "-dualwordofweight" + number_pat ); if ( s.contains( dualdel_pat ) ) { FML( dualdel_pat ); FETCH( prevector< matrix > Bs, List(MatF2){homogeneous} ); int r = take_int( middle, number_pattern ); SLList< matrix > Ms1, Ms2; for ( i = 0; i < Bs.length; i++ ) { matrix B = Bs(i); B.reduce_nz( ); if ( r >= B.ncols ) ERROR( "Illegal dual word weight." ); SLList< vector > L = iso_dual_words_of_given_weight(B,r); forPixDef( p, L ) { matrix M = B; M.delete_columns( L(p) ); M.reduce_nz( ); matrix Mc = canonical_form(M); forPixDef( q, Ms1 ) if ( Mc == Ms1(q) ) break; if ( q == 0 ) { Ms1.append(Mc); Ms2.append(M); } } } if ( Ms2.length( ) == 0 ) ERROR( "There is no dual word of weight " << r << "." ); FIN( List(MatF2{reduced}), Ms2 ); } // Test for a "~ dual word of weight" operator. static Regex dualtilde_pat(at_pat + "~dualwordofweight" + number_pat); if ( s.contains( dualtilde_pat ) ) { FML( dualtilde_pat ); pmd_tilde_dual( s, first, middle, last, at_codes, at_count ); continue; } // Test for a "+ dual word of weight" operator. static Regex dualadd_pat(at_pat + "\\+dualwordofweight" + number_pat); if ( s.contains( dualadd_pat ) ) { FML( dualadd_pat ); FETCH( prevector< matrix > Bs, List(MatF2){homogeneous} ); int r = take_int( middle, number_pattern ); if ( r < 3 || r > 6 ) ERROR( "Illegal use of + dual word of weight operator." ); SLList< matrix > Ms; for ( i = 0; i < Bs.length; i++ ) { Bs(i).reduce_nz( ); SLList< matrix > Ms0 = enlarge_by_dual_word(Bs(i), r); forPixDef( p, Ms0 ) { forPixDef( q, Ms ) if ( isomorphic( Ms0(p), Ms(q) ) ) break; if ( q == 0 ) Ms.append( Ms0(p) ); } } FIN( List(MatF2), Ms ); } // Test for a "+ column" operator. static Regex plcol_pat( at_pat + "\\+column" + number_pat ); if ( s.contains( plcol_pat ) ) { FML( plcol_pat ); FETCH( matrix B, MatF2 ); int r = take_int( middle, number_pattern ) - 1; if ( r >= B.ncols ) ERROR( "Illegal column number." ); matrix Bp( B.nrows, B.ncols+1 ); for ( j = 0; j <= r; j++ ) for ( int l = 0; l < B.nrows; l++ ) Bp(l,j) = B(l,j); for ( j = r; j < B.ncols; j++ ) for ( int l = 0; l < B.nrows; l++ ) Bp(l,j+1) = B(l,j); FIN( MatF2, Bp ); } // Test for transforms. (Again: Bad Kluge.) if ( s.contains( transform_pat ) ) { FML( transform_pat ); evaluate_transforms( middle, at_codes, at_count ); s = first + "@" + dec(at_count++) + last; continue; } // Test for a hcat expression. static Regex hcat_patp( "(" + nontrivial_list_of( "@" + number_pat, "|" ) + ")" ); if( !something_changed && s.contains( hcat_patp ) ) { FML( hcat_patp ); middle.del( '(' ); middle.del( ')' ); prevector MsS = unpack( middle, "|" ); prevector< matrix > Ms( MsS.length ); int maxrows = 0; for ( i = 0; i < Ms.length; i++ ) { int jj = as_int( MsS(i).after( "@" ) ); at_codes(jj).convert( "MatF2" ); Ms(i) = at_codes(jj); maxrows = max( maxrows, Ms(i).nrows ); } matrix B; for ( i = 0; i < Ms.length; i++ ) { if ( Ms(i).nrows != maxrows ) Ms(i).resize( maxrows, Ms(i).ncols ); if ( i == 0 ) B = Ms(0); else { matrix Bnew; hcat( B, Ms(i), Bnew ); B = Bnew; } } at_codes(at_count) = generic_object( "MatF2", B ); s = first + "(@" + dec(at_count++) + ")" + last; if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); continue; } static Regex hcat_pat( "@" + number_pat + "|@" + number_pat ); if( !something_changed && s.contains( hcat_pat ) ) { FML( hcat_pat ); i = take_int( middle, number_pattern ); at_codes(i).convert( "MatF2" ); j = take_int( middle, number_pattern ); at_codes(j).convert( "MatF2" ); matrix A = at_codes(i), B = at_codes(j), C; if ( A.nrows < B.nrows ) A.resize( B.nrows, A.ncols ); if ( B.nrows < A.nrows ) B.resize( A.nrows, B.ncols ); hcat(A, B, C); FIN(MatF2, C); } } } TEX( ![ \verb|evaluate_expression|:\ This routine accepts as input a string, and evaluates it, producing as output an object of some type. A pair is returned, consisting of a string (naming the type) and a pointer to the object. See \S\ref{matrix-descriptor-section} for a list of the output types. A list of source configs (entering into the given expression) is returned as the argument \verb|sources|, assuming that the parameter \verb|:= ! ingredient tracking| is set. ]! ) index_method(evaluate_expression) set_compile_file(op.cc) generic_object evaluate_expression( String s, codetable& results, codehome* home, String& code_label, SLList& sources ) { prevector at_codes(1000); HIDE( ![ static Regex number_pattern( number_pat ); static Regex pos_number_pattern( pos_number ); static Regex pos_list_pattern( pos_list ); static Regex zero_one_pat( "[01]+" ); ]! ) String s_save = s; int at_count = 0; int i, j, k; if ( s.contains('@') ) ERROR( "Syntax error in expression." ); TEX( ![ \begin{quote} Check for balance. \end{quote} ]! ) int paren_count = 0, brack_count = 0; for ( i = 0; i < s.length( ); i++ ) { if ( s[i] == '(' ) paren_count++; else if ( s[i] == ')' ) paren_count--; else if ( s[i] == '{' ) brack_count++; else if ( s[i] == '}' ) brack_count--; if ( paren_count < 0 || brack_count < 0 ) ERROR( "Unbalanced parentheses or curly brackets in " "expression." ); } if ( paren_count != 0 || brack_count != 0 ) ERROR( "Unbalanced parentheses or curly brackets in " << "expression." ); TEX( ![ \begin{quote} Carry out substitutions. \end{quote} ]! ) pmd_subs(s); TEX( ![ \begin{quote} Check for symbols in globals. \end{quote} ]! ) static Regex global_pat( "\\[[a-zA-Z_0-9]+\\.[a-zA-Z_0-9]+\\]" ); static Regex local_pat( "\\[[a-zA-Z_0-9]+\\]" ); String s_new; for ( i = 0; i < s.length( ); i++ ) { if ( s.contains( "[", i ) && ( s.contains( local_pat, i ) || s.contains( global_pat, i ) ) ) { Pix p; String middle; if ( s.contains( local_pat, i ) ) { middle = s.at( local_pat, i ); forPix( p, globals ) { if ( globals(p).first == scope && globals(p).second == middle ) { at_codes(at_count) = globals(p).third; break; } } } else { middle = s.at( global_pat, i ); String scope_name = middle.before( "." ) + "]"; String object_name = "[" + middle.after( "." ); forPix( p, globals ) { if ( globals(p).first == scope_name && globals(p).second == object_name ) { at_codes(at_count) = globals(p).third; break; } } } if ( p == 0 ) { s_new += s[i]; continue; } s_new += String("@") + dec(at_count++); if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); i += middle.length( ) - 1; } else s_new += s[i]; } s = s_new; TEX( ![ \begin{quote} Now process configuration lists. \end{quote} ]! ) static Regex clp( "\\[[a-zA-Z_0-9]+\\.[-*{}a-z.,:A-Z_0-9!]+\\]" ); s_new = ""; for ( i = 0; i < s.length( ); i++ ) { if ( s.contains( clp, i ) && s.contains( "[", i ) ) { String middle = s.at( clp, i ); String middle_save = middle; if ( !middle.contains( "." ) ) ERROR( middle << " doesn't have the correct form." ); String home_name = middle.before( "." ) + "]"; String config_name = "[" + middle.after( "." ); codehome* xhome; if (home != 0 && home_name == code_label) xhome = home; else xhome = results.get_home( home_name, false ); prevector configs; packed_matrix_list Bs; if ( !ingredient_tracking ) { forPixDef( q, xhome->config_lists ) if ( xhome->config_lists(q).title == config_name ) { Bs = xhome->config_lists(q).fetch_all( ); goto save_Bs; } } configs = expand_config_list(xhome, config_name); if ( configs.length == 0 ) ERROR(middle_save << " is a list of zero configurations."); for ( j = 0; j < configs.length; j++ ) { String new_label = juxt( home_name, configs(j) ); if (ingredient_tracking) sources.append( new_label ); matrix B = fetch_known_matrix(new_label, results, home, code_label); if ( B.x == 0 ) ERROR( "I can't identify " << new_label << "." ); if ( j == 0 ) { Bs.first = B.nrows; Bs.second = B.ncols; } else if ( Bs.first != B.nrows || Bs.second != B.ncols ) ERROR( "Inconsistent matrix sizes in " << middle_save << "." ); Bs.third.append( pack(B) ); } save_Bs: at_codes(at_count) = generic_object( "List(MatF2){homogeneous}", Bs ); s_new += String("@") + dec(at_count++); if ( at_count >= at_codes.length ) at_codes.resize( at_codes.length + 1000 ); i += middle_save.length( ) - 1; } else s_new += s[i]; } s = s_new; TEX( ![ \begin{quote} Expand generalized {\tt Choose} expressions. \end{quote} ]! ) s_new = ""; static Regex gen_Choose_pat( "Choose(" + number_pat + ",{" + nontrivial_list_of( number_pat ) + "})" ); for ( i = 0; i < s.length( ); i++ ) { if ( s.contains("Ch", i) && s.contains(gen_Choose_pat, i) ) { String t = s.at( gen_Choose_pat, i ); String t2 = t.after( "Choose(" ); int n = take_int( t2, number_pattern ); t2.del( ",{" ); t2.del( "})" ); s_new += "("; prevector ks( t2 ); for ( j = 0; j < ks.length; j++ ) { if ( j > 0 ) s_new += "|"; s_new += String("Choose(") + dec(n) + "," + dec(int(ks(j))) + ")"; } s_new += ")"; i += t.length( ) - 1; } else s_new += s[i]; } s = s_new; ee_main( s, at_codes, at_count, results, home, code_label ); while(1) { if ( s.length( ) >= 3 && s[0] == '(' && s[ s.length( ) - 1 ] == ')' ) { s.del( "(", 0 ); s.del( ")", -1 ); } else break; } static Regex final_pat( "@" + number_pat ); if ( !s.matches (final_pat) ) ERROR("Syntax error in expression."); return at_codes( as_int( s.after( "@" ) ) ); } TEX( \block{Routines invoked by main program to execute particular commands} ) set_compile_file(execute1.cc) HIDE( ![ ifelse(UNAME,Openstep,![#include ]!) #include #include #include #include "homedefs.h" #include "state.h" #include "bitvec.h" #include "codetable.h" #include "opt.h" typedef triple< int, int, OSLList< vector > > packed_matrix_list; matrix unpack(char*, int, int); vector pack(matrix); #include "generic.h" extern int warnings_are_fatal, auto_group_computation, try_to_kill_vocal, ingredient_tracking, try_to_kill_maxvars, auto_analyze_local_relations, via_lp_quiet, show_quiet, show_config_creation, verify_feasibility; extern int cplex_verification_failure_accepted; Integer round_down_to_power_of_2(Integer); Integer round_up_to_power_of_2(Integer); void log2(const Integer&, Integer&, Integer&); int min_distance(const matrix&, int); prevector< matrix > joint_we(const config_core&); String make_j_var(int, int, int); void sort_by_secondy( prevector< pair< int, vector > >& ); matrix canonical_form(matrix); Integer*** make_krawtchouk(int); void parse_j_var(String, int&, int&, int&); void joint_to_qv(constraint, qvconstraint&, const prevector&, Pix, codehome&, Integer ***); int yno(String); inline bool test(const Rational& a, const Rational& b, char sense) { if ( sense == '=' ) return a == b; if ( sense == '<' ) return a <= b; return a >= b; } bool joint_infeasible(codehome&, codetable&, constraintlist = constraintlist( )); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); prevector expand_config_list(codehome*, String); bool is_zero_one_matrix(const String&, bool = false); generic_object evaluate_expression(String, codetable&, codehome*, String&, SLList&); void execute_config_command(String, String, codehome*, bool, codetable&, constraintlist, String); matrix fetch_known_matrix(String, const codetable&, codehome*, String&); void execute_bound(codehome*, String, codetable&); void execute_round_local(codehome*, codetable&); extern constraintlist input_mask; long size_of_file(String); int take_int(String&, const Regex&); extern String config_list, label_pat, gen_label_pat, var; void execute_find_cyclic_codes(codehome*, int, codetable&); void execute_kill_variable_by(codehome*, prevector, bool, codetable&); void execute_via_varying(String, prevector, codehome*, bool, codetable&); void execute_macaulay(const matrix&); void execute_up_to_isomorphism_show(codehome*, String, bool, codetable&); String list_of(const String&, const String& = ","); void reformat_constraintlist(constraintlist, prevector&, prevector< pair >&); bool check(const constraint&, const vector&, const config_core&, int, const weightlist&); void set_numerical_parameter(const String&, const String&, const String&); ostream& operator<<(ostream&, const prevector&); ostream& operator<<(ostream&, const prevector&); static Regex alphanumericu( "[a-zA-Z0-9_]*" ); ]! ) TEX( ![ For an $[n,k,w]$ code with $\verb|low| \leq \verb|div4| \leq \verb|high|$, modify \verb|low| and \verb|high| to reflect a stronger statement about \verb|div4| that can be made. If it is found that there is no code, return some (meaningless) values for \verb|low| and \verb|high| with the property that $\verb|low| > \verb|high|$. ]! ) index_method(round_div4) void round_div4( Integer& low, Integer& high, int n, int k, const config& c, codetable& results ) { weightlist w = c.share->ww; bool maybe_even = true, maybe_odd = true; if ( w.divisible(2) ) maybe_odd = false; else { forPixDef( p, w ) if ( odd( w(p) ) && c.known( String("y") + dec(w(p)) + ">=1" ) ) { maybe_even = false; break; } if ( c.known( String("div2<") + dec(Ipow(2,k)) ) ) maybe_even = false; } w.make_divisible(4); // Find the smallest r for which we know that there is no // doubly even subcode of dimension r. int r = min( k, results.max_dim_of_code(n, w) ) + 1; // Make a list of the possible values for div4, not taking // into account low and high yet. OSLList possible, possible2; for ( int j = 0; j < 2; j++ ) { if ( j == 0 && !maybe_even ) continue; if ( j == 1 ) { if ( !maybe_odd ) continue; k--; } for ( int i = r - 1; i >= (k-1)/2; i-- ) { Integer candidate = Ipow(2, k-1) - Ipow(2, i); if ( candidate > 0 ) possible.add(candidate); } possible.add( Ipow(2, k-1) ); for ( int i = (k-1)/2; i <= r - 2; i++ ) possible.add( Ipow(2, k-1) + Ipow(2, i) ); } // Use the list to improve low and high. forPixDef( p, possible ) if ( possible(p) >= low && possible(p) <= high ) possible2.add( possible(p) ); if ( possible2.empty( ) ) { low = 1; high = 0; } else { low = possible2.Min( ); high = possible2.Max( ); } } index_method(round_variable) void round_variable( String var, Integer& low, Integer& high, int n, int k, const config& c, codetable& results ) { weightlist& w = c.share->ww; if ( var == "div4" ) round_div4( low, high, n, k, c, results ); else if ( var == "div2" ) { low = max( Ipow(2, k-1), low ); high = min( Ipow(2, k), high ); if ( low > Ipow(2, k-1) ) low = max( low, Ipow(2, k) ); if ( high < Ipow(2, k) ) high = min( high, Ipow(2, k-1) ); } else if ( var == "co" ) { if ( low == 0 ) low = 1; Integer ll, lh, hl, hh; log2( low, ll, lh ); log2( high, hl, hh ); if ( w.divisible(2) ) { if ( even(k) && odd(lh) ) ++lh; if ( odd(k) && even(lh) ) ++lh; if ( even(k) && odd(hl) ) --hl; if ( odd(k) && even(hl) ) --hl; } low = Ipow(2, lh); high = Ipow(2, hl); } } index_command(infer) void execute_infer_command(codehome* home, config& cur, constraint c, codetable& results, bool gullible) { static Regex subword( "sub[01]*" ); if (gullible) { forPixDef( q, c.LHS ) cur.check_variable( c.LHS(q).var ); } String variable; // The following line // if (gullible) goto infer_ok; // resulted in strange and somewhat unpredictable errors. I think the // problem resulted from a compiler error which had something to do with // jumping over variable definitions. (Perhaps I was being punished for // using the evil goto statement.) In any case I circumvented the problem // by eliminating the jump, as accomplished by the following line: if (!gullible) { if ( !c.simple( ) ) ERROR("Incorrect syntax."); variable = c.LHS.front( ).var; cur.check_variable(variable); Pix p, q; Integer l = 0; Integer h = -1; cur.evaluate(variable, l, h); Integer l_save = l, h_save = h; OSLList badvals; forPix( p, home->configs.vertices ) { config& d = home->configs(p); if ( d.share->realizable == -1 && mostly_equal(home->configs(home->current), d) ) { SLList unknowns; forPix( q, d.assumed_cons ) if ( !cur.known( d.assumed_cons(q) ) ) unknowns.append( d.assumed_cons(q) ); if ( unknowns.length( ) != 1 ) continue; constraint& cp = unknowns.front( ); if ( !cp.simple( ) || cp.LHS.front( ).var != variable ) continue; if ( cp.sense == '=' ) badvals.add( cp.RHS ); else if ( cp.sense == '>' ) h = (h == -1) ? cp.RHS - 1 : min( h, cp.RHS - 1 ); else if ( cp.sense == '<' ) l = max(l, cp.RHS + 1); } } weightlist w = cur.share->ww; while(1) { if ( badvals.contains(l) ) ++l; else if ( badvals.contains(h) ) --h; else break; } round_variable( variable, l, h, home->n, home->dim, cur, results ); bool nan; if ( c.sense == '<' && h <= c.RHS ) goto infer_ok; if ( c.sense == '>' && l >= c.RHS ) goto infer_ok; if ( c.sense == '=' && h == c.RHS && l == c.RHS ) goto infer_ok; if ( l != l_save ) cur.add_constraint( variable + ">=" + dec(l), results, nan ); if ( h != h_save ) cur.add_constraint( variable + "<=" + dec(h), results, nan ); if ( variable[0] == 'm' && c.sense == '=' && c.RHS == 0 ) { int dp = as_int( variable.after("mu") ); String cf = String(dec(home->n - dp)) + "," + dec(dp) + "::{01}"; Pix i = home->configs.find( config( home, cf ) ); if ( i == 0 || home->configs(i).share->realizable != -1 ) ERROR("The configuration " << cf << " must be unrealizable."); goto infer_ok; } if ( variable[0] == 'y' && c.sense == '=' && c.RHS == 0 ) { int i = yno(variable); forPixDef( p, home->configs ) { config& cf = home->configs(p); int n = home->n; if (i == n && !(cf.part.length == 1)) continue; if (i < n && !(cf.part.length == 2 && cf.part(0) == i)) continue; if ( cf.small.basis.nrows != 1 ) continue; if ( i < n && !(cf.small.basis(0,1).x == 0) ) continue; if ( cf.dualsmall.basis.nrows != 0 ) continue; forPixDef( q, cf.assumed_cons ) { if ( !cf.assumed_cons(q).joint( ) ) break; if ( !cur.known( cf.assumed_cons(q) ) ) break; } if ( q != 0 ) continue; goto infer_ok; } } if ( variable == "div8" && c.sense == '=' && c.RHS == Ipow(2, home->dim) ) { if ( cur.known( String("div8>") + dec(Ipow(2, home->dim) - Ipow(2, home->dim - 3)) ) ) goto infer_ok; } if ( variable[0] == 'y' && c.sense == '>' && c.RHS == 1 ) { if ( cur.share->ww.length( ) >= 3 ) { if ( cur.share->ww.min( ) == yno(variable) && codebase( home->n, home->dim, cur.share->ww.element(2) ).griesmer( ) > home->n ) goto infer_ok; } } if ( variable[0] == 'y' && c.sense == '>' ) { constraintlist cl = cur.known_cons( ); forPixDef( p, cl ) { constraint& cn = cl(p); if ( cn.simple( ) && cn.LHS.front( ).var[0] == 's' && cn.sense != '<' && cn.RHS >= c.RHS ) { String var = cn.LHS.front( ).var.after( subword ); if ( var == "" ) continue; int i_in_sub_var = as_int( var.after("_") ); if ( yno(variable) == i_in_sub_var ) goto infer_ok; } } } if ( variable[0] == 'x' && cur.small.basis.nrows < home->dim ) { wordtype w( &cur, variable ); home->activate(false, results); if ( c.sense == '=' && c.RHS == 0 ) { p = subdivide( home->configs(home->current), w, results ); if ( home->configs(p).share->realizable == -1 ) goto infer_ok; } if ( c.sense == '>' ) { ShareGraph& cs = home->configs; forPix( q, cs ) { SLList ed = cs.edges[ make_pair( home->current, q) ]; forPixDef( r, ed ) { wordtype& edge = ed(r); forPixDef( s, cs(q).con ) { constraint& x = cs(q).con(s); if ( !(x.simple_local( ) && x.sense != '<' && x.RHS >= c.RHS) ) continue; wordtype v( &cs(q), x.LHS.front( ).var ); if ( is_pullback( v, w, edge ) ) goto infer_ok; } } } } } if ( variable[0] == 's' ) { vector wd = prevector(variable.after("sub"),0); int wt = wd * cur.part; // "length" of subcode if ( cur.small.basis.rowspace_member(wd) && !wd.if_zero( ) && wt < 2 * cur.share->ww.min( ) && c.sense == '=' && c.RHS == 2 ) goto infer_ok; int low_dim = home->dim - (home->n - wt); // Check to see if the variable represents the number of // words disjoint from a dual word. vector wdp = wd.complement( ); if ( cur.dualsmall.basis.rowspace_member(wdp) ) low_dim++; Integer low = Ipow(2, max(0, low_dim) ); // Use nonexistence of subcodes to get an upper bound on // the variable. Integer high = Ipow(2, results.max_dim_of_code(wt, cur.share->ww) ); // Take into account known constraints. cur.evaluate(variable, low, high); low = round_up_to_power_of_2( low ); high = round_down_to_power_of_2( high ); // Now decide if the constraint really can be inferred. if ( test( Rational(low), c.RHS, c.sense ) && test( Rational(high), c.RHS, c.sense ) ) goto infer_ok; } ERROR("Constraint " << c << " cannot be inferred."); } infer_ok: bool new_active_needed = false; cur.add_constraint(c, results, new_active_needed); if (new_active_needed) home->deactivate( ); } index_command(kill) void execute_kill_variable_by( codehome* home, prevector vars, bool gullible, codetable& results ) { Pix curp = home->current; if ( curp == 0 ) ERROR("The current configuration is undefined."); config& c = home->configs(curp); if ( c.share->realizable == -1 ) ERROR( "You are trying to execute a kill command from an " << "unrealizable configuration." ); bool nan; // not really used // Deal with the gullible case. if (gullible) { for ( int j = 0; j < vars.length; j++ ) { String var = vars(j); if ( var.contains( "by" ) ) var = var.before( "by" ); if ( var == "ndiv4" ) home->ww(curp).make_divisible(4); else if ( var == "ndiv8" ) home->ww(curp).make_divisible(8); else if ( var[0] == '[' ) home->set_unrealizable(home->label_to_Pix(var, results)); else { c.check_variable(var); c.add_constraint( var + "=0", results, nan ); } } home->deactivate( ); return; } // Look for variables of the form "yr" or "yr by ...". These can be // converted into one or more of the other variables. HIDE( ![ static Regex gen_label_pattern( gen_label_pat ); ]! ) home->activate(false, results); SLList varsx; for ( int j = 0; j < vars.length; j++ ) { String v = vars(j); if ( v.contains( "by" ) ) v = v.before( "by" ); if ( v.matches( gen_label_pattern ) ) { varsx.append( vars(j) ); continue; } if ( v == "ndiv4" || v == "ndiv8" ) { varsx.append( vars(j) ); continue; } c.check_variable(v); if ( c.known( v + "=0" ) ) { WARNING( "I already know that " << v << " = 0." ); continue; } if ( v[0] == 'y' ) { String tail; if ( vars(j).contains("by") ) tail = "by" + vars(j).after("by"); int w = yno(v); SLList to_kill = home->active->vtable.has_member_of_weight(w); if ( to_kill.length( ) == 0 ) WARNING( "There are no admissible basic local " << "variables of weight " << w << "." ); forPixDef( p, to_kill ) varsx.append( to_kill(p).variable( ) + tail ); } else varsx.append( vars(j) ); } vars = varsx; // Cycle through the variables and kill them. for ( int j = 0; j < vars.length; j++ ) { bool done = false; home->set_current(curp); home->activate(false, results); // Check for variable = ndiv4 or ndiv8. These cases are // dispensed with quickly. for ( int ii = 2; ii <= 3; ii++ ) { int divx = Ipow( 2, ii ); int divxm = Ipow( 2, ii-1 ); if ( vars(j) == String("ndiv") + dec(divx) ) { if ( !home->ww(curp).divisible(divxm) ) { WARNING( "I don't know that all words have " << "weight divisible by " << divxm << "." ); done = true; break; } if ( home->ww(curp).divisible(divx) ) { WARNING( "I already know that all words have " << "weight divisible by " << divx << "." ); done = true; break; } Integer low = Ipow(2, home->dim) - Ipow(2, home->dim - ii); if ( !home->show( String("div") + divx + ">" + dec(low), results ) ) { WARNING( String("I couldn't kill ndiv") + divx + "." ); } else home->ww(curp).make_divisible(divx); done = true; break; } } if (done) { home->set_current(curp); continue; } // Determine the variable and config to be killed. HIDE( ![ static Regex basic_joint_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); ]! ) static Regex co_pattern( "co" + number_pat ); String v = vars(j); if ( v.contains( "by" ) ) v = v.before( "by" ); String kns; // known constraints (if needed) if ( v[0] == 'j' || v[0] == 'c' ) { constraintlist kn = c.share->ycon; forPixDef( p, home->ww(home->base) ) { int w = home->ww(home->base)(p); if ( !home->ww(curp).contains(w) ) kn.merge( constraint(String("y") + dec(w) + "=0") ); } kns = "{" + String(kn) + "}"; kns.gsub( " ", "" ); } if ( v[0] == 'x' ) { wordtype wt( &c, v ); if ( !home->active->vtable.admissible(wt) ) { WARNING( "The basic local variable " << v << " is not " << "admissible. So trying to kill it is pointless." ); home->set_current(curp); continue; } home->set_current( subdivide( c, wt, results ) ); } else if ( v.matches( basic_joint_pattern ) ) { int r, s, t; parse_j_var( v, r, s, t ); int a = (r + t - s)/2, b = (r + s - t)/2, c = (s + t - r)/2; int d = home->n - a - b - c; if ( a == 0 || b == 0 || c == 0 ) ERROR( "kill " << v << " is silly. Kill the " << "corresponding global variable instead." ); kns.gsub( " ", "" ); if ( d == 0 ) home->set_config( String(dec(a)) + "," + dec(b) + "," + dec(c) + ":{110,011}::" + kns, results ); else home->set_config( String(dec(a)) + "," + dec(b) + "," + dec(c) + "," + dec(d) + ":{1100,0110}::" + kns, results ); } else if ( v.matches( co_pattern ) ) { int r = as_int( v.after( "co" ) ); if ( r == 0 ) ERROR( "You can't kill co0." ); if ( r == home->n ) home->set_config( String(dec(home->n)) + ":{1}:{1}:" + kns, results ); else home->set_config( String(dec(r)) + "," + dec(home->n - r) + ":{10}:{10}:" + kns, results ); } else if ( v.matches( gen_label_pattern ) ) { Pix kp = home->label_to_Pix(v, results); home->set_current(kp); } else { WARNING( "I don't know how to kill a variable of the form " << v << "." ); home->set_current(curp); continue; } Pix startp = home->current; if ( home->configs(home->current).share->realizable == -1 ) { if ( v.matches( gen_label_pattern ) ) WARNING( "You don't need to kill " << v << ". It is already dead." ) else c.add_constraint( v + "=0", results, nan ); home->set_current(curp); continue; } home->configs(home->current).check_secondary_residuals( results ); if ( home->active == 0 ) home->activate(false, results); if ( !vars(j).contains( "by" ) ) { if ( !home->contradiction(true, results, true) ) { WARNING( "I couldn't kill " << v << "." ); home->set_current(curp); continue; } } else { prevector lvs; bool alt_list = vars(j).contains( "," ); vars(j) = vars(j).after("by"); vars(j).gsub( "(", 0 ); vars(j).gsub( ")", 0 ); lvs = unpack( vars(j), (alt_list ? "," : "|") ); if ( lvs.length == 1 ) alt_list = true; if ( lvs.length == 0 ) ERROR( "Invalid use of kill command." ); config& d = home->configs(home->current); if ( d.share->realizable == -1 ) { WARNING( "You could use simply \"kill " << v << "\"." ); c.add_constraint( v + "=0", results, nan ); home->set_current(curp); continue; } int i; if (alt_list) { d.check_secondary_residuals(results); for ( i = 0; i < lvs.length; i++ ) { d.check_variable(lvs(i)); if ( lvs(i)[0] != 'x' ) ERROR( lvs(i) << " is not a basic local variable." ); wordtype wx( &d, lvs(i) ); Pix ppp = home->current; home->activate(false, results); if ( !home->active->vtable.admissible(wx) ) { WARNING( "The basic local variable " << lvs(i) << " is not admissible. So you may as well " << "remove it from your kill command." ); continue; } home->set_current( subdivide( d, wx, results ) ); config& e = home->configs(home->current); if ( !(e.share->realizable == -1) ) { e.check_secondary_residuals(results); if ( !home->contradiction(false, results, true) ) { WARNING( "Kill of " << v << " failed at " << "step " << lvs(i) << "." ); break; } } home->set_current(ppp); home->configs(ppp).add_constraint( lvs(i) + "=0", results, nan ); } if ( i < lvs.length ) { home->set_current(curp); continue; } if ( !home->contradiction(false, results, true) ) { WARNING( "Kill of " << v << " failed at final step." ); home->set_current(curp); continue; } } else { home->set_current(startp); for ( i = 0; i < lvs.length; i++ ) { config& e = home->configs(home->current); if ( e.share->realizable == -1 ) { c.add_constraint( v + "=0", results, nan ); break; } e.check_secondary_residuals(results); e.check_variable(lvs(i)); if ( lvs(i)[0] != 'x' ) ERROR( lvs(i) << " is not a basic local variable." ); wordtype wx( &e, lvs(i) ); if ( !home->show( lvs(i) + "!=0", results ) ) { WARNING( "I couldn't show that " << lvs(i) << " is nonzero." ); break; } home->activate(false, results); home->set_current( subdivide( e, wx, results ) ); } if ( i < lvs.length ) { home->set_current(curp); continue; } if (!(home->configs(home->current).share->realizable == -1)) { home->configs(home->current). check_secondary_residuals(results); if ( !home->contradiction(false, results, true) ) { WARNING( "Kill of " << v << " failed at last step." ); home->set_current(curp); continue; } } } } home->set_current(curp); if ( v.matches( gen_label_pattern ) ) home->set_unrealizable( home->label_to_Pix(v, results) ); else c.add_constraint( v + "=0", results, nan ); home->set_current(curp); } home->deactivate( ); } HIDE( ![ constraint translate(const config&, const constraint&, const String&, int, int, bool = false); ]! ) TEX( Note that the following code for {\tt incorporate} does not activate any configuration. ) index_command(incorporate) void execute_incorporate_command( codehome* home, String code_label, String label1, String label2, String label3, String sub_var, Pix pix2, Pix pix3, codetable& results, bool gullible ) { if ( home->incorporate_labels.contains(label1) ) ERROR( "You can't use the same label for two incorporate " << "statements within a given code type." ); home->incorporate_labels.append( label1 ); codehome* sub_home = results.open(pix2); if ( sub_home->opt.dual_may_be_code_of_design || sub_home->opt.partition_of_word_by_dual_words || (sub_home->opt.doubly_even_part_is_subcode && !home->opt.doubly_even_part_is_subcode) || (sub_home->opt.maybe_subcode_of != home->opt.maybe_subcode_of && sub_home->opt.maybe_subcode_of != code_label) ) ERROR("Illegal use of type options."); config& c = home->configs(pix3); vector sub_word(sub_var, 0); if ( sub_word.length != c.part.length ) ERROR("Variable sub" << sub_var << " is not compatible with configuration."); Pix p, q; int i, j; if ( sub_word * c.part != sub_home->n ) ERROR("The length of code type " << label2 << " is not compatible with the variable sub" << sub_var << "."); constraint sub_con("sub" + sub_var + ">=" + dec(Ipow(2, sub_home->dim))); constraint sub_conx("sub" + sub_var + "=" + dec(Ipow(2, sub_home->dim))); forPix( p, c.assumed_cons ) { if ( !c.assumed_cons(p).global( ) && c.assumed_cons(p) != sub_con && c.assumed_cons(p) != sub_conx ) ERROR( "The configuration " << label3 << " has an illegal assumed constraint." ); } if ( !c.known( sub_con ) ) execute_infer_command(home, c, sub_con, results, false); if ( sub_word.weight( ) != 1 ) ERROR("The word " << sub_var << " must have weight one."); if ( !gullible ) { forPix( p, home->ww(pix3) ) { int we = home->ww(pix3)(p); if ( we <= sub_home->n && !sub_home->w.contains(we) ) WARNING( "The weight " << we << " should be in the weight" << " list for " << label2 << "." ); } } config_core sub_core( sub_home->configs(sub_home->base) ); forPix( p, sub_home->assumed_cons ) { constraint cn = sub_home->assumed_cons(p); static Regex j_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); if ( !cn.local( ) ) { if ( cn.simple( ) && cn.sense == '=' && cn.RHS == 0 && cn.LHS.front( ).var.matches(j_pattern) && c.known(cn) ) continue; else ERROR( "The assumed constraints of " << label2 << " cannot in general have joint variables in them." ); } if ( c.small.basis.rowspace_member( sub_word ) && constraintlist(cn) == constraintlist( String("y") + dec(sub_home->n) + "=1" ) ) continue; term_sum tx = sub_core.simplify_global_vars( cn.LHS, sub_home->ww(sub_home->base), sub_home->dim ); constraint cnew( cn.sense, cn.RHS ); forPix( q, tx ) { String va = "x" + sub_var; va.gsub("0", "_0"); va.gsub( "1", String("_") + dec( yno( tx(q).var ) ) ); cnew.addterm( tx(q).coeff, va ); } if ( !c.known( cnew ) ) { if ( !home->show( cnew, results, true ) ) WARNING( "Since " << cn << " is an assumed constraint for " << label2 << ", " << cnew << " must be known for " << label3 << "." ); } } TEX(![ \begin{quote} Merge in the configurations from the subcode. We keep track of the \verb|config_share| objects by constructing a temporary table which contains pairs consisting of a pointer to the old share object and a pointer to a new share object. Similarly, we make such a table for the {\tt config} objects. \end{quote} ]!) // Make real the config_lists_on_disk for subhome. forPix( p, sub_home->config_lists ) { config_list_on_disk& cfd = sub_home->config_lists(p); String title_head = cfd.title.before( '1' ); for ( i = 1; i <= cfd.count; i++ ) sub_home->label_to_Pix( title_head + dec(i) + "]", results ); } int insertion_point = sub_word.find(1); SLList< pair > share_dictionary; Map< Pix, Pix > config_dictionary; forPix( p, sub_home->configs ) { config& cs = sub_home->configs(p); if ( !cs.assumed_cons.local( ) ) ERROR( "The assumed constraints " << " of the configurations of " << label2 << " may not have joint " << "variables in their assumed constraints." ); int new_length = c.part.length + cs.part.length - 1; config cnew; cnew.home = home; forPixDef( pp, c.assumed_cons ) if ( c.assumed_cons(pp).joint( ) ) cnew.assumed_cons.append( c.assumed_cons(pp) ); // Make the new sub variable. String sub_var2 = replicate( "0", insertion_point ) + replicate( "1", cs.part.length ) + replicate( "0", c.part.length - insertion_point - 1 ); TEX( ![ \begin{quotea} If the {\tt share} object associated to {\tt cs} is not already in the share dictionary, create a new {\tt share} object, and add a dictionary entry. \end{quotea} ]! ) forPix( q, share_dictionary ) if ( share_dictionary(q).first == cs.share ) break; if ( q != 0 ) cnew.share = share_dictionary(q).second; else { config_share* cshare = new config_share; cnew.share = cshare; share_dictionary.append( make_pair(cs.share, cshare) ); TEX( ![ \begin{quoteb} Build the new share object. Unrealizability can be copied, but not realizability. \end{quoteb} ]! ) cshare->realizable = (cs.share->realizable == -1) ? -1 : 0; cshare->ww = c.share->ww; cshare->dual_min_low = c.share->dual_min_low; cshare->dual_min_high = c.share->dual_min_high; } TEX(![ \begin{quotea} If the working weightlist for \verb|c.share| has entries which are not in \verb|cs.share|, these are translated into constraints. Then we copy the working weightlist for \verb|cs.share|. \end{quotea} ]!) forPix( q, c.share->ww ) { if ( c.share->ww(q) > sub_home->n ) break; if ( !cs.share->ww.contains( c.share->ww(q) ) ) cnew.con.append( "sub" + sub_var2 + "_" + dec(c.share->ww(q)) + "=0" ); } // Translate dual_min_low and dual_min_high into constraints. for ( i = 1; i < cs.share->dual_min_low; i++ ) cnew.con.append( translate ( cs, String("mu") + dec(i) + "=0", sub_var2, c.part.length, insertion_point ) ); if ( cs.share->dual_min_high != sub_home->n ) { constraint woof( '>', 1 ); for ( i = cs.share->dual_min_low; i <= cs.share->dual_min_high; i++ ) woof.addterm( 1, String("mu") + dec(i) ); cnew.con.append( translate ( cs, woof, sub_var2, c.part.length, insertion_point ) ); } // Translate known constraints in share. forPix( q, cs.share->ycon ) { if ( cs.share->ycon.local( ) ) cnew.con.append( translate ( cs, cs.share->ycon(q), sub_var2, c.part.length, insertion_point ) ); } // Make the new partition. cnew.part = partition(new_length); cnew.part.n = home->n; for ( i = 0; i < insertion_point; i++ ) cnew.part(i) = c.part(i); for ( i = 0; i < cs.part.length; i++ ) cnew.part( insertion_point + i ) = cs.part(i); for ( i = insertion_point + 1; i < c.part.length; i++ ) cnew.part( cs.part.length + i - 1 ) = c.part(i); // Make the new small basis. cnew.small.basis = matrix( c.small.basis.nrows + cs.small.basis.nrows, new_length ); for ( i = 0; i < c.small.basis.nrows; i++ ) { for ( j = 0; j < insertion_point; j++ ) cnew.small.basis(i, j) = c.small.basis(i, j); for ( j = 0; j < cs.part.length; j++ ) cnew.small.basis(i, insertion_point + j) = c.small.basis(i, insertion_point); for ( j = insertion_point + 1; j < c.part.length; j++ ) cnew.small.basis(i, cs.part.length + j - 1 ) = c.small.basis(i, j); } for ( i = 0; i < cs.small.basis.nrows; i++ ) { for ( j = 0; j < insertion_point; j++ ) cnew.small.basis(i + c.small.basis.nrows, j) = 0; for ( j = 0; j < cs.part.length; j++ ) cnew.small.basis(i + c.small.basis.nrows, insertion_point + j) = cs.small.basis(i, j); for ( j = insertion_point + 1; j < c.part.length; j++ ) cnew.small.basis(i + c.small.basis.nrows, cs.part.length + j - 1 ) = 0; } cnew.small.basis.reduce_nz( ); cnew.leading1s = cnew.small.basis.leading_ones( ); // Make the new dual small basis. // Erasing "= matrix" makes program bomb. cnew.dualsmall.basis = matrix(c.dualsmall.basis.nrows, new_length ); for ( i = 0; i < c.dualsmall.basis.nrows; i++ ) { for ( j = 0; j < insertion_point; j++ ) cnew.dualsmall.basis(i, j) = c.dualsmall.basis(i, j); for ( j = 0; j < cs.part.length; j++ ) cnew.dualsmall.basis(i, insertion_point + j) = c.dualsmall.basis(i, insertion_point); for ( j = insertion_point + 1; j < c.part.length; j++ ) cnew.dualsmall.basis(i, cs.part.length + j - 1 ) = c.dualsmall.basis(i, j); } // Convert dual small basis info into assumed constraints. for ( i = 0; i < cs.dualsmall.basis.nrows; i++ ) { String dual_con[new_length + 1]; dual_con[0] = "q"; for ( j = 1; j <= new_length; j++ ) dual_con[j] = "_z"; for ( j = 0; j < cs.part.length; j++ ) dual_con[insertion_point + j + 1] = String("_") + dec( cs.dualsmall.basis(i,j).x ? cs.part(j).x : 0 ); String dc; for ( j = 0; j <= new_length; j++ ) dc += dual_con[j]; cnew.assumed_cons.append( constraint( dc + "=" + dec(Ipow(2, sub_home->dim)) )); } // Translate constraints. forPixDef( ppp, cs.assumed_cons ) { if ( cs.assumed_cons(ppp).local( ) ) cnew.assumed_cons.append(translate(cs, cs.assumed_cons(ppp), sub_var2, c.part.length, insertion_point, true)); } forPix( ppp, cs.con ) { if ( cs.con(ppp).local( ) ) cnew.con.append( translate( cs, cs.con(ppp), sub_var2, c.part.length, insertion_point ) ); } // Translate automorphisms. for ( i = 0; i < cs.aut.length; i++ ) { Permutation per(cnew.part.length); for ( j = 0; j < cs.part.length; j++ ) per( j + insertion_point ) = cs.aut(i)(j) + insertion_point; cnew.aut.append(per); } // Copy automorphism labels. cnew.auto_labels = cs.auto_labels; // Merge the new configuration into the ShareGraph. q = home->configs.vertices.append( cnew ); config_dictionary[p] = q; } TEX( \begin{quote} Translate the configuration labels. \end{quote} ) forPix( p, sub_home->labels ) { String new_label = label1 + "->" + sub_home->labels(p).first; new_label.gsub("[", 0); new_label.gsub("]", 0); home->labels.append( make_pair( "[" + new_label + "]", config_dictionary[ sub_home->labels(p).second ] ) ); } TEX( \begin{quote} Translate the {\tt ShareGraph} edges. Add a logical edge from c to the base configuration of the subcode. \end{quote} ) forPix( p, sub_home->configs.edges ) { Pix p1 = sub_home->configs.edges(p).first; config& c1_old = sub_home->configs(p1); Pix p2 = sub_home->configs.edges(p).second; Pix q1 = config_dictionary[p1]; Pix q2 = config_dictionary[p2]; SLList new_edges; config& c1 = home->configs(q1); SLList& wl = sub_home->configs.edges.take(p); forPixDef( pp, wl ) { // Make constructive edge. wordtype w(&c1); for ( int jj = 0; jj < c1_old.part.length; jj++ ) w(insertion_point + jj) = wl(pp)(jj); new_edges.append(w); } home->configs.edges[ make_pair( q1, q2 ) ] = new_edges; } home->configs.join( pix3, config_dictionary[ sub_home->base ] ); TEX( \begin{quote} Translate the {\tt implications} and {\tt disjoint} members of the subcode. \end{quote} ) forPix( p, sub_home->implications ) { pair< Pix, SLList > imp = sub_home->implications(p); imp.first = config_dictionary[ imp.first ]; forPixDef( pp, imp.second ) imp.second(pp) = config_dictionary[ imp.second(pp) ]; home->implications.append( imp ); } forPix( p, sub_home->implications2 ) { pair imp2 = sub_home->implications2(p); imp2.first = label1 + imp2.first; imp2.first.gsub( "][", "->" ); imp2.second = label1 + imp2.second; imp2.second.gsub( "][", "->" ); home->implications2.append( imp2 ); } forPix( p, sub_home->disjoint ) { pair< Pix, Pix > dis = sub_home->disjoint(p); dis.first = config_dictionary[ dis.first ]; dis.second = config_dictionary[ dis.second ]; home->disjoint.append(dis); } } index_method(pixcmp) int pixcmp(const Pix& a, const Pix& b) { return int(a) - int(b); } TEX( ![ \verb|execute_deduce|:\ Given configurations \mconfig and \lconfigs for a given codehome \verb|home|, show that the realization of \mconfig equals the union of the realizations of \lconfigs. ]! ) index_method(execute_deduce) String execute_deduce( codehome* home, String& mlabel, prevector& labels, bool gullible, const codetable& results, bool finish ) { int i, j; Pix mpix = home->label_to_Pix(mlabel, results); prevector pixes(labels.length); for ( i = 0; i < labels.length; i++ ) pixes(i) = home->label_to_Pix(labels(i), results); if (!gullible) { Pix p, q, r; TEX( \begin{quotea} Test to see if everything we need to know is already known, in the case where mlabel = [base]. \end{quotea} ) if ( mlabel == "[base]" ) { forPix( p, home->implications ) { Pix p1 = home->implications(p).first; if ( home->configs(p1).share != home->configs(mpix).share ) continue; SLList& pixes2 = home->implications(p).second; if ( labels.length != pixes2.length( ) ) continue; prevector pixes1v(pixes), pixes2v(pixes2); pixes1v.sort( &pixcmp ); pixes2v.sort( &pixcmp ); if ( pixes1v == pixes2v ) { if ( labels.length == 0 ) home->set_unrealizable(mpix); if ( labels.length == 1 ) home->configs.join( mpix, pixes(0) ); home->set_current(0); return ""; } } } SLList cs = home->configs.sharelist( ); state_list st; TEX( \begin{quotea} Use {\tt implications2} to enlarge {\tt implications}. \end{quotea} ) forPix( q, home->implications2 ) { pair imps = home->implications2(q); Pix mp = home->label_to_Pix( imps.first, results, 2 ); if ( mp == 0 ) continue; prevector ls = expand_config_list( home, imps.second ); SLList pixesv; for ( i = 0; i < ls.length; i++ ) { r = home->label_to_Pix( ls(i), results, 2 ); if ( r == 0 ) break; pixesv.append(r); } if ( i == ls.length ) home->implications.append( make_pair( mp, pixesv ) ); } TEX( \begin{quotea} Verify that ${\cal R}(m) \IN {\cal R}(\ell_1) \manycup {\cal R}(\ell_r)$. \end{quotea} ) forPix( q, cs ) st[ cs(q) ] = (cs(q)->realizable == -1); for ( i = 0; i < labels.length; i++ ) st[ home->configs(pixes(i)).share ] = true; SLList< multiedge > ml = home->convert_implications( ); st.propagate(ml); if ( !st[ home->configs(mpix).share ] ) { cerr << "(execute_deduce: dumping report to " << "calculations/dump)\n"; ofstream dump( "calculations/dump" ); DLList& configs = home->configs.vertices; int share_count = 1, unlabelled_config_count = 1; Map< Pix, String > lab; dump << "\nAbbreviated dump of all configurations associated to " << "the current code type. Unlabelled configurations are " << "given temporary labels of the form [$n], " << "n = 1,2,... .\n\n"; forPix( p, cs ) { dump << "Configuration equivalence class " << share_count++ << ":\n"; if ( st[cs(p)] ) dump << "[implied by the union of the given configs]\n"; if ( cs(p)->realizable == -1 ) dump << "[unrealizable]\n"; if ( cs(p)->realizable == 1 ) dump << "[realizable]\n"; dump << "\n"; bool first_config = true; forPix( q, configs ) if ( configs(q).share == cs(p) ) { // Make a label for the configuration. forPixDef( r, home->labels ) if ( q == home->labels(r).second ) break; if ( r != 0 ) lab[q] = home->labels(r).first; else lab[q] = String("[$") + dec(unlabelled_config_count++) + "]"; if ( !first_config ) dump << ", "; if (first_config) first_config = false; dump << lab[q]; } dump << "\n\n"; } dump << "Implications:\n"; dump << " (all configs) |-> [base]\n"; forPix( p, home->implications ) { pair< Pix, SLList >& imp = home->implications(p); if ( imp.second.length( ) == 1 && lab[imp.second.front( )] == "[base]" ) continue; dump << " " << lab[imp.first] << " |-> "; forPixDef( q, imp.second ) { if ( q != imp.second.first( ) ) dump << " or "; dump << lab[imp.second(q)]; } dump << ";\n"; } forPix( p, home->implications2 ) { pair& imp2 = home->implications2(p); dump << " " << imp2.first << " <--> " << imp2.second << "\n"; } dump << "\n"; if ( labels.length != 0 ) return String("I don't know that the realization of ") + mlabel + " is contained in the union of the " + "realizations of the other given configurations."; else return String("I don't know that ") + mlabel + " is unrealizable."; } TEX( \begin{quotea} Verify that ${\cal R}(\ell_i) \IN {\cal R}(m)$ for each $i$. \end{quotea} ) state_list< config_share* > sti; for ( i = 0; i < labels.length; i++ ) { forPix( q, cs ) sti[ cs(q) ] = false; sti[home->configs(mpix).share] = true; sti.propagate(ml); if ( !sti[ home->configs(pixes(i)).share ] ) { config& cm = home->configs(mpix); config& cl = home->configs( pixes(i) ); if ( cm.basal( ) && cl.small.basis.nrows == home->dim ) { vector y = cl.small.basis.enumerate_weights( ); forPix( p, cm.assumed_cons ) if ( !check( cm.assumed_cons(p), y, config_core(cm), home->dim, cm.share->ww ) ) break; if (p == 0) continue; } return String("I don't know that ") + labels(i) + " implies " + mlabel + "."; } } } if (finish) { if ( labels.length == 0 ) home->set_unrealizable(mpix); if ( labels.length == 1 ) home->configs.join( mpix, pixes(0) ); home->set_current(0); return ""; } return ""; } TEX( ![ \verb|round_by_lp|: Use linear programming to iteratively round variables associated to the configuration. Use split linear programming if {\tt split} is set, or joint linear programming if {\tt joint} is set, or both. There are three modes. If $\verb|mode| = 0$, get the best bounds we can and put them in \verb|bound|. If $\verb|mode| = 1$, do the same but verify the bounds. If $\verb|mode| = 2$, try to show that the given \verb|bound| can be achieved. (An upper bound of $-1$ is treated as infinity, and hence no request.) If $\verb|mode| = 3$, ignore \verb|bound|, but try to get a contradiction. In modes $2$ and $3$, return {\tt true} if successful. In modes $0$ and $1$, return {\tt true} if infeasibility found. ]! ) index_method(round_by_lp) bool round_by_lp( config& c, prevector var, prevector< pair >& bound, bool split, bool joint, int mode, bool quiet, codetable& results ) { if ( !split && !joint ) ERROR( "Either split linear programming or joint linear programming " << "(or both) must be chosen." ); int force_precision_save = force_precision; prevector< pair > known( var.length ); for ( int i = 0; i < var.length; i++ ) { term_sum t( var(i) ); forPixDef( p, t ) c.check_variable( t(p).var ); if ( var(i).contains( '-' ) ) ERROR("Sorry, I can't (at present) handle the negative stuff."); known(i).first = 0; known(i).second = -1; c.evaluate( var(i), known(i).first, known(i).second ); } if ( mode == 3 ) { for ( int i = 0; i < var.length; i++ ) if ( known(i).second < known(i).first ) ERROR( "The known constraints for the configuration " << "are already contradictory." ); } bool current_mode = joint; bool failure_encountered = false; restart: while(1) { bool improvement_found = false, at_given_bounds = true; for ( int i = 0; i < var.length; i++ ) { if ( mode == 2 && known(i).first >= bound(i).first && ( bound(i).second == -1 || known(i).second <= bound(i).second ) ) continue; at_given_bounds = false; // Is optimization possible using the current method? constraint temp( var(i) + "=0" ); if ( current_mode && !temp.joint( ) ) continue; if ( !current_mode && !temp.local( ) ) continue; // Get bounds. opt_table o(c.home); String goal = "minmax"; if ( mode == 2 && known(i).first < bound(i).first && known(i).second <= bound(i).second ) goal = "min"; else if ( mode == 2 && known(i).first >= bound(i).first && known(i).second > bound(i).second ) goal = "max"; o.add( var(i), goal ); o.compute( results, current_mode ); opt_card x = o.data.front( ); Integer low, high; for ( int pass = 1; pass <= 2; pass++ ) { // Pass 1: verify lower bound. Pass 2: verify upper bound. constraint better; better.LHS = var(i); bool go = false; if ( pass == 1 && goal.contains( "min" ) ) { low = ceil( Rational(x.min) - Rational(0.000001) ); if ( low > known(i).first ) { better.sense = '>'; better.RHS = low; go = true; } } if ( pass == 2 && goal.contains( "max" ) ) { high = floor( Rational(x.max) + Rational(0.000001) ); if ( high < known(i).second ) { better.sense = '<'; better.RHS = high; go = true; } } if (go) { cplex_verification_failure_accepted = 1; bool verify_worked = false; if ( mode == 0 || c.home->show( better, results, quiet, constraintlist( ), current_mode, true ) ) verify_worked = true; else { if ( !quiet ) cerr << "Attempt to verify bound " << better << " failed.\n"; force_precision = max(force_precision, current_precision + 1); current_precision++; if (homebrew) { if ( !quiet ) cerr << "Trying to reverify " << "using homebrew simplex.\n"; bool homebrew_save = force_homebrew; force_homebrew = 1; if ( c.home->show(better, results, quiet, constraintlist( ), current_mode, true) ) verify_worked = true; else if ( !quiet ) cerr << "Verification failed again.\n"; force_homebrew = homebrew_save; } } if (verify_worked) { improvement_found = true; failure_encountered = false; if ( pass == 1 ) known(i).first = low; else known(i).second = high; round_variable(var(i), known(i).first, known(i).second, c.home->n, c.home->dim, c, results); if ( pass == 1 ) better.RHS = known(i).first; else better.RHS = known(i).second; if ( !quiet ) cerr << "Now I know " << better << ".\n"; if ( known(i).second < known(i).first ) { if ( mode != 2 ) { force_precision = force_precision_save; return true; } else ERROR( "Actually the current " << "configuration is infeasible." ); } bool nan = false; c.add_constraint( better, results, nan, true ); if (nan) c.home->deactivate( ); } cplex_verification_failure_accepted = 0; } } } if ( mode == 2 && at_given_bounds ) { force_precision = force_precision_save; return true; } if ( !improvement_found ) break; } if ( joint && split && !failure_encountered ) { failure_encountered = true; current_mode = !current_mode; goto restart; } if ( mode == 0 || mode == 1 ) bound = known; force_precision = force_precision_save; return false; } HIDE( ![ int String_cmp(const String&, const String&); ]! ) index_command(via lp) void execute_via_lp_command( codehome* home, String label1, bool gullible, codetable& results, bool joint, prevector iterate, bool common, bool must_fail = false ) { Pix q = home->label_to_Pix(label1, results); if (!gullible) { int verify_feasibility_save; if (must_fail) { verify_feasibility_save = verify_feasibility; verify_feasibility = 1; } home->set_current(q); TEX(![ \begin{quotea} Find all known simple constraints, i.e.\ those constraints whose \LHS\ is a variable. Try to get a contradiction from these, together with the constraints implied by the working weightlist. \end{quotea} ]!) constraintlist c = home->configs(home->current).known_cons( ); constraintlist c_simple; forPixDef( p, c ) if ( c(p).simple( ) ) c_simple.append( c(p) ); OSLList vars; forPix( p, c_simple ) vars.add( c_simple(p).LHS.front( ).var ); forPix( p, vars ) { Integer low = 0, high = -1; c_simple.evaluate( vars(p), low, high ); if ( high != -1 && high < low ) break; if ( low > 0 && vars(p)[0] == 'y' ) if ( !home->ww(q).contains( yno( vars(p) ) ) ) break; } if ( p != 0 && iterate.length != 0 ) WARNING( "There is no need to iterate." ); if ( p == 0 && iterate.length == 0 ) { if ( (joint && !joint_infeasible(*home, results)) || (!joint && !home->contradiction(via_lp_quiet, results)) ) { if (!must_fail) WARNING("Contradiction failed.") else verify_feasibility = verify_feasibility_save; return; } else if (must_fail) { WARNING("Contradiction did NOT fail."); verify_feasibility = verify_feasibility_save; return; } } if ( p == 0 && iterate.length != 0 ) { SLList it_vars0; static Regex var_pattern(var); for ( int i = 0; i < iterate.length; i++ ) { if ( iterate(i).matches( var_pattern ) ) it_vars0.append( iterate(i) ); else if ( iterate(i) == "y*" ) { weightlist& ww = home->ww(home->current); forPixDef( qq, ww ) if ( ww(qq) != 0 ) it_vars0.append(String("y") + dec(ww(qq))); } else ERROR( "Illegal variable " << iterate(i) << " for via lp iteration." ); } prevector it_vars(it_vars0); prevector< pair > bound; if ( !round_by_lp(home->configs(q), it_vars, bound, common | !joint, common | joint, 3, via_lp_quiet, results) ) ERROR( "Contradiction failed." ); } } home->set_unrealizable(q); home->set_current( 0 ); } TEX( ![ \verb|process_config_target_list|:\ Given a list of configuration labels, sort the corresponding configurations according to whether they are basal, terminal, or neither. For those that are terminal, compute the weight enumerator. Also compute the list of pixes corresponding to the configurations. ]! ) index_method(process_config_target_list) void process_config_target_list( codehome* home, prevector labels, SLList< pair< config, vector > >& terminals, SLList& basals, SLList& others, SLList& pixlist, bool gullible, const codetable& results ) { int i; Pix pixes[labels.length]; for ( i = 0; i < labels.length; i++ ) { pixes[i] = home->label_to_Pix(labels(i), results); pixlist.append( pixes[i] ); } if (!gullible) { for ( i = 0; i < labels.length; i++ ) { config& ci = home->configs( pixes[i] ); if ( ci.basal( ) ) basals.append(ci); else if ( ci.terminal( ) ) { vector y = ci.smallcode_we( ); if ( !home->check_globals( ci.assumed_cons, y, config_core(ci) ) ) ERROR( "An assumed constraint of " << labels(i) << " fails for it." ); terminals.append( make_pair( ci, y ) ); } else others.append(ci); } } } index_method(check_config_list) bool check_config_list( codehome* home, const matrix& ext, const SLList< pair< config, vector > >& terminals, const SLList& basals, const SLList& others ) { int i; Pix p, q, r; vector we = ext.enumerate_weights( ); TEX( \begin{quote} First look for matches with basal configurations. \end{quote} ) config_core core( home->configs(home->current) ); forPix( q, basals ) { const constraintlist& ac = basals(q).assumed_cons; if ( home->check_globals( ac, we, core ) ) return true; } TEX( \begin{quote} Now look for matches with terminal configurations. \end{quote} ) config_core ci; ci.part.set_all_ones(home->n); ci.smallbasis = ext; ci.dualsmallbasis.set_size(0, home->n); forPix( q, terminals ) if ( we == terminals(q).second ) if ( home->isomorphic( config_core(terminals(q).first), ci, true ) ) return true; TEX( \begin{quote} Now look for matches with configurations which are neither basal nor terminal. \end{quote} ) forPix( r, others ) { config_core corer( others(r) ); if (!home->check_globals(others(r).known_cons( ), we, corer)) continue; // Make a terminal configuration. (This is silly. We should modify // configuration_search to take a matrix for its first argument.) config c1; c1.home = home; c1.part.set_all_ones(home->n); c1.small.basis = ext; c1.dualsmall.basis.set_size(0, home->n); c1.share = 0; // Don't use! if ( configuration_search( c1, others(r), "", "" ) ) return true; } return false; } index_command(via extension) void execute_via_extension( codehome* home, String label1, prevector labels, bool alternate_extension_method, bool gullible, codetable& results, String pound_label_head, int& pound_label_ctr ) { bool fail_flag = false; SLList basals, others; SLList< pair< config, vector > > terminals; SLList pixlist; process_config_target_list( home, labels, terminals, basals, others, pixlist, gullible, results ); Pix pix1 = home->label_to_Pix( label1, results ); if (!gullible) { home->set_current( pix1 ); if ( !home->configs(home->current).no_bad_weights( ) ) { cerr << "Configuration " << label1 << " has a word of " << "a weight which we know can't occur.\n"; home->set_unrealizable(pix1); home->set_current(0); return; } bool enumerators_only = false; if ( terminals.length( ) == 0 && others.length( ) == 0 && pound_label_head == "" ) { if ( !(basals.length( ) == 1 && basals.front( ).assumed_cons.length( ) == 0) ) { cerr << "(The extensions will be listed, but only " << "one per weight enumerator.)\n"; enumerators_only = true; } } SLList< matrix > ext0= home->list_extensions(alternate_extension_method, enumerators_only, results); prevector< matrix > ext(ext0); int pound_label_ctr_first = pound_label_ctr; for ( int i = 0; i < ext.length; i++ ) if (check_config_list( home, ext(i), terminals, basals, others )) cerr << "Extension " << i + 1 << " of " << ext.length << " found.\n"; else if ( pound_label_head != "" ) { int k; for ( k = 1; k < pound_label_ctr_first; k++ ) { String pound_labelk = pound_label_head + dec(k) + "]"; Pix p = home->label_to_Pix(pound_labelk, results); if ( isomorphic(ext(i), home->configs(p).small.basis) ) { cerr << "Extension " << i + 1 << " of " << ext.length << " found.\n"; break; } } if ( k == pound_label_ctr_first ) { String pound_label = pound_label_head + dec(pound_label_ctr++) + "]"; cerr << "creating " << pound_label << " terminal " << ext(i) << ";\n"; config c( home, ext(i) ); if ( auto_group_computation ) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; } Pix j = home->merge_config(c); pixlist.append(j); home->labels.append( make_pair(pound_label, j) ); } } else { fail_flag = true; WARNING( "Extension " << i + 1 << " of " << ext.length << " NOT found. It has weight enumerator " << as_poly(ext(i).enumerate_weights( )) ); } } if (!fail_flag) home->implications.append( make_pair(pix1, pixlist) ); home->set_current(0); } index_command(dump) void execute_dump( codehome* home ) { SLList shares = home->configs.sharelist( ); DLList& configs = home->configs.vertices; int share_count = 1, unlabelled_config_count = 1; Map< Pix, String > lab; cerr << "\nDump of all configurations associated to the " << "current code type. Unlabelled configurations are given" << " temporary labels of the form [$n], n = 1,2,... .\n\n"; forPixDef( p, shares ) { cerr << "Configuration equivalence class " << share_count++ << ":\n\n"; forPixDef( q, configs ) if ( configs(q).share == shares(p) ) { // Make a label for the configuration. forPixDef( r, home->labels ) if ( q == home->labels(r).second ) break; if ( r != 0 ) lab[q] = home->labels(r).first; else lab[q] = String("[$") + dec(unlabelled_config_count++) + "]"; cerr << " " << lab[q] << "\n" << configs(q) << "\n"; } } cerr << "Implications:\n"; cerr << " (all configs) |-> [base]\n"; forPix( p, home->implications ) { pair< Pix, SLList >& imp = home->implications(p); if ( imp.second.length( ) == 1 && lab[imp.second.front( )] == "[base]" ) continue; cerr << " " << lab[imp.first] << " |-> "; forPixDef( q, imp.second ) { if ( q != imp.second.first( ) ) cerr << " or "; cerr << lab[imp.second(q)]; } cerr << ";\n"; } forPix( p, home->implications2 ) { pair& imp2 = home->implications2(p); cerr << " " << imp2.first << " <--> " << imp2.second << "\n"; } cerr << "\n"; } HIDE( ![ template void sort_by_second( prevector< pair >& ); ]! ) index_command(try to kill) void execute_try_to_kill_current( codehome* home, codetable& results, bool gullible ) { if ( home->current == 0 ) ERROR("The current configuration is undefined."); config& c = home->configs(home->current); home->activate(true, results); if ( c.assumed_cons.global( ) ) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; } EquivRelIntList e = home->active->auto_equiv( ); int i, class_count = 0; prevector< pair< wordtype, int > > blv( e.orbit_count( ) - 1 ); mawhometable& vt = home->active->vtable; for ( i = 1; i < e.length; i++ ) if ( e.minimal(i) ) blv(class_count++).first = vt(i).maw; Pix curp = home->current; cerr << "There are " << blv.length << " variables that I'll try to kill.\n"; int auto_analyze_local_relations_save = auto_analyze_local_relations; auto_analyze_local_relations = false; for ( i = 0; i < blv.length; i++ ) { home->set_current( subdivide ( home->configs(home->current), blv(i).first, results ) ); if ( home->configs(home->current).share->realizable == -1 ) blv(i).second = 0; else { home->activate(true, results); blv(i).second = home->active->vtable.length; home->set_current(curp); home->activate(true, results); } } auto_analyze_local_relations = auto_analyze_local_relations_save; sort_by_second(blv); ofstream to_kill( calculations_dir + "/to_kill" ); for ( i = 0; i < blv.length; i++ ) to_kill << "will try to kill " << blv(i).first.variable( ) << " (" << blv(i).second << " variables)\n"; to_kill.close( ); cerr << "A list of the variables to be killed may be found in " << "\"" << calculations_dir << "/to_kill\".\n"; for ( i = 0; i < blv.length; i++ ) { cerr << "trying to kill " << blv(i).first.variable( ); if ( blv(i).second == 0 ) { cerr << "... done (previously)\n"; bool nan; home->set_current(curp); home->configs(curp).add_constraint( blv(i).first.variable( ) + "=0", results, nan ); if ( home->contradiction(true, results) ) { cerr << "split linear programming kills [current]\n"; home->set_unrealizable(curp); home->set_current(0); return; } continue; } home->set_current( subdivide ( home->configs(home->current), blv(i).first, results ) ); home->configs(home->current).check_secondary_residuals(results); home->activate(true, results); cerr << " (" << home->active->vtable.length << " variables)... "; if ( !gullible && home->contradiction(true, results) ) { cerr << "done\n"; bool nan; home->set_current(curp); home->configs(curp).add_constraint( blv(i).first.variable( ) + "=0", results, nan ); if ( home->contradiction(true, results) ) { cerr << "split linear programming kills [current]\n"; home->set_unrealizable(curp); home->set_current(0); return; } } else { if (!gullible) cerr << "failed\n"; else cerr << "skipped\n"; home->set_current(curp); home->activate(true, results); } } } index_command(disjoint) void execute_disjoint( codehome* home, prevector labels, bool gullible, const codetable& results ) { int i, j, k, l; // If the configurations are all terminal, with no assumed constraints, // and there are at least 20 of them, we use a different procedure. // One problem is that we do not append to home->disjoint, which would // take up too much space. Ultimately some other member should be added // to class codehome to encode the known disjointness information in a // more efficient way. if ( labels.length >= 20 ) { prevector< pair< int, vector > > raw( labels.length ); Pix pixes[labels.length]; for ( i = 0; i < labels.length; i++ ) { forPixDef( p, home->config_lists ) if ( home->config_lists(p).member( labels(i) ) != 0 ) break; if ( p == 0 ) { pixes[i] = home->label_to_Pix(labels(i), results); config& ci = home->configs( pixes[i] ); if ( !ci.terminal( ) ) break; if ( ci.assumed_cons.length( ) != 0 ) break; } } if ( i == labels.length ) { if (gullible) return; for ( i = 0; i < labels.length; i++ ) { forPixDef( p, home->config_lists ) { int r = home->config_lists(p).member( labels(i) ); if ( r != 0 ) { raw(i) = make_pair( i, pack( canonical_form( home->config_lists(p).fetch(r) ) ) ); break; } } if ( p == 0 ) { config& ci = home->configs( pixes[i] ); raw(i) = make_pair( i, pack( canonical_form( ci.basic_small( ) ) ) ); } } sort_by_secondy(raw); bool fail = false; for ( j = 1; j < raw.length; j++ ) if ( raw(j).second == raw(j-1).second ) { cerr << "The terminal configurations " << labels( raw(j-1).first ) << " and " << labels( raw(j).first ) << " are isomorphic.\n"; fail = true; } if (fail) WARNING( "Attempt to prove disjointness fails." ); return; } } Pix pixes[labels.length]; vector wes[labels.length]; matrix canon[labels.length]; for ( i = 0; i < labels.length; i++ ) { pixes[i] = home->label_to_Pix(labels(i), results); config& ci = home->configs( pixes[i] ); wes[i] = ci.basic_small( ).enumerate_weights( ); } for ( i = 0; i < labels.length; i++ ) for ( j = i+1; j < labels.length; j++ ) { constraintlist l1, l2; Pix p, q; config *c1, *c2; if (gullible) goto disjoint_yes; l1 = home->configs(pixes[i]).assumed_cons; l1.merge(home->configs(pixes[i]).share->ycon); l2 = home->configs(pixes[j]).assumed_cons; l2.merge(home->configs(pixes[j]).share->ycon); forPix( p, l1 ) forPix( q, l2 ) if ( l1(p).simple( ) && l2(q).simple( ) && l1(p).LHS.front( ).var == l2(q).LHS.front( ).var ) { if ( l1(p).sense != '<' && l2(q).sense != '>' && l2(q).RHS < l1(p).RHS ) goto disjoint_yes; if ( l1(p).sense != '>' && l2(q).sense != '<' && l1(p).RHS < l2(q).RHS ) goto disjoint_yes; } c1 = &(home->configs(pixes[i])); c2 = &(home->configs(pixes[j])); if ( home->configs(pixes[i]).terminal( ) ); else if ( home->configs(pixes[j]).terminal( ) ) swap( c1, c2 ); else goto disjoint_no; if ( c1->terminal( ) && c2->terminal( ) ) { if ( wes[i] != wes[j] ) goto disjoint_yes; if (c1->part.length == c1->part.n && c2->part.length == c2->part.n) { if ( canon[i].x == 0 ) canon[i] = canonical_form( c1->small.basis ); if ( canon[j].x == 0 ) canon[j] = canonical_form( c2->small.basis ); if ( canon[i] != canon[j] ) goto disjoint_yes; } else if ( !home->isomorphic(*c1,*c2,true) ) goto disjoint_yes; WARNING( "The terminal configurations " << labels(i) << " and " << labels(j) << " are isomorphic." ); continue; } if ( !configuration_search(*c1, *c2, "", "") ) goto disjoint_yes; disjoint_no: WARNING("The realizations of configurations " << labels(i) << " and " << labels(j) << " may not be disjoint."); continue; disjoint_yes: home->disjoint.append( make_pair( pixes[i], pixes[j] ) ); } home->set_current(0); } index_command(up to isomorphism show) void execute_up_to_isomorphism_show( codehome* home, String vr, bool gullible, codetable& results ) { if ( home->current == 0 ) ERROR("The current configuration is undefined."); config& cur = home->configs(home->current); cur.check_variable(vr); if ( vr[0] != 'x' ) ERROR(vr << " is not a basic local variable."); home->activate(false, results); wordtype w(&cur, vr); int vno = home->active->vtable.mfind(w); if ( vno == -1 ) ERROR("The basic local variable " << vr << " is not admissible."); if (!gullible) { pair< Permutationlist, Integer > pp = cur.find_automorphism_group( ); cur.aut = pp.first; EquivRelIntList e = home->active->auto_equiv( ); if ( cur.small.basis.nrows == home->dim || e.orbit_count( ) != 2 || e.equiv(vno, 0) ) { constraint con( '>', 1 ); con.addterm( 1, home->active->vtable(vno).maw.variable( ) ); int vnoe = vno; while( (vnoe = e(vnoe)) != vno ) con.addterm( 1, home->active->vtable(vnoe).maw.variable() ); constraintlist clist; clist.append(con); if ( !home->show( clist, results ) ) ERROR( "Show failed." ); } } home->configs.join( home->current, subdivide( home->configs(home->current), w, results ) ); } index_command(via variable split) void execute_via_variable_split( codehome* home, String label0, prevector labels, bool gullible, const codetable& results ) { prevector pixes(labels.length); int i, j; Pix p, q; for ( i = 0; i < labels.length; i++ ) pixes(i) = home->label_to_Pix( labels(i), results ); Pix pix0 = home->label_to_Pix( label0, results ); if (!gullible) { config& c0 = home->configs(pix0); for ( j = 0; j < labels.length; j++ ) if ( !mostly_equal( c0, home->configs( pixes(j) ) ) ) ERROR( "The configurations may differ only in" << " their assumed constraints." ); constraintlist as0 = c0.assumed_cons, as[ labels.length ]; for ( i = 0; i < labels.length; i++ ) { as[i] = home->configs( pixes(i) ).assumed_cons; forPix( p, as0 ) { forPix( q, as[i] ) { if (constraintlist(as0(p)) == constraintlist(as[i](q))) { as[i].del(q); goto found_it; } } ERROR( "The constraint " << as0(p) << " is assumed for " << label0 << ", but not for " << labels(i) << "." ); found_it: continue; } } OSLList vars; for ( i = 0; i < labels.length; i++ ) forPix( q, as[i] ) { if ( !as[i](q).simple( ) ) ERROR( "The constraint " << as[i](q) << " is not simple." ); vars.add( as[i](q).LHS.front( ).var ); } prevector varsv(vars); TEX( \begin{quotea} Determine all values which occur as the \RHS\ of a constraint whose \LHS\ is a variable in {\tt varsv}. Then add a phantom value between each pair of values. \end{quotea} ) OSLList values0[varsv.length]; for ( i = 0; i < labels.length; i++ ) forPix( q, as[i] ) { String v = as[i](q).LHS.front( ).var; values0[ varsv.find(v) ].add( as[i](q).RHS ); } OSLList values[varsv.length]; for ( i = 0; i < varsv.length; i++ ) { values[i].add(0); Pix prev = 0; forPix( q, values0[i] ) { values[i].add( values0[i](q) ); if ( prev != 0 ) values[i].add((values0[i](prev) + values0[i](q)) / 2); prev = q; } values[i].add( values0[i](prev) + 1 ); } TEX(![ \begin{quotea} Cycle through each possible assignment of values to variables, using only values from the lists {\tt values}. \end{quotea} ]!) prevector vp(varsv.length); for ( i = 0; i < vp.length; i++ ) vp(i) = values[i].first( ); do { for ( i = 0; i < labels.length; i++ ) { forPix( q, as[i] ) { String v = as[i](q).LHS.front( ).var; j = varsv.find(v); TEX( ![ \begin{quoted} Break if the constraint {\tt as[i](q)} is not satisfied when {\tt values[j]( vp(j) )} is substituted in for {\tt v}. \end{quoted} ]! ) if ( !test( values[j](vp(j)), as[i](q).RHS, as[i](q).sense ) ) break; } if ( q == 0 ) break; } if ( i == labels.length ) ERROR( "Command fails." ); // Advance the pix vector. for ( i = vp.length - 1; i >= 0; i-- ) { values[i].next( vp(i) ); if ( vp(i) == 0 ) vp(i) = values[i].first( ); else break; } } while( i >= 0 ); } home->implications.append( make_pair( pix0, make_listv(pixes) ) ); for ( i = 0; i < labels.length; i++ ) home->implications.append( make_pair( pixes(i), make_list(pix0) ) ); } index_command(implies) void execute_implies( codehome* home, String label1, String label2, Pix pix1, Pix pix2, bool gullible ) { config& c1 = home->configs(pix1); config& c2 = home->configs(pix2); if (gullible) goto implies_ok; if ( !(c2.part.length == 1 && c2.small.basis.nrows == 0 && c2.dualsmall.basis.nrows == 0) && !mostly_equal(c1, c2) ) ERROR("The partitions, small bases, or dual small " << "bases do not satisfy the requirements of this command."); forPixDef( i, c2.assumed_cons ) if ( !c1.known(c2.assumed_cons(i)) ) ERROR( "Assumed constraint " << c2.assumed_cons(i) << " of " << label2 << " is not known for " << label1 << "." ); implies_ok: home->implications.append(make_pair(pix1, make_list(pix2) )); home->set_current(0); } index_command(=) void execute_equals( codehome* home, Pix pix1, Pix pix2, bool gullible ) { if (!gullible) { config* c1 = &(home->configs(pix1)); config* c2 = &(home->configs(pix2)); constraintlist ac1(c1->assumed_cons), ac2(c2->assumed_cons); constraint ex; Pix p; // Test for refinement. int c2part_ptr_first, c2part_ptr_last = 0; matrix c2small = c2->small.basis; matrix c2dualsmall = c2->dualsmall.basis; if ( c1->small.basis.nrows != c2->small.basis.nrows || c1->dualsmall.basis.nrows != c2->dualsmall.basis.nrows ) goto phase2; int i, j, k; for ( i = 0; i < c1->part.length; i++ ) { int to_fill = c1->part(i); c2part_ptr_first = c2part_ptr_last; while ( to_fill > 0 ) { if ( c2part_ptr_last > c2->part.length - 1 ) goto phase2; to_fill -= c2->part(c2part_ptr_last++); } if ( to_fill < 0 ) goto phase2; for ( k = c2part_ptr_first; k < c2part_ptr_last; k++ ) for ( j = 0; j < c1->small.basis.nrows; j++ ) c2small(j,k) = c1->small.basis(j,i); for ( j = 0; j < c1->dualsmall.basis.nrows; j++ ) c2dualsmall(j,k) = c1->dualsmall.basis(j,i); } c2small.reduce( ); if ( c2small != c2->small.basis ) goto phase2; c2dualsmall.reduce( ); if ( c2dualsmall != c2->dualsmall.basis ) goto phase2; if ( c2->terminal( ) && c2->share->realizable == 1 ) { if ( !(ac1 <= ac2) ) goto phase2; } else if ( !(ac1 == ac2) ) goto phase2; goto finish; phase2: // Test for realizable full case. matrix M1 = c1->basic_small( ); matrix M2 = c2->basic_small( ); if ( c1->share->realizable != 1 || c2->share->realizable != 1 ) goto phase3; if ( c1->small.basis.nrows != home->dim ) goto phase3; if ( c2->small.basis.nrows != home->dim ) goto phase3; if ( isomorphic( M1, M2 ) ) goto finish; phase3: if ( c1->small.basis.nrows == 1 && c1->small.basis.ncols == 1 ) swap( c1, c2 ); if ( c1->small.basis.nrows == 0 && c1->dualsmall.basis.nrows == 0 && c2->small.basis.nrows == 1 && c2->small.basis.ncols == 1 && c2->dualsmall.basis.nrows == 0 ) ex = String("y") + dec( home-> n ) + "=1"; else { if ( c1->small.basis.nrows != 0 || c1->dualsmall.basis.nrows != 0 || c2->part.length != 2 ) swap( c1, c2 ); if ( c1->small.basis.nrows != 0 || c1->dualsmall.basis.nrows != 0 || c2->part.length != 2 ) goto oops; if ( c2->small.basis.nrows == 0 && c2->dualsmall.basis == matrix( 2, "{01}" ) ) ex = String("mu") + dec( c2->part(1).x ) + "!=0"; else if ( c2->dualsmall.basis.nrows == 0 && c2->small.basis == matrix( 2, "{10}" ) ) ex = String("y") + dec( c2->part(0).x ) + "!=0"; else goto oops; } if ( !ac1.joint( ) || !ac2.joint( ) ) goto oops; ac2.append( ex ); forPix( p, ac2 ) if ( !c1->known( ac2(p) ) ) goto oops; forPix( p, ac1 ) if ( !c2->known( ac1(p) ) && constraintlist(ac1(p)) != constraintlist(ex) ) goto oops; } finish: home->configs.join( pix1, pix2 ); home->set_current(0); return; oops: ERROR( "Configurations do not match the requirements for =." ); } index_command(via configuration search) void execute_via_configuration_search( codehome* home, String label1, String label2, Pix pix1, Pix pix2, bool gullible ) { config& c1 = home->configs(pix1); config& c2 = home->configs(pix2); if ( gullible ) goto via_configuration_search_ok; if (!c1.terminal( )) ERROR(label1 << " is not a terminal configuration."); if ( c2.dualsmall.basis.nrows != 0 ) ERROR( "Configuration " << label2 << " must have zero dual small code." ); forPixDef( p, c2.assumed_cons ) if ( !c1.known( c2.assumed_cons(p) ) ) ERROR( "The constraint " << c2.assumed_cons(p) << " is assumed for " << label2 << " but not known " << "for " << label2 << "." ); if ( !configuration_search( c1, c2, label1, label2 ) ) ERROR( "Search failed." ); via_configuration_search_ok: home->implications.append( make_pair( pix1, make_list(pix2) ) ); } index_command(load constraints by parity check from) void execute_load_constraints( codehome* home, codetable& results, String cd, Pix p ) { if ( home->current != home->base ) ERROR("Current configuration must be base."); if ( !home->assumed_cons.empty( ) ) ERROR("Current code type may have no assumed constraints."); codehome* r = results.open(p); if ( !r->assumed_cons.empty( ) ) ERROR("The code type " << cd << " may have no assumed constraints."); if ( home->dim != r->dim ) ERROR("Dimensions wrong."); if ( home->n != r->n - 1 ) ERROR("Code lengths wrong."); weightlist& w = home->ww(home->base); forPixDef( pp, w ) { int wp = w(pp) + odd( w(pp) ); if ( !r->w.contains(wp) ) ERROR("Weight " << wp << " is missing from the " << "assumed weight list for " << cd << "."); } bool new_active_needed = false; for ( int i = 2; i <= r->n; i += 2 ) if ( !r->ww(r->base).contains(i) ) { w.del(i); w.del(i-1); new_active_needed = true; } constraintlist& c = r->configs(r->base).share->ycon; config_core core( r->configs(r->base) ); forPix( p, c ) { constraint cp_new( c(p).sense, c(p).RHS ); term_sum ts = core.simplify_global_vars( c(p).LHS, r->ww(r->base), r->dim ); forPixDef( q, ts ) { term t = ts(q); int var_no = yno( t.var ); if ( even(var_no) ) { if ( var_no != r->n ) cp_new.LHS.append(t); if ( var_no != 0 ) { t.var = String("y") + dec(var_no - 1); cp_new.LHS.append(t); } } } home->configs(home->base).add_constraint(cp_new, results, new_active_needed); } if (new_active_needed) home->deactivate( ); } TEX( ![ \verb|dual_of_we|:\ Compute the dual of a weight enumerator. If the optional boolean parameter is set, stop after encountering a nonzero term. ]! ) index_method(dual_of_we) vector dual_of_we( vector we, bool only_low = false ) { int i, j, n = we.length - 1; matrix ch(n+1, n+1); for ( i = 0; i <= n; i++ ) for ( j = 0; j <= i; j++ ) ch(i, j) = choose(i, j); vector dwe(n+1); dwe.set_zero( ); Integer total = 0, sum; for ( i = 0; i <= n; i++ ) total += we(i); for ( int l = 0; l <= n; l++ ) { for ( i = 0; i <= n; i++ ) { sum = 0; for ( j = 0; j <= i; j++ ) if ( j <= l && l - j <= n - i ) sum += minus1_to_the(j) * ch( i, j ) * ch( n - i, l - j ); dwe(l) += sum * we(i); } if ( only_low && l > 0 && dwe(l) > 0 ) break; } for ( i = 0; i <= n; i++ ) dwe(i) /= total; return dwe; } TEX( ![ {\tt realizable}: Determine if a terminal configuration is realizable. Rather than work with a configuration, this routine takes as input only the data from a configuration that it needs. ]! ) index_method(realizable) bool realizable( config_core& c, constraintlist& assumed_cons, codehome* home, codetable& results ) { int i, j, k, n = home->n; // If convenient, do a pretest to see if there is a word whose weight // is too small. if ( c.part.length == n && 2 * home->dim <= n ) { int d = home->w.min( ); if ( min_distance( c.smallbasis, d ) == 0 ) return false; } // Now do a full check to see if there are words of illegal weight. vector y = c.smallcode_we( ); for ( j = 0; j <= n; j++ ) if ( y(j) != 0 && !home->w.contains(j) ) return false; // Check to see that all assumed constraints are satisfied. constraintlist as = home->assumed_cons; as.merge( assumed_cons ); if ( !home->check_globals( as, y, c ) ) return false; constraintlist joints; forPixDef( p, as ) { if ( !as(p).joint( ) ) INTERNAL_ERROR( "realizable has encountered " << "a constraint containing a local or illegal variable." ); if ( !as(p).global( ) ) joints.append( as(p) ); } if ( joints.length( ) != 0 ) { prevector< matrix > J = joint_we( c ); qvconstraint ex; home->basic_joint_vars(&home->configs(home->base), results); prevector& vars = home->configs(home->base).share->wjv; if ( vars.length == 0 ) INTERNAL_ERROR( "bool realizable -- funny unrealizability" ); for ( i = 0; i <= n; i++ ) for ( j = i; j <= n; j++ ) for ( k = 0; k <= n; k++ ) if ( J(k)(i,j) != 0 ) { int i1 = i, i2 = j, i3 = i + j - 2*k; var = make_j_var( i1, i2, i3 ); if ( !vars.member(var) ) return false; } Integer ***combo = make_krawtchouk( n ); forPixDef( q, joints ) { joint_to_qv( joints(q), ex, vars, home->base, *home, combo ); Rational LHS = 0; for ( i = 0; i < ex.LHS.length; i++ ) { if ( ex.LHS(i) != Rational(0) ) { int i1, i2, i3; parse_j_var( vars(i), i1, i2, i3 ); LHS += ex.LHS(i) * J( (i1+i2-i3)/2 )(i1, i2); } } if ( !test( LHS, ex.RHS, ex.sense ) ) return false; } } // Check to see that options are satisfied. if ( !home->options_satisfied(c) ) return false; // Do an internal consistency check. for ( j = 0; j <= n; j++ ) if ( y(j) != 0 && !home->ww(home->base).contains(j) ) INTERNAL_ERROR( "I've encountered a code having a word " << "of weight " << j << ", which I know is " << "impossible. So either you have discovered " << "an error in Split, or else some command " << "preceding this command has been executed in " "gullible mode, and it would fail otherwise." ); return true; } index_method(execute_realizable) void execute_realizable( codehome* home, prevector labels, bool gullible, codetable& results ) { Pix pixes[labels.length]; for ( int i = 0; i < labels.length; i++ ) { pixes[i] = home->label_to_Pix(labels(i), results); config& c = home->configs(pixes[i]); config_core core(c); if ( !c.terminal( ) ) ERROR(labels(i) << " is not a terminal configuration."); if ( !gullible && c.share->realizable != -1 && !realizable( core, c.assumed_cons, home, results ) ) WARNING("Configuration " << labels(i) << " is not realizable.") else { c.share->realizable = 1; home->configs(home->base).share->realizable = 1; if ( !c.assumed_cons.empty( ) ) { forPixDef( q, home->configs ) { config& d = home->configs(q); if ( mostly_equal(c, d) && d.assumed_cons <= c.assumed_cons ) home->configs.join( pixes[i], q ); } } } } home->set_current(0); } index_method(to_String) String to_String( prevector< matrix > M ) { String ans = "{"; for ( int i = 0; i < M.length; i++ ) { if ( i > 0 ) ans += ","; ans += M(i); } return ans + "}"; } index_command(classification of) String execute_classification_of( codehome* home, String code_label, String& mlabel, prevector labels, String labels_name, bool gullible, codetable& results ) { int i, j; Pix p, q, r; static Regex special_LHS_pat( "\\[[a-zA-Z]+" + pos_number + "\\.\\." + pos_number +"\\]" ); TEX( ![ \begin{quote} Use {\tt implications2} to collapse {\tt labels} if possible. \end{quote} ]! ) begin_collapse: forPix( p, home->implications2 ) { static Regex numdotdot( pos_number + "\\.\\." ); static Regex pos_number_pattern(pos_number); String title = home->implications2(p).second; if ( title.contains( "->" ) ) continue; String title_head = title.before( numdotdot ); String first_no_s = title.at( numdotdot ); first_no_s.del( ".." ); int first_no = as_int( first_no_s ); String afterdotdot = title.after( ".." ); int last_no = take_int( afterdotdot, pos_number_pattern ); String first_label = title_head + dec(first_no) + "]"; for ( i = 0; i < labels.length; i++ ) if ( labels(i) == first_label ) break; if ( i + last_no - first_no < labels.length ) { int firsti = i; for ( j = first_no + 1; j <= last_no; j++ ) { String i_label = title_head + dec(j) + "]"; if ( labels(++i) != i_label ) break; } if ( j == last_no + 1 ) { prevector labels_new( labels.length - (last_no - first_no) ); for ( j = 0; j < firsti; j++ ) labels_new(j) = labels(j); labels_new(firsti) = home->implications2(p).first; for ( j = firsti + last_no - first_no + 1; j < labels.length; j++ ) labels_new(++firsti) = labels(j); labels = labels_new; goto begin_collapse; } } } prevector pixes(labels.length); bool pixes_created = false; if ( !labels_name.matches( special_LHS_pat ) ) { for ( i = 0; i < labels.length; i++ ) pixes(i) = home->label_to_Pix(labels(i), results); pixes_created = true; } Pix mpix = home->label_to_Pix(mlabel, results); bool need_implications = true; int n, k, d; if (gullible) goto all_done; // Check for certain codes at the Griesmer bound. n = home->n; k = home->dim; d = home->w.min( ); { if ( n == home->griesmer( ) && labels.length == 1 ) { if (k >= 3 && k != 5 && Integer(d) == Ipow(2,k-2) + 2) goto all_done; else { for ( int b = 1; b <= k-1; b++ ) if (Integer(d) == Ipow(2,k-1) - Ipow(2,b-1)) goto all_done; for ( int b = 1; b <= k; b++ ) { for ( int a = b+1; b <= k-a; b++ ) { if ( (a != 3 || b != 2) && Integer(d) == Ipow(2,k-1) - Ipow(2,a-1) - Ipow(2,b-1) ) goto all_done; } } } } } // The following bracketing is needed to avoid a segmentation fault, // presumably connected somehow with goto's jumping over it. { // Try to get classification by construction P. // First check: is this the base configuration? if ( mlabel != "[base]" ) goto unresidue; // Now determine if [n - 2^(k-1), k-1, d - 2^(k-2)] codes have // been classified. int n0 = n - int(Ipow(2,k-1)), k0 = k-1, d0 = d - int(Ipow(2,k-2)); prevector< matrix > gens; forPix( p, results.open ) { codehome* h = results.open(p); if ( h->dc.first != 'c' || h->n != n0 || h->dim != k0 || !h->assumed_cons.empty( ) || !h->opt.none_chosen( ) || h->w != weightlist( dec(d0), n0 ) ) continue; prevector labs = h->dc.second; gens.set_size( labs.length ); for ( i = 0; i < labs.length; i++ ) { config& c = h->configs(h->label_to_Pix( labs(i), results )); if ( !c.terminal( ) ) break; gens(i) = c.basic_small( ); } if ( i == labs.length ) break; else { // At this point we've almost failed, but check the // case of [n0, n0-1, 2] codes. if ( d0 == 2 && k0 == n0 - 1 ) { gens.set_size(1); matrix E( k0, n0 ); for ( i = 0; i < k0; i++ ) E(i, i) = E(i, i+1) = 1; gens(0) = E; break; } } } if ( p == 0 ) goto unresidue; // Test for required constraints. prevector con(3); con(0) = String("y") + dec(Ipow(2,k-1)) + "!=0"; con(1) = String("mu1=0"); con(2) = String("mu2=0"); home->set_current(home->base); for ( i = 0; i < 3; i++ ) if (!home->configs(home->base).known(con(i)) && !home->show(con(i), results, true) && !home->show(con(i), results, true, constraintlist( ), true)) goto unresidue; // Compute matrices associated to the given labels. if ( !pixes_created ) { for ( i = 0; i < labels.length; i++ ) pixes(i) = home->label_to_Pix(labels(i), results); pixes_created = true; } prevector< matrix > mat( labels.length ); for ( i = 0; i < labels.length; i++ ) { config& c = home->configs( pixes(i) ); if ( !c.terminal( ) ) break; mat(i) = c.basic_small( ); } if ( i != labels.length ) goto unresidue; // Generate and evaluate expression for P(gens). SLList sources; String expr = "IsoEq(Realizable([current],IsoReps(P(" + to_String(gens) + ")))," + to_String(mat) + ")"; String nul( "" ); generic_object g = evaluate_expression(expr, results, home, nul, sources); g.convert( "Bool" ); if ( bool(g) ) goto all_done; } unresidue: { // Test for classification by Unresidue. String descrip; static Regex label_pattern( label_pat ); if ( labels_name.matches( label_pattern ) ) { p = home->label_to_Pix( labels_name, results ); descrip = home->configs(p).title; descrip.gsub( RXwhite, "" ); if ( descrip.contains( "Unresidue(", 0 ) ) goto unresidue_found; goto build; } if ( !labels_name.contains( ".." ) ) goto build; forPix( p, home->config_lists ) { config_list_on_disk& cld = home->config_lists(p); descrip = cld.descrip; descrip.gsub( RXwhite, "" ); if ( cld.title == labels_name && descrip.contains( "Unresidue(", 0 ) ) break; } if ( p == 0 ) goto build; unresidue_found: descrip.del( "Unresidue(" ); if ( code_label != take( descrip, label_pattern ) ) goto build; descrip.del( ',' ); if ( mlabel != take( descrip, label_pattern ) ) goto build; descrip.del( ',' ); descrip.del( ')', -1 ); String t2 = descrip.after("["); HIDE( ![ static Regex pos_number_pattern( pos_number ); static Regex gen_label_pattern( gen_label_pat ); ]! ) String clabel = "[" + take( t2, alphanumericu ) + "]"; codehome* xhome = results.get_home(clabel); if ( xhome == 0 ) INTERNAL_ERROR( "execute_classification of - no home" ); t2.del("."); t2 = "[" + t2; if ( xhome->dim != home->dim - 1 || !xhome->opt.none_chosen( ) ) goto build; if ( xhome->dc.first != 'c' ) goto build; Pix p = home->label_to_Pix( mlabel, results ); if ( xhome->assumed_cons.length( ) != 0 ) { forPixDef( p2, xhome->assumed_cons ) { constraint xc = xhome->assumed_cons(p2); if ( !( xc.simple( ) && xc.RHS == 0 && xc.LHS.front( ).var.contains( "mu", 0 ) && home->configs(p).known( xc ) ) ) goto build; } } int n = home->n, r = xhome->n, d = home->w.min( ); constraint nz = String("y") + dec(n-r) + "!=0"; if ( !home->configs(p).known(nz) ) ERROR( nz << " should be known for " << mlabel ); if ( n-r < d || n-r >= 2*d ) goto build; config b = config( home, String(dec(n-r)) + "," + dec(r) + ":{10}" ); home->set_config( b, results ); home->activate( true, results, false ); for ( int l = 0; l < home->active->vtable.length; l++ ) if ( !xhome->w.contains( home->active->vtable(l).maw(1) ) ) goto build; if ( xhome->dc.second == expand_config_list(xhome, t2) ) goto all_done; } build: { // Test for classification by Build. if ( !labels_name.contains( ".." ) ) goto minus_column; String descrip; forPix( p, home->config_lists ) { config_list_on_disk& cld = home->config_lists(p); descrip = cld.descrip; descrip.gsub( RXwhite, "" ); if ( cld.title == labels_name && descrip.contains( "Build(", 0 ) ) break; } if ( p == 0 ) goto minus_column; descrip.del( "Build(" ); static Regex label_pattern( label_pat ); if ( code_label != take( descrip, label_pattern ) ) goto minus_column; descrip.del( ',' ); descrip.del( ')', -1 ); Pix p1 = home->label_to_Pix( descrip, results ); Pix p2 = home->label_to_Pix( mlabel, results ); if ( home->configs(p1).share == home->configs(p2).share ) goto all_done; } minus_column: { // Test for classification by column deletion. if ( !labels_name.contains( ".." ) ) goto main; String descrip; forPix( p, home->config_lists ) { config_list_on_disk& cld = home->config_lists(p); descrip = cld.descrip; descrip.gsub( RXwhite, "" ); if ( cld.title == labels_name && descrip.contains( "-column", -1 ) ) break; } if ( p == 0 ) goto main; descrip.del( "-column", -1 ); String t2 = descrip.after("["); HIDE( ![ static Regex pos_number_pattern( pos_number ); static Regex gen_label_pattern( gen_label_pat ); ]! ) String clabel = "[" + take( t2, alphanumericu ) + "]"; codehome* xhome = results.get_home(clabel); if ( xhome == 0 ) INTERNAL_ERROR( "execute_classification of - no home" ); t2.del("."); t2 = "[" + t2; if ( xhome->dim != home->dim || !xhome->opt.none_chosen( ) ) goto main; if ( xhome->assumed_cons.length( ) != 0 ) goto main; if ( xhome->dc.first != 'c' ) goto main; if ( xhome->n != home->n + 1 ) goto main; forPix( p, home->ww(home->base) ) { int wt = home->ww(home->base)(p); if ( even(wt) && !xhome->w.contains(wt) ) goto main; if ( odd(wt) && !xhome->w.contains(wt+1) ) goto main; } goto all_done; } main: { need_implications = false; if ( !pixes_created ) { for ( i = 0; i < labels.length; i++ ) pixes(i) = home->label_to_Pix(labels(i), results); pixes_created = true; } String errmesg = execute_deduce( home, mlabel, labels, gullible, results, false ); if ( errmesg != "" ) return errmesg; } { SLList cs = home->configs.sharelist( ); state_list st, st_old, st_unreal, st_real; SLList< multiedge > ml = home->convert_implications( ); TEX( \begin{quotea} Determine which configuration equivalence classes are known to be unrealizable. \end{quotea} ) forPix( q, cs ) st_unreal[ cs(q) ] = (cs(q)->realizable == -1); st_unreal.propagate(ml); SLList< multiedge > ml_clean; forPix( q, ml ) { if ( st_unreal[ ml(q).first ] ) continue; multiedge m; m.first = ml(q).first; forPixDef( r, ml(q).second ) if ( !st_unreal[ ml(q).second(r) ] ) m.second.add( ml(q).second(r) ); ml_clean.append(m); } TEX(![ \begin{quotea} Verify that ${\cal R}(\ell_1), \ldots, {\cal R}(\ell_r)$ are all realizable. \end{quotea} ]!) forPix( q, cs ) { if ( cs(q)->realizable == 1 ) st_real[ cs(q) ] = true; else st_real[ cs(q) ] = false; } st_real.reverse_propagate(ml_clean); for ( i = 0; i < labels.length; i++ ) if ( st_unreal[ home->configs(pixes(i)).share ] || !st_real[ home->configs(pixes(i)).share ] ) { prevector l(1); l(0) = labels(i); execute_realizable( home, l, gullible, results ); } TEX(![ \begin{quotea} Show that ${\cal R}(\ell_1),\ldots,{\cal R}(\ell_r)$ are pairwise disjoint. We proceed by making a list of all pairs of configuration equivalence classes. We associate to each pair the value {\tt true} if the corresponding realizations are known to be disjoint, else {\tt false}. \end{quotea} ]!) if ( home->disjoint.length( ) != 0 ) { Map< pair, bool> dis; forPix( p, cs ) { forPix( q, cs ) dis[make_pair(cs(p), cs(q))] = false; } forPix( p, home->disjoint ) { dis[ make_pair( home->configs(home->disjoint(p).first). share, home->configs(home->disjoint(p).second).share )] = true; dis[ make_pair( home->configs(home->disjoint(p).second). share, home->configs(home->disjoint(p).first).share ) ] = true; } do { forPix( p, ml_clean ) { if ( ml_clean(p).second.length( ) == 1 ) { config_share *s1, *s2; s1 = ml_clean(p).first; s2 = ml_clean(p).second.front( ); TEX(![ \begin{quotee} ${\cal R}(s_1) \IN {\cal R}(s_2)$, $s_2 \cap x = \emptyset \Longrightarrow s_1 \cap x = \emptyset$ \end{quotee} ]!) bool succeeded = false; forPix( q, dis.data ) { if ( !dis.data(q).second && dis.data(q).first.first == s1 && dis[ make_pair( s2, dis.data(q).first.second ) ] ) { dis.data(q).second = true; succeeded = true; } } TEX(![ \begin{quotee} ${\cal R}(s_1) \IN {\cal R}(s_2)$, $x \cap s_2 = \emptyset \Longrightarrow x \cap s_1 = \emptyset$ \end{quotee} ]!) forPix( q, dis.data ) { if ( !dis.data(q).second && dis.data(q).first.second == s1 && dis[ make_pair( dis.data(q).first.first, s2 ) ] ) { dis.data(q).second = true; succeeded = true; } } if (succeeded) break; } } for ( i = 0; i < labels.length; i++ ) for ( j = i+1; j < labels.length; j++ ) if ( !dis[ make_pair( home->configs(pixes(i)).share, home->configs(pixes(j)).share) ] ) goto not_done_yet; goto all_done; not_done_yet: continue; } while ( p != 0 ); } execute_disjoint( home, labels, false, results ); } all_done: if ( labels.length == 0 ) home->set_unrealizable(mpix); else home->configs(mpix).share->realizable = 1; if (pixes_created) { if ( labels.length == 1 ) home->configs.join( mpix, pixes(0) ); for ( i = 0; i < labels.length; i++ ) home->configs(pixes(i)).share->realizable = 1; } // Test for uniqueness. if (pixes_created) { for ( i = 0; i < labels.length; i++ ) if ( !home->configs(pixes(i)).terminal( ) ) break; if ( i == labels.length && mpix == home->base ) { home->classified = true; if ( labels.length == 1 && (gullible || home->configs(home->base).share->realizable == 1) ) home->unique = true; } } // Merge constraints true for all the configs. if ( labels.length > 0 && pixes_created ) { weightlist& w = home->ww(mpix); next_weight: forPix( p, w ) { for ( i = 0; i < labels.length; i++ ) if ( home->ww(pixes(i)).contains( w(p) ) ) break; if ( i == labels.length ) { w.del( w(p) ); goto next_weight; } } constraintlist true_for_all = home->configs(pixes(0)).assumed_cons; weightlist wd = diff( home->ww(home->base), home->ww(pixes(0)) ); forPix( p, wd ) true_for_all.merge(constraint(String("y") + dec(wd(p)) + "=0")); for ( i = 1; i < labels.length; i++ ) { constraintlist tfa = home->configs(pixes(i)).assumed_cons; wd = diff( home->ww(home->base), home->ww(pixes(i)) ); forPix( p, wd ) tfa.merge( constraint( String("y") + dec(wd(p)) + "=0" ) ); true_for_all = intersection( true_for_all, tfa ); } home->configs(mpix).share->ycon.merge( true_for_all ); } // Append implications. if (need_implications) { if ( !pixes_created ) home->implications2.append( make_pair(mlabel, labels_name) ); else { SLList pixesv; for ( i = 0; i < labels.length; i++ ) pixesv.append( pixes(i) ); home->implications.append( make_pair(mpix, pixesv) ); } } home->set_current(0); return ""; } index_command(automorphism) void execute_automorphism( codehome* home, String label, Permutation p, bool gullible, codetable& results ) { if ( home->current == 0 ) ERROR("The current configuration is undefined."); config& c = home->configs(home->current); if ( label != "" ) { forPixDef( p, c.auto_labels ) if ( c.auto_labels(p).first == label ) ERROR("You are trying to redefine a label."); } if ( !gullible && (p.length != c.part.length || !c.is_automorphism(p, results)) ) WARNING("That is not an automorphism.") else { c.aut.append(p); if ( label != "" ) c.auto_labels.append(make_pair(label, c.aut.length - 1)); } } index_command(via dual nonexistence infer) void execute_via_dual_nonexistence( codehome* home, codetable& results, bool gullible ) { if (!gullible) { if ( home->assumed_cons.length( ) != 0 ) ERROR("Sorry, in this version, the code type " << " can't have assumed constraints."); int d = home->ww(home->base).min( ); constraintlist l; for ( int i = 1; i < d; i++ ) l.append( String("mu") + dec(i) + "=0" ); int dp = home->configs(home->base).share->dual_min_low; codebase cb( home->n, home->n - home->dim, weightlist( dec(dp), home->n ), l ); if ( home->ww(home->base).divisible(2) ) cb.assumed_cons.append( String("y") + dec(home->n) + "=1" ); if ( !results.not_exist(cb) ) WARNING("The required nonexistence result is not known."); } home->set_unrealizable( home->base ); } index_command(report group size) void execute_report_group_size( codehome* home, prevector labels ) { if ( home->current == 0 ) ERROR("The current configuration is undefined."); config& c = home->configs(home->current); Permutationlist gen(c.part.length), gp(c.part.length); for ( int i = 0; i < labels.length; i++ ) { forPixDef( p, c.auto_labels ) if ( c.auto_labels(p).first == labels(i) ) { gen.append(c.aut(c.auto_labels(p).second) ); break; } if ( p == 0 ) ERROR(" Unknown label -- " << labels(i) << "." ); gp.generate(gen); cerr << "The group generated by the first " << i + 1 << " automorphisms has " << gp.length << " elements.\n"; } } index_command(:=) void execute_colon_equals( String commandx, codehome* home, String code_label, String commandx_save, bool gullible, codetable& results ) { String LHS = commandx.before( ":=" ); prevector labs = expand_config_list( home, LHS ); commandx = commandx.after( ":=" ); String mat_des = commandx, rmat_des, cons; if ( commandx.contains( "::" ) ) { mat_des = mat_des.before( "::" ); cons = commandx.after( "::" ); } Pix p; packed_matrix_list B; generic_object g; String title = commandx_save; title = title.after( ":=" ); title.del( ";", -1 ); if ( title.contains( "::" ) ) title = title.before( "::" ); static Regex special_LHS_pat( "\\[[a-zA-Z]+" + pos_number + "\\.\\." + pos_number +"\\]" ); int n = home->n, k = home->dim; String fn = "hints/" + code_label + "/" + LHS; prevector linesv; SLList lines, sources; bool hints_used = false; int i, j; if ( !gullible || code_label == "" ) goto must_do_work; { ifstream cfile( fn ); if ( cfile.peek( ) == EOF ) goto must_do_work; String nlinesx; cfile >> nlinesx; int nlines = as_int(nlinesx); int nchars = nlinesx.length( ) + 1; for ( i = 0; i < nlines; i++ ) { char* line; cfile.gets(&line, '\n'); String linex = line; lines.append(linex); nchars += linex.length( ) + 1; delete line; } cfile.close( ); linesv = lines; if ( nlines == 0 || linesv(0) != mat_des ) goto must_do_work; for ( i = 1; i < nlines; i++ ) { if ( !linesv(i).contains( "=" ) ) goto must_do_work; String source = linesv(i).before( "=" ); String target = linesv(i).after( "=" ); if ( !is_zero_one_matrix( target ) ) { cerr << "Corruption detected in " << fn << ". It will be deleted.\n"; unlink(fn); goto must_do_work; } matrix M(target); matrix A = fetch_known_matrix(source, results, home, code_label); if ( A.x == 0 ) continue; if ( A != M ) goto must_do_work; } int nbytes = (n * k - 1)/8 + 1; long file_size = nchars + labs.length * nbytes; if ( size_of_file(fn) != file_size ) { cerr << "Corruption detected in " << fn << ". It will be deleted.\n"; unlink(fn); goto must_do_work; } config_list_on_disk cfd; cfd.n = n; cfd.k = k; cfd.chars_to_skip_over = nchars; cfd.filename = fn; cfd.count = labs.length; cfd.title = LHS; cfd.descrip = title; if ( labs.length > 1 && LHS.matches( special_LHS_pat ) && cons == "" ) { home->config_lists.append( cfd ); home->set_current(0); return; } B = cfd.fetch_all( ); hints_used = true; goto work_skipped; } must_do_work: rmat_des = mat_des; if ( !mat_des.contains( "cyclic{" ) ) rmat_des = "Reduce(" + mat_des + ")"; g = evaluate_expression( rmat_des, results, home, code_label, sources ); g.convert( "List(MatF2){homogeneous}" ); B = g; if ( B.third.length( ) == 0 ) ERROR( "You have a list of zero matrices." ); work_skipped: if ( B.third.length( ) != labs.length ) WARNRET( "You have " << labs.length << " labels on the " << "left but " << B.third.length( ) << " codes on the right." ); if ( cons != "" && cons != "{!}" && labs.length > 1 ) WARNRET( "You cannot use constraints if there is more " << "than one label." ); if ( labs.length == 0 ) WARNRET( "Nonsense!" ); i = 0; bool terminal = true; forPix( p, B.third ) { matrix M = unpack(B.third(p).x, B.first, B.second); M.reduce_nz( ); if ( M.ncols != home->n ) WARNRET( "You have tried to define a code of length " << M.ncols << ". It should have length " << home->n << " instead." ); if ( M.nrows > home->dim ) WARNRET( "The code type has dimension " << home->dim << ", but you have tried to define " << "a configuration of dimension " << M.nrows << "." ); if ( M.nrows < home->dim ) terminal = false; if ( M.nrows == home->dim && !gullible ) { config_core c; c.part.set_all_ones(n); c.smallbasis = M; constraintlist nullc; if ( !realizable(c, nullc, home, results) ) { WARNRET( "Configuration " << labs(i) << " is not realizable." ); } else home->configs(home->base).share->realizable = 1; } i++; } if ( terminal && !hints_used && code_label != "" ) { mkdir( "hints/" + code_label, 00777 ); ofstream cfile( fn ); String ln = dec( 1 + sources.length( ) ) + String("\n"); cfile << ln << mat_des << "\n"; int nchars = ln.length( ) + mat_des.length( ) + 1; if ( ingredient_tracking ) { forPix( p, sources ) { String source_string = sources(p) + "=" + String( fetch_known_matrix( sources(p), results, home, code_label) ) + "\n"; nchars += source_string.length( ); cfile << source_string; } } forPix( p, B.third ) cfile << B.third(p); cfile.close( ); if ( labs.length > 1 && LHS.matches( special_LHS_pat ) && cons == "" ) { config_list_on_disk cfd; cfd.n = n; cfd.k = k; cfd.chars_to_skip_over = nchars; cfd.filename = fn; cfd.count = labs.length; cfd.title = LHS; cfd.descrip = title; home->config_lists.append( cfd ); home->set_current(0); return; } } i = 0; forPix( p, B.third ) { matrix M = unpack(B.third(p).x, B.first, B.second); matrix M_orig = M; M.reduce_nz( ); String Bstring = M; String consx = cons; if ( cons == "{!}" ) { consx = "{"; vector y = M.enumerate_weights( ); bool first = true; forPixDef( q, home->w ) { int wt = home->w(q); if ( wt == 0 ) continue; if ( !first ) consx += ","; consx += String("y") + dec(wt) + "=" + dec(y(wt)); first = false; } consx += "}"; } if ( consx != "" ) Bstring += "::" + consx; String config_string = labs(i) + "config1" + replicate(",1", home->n - 1) + ":" + Bstring; execute_config_command( config_string, config_string, home, false, results, input_mask, code_label ); String titlex = title; if ( labs.length != 1 ) titlex += String(" (#") + dec(i+1) + ")"; home->configs(home->current).title = titlex; home->configs(home->current).gen = M_orig; if ( cons != "" ) { String lab_bang = labs(i); lab_bang.at("]") = "!]"; config_string = lab_bang + "config" + String(dec(home->n)) + ":::" + consx; execute_config_command( config_string, config_string, home, false, results, input_mask, code_label ); Pix pix1 = home->label_to_Pix(labs(i), results); Pix pix2 = home->label_to_Pix(lab_bang, results); home->implications.append(make_pair(pix1, make_list(pix2) )); } i++; } if (terminal) execute_realizable(home, labs, gullible, results); if ( labs.length == 1 ) home->set_current( home->label_to_Pix(labs(0), results) ); else home->set_current(0); } index_method(try_to_kill_jvars) void try_to_kill_jvars( codehome* home, codetable& results, int rr = -1 ) { Pix curp = home->current; home->basic_joint_vars(&home->configs(curp), results); prevector jvars = home->configs(curp).share->wjv; if ( jvars.length == 0 ) INTERNAL_ERROR( "wjv length = 0 in try_to_kill_jvars" ); bool nan; // Figure out what constraints are known. constraintlist kn = home->configs(curp).share->ycon; forPixDef( p, home->ww(home->base) ) { int w = home->ww(home->base)(p); if ( !home->ww(curp).contains(w) ) kn.merge( constraint( String("y") + dec(w) + "=0" ) ); } String kns = "{" + String(kn) + "}"; kns.gsub( " ", "" ); for ( int i = 0; i < jvars.length; i++ ) { int r, s, t; parse_j_var( jvars(i), r, s, t ); if ( rr != -1 && r != rr && s != rr && t != rr ) continue; int a = (r + t - s)/2; int b = (r + s - t)/2; int c = (s + t - r)/2; int d = home->n - a - b - c; if ( a == 0 || b == 0 || c == 0 ) continue; if ( d == 0 ) home->set_config( String(dec(a)) + "," + dec(b) + "," + dec(c) + ":{110,011}::" + kns, results ); else home->set_config( String(dec(a)) + "," + dec(b) + "," + dec(c) + "," + dec(d) + ":{1100,0110}::" + kns, results ); if ( home->configs(home->current).share->realizable == -1 ) { cerr << "trying to kill joint variable " << jvars(i) << " (" << i+1 << " of " << jvars.length << " vars)\n"; cerr << "[" << jvars(i) << " killed]"; if (try_to_kill_vocal) cerr << "\n"; home->set_current(curp); home->configs(curp).add_constraint( jvars(i) + "=0", results, nan ); kns.del( "}", -1 ); kns += "," + jvars(i) + "=0}"; continue; } bool auto_analyze_local_relations_save = auto_analyze_local_relations; auto_analyze_local_relations = 0; home->configs(home->current).check_secondary_residuals(results); if ( home->active == 0 ) home->activate(true, results); auto_analyze_local_relations = auto_analyze_local_relations_save; if ( try_to_kill_maxvars > 0 && home->active->vtable.length > try_to_kill_maxvars ) continue; if (auto_analyze_local_relations) { home->deactivate( ); if ( home->configs(home->current).share->realizable == -1 ) { cerr << "trying to kill joint variable " << jvars(i) << " (" << i+1 << " of " << jvars.length << " vars)\n"; cerr << "[" << jvars(i) << " killed]"; if (try_to_kill_vocal) cerr << "\n"; home->set_current(curp); home->configs(curp).add_constraint( jvars(i) + "=0", results, nan ); kns.del( "}", -1 ); kns += "," + jvars(i) + "=0}"; continue; } home->activate(true, results); home->deactivate( ); auto_analyze_local_relations = 0; home->activate(true, results); auto_analyze_local_relations = 1; } if (try_to_kill_vocal) cerr << "trying to kill joint variable " << jvars(i) << " (" << i+1 << " of " << jvars.length << " vars) using " << home->active->vtable.length << " variables \n"; if ( home->contradiction(true, results) ) { cerr << "[" << jvars(i) << " killed]"; if (try_to_kill_vocal) cerr << "\n"; home->set_current(curp); home->configs(curp).add_constraint( jvars(i) + "=0", results, nan ); kns.del( "}", -1 ); if ( kns.length( ) > 1 ) kns += ","; kns += jvars(i) + "=0}"; } } home->set_current(curp); } index_command(find cyclic codes) index_command(round local variables) index_command(flags) index_command(credit) index_command(note) index_command(check secondary residuals) index_command(bound) index_command(try to kill) index_command(kill) index_command(via varying) index_command(macaulay) index_command(up to isomorphism show) index_command(show) index_command(alt) index_method(execute_other_commands) void execute_other_commands( bool& result, String commandx, codehome* home, codetable& results, String commandx_save, String last_command, String code_label, bool gullible ) { result = true; static Regex find_cyclic_pat( "findcycliccodes" + orsign + "find" + number_pat + "-cycliccodes" ); String local_var_seq( left + var + orsign + "(" + list_of( var, "|" ) + ")" + right ); String alt_local_var_seq( left + var + orsign + "(" + list_of( var, "," ) + ")" + right ); String kill_unit(left + var + orsign + var + "by" + local_var_seq + orsign + var + "by" + alt_local_var_seq + orsign + gen_label_pat + "by" + local_var_seq + orsign + gen_label_pat + "by" + alt_local_var_seq + right); static Regex kill_variable_by_pattern( "kill" + list_of( kill_unit ) ); static Regex via_varying_pattern( "viavaryingy" + number_pat + "\\[current\\]implies" + list_of( gen_label_pat, "or" ) ); HIDE( ![ static Regex number_pattern( number_pat ); static Regex gen_label_pattern( gen_label_pat ); ]! ) if ( commandx.matches( find_cyclic_pat ) ) { if ( home->current != home->base ) WARNRET("Current configuration must be base."); commandx = commandx.after("find"); int q = 1; if ( commandx[0] != 'c' ) q = take_int(commandx, number_pattern); execute_find_cyclic_codes( home, q, results ); } else if ( commandx.matches( "roundlocalvariables" ) ) { execute_round_local( home, results ); } else if ( commandx.contains( "flags:", 0 ) ) { commandx.del( "flags:" ); prevector flags = unpack(commandx); for ( int i = 0; i < flags.length; i++ ) { if ( flags(i) == "findnomore" ) { if ( home->current == 0 || home->current != home->base ) WARNRET( "The current configuration must be [base]." ); results.ignore.append( make_triple( home->n, home->dim, home->w.min( ) ) ); } else if ( flags(i) == "noautomorphismgroupcomputation" ) { if ( home->current == 0 || home->current != home->base ) WARNRET( "The current configuration must be [base]." ); home->configs(home->current).no_auto = true; } else WARNRET( "Unrecognized flag." ); } } else if ( commandx.contains( "credit:", 0 ) ) { if ( home->current == 0 ) WARNRET("The current configuration is undefined."); String woof = commandx_save.after( "credit: " ); woof.gsub( "\n", " " ); woof.gsub( ", existence due to", ";existence due to" ); woof.gsub( ", nonexistence due to", ";nonexistence due to" ); woof.gsub( ", uniqueness due to", ";uniqueness due to" ); woof.gsub( ", classification due to", ";classification due to" ); prevector parts = unpack( woof, ';' ); for ( int i = 0; i < parts.length; i++ ) { if ( parts(i).contains( "existence due to ", 0 ) ) { home->configs(home->current).credit_e = parts(i).after( "due to " ); continue; } if ( home->current != home->base ) WARNRET( "The current configuration must be [base]." ); if ( parts(i).contains( "uniqueness due to ", 0 ) ) home->configs(home->current).credit_u = parts(i).after( "due to " ); else if ( parts(i).contains( "classification due to ", 0 ) ) home->configs(home->current).credit_c = parts(i).after( "due to " ); else if ( parts(i).contains( "nonexistence due to ", 0 ) ); // Note that nothing is done with nonexistence now. else WARNRET( "I don't recognize the syntax of your credit line." << " However, the program is (contrary to the Split " << "documentation) finicky about the location of white space " << "in credit lines. Have a look at the examples in " << "inputs/code.data1 to see what works." ); } } else if ( commandx.contains( "note:", 0 ) ) { String note = commandx_save.after( ":" ); if ( home->current == 0 ) { static Regex colon_eq_command( config_list + ":=.*" ); if ( last_command.matches( colon_eq_command ) ) { String label = last_command.before(":="); label.gsub(RXwhite,""); home->notes_to_config_lists.append(make_pair(label, note)); return; } WARNRET("The current configuration is undefined."); } home->configs(home->current).note = note; } else if ( commandx == "checksecondaryresiduals" ) { if ( home->current == 0 ) ERROR( "[current] is undefined" ); home->configs(home->current).check_secondary_residuals(results); } else if ( commandx.contains( "bound", 0 ) ) { execute_bound( home, commandx.after("bound"), results ); } else if ( commandx.contains( "trytokill", 0 ) ) { commandx = commandx.after( "trytokill" ); static Regex jyr_pat( "jy" + number_pat + "[*]" ); if ( commandx == "x*" ) execute_try_to_kill_current( home, results, gullible ); else if ( commandx == "jy*" ) { if ( home->current == 0 ) ERROR( "[current] is undefined" ); try_to_kill_jvars( home, results ); } else if ( commandx.matches( jyr_pat ) ) { if ( home->current == 0 ) ERROR( "[current] is undefined" ); int r = take_int( commandx, number_pattern ); try_to_kill_jvars( home, results, r ); } else WARNING( "Your variable list is not one of the allowed " << "formats." ); } else if ( commandx.matches( kill_variable_by_pattern ) ) { commandx = commandx.after("kill"); int parencount = 0; SLList vars0; String cur_string; for ( int i = 0; i < commandx.length( ); i++ ) { if ( commandx[i] == ',' && parencount == 0 ) { vars0.append(cur_string); cur_string = ""; } else { cur_string += commandx[i]; if ( commandx[i] == '(' ) parencount++; if ( commandx[i] == ')' ) parencount--; } } vars0.append(cur_string); prevector vars(vars0); execute_kill_variable_by( home, vars, gullible, results ); } else if ( commandx.matches( via_varying_pattern ) ) { commandx = commandx.after( "viavaryingy" ); String yi = "y" + take( commandx, number_pattern ); commandx = commandx.after( "[current]implies" ); prevector labels = unpack( commandx, "or" ); execute_via_varying( yi, labels, home, gullible, results ); } else if ( commandx.matches( "macaulay" ) ) { if ( home->current == 0 ) WARNRET("The current configuration is undefined."); config& c = home->configs(home->current); if ( !c.terminal( ) ) WARNRET("The current configuration must be terminal."); matrix M = c.basic_small( ); execute_macaulay( M ); } else if ( commandx.matches( "uptoisomorphismshow" + var + "!=0" ) ) { commandx = commandx.after("uptoisomorphismshow"); static Regex var_pattern(var); String variable = take(commandx, var_pattern); execute_up_to_isomorphism_show(home, variable, gullible, results); } else if ( commandx.contains( "show", 0 ) ) { if ( home->current == 0 ) WARNRET("The current configuration is undefined."); String joint_string; commandx.del( "show" ); bool joint = false, joint_set = false, iterate = false; bool common = false; if ( commandx.contains( ")" ) && commandx[0] == '(' ) { String args = commandx.before( ")" ); args.del( "(", 0 ); commandx = commandx.after( ")" ); prevector argsv = unpack(args); static Regex joint_pat( "joint:" + number_pat ); if ( !gullible ) { for ( int i = 0; i < argsv.length; i++ ) { if ( argsv(i) == "joint" ) joint = true; else if ( argsv(i).matches( joint_pat ) ) { joint = joint_set = true; joint_string = argsv(i).after( ":" ); set_numerical_parameter( "usedualdualforjoint", joint_string, "save" ); set_numerical_parameter( "usedualdualforjoint", joint_string, "set" ); } else if ( argsv(i) == "iterate" ) iterate = true; else if ( argsv(i) == "common" ) { iterate = true; common = true; } else ERROR( "Illegal argument to show." ); } } } bool new_active_needed = false; config& c = home->configs(home->current); constraintlist clist(commandx); forPixDef( p, clist ) { forPixDef( q, clist(p).LHS ) c.check_variable( clist(p).LHS(q).var ); } bool answer; if (!gullible) { if ( !iterate ) answer = home->show(clist, results, show_quiet, constraintlist( ), joint); else { prevector var; prevector< pair > bound; reformat_constraintlist( clist, var, bound ); answer = round_by_lp( c, var, bound, common | !joint, common | joint, 2, show_quiet, results ); } if (joint_set) set_numerical_parameter( "usedualdualforjoint", joint_string, "restore" ); if (!answer) WARNRET( "Show failed." ); } forPix( p, clist ) c.add_constraint( clist(p), results, new_active_needed, !show_config_creation ); if (new_active_needed) home->deactivate( ); } else if ( commandx.contains( "alt", 0 ) ) { if ( home->current == 0 ) WARNRET( "Current configuration is undefined." ); config& c = home->configs(home->current); if ( !c.terminal( ) ) WARNRET( "The current configuration must be terminal." ); commandx = commandx.after( "alt" ); SLList sources; generic_object g = evaluate_expression( commandx, results, home, code_label, sources ); g.convert( "MatF2" ); matrix M = g; M.reduce_nz( ); if ( !isomorphic( M, c.basic_small( ) ) ) WARNRET( "Your alternate description is not " << "isomorphic to the current configuration." ); String ti = commandx_save.after("alt"); if ( ti[0] == ' ' ) ti = ti.after( " " ); c.alt_title = ti; } else result = false; } set_compile_file(execute2.cc) HIDE( ![ ifelse(UNAME,Openstep,![#include ]!) #include #include #include #include #include #include #include #include #include "homedefs.h" #include #include "state.h" #include "bitvec.h" #include "codetable.h" #include "opt.h" #include "graph.h" typedef triple< int, int, OSLList< vector > > packed_matrix_list; matrix unpack(char*, int, int); vector pack(matrix); #include "generic.h" matrix canonical_form(matrix); #include "uniq.h" extern int warnings_are_fatal, auto_macaulay, fill_weight; extern int dual_transform_length_limit, auto_joint_list, auto_group_computation, auto_dual_column_deletion, auto_residual_transform, group_size_limit, auto_dual_residual_transform, auto_group_residual_transform, auto_group_residual_transform_alt, auto_puncture_transform, find_regular_group_element, auto_dual_transform, gullible, auto_orbit_transform, nzv_length_max, i1low, i1high, max_create, i2low, i2high, show_roots, auto_enlarge_by_dual_word, random_search, auto_cyclic_test, min_vector_weight, use_joint_variables, clear_newcodes, bound_dual_search, debug, bound_quiet, bound_verify, status_quiet; extern long total_time_used; extern constraintlist input_mask, output_mask; extern "C" int isdigit(int); Integer round_down_to_power_of_2(Integer); Integer round_up_to_power_of_2(Integer); void parse_j_var(String, int&, int&, int&); String make_j_var(int, int, int); bool sub_to_dual_radius(int, partition, matrix, int); void code_search(int, prevector< prevector >, codetable&, String, int, vector, int, codehome*, matrix = matrix(0,0)); void random_code_search(int, prevector< prevector >, codetable&, String, int, vector, int, codehome*, matrix = matrix(0,0)); bool iso_member(const matrix&, const SLList< matrix >&); Permutation get_canonical(vertex_colored_graph&, int); bool realizable(config_core&, constraintlist&, codehome*, codetable&); bool round_by_lp(config&, prevector, prevector< pair >&, bool, bool, int, bool, codetable&); void reformat_constraintlist(constraintlist, prevector&, prevector< pair >&); vector dual_of_we(vector, bool = false); void log2(const Integer&, Integer&, Integer&); typedef vector polyF2; inline int deg( const polyF2& f ) { int i; for ( i = f.length-1; i >= 0; i-- ) if ( f(i).x != 0 ) break; return i; } polyF2 remainder(polyF2, const polyF2&); pair< int, vector > roots(polyF2); int yno(String); int rcmp(const number&, const number&); int rcmp(const int&, const int&); int take_int(String&, const Regex&); int String_cmp(const String&, const String&); SLList< pair< int, matrix > > punctured_codes(const matrix&); SLList< vector > dual_words_of_given_weight(matrix, int); prevector< vector > tuple_orbits(matrix, int); String list_of(const String&, const String& = ","); generic_object evaluate_expression(String, codetable&, codehome*, String&, SLList&); void sort_by_secondx( prevector< pair >& ); int min_distance(const matrix&, int); extern long time_used_by_build; extern int allowed_failures, doubly_even_test, no_test_if_classified; extern int auto_mu1; extern String LHS_pat, label_pat, bang_label_pat, gen_label_pat, config_list, config_list_piece; void auto_orbit_search(matrix, String, codetable&, codehome*); int process_new_matrix(codehome*, matrix, String, codetable&, int = 0, bool = false, int = 0, bool = false); prevector< triple< int, int, prevector< pair > > > sblv_triple_maker(const partition&, const partition&, const wordtype&, wordtype&, int = 0); SLList codeword_orbits(config&); void auto_dual_search(matrix, String, codetable&, codehome*); void execute_macaulay(const matrix&); void execute_equals(codehome*, Pix, Pix, bool); void execute_kill_variable_by(codehome*, prevector, bool, codetable&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); inline bool test(const Rational& a, const Rational& b, char sense) { if ( sense == '=' ) return a == b; if ( sense == '<' ) return a <= b; return a >= b; } matrix subdivide_matrix(const matrix&, const partition&, const wordtype&, bool, bool = true); pair< Permutationlist, Integer > find_automorphism_group(const matrix&); config_core canonical_form( config_core, bool = false ); prevector< prevector > orbits( prevector< matrix > ); bool isomorphic( prevector< prevector >* ); extern SLList< matrix > newcodes; extern "C" int srandomx(unsigned); extern "C" long randomx( ); matrix direct_sum(prevector< matrix >); prevector expand_config_list(codehome*, String); void mul( const vector&, const matrix&, vector&); ostream& operator<<(ostream&, const prevector&); ]! ) index_command(config from) void execute_config_from( codehome* home, String vars, String label, bool gullible, codetable& results ) { if ( home->current == 0 ) ERROR("The current configuration is undefined."); prevector lvs = unpack( vars, "|" ); for ( int i = 0; i < lvs.length; i++ ) { config& cs = home->configs(home->current); cs.check_variable(lvs(i)); if ( lvs(i)[0] != 'x' ) ERROR( lvs(i) << " is not a basic local variable." ); wordtype wx( &cs, lvs(i) ); if ( !gullible && !cs.known( lvs(i) + "!=0" ) && !home->show( lvs(i) + "!=0", results ) ) ERROR("I couldn't show that " << lvs(i) << " is nonzero."); home->activate(false, results); Pix pi = subdivide( cs, wx, results ); home->configs.join( home->current, pi, wx ); home->set_current(pi); } if ( !label.empty( ) ) { forPixDef( j, home->labels ) if ( home->labels(j).first == label ) ERROR("Same label for configuration used twice."); home->labels.append( make_pair( label, home->current ) ); } } index_method(bound_by_dual_search) void bound_by_dual_search( term_sum t, codehome* home, codetable& results, bool joint ) { constraint c; c.LHS = t; Integer low, high, not_low, not_high; bool lower_bound_found = false, upper_bound_found = false; // Check for known bounds. forPixDef( p, t ) if ( t(p).coeff < Rational(0) ) break; bool nonneg = (p == 0); if (nonneg) { String x(t); x.gsub(RXwhite,""); low = 0; high = -1; home->configs(home->current).evaluate( x, low, high ); lower_bound_found = true; not_high = low - 1; if ( high >= 0 ) { upper_bound_found = true; not_low = high + 1, cerr << "I know: " << low << " <= " << t << " <= " << high << ".\n"; // Test to see if known bounds are sharp. c.sense = '>'; c.RHS = low + 1; if (debug) cerr << "testing to see if " << c << "\n"; if ( !home->show( c, results, true, constraintlist( ), joint ) ) { c.sense = '<'; c.RHS = high - 1; if (debug) cerr << "testing to see if " << c << "\n"; if (!home->show(c, results, true, constraintlist( ), joint)) { cerr << "Final conclusion: " << low << " <= " << t << " <= " << high << ".\n"; return; } } } else cerr << "I know: " << low << " <= " << t << ".\n"; } // Get lower bound on t. if ( !lower_bound_found ) { if (nonneg) { low = 0; cerr << "I know: 0 <= " << t << ".\n"; } else { c.sense = '>'; c.RHS = 0; if (debug) cerr << "testing to see if " << c << "\n"; if ( home->show( c, results, true, constraintlist( ), joint ) ) low = 0; else { c.RHS = -1000; while(1) { if (debug) cerr << "testing to see if " << c << "\n"; if ( home->show( c, results, true, constraintlist( ), joint ) ) { low = c.RHS; break; } c.RHS *= 1000; } } cerr << "I know: " << low << " <= " << t << ".\n"; } } // Now get upper bound on t. if ( !upper_bound_found ) { c.sense = '<'; c.RHS = 0; if (debug) cerr << "testing to see if " << c << "\n"; if (home->show(c, results, true, constraintlist( ), joint)) high = 0; else { c.RHS = 1000; while(1) { if (debug) cerr << "testing to see if " << c << "\n"; if (home->show(c, results, true, constraintlist( ), joint)) { high = c.RHS; break; } c.RHS *= 1000; } } cerr << "Now I know: " << low << " <= " << t << " <= " << high << ".\n"; not_low = high + 1; not_high = low - 1; while( c.RHS >= 10 ) { c.RHS /= 10; if (debug) cerr << "testing to see if " << c << "\n"; if ( home->show( c, results, true, constraintlist( ), joint ) ) { high = c.RHS; cerr << "Now I know: " << low << " <= " << t << " <= " << high << ".\n"; } else { not_high = c.RHS; break; } } } while(1) { if (low + 1 == not_low && high - 1 == not_high) break; if ( low + 1 != not_low ) { // Try to raise low. c.sense = '>'; Integer sum = low + not_low; if ( odd(sum) ) ++sum; c.RHS = sum/2; if (debug) cerr << "testing to see if " << c << "\n"; if ( home->show( c, results, true, constraintlist( ), joint ) ) { low = c.RHS; not_high = max( not_high, low - 2 ); cerr << "Now I know: " << low << " <= " << t << " <= " << high << ".\n"; } else not_low = c.RHS; } if ( high - 1 != not_high ) { // Try to lower high. c.sense = '<'; Integer sum = high + not_high; if ( odd(sum) ) ++sum; c.RHS = sum/2; if (debug) cerr << "testing to see if " << c << "\n"; if ( home->show( c, results, true, constraintlist( ), joint ) ) { high = c.RHS; not_low = min( not_low, high + 2 ); cerr << "Now I know: " << low << " <= " << t << " <= " << high << ".\n"; } else not_high = c.RHS; } } cerr << "Final conclusion: " << low << " <= " << t << " <= " << high << ".\n"; } index_command(bound) void execute_bound( codehome* home, String s, codetable& results ) { if ( home->current == 0 ) ERROR("The current configuration is undefined."); bool joint = false, iterate = false, common = false; if ( s.contains( ")" ) && s[0] == '(' ) { String args = s.before( ")" ); args.del( "(", 0 ); s = s.after( ")" ); prevector argsv = unpack(args); for ( int i = 0; i < argsv.length; i++ ) { if ( argsv(i) == "joint" ) joint = true; else if ( argsv(i) == "iterate" ) iterate = true; else if ( argsv(i) == "common" ) { iterate = true; common = true; } else ERROR( "Illegal argument to bound." ); } } config& c = home->configs(home->current); prevector ss = unpack(s); if ( c.share->realizable == -1 ) WARNRET( "The current configuration is unrealizable." ); home->activate(false, results); opt_table search(home), search_joint(home); SLList brack, brack_joint; weightlist w = home->ww(home->current); w.del(0); for ( int i = 0; i < ss.length; i++ ) { String v = ss(i); if ( v.length( ) == 0 ) continue; if ( v.length( ) == 1 ) WARNRET("Syntax incorrect."); bool bracket = false; if ( v[0] == '[' ) { v.del('['); if ( v[ v.length( ) - 1 ] != ']' ) WARNRET("Syntax incorrect."); v.del(']'); bracket = true; } if ( v == "y*" ) { forPixDef( p, w ) { if (!joint) { search.add( term_sum( "y" + String(dec(w(p))) ) ); brack.append( bracket ); } else { search_joint.add( term_sum("y" + String(dec(w(p)))) ); brack_joint.append( bracket ); } } } else if ( v == "x*" ) { if (joint) WARNRET( "You can't use the (joint) option with " << "local variables." ); if ( c.assumed_cons.global( ) ) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; } EquivRelIntList e = home->active->auto_equiv( ); for ( int j = 1; j < e.length; j++ ) if ( e.minimal(j) ) { search.add( term_sum( home->active->vtable(j).maw.variable( ) ) ); brack.append( bracket ); } } else if ( v == "mu*" ) { for ( int j = c.share->dual_min_low; j <= c.share->dual_min_high; j++ ) { if (!joint) { search.add( String("mu") + dec(j) ); brack.append( bracket ); } else { search_joint.add( String("mu") + dec(j) ); brack_joint.append( bracket ); } } } else if ( v == "~x*" ) { if (joint) WARNRET( "You can't use the (joint) option with " << "local variables." ); if ( !c.assumed_cons.global( ) ) WARNRET( "Since there are local variables in the assumed " << "constraints for [current], you can't bound " << "~x*." ); pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; EquivRelIntList e = home->active->auto_equiv( ); int class_count = 1; mawhometable& vt = home->active->vtable; for ( int ii = 1; ii < e.length; ii++ ) { if ( e.minimal(ii) ) { opt_card oc; oc.request = "minmax"; oc.var.append( term (1, vt(ii).maw.variable( ) )); int j = ii; while( (j = e(j)) != ii ) oc.var.append( term (1, vt(j).maw.variable( ) ) ); search.data.append(oc); brack.append( bracket ); } } } else if ( v == "j*" ) { home->basic_joint_vars(&home->configs(home->current), results); prevector bjv = home->configs(home->current).share->wjv; if ( bjv.length == 0 ) INTERNAL_ERROR( "wjv length = 0 in execute_bound" ); for ( int j = 1; j < bjv.length; j++ ) { search_joint.add( bjv(j) ); brack_joint.append( bracket ); } } else if ( v == "jyd*" ) { forPixDef( p, w ) { for ( int j = c.share->dual_min_low; j <= min( int(c.share->dual_min_high), home->n - w(p) ); j++ ) { search_joint.add( String("jy") + dec(w(p)) + "d" + dec(j) ); brack_joint.append( bracket ); } } } else { bool local = false, jointc = false; if_no_match( v, LHS_pat ) WARNRET(v << " is not of the right form."); term_sum t( v ); forPixDef( p, t ) { c.check_variable( t(p).var ); if ( local_var( t(p).var ) ) local = true; if ( joint_var( t(p).var ) ) jointc = true; } if ( local && jointc ) WARNRET( "You have mixed local and joint variables." ); if ( local && joint ) WARNRET( "Don't use (joint) option with local variables." ); if (jointc || joint) { search_joint.add( v ); brack_joint.append( bracket ); } else { search.add( v ); brack.append( bracket ); } } } if (iterate) { int l = search.data.length( ) + search_joint.data.length( ); prevector var(l); int i = 0; forPixDef( p, search.data ) var(i++) = search.data(p).var; forPix( p, search_joint.data ) var(i++) = search_joint.data(p).var; prevector< pair > bound; if ( round_by_lp( c, var, bound, common | !joint, common | joint, bound_verify, bound_quiet, results ) ) WARNRET( "It would appear that the current " << "configuration is infeasible." ); for ( i = 0; i < var.length; i++ ) { if ( bound(i).first == bound(i).second ) cerr << var(i) << " = " << bound(i).first << "\n"; else if ( bound(i).first == 0 ) cerr << var(i) << " <= " << bound(i).second << "\n"; else cerr << bound(i).first << " <= " << var(i) << " <= " << bound(i).second << "\n"; } return; } if ( !search.data.empty( ) ) { if (bound_dual_search) { forPixDef( p, search.data ) bound_by_dual_search( search.data(p).var, home, results, false ); } else { search.compute(results); if ( !search.feasible ) WARNRET( "It would appear that the current " << "configuration is infeasible." ); Pix pb = brack.first( ); forPixDef( p, search.data ) { if (!brack(pb) || search.data(p).min >= 1e-6 || search.data(p).max <= 1 - 1e-6) cerr << search.data(p); brack.next(pb); } } } if ( !search_joint.data.empty( ) ) { if (bound_dual_search) { forPixDef( p, search_joint.data ) bound_by_dual_search( search_joint.data(p).var, home, results, true ); } else { search_joint.compute(results, true); if ( !search_joint.feasible ) { WARNING( "It would appear that the current " << "configuration is infeasible." ) return; } Pix pb = brack_joint.first( ); forPixDef( p, search_joint.data ) { if ( !brack(pb) || search_joint.data(p).min >= 1e-6 || search_joint.data(p).max <= 1 - 1e-6 ) cerr << search_joint.data(p); brack_joint.next(pb); } } } } TEX( ![ The following class stores a list of wordtypes as a string of zeros and ones. For example, if the partition is $2,5,6$ and the wordtype is $1,3,4$, the wordtype would contribute {\tt 1011100111100} to the string. ]! ) index_class(compressed_wordtype_list) class compressed_wordtype_list { public: bitvec b; int length; // number of wordtypes compressed_wordtype_list( ) { } compressed_wordtype_list(const partition& p, SLList l) : length( l.length( ) ), b( p.n * l.length( ) ) { int i, j, k, b_ptr = 0; forPixDef( q, l ) { wordtype& w = l(q); for ( j = 0; j < p.length; j++ ) { int ones = w(j); int zeros = p(j) - w(j); for ( k = 0; k < ones; k++ ) b.set(b_ptr++); for ( k = 0; k < zeros; k++) b.set(b_ptr++, false); } } } index_method(uncompress) SLList uncompress(const config& c) const { SLList l; int i, j, k, ptr = 0; for ( i = 0; i < length; i++ ) { vector v(c.part.length); for ( j = 0; j < c.part.length; j++ ) { int r = c.part(j); for ( k = 0; k < r; k++ ) v(j) += b.value(ptr++); } wordtype w(v); w.c = &c; l.append(w); } return l; } HIDE( ![ friend bool operator==(const compressed_wordtype_list& w1, const compressed_wordtype_list& w2) { INTERNAL_ERROR( "== not implemented for class compressed_wordtype_list" ); } ]! ) }; HIDE( ![ void process_config_target_list(codehome*, prevector, SLList< pair< config, vector > >&, SLList&, SLList&, SLList&, bool, const codetable&); bool check_config_list(codehome*, const matrix&, const SLList< pair< config, vector > >&, const SLList&, const SLList&); ]! ) TEX( ![ \verb|subdivide_wordtype_list|: The main inputs to this routine are configurations {\tt b}, {\tt c}, and {\tt d}, a wordtype {\tt w}, and a list of wordtypes for {\tt c} named {\tt list}. The relation of these configurations is to be as follows. First, the only use of {\tt b} is to access {\tt b.share->ww} and {\tt b.share->wjv}. Presumably {\tt c} is then obtained from {\tt b} by a sequence of subdivisions. Then {\tt d} is obtained from {\tt c} by subdivision along {\tt w}. The configurations {\tt c} and {\tt d} are not required to be fully defined. In particular, we do not require that their {\tt share} members be defined. Upon entry, {\tt list} is to be the list of minimal admissible wordtypes for {\tt c} (exclusive of the trivial wordtype). A list of minimal admissible wordtypes for {\tt d} is returned. If the variable \verb|use_joints| is set, we utilize knowledge of joint variables to prune the returned list. The code below has much in common with \verb|subdivide_basic_local_variable|. Something should be done to eliminate the replication. ]! ) index_method(subdivide_wordtype_list) SLList subdivide_wordtype_list( SLList list, codehome* home, Pix bpix, config& c, config& d, wordtype w, codetable& results, bool use_joints, bool return_all ) { partition P = d.part; config& b = home->configs(bpix); int i, j; SLList listn; prevector bsw(home->n + 1); for ( i = 0; i <= home->n; i++ ) bsw(i) = false; forPixDef( ppp, b.share->ww ) bsw( b.share->ww(ppp) ) = true; forPixDef( z, list ) { wordtype v = list(z), vnew = vector(P.length); vnew.c = &d; wordtype vnew2 = vnew; prevector< triple< int, int, prevector< pair > > > t = sblv_triple_maker( P, c.part, v, vnew ); vector indx( t.length ); wordtype vup = v; for ( i = 0; i < v.length; i++ ) if ( w(i) == c.part(i) ) vup(i) = w(i) - v(i); while(1) { for ( i = 0; i < t.length; i++ ) { vnew(t(i).first) = t(i).third(indx(i)).first; vnew(t(i).first + 1) = t(i).third(indx(i)).second; } for ( i = 0; i < t.length; i++ ) vup( t(i).second ) = P( t(i).first ) - vnew(t(i).first) + vnew( t(i).first + 1 ); // Check for admissibility of vup. Note the following possibly // better alternative approach: Cycle through the list of // wordtypes wq (given up to equivalence). Check to see if wq is // ``related'' to vup (easy calculation). If not (for all wq), // vup is inadmissible. Also check against joint variable // information. bool adm = true; wordtype wu(&c); for ( i = 0; i < c.small.x.nrows; i++ ) { wu.act( c.small.x(i), vup ); if ( !bsw( sum(wu) ) ) { adm = false; break; } } if ( adm && use_joints ) { home->basic_joint_vars(&home->configs(bpix), results); for (i = 0; i < c.small.x.nrows; i++) for (j = i+1; j < c.small.x.nrows; j++) { wu.act( c.small.x(i), vup ); int i1 = sum(wu); wu.act( c.small.x(j), vup ); int i2 = sum(wu); word wij = c.small.x(i) + c.small.x(j); int i3 = wij * c.part; var = make_j_var(i1, i2, i3); if ( !b.share->wjv.member(var) ) { adm = false; goto joint_fails; } } } joint_fails: if ( adm && home->opt.dual_radius > 0 ) { // Check covering radius. partition px = subdivide_partition( P, vnew ); matrix bx = subdivide_matrix( d.small.basis, P, vnew, true ); if ( home->opt.dual_radius_length == home->n ) { if ( !sub_to_dual_radius( home->opt.dual_radius, px, bx, home->opt.dual_radius_dim ) ) adm = false; } else { partition dp( px.length + 1 ); for ( i = 0; i < px.length; i++ ) dp(i) = px(i); dp(px.length) = home->opt.dual_radius_length - home->n; bx.resize( bx.nrows, bx.ncols + 1 ); if ( !sub_to_dual_radius(home->opt.dual_radius, dp, bx, home->opt.dual_radius_dim)) adm = false; } } if (adm) listn.append(vnew); for ( i = t.length - 1; i >= 0; i-- ) if ( indx(i) < t(i).third.length - 1 ) break; if ( i < 0 ) break; for ( j = t.length - 1; j > i; j-- ) indx(j) = 0; ++indx(i); } } if (return_all) return listn; TEX( ![ \begin{quote} Delete wordtypes equivalent to the trivial wordtype. (Do they exist?) \end{quote} ]! ) SLList listn2; word www( P.length ); forPixDef( qo, listn ) { wordtype wdt = listn(qo); for ( i = 0; i < P.length; i++ ) { if ( 0 < wdt(i) && wdt(i) < P(i) ) break; www(i) = (wdt(i) != 0); } if ( i < P.length || !d.small.basis.rowspace_member( www ) ) listn2.append( wdt ); } TEX( ![ \begin{quote} Reduce to a list of inequivalent wordtypes. (Is there a way of avoiding them in the first place?) \end{quote} ]! ) SLList listn3; prevector listn2v(listn2); for ( i = 0; i < listn2v.length; i++ ) d.make_minimal(listn2v(i)); listn2v.unique_sort(&wcmp); for ( i = 0; i < listn2v.length; i++ ) listn3.append(listn2v(i)); return listn3; } TEX( ![ Given a configuration {\tt c}, compute its list of minimal admissible wordtypes (not including zero). This is also done by the \verb|config_active| constructor, but here we try to do it more efficiently, which is possible if {\tt c} was obtained from another configuration by subdivision. ]! ) index_method(make_wordtype_list) SLList make_wordtype_list( codehome* home, Pix dpix, codetable& results, bool use_joints ) { Pix curr = home->current; SLList list; mawhometable mw; forPixDef( p, home->configs.edges ) { if ( dpix == home->configs.edges(p).second ) { Pix cpix = home->configs.edges(p).first; SLList ws = home->configs.edges[make_pair(cpix, dpix)]; if ( !ws.empty( ) ) { wordtype w = ws.front( ); config& c = home->configs(cpix); config& d = home->configs(dpix); home->set_current(cpix); home->activate( true, results, true ); mw = home->active->vtable; home->deactivate( ); // Generate the list of wordtypes for c, not including 0. for ( int i = 1; i < mw.length; i++ ) list.append( mw(i).maw ); list = subdivide_wordtype_list( list, home, cpix, c, d, w, results, use_joints, false ); home->set_current(curr); return list; } } } home->activate( true, results, true ); mw = home->active->vtable; for ( int i = 1; i < mw.length; i++ ) list.append( mw(i).maw ); home->deactivate( ); home->set_current(curr); return list; } index_command(via building) void execute_via_building( codehome* home, int show_terminals, int show_all_configs, bool gullible, String label1, prevector labels, bool via_building_show_extra_info, bool depth_first, codetable& results, String pound_label_head, int& pound_label_ctr, SLList< matrix >& terminals_m ) { time_used_by_build -= time(0); int pound_label_ctr_first = pound_label_ctr; Pix p, q, pix1 = home->label_to_Pix( label1, results ); home->set_current( pix1 ); config& b = home->configs(pix1); constraintlist bass; forPix( p, b.assumed_cons ) if ( b.assumed_cons(p).joint( ) ) bass.append( b.assumed_cons(p) ); if ( b.terminal( ) ) ERROR( "It is silly to invoke this command on a " << "terminal configuration." ); Integer fill_low, fill_high; if ( fill_weight > 0 ) b.evaluate( String("y") + dec(fill_weight), fill_low, fill_high ); SLList basals, others; uniq_mat_list terminals_found_can(home->n); SLList< pair< config, vector > > terminals; SLList pixlist; process_config_target_list( home, labels, terminals, basals, others, pixlist, gullible, results ); if (gullible) { home->implications.append( make_pair(home->current, pixlist) ); time_used_by_build += time(0); home->set_current(0); return; } SLList< triple< config_core, compressed_wordtype_list, bool > > stack; SLList stack_can; TEX(![ \begin{quote} The \verb|compressed_wordtype_list| is a list of all minimal, admissible, nontrivial basic local variables for the configuration; the {\tt bool} is set to {\tt false} when the configuration has been subdivided along each of these basic local variables. \end{quote} ]!) int config_count = 0, terminal_config_count = 0; int yvar = 0; if ( basals.length( ) == 1 && pixlist.length( ) == 1 && basals.front( ).assumed_cons.length( ) == 1 && basals.front( ).assumed_cons.front( ).simple_global( ) && basals.front( ).assumed_cons.front( ).sense == '<' ) yvar = yno(basals.front().assumed_cons.front( ).LHS.front( ).var); TEX( ![ \begin{quote} First we initialize the stack by putting on the current configuration. \end{quote} ]! ) SLList list0; Integer ybound; if ( yvar == 0 ) list0 = make_wordtype_list( home, pix1, results, use_joint_variables ); else { home->activate( true, results, false ); mawhometable& m = home->active->vtable; ybound = basals.front().assumed_cons.front( ).RHS; for ( int l = 1; l < m.length; l++ ) { forPix( p, m(l).w ) { wordtype alttype = m(l).maw; alttype.act( m(l).w(p) ); if ( sum(alttype) == yvar ) { list0.append( m(l).maw ); break; } } } home->deactivate( ); } stack.append( make_triple( config_core(home->configs(home->current)), compressed_wordtype_list(b.part, list0), true ) ); stack_can.append( canonical_form( config_core( home->configs(home->current) ) ) ); if (show_all_configs) cerr << "\nConfiguration " << ++config_count << "\n" << b << "will have <= " << list0.length( ) << " configurations directly below it.\n\n"; constraintlist kn = b.known_cons( ); config_core bcore(b); forPix( p, kn ) if ( kn(p).global( ) ) kn(p).LHS = bcore.simplify_global_vars( kn(p).LHS, b.share->ww, home->dim ); // Now for the main loop. while(1) { // Check to see if we're done and count nodes. int nodes = 0; int stack_length = 0; forPix( p, stack ) if ( stack(p).third ) { nodes += stack(p).second.length; stack_length++; } if ( nodes == 0 ) break; if (via_building_show_extra_info) cerr << "\nThere are now " << stack_length << " configurations " << "in the stack. When these are processed, there may be " << "as many as " << nodes << " configurations in the " << "stack, but in all likelihood there will not be so " << "many, because some of them will be isomorphic.\n\n"; TEX( ![ \begin{quotea} Find a stack element with a wordtype list of minimal length, unless \verb|depth_first| is set. \end{quotea} ]! ) if ( !depth_first ) { int lenx = -1; forPix( p, stack ) if ( stack(p).third && (lenx < 0 || stack(p).second.length < lenx ) ) { q = p; lenx = stack(p).second.length; } } else { int dimx = -1, lenx; forPix( p, stack ) if ( stack(p).third ) { if ( stack(p).first.smallbasis.nrows > dimx ) { q = p; dimx = stack(p).first.smallbasis.nrows; lenx = stack(p).second.length; } else if ( stack(p).first.smallbasis.nrows == dimx && stack(p).second.length < lenx ) { q = p; lenx = stack(p).second.length; } } } int i, j, k; config c; c.home = home; c.part = stack(q).first.part; c.small.basis = stack(q).first.smallbasis; c.dualsmall.basis = stack(q).first.dualsmallbasis; c.leading1s = c.small.basis.leading_ones( ); c.small.build( ); vector w0; if ( fill_weight > 0 ) w0 = c.smallcode_we( ); SLList list = stack(q).second.uncompress(c), list2; TEX( ![ \begin{quotea} We can reduce the set of variables which we will subdivide along by taking into account automorphisms of the configuration. \end{quotea} ]! ) prevector listv(list); for ( i = 0; i < listv.length; i++ ) c.make_minimal( listv(i) ); listv.sort(&wcmp); if ( listv.length == 1 ) list2.append( listv(0) ); else { wordtype alt(&c); int pp; pair< Permutationlist, Integer> au = c.find_automorphism_group(); EquivRelIntList e(listv.length + 1); // The last element of e is a "dummy" place for an inadmissible // variable. for ( i = 0; i < listv.length; i++ ) { for ( j = 0; j < au.first.length; j++ ) { alt = listv(i); au.first(j).act(alt); c.make_minimal(alt); pp = listv.pos(alt, &wcmp); // Test if an admissible basic local variable is // automorphism-equivalent to an inadmissible basic // local variable. if ( pp < 0 ) e.join( i, listv.length ); else e.join( i, pp ); } } for ( i = 0; i < listv.length; i++ ) if ( e.minimal(i) ) list2.append( listv(i) ); } forPix( p, list2 ) { TEX( ![ \begin{quotebneg} Subdivide to get a new configuration. If the new configuration is terminal, we force its dual small code to be zero. \end{quotebneg} ]! ) wordtype w = list2(p); config d; d.home = c.home; d.part = subdivide_partition( c.part, w ); partition P = d.part; int s = d.part.length; d.small.basis = subdivide_matrix(c.small.basis, c.part, w, true); if ( d.small.basis.nrows != home->dim ) d.dualsmall.basis = subdivide_matrix( c.dualsmall.basis, c.part, w, false ); else d.dualsmall.basis.set_size( 0, s ); d.leading1s = d.small.basis.leading_ones( ); // Have we already looked at d (non-terminal case)? Pix uu = 0; time_used_by_build += time(0); if ( d.small.basis.nrows != home->dim ) { config_core dc = canonical_form( config_core(d) ); forPix( uu, stack_can ) if ( dc == stack_can(uu) ) break; } time_used_by_build -= time(0); vector wts; if ( uu == 0 ) { wts = d.smallcode_we( ); if ( fill_weight > 0 && wts(fill_weight) < fill_low && wts(fill_weight) == w0(fill_weight) ) uu = q; } // Does d violate a known simple global constraint? if ( uu == 0 && d.small.basis.nrows != home->dim ) forPix( uu, kn ) if ( kn(uu).simple_global( ) && kn(uu).sense != '>' ) { int yn = yno( kn(uu).LHS.front( ).var ); if ( wts(yn) > kn(uu).RHS ) break; } goto skip_cover; // Check covering radius. if ( uu == 0 && d.small.basis.nrows != home->dim && home->opt.dual_radius > 0 ) { if ( home->opt.dual_radius_length == home->n ) { if ( !sub_to_dual_radius( home->opt.dual_radius, d.part, d.small.basis, home->opt.dual_radius_dim ) ) uu = q; } else { partition dp( d.part.length + 1 ); for ( i = 0; i < d.part.length; i++ ) dp(i) = d.part(i); dp(d.part.length) = home->opt.dual_radius_length - home->n; matrix ds( d.small.basis ); ds.resize( ds.nrows, ds.ncols + 1 ); if ( !sub_to_dual_radius(home->opt.dual_radius, dp, ds, home->opt.dual_radius_dim) ) uu = q; } } skip_cover: TEX( ![ \begin{quoteb} Deal with the case where $d$ is terminal. First check to see if it satisfies all known global constraints. Next check to see if options are satisfied. Then check to see if the given terminal configuration has already been encountered. An experiment should be done to determine if reversing the order of the last two steps would be faster. \end{quoteb} ]! ) Pix pp; if ( uu == 0 && d.small.basis.nrows == home->dim ) { Pix qm, rr, ccc; config_core dcore(d); matrix dm; bool found; if (!realizable( dcore, bass, home, results )) goto get_out; dm = d.basic_small( ); // Have we already looked at d? time_used_by_build += time(0); if ( !terminals_found_can.add(dm) ) { time_used_by_build -= time(0); goto get_out; } time_used_by_build -= time(0); found = check_config_list( home, d.basic_small( ), terminals, basals, others ); if ( show_terminals || auto_macaulay || (!found && pound_label_head == "") ) { cerr << "Terminal configuration [#" << ++terminal_config_count << "] "; for ( i = 0; i < d.part.length; i++ ) { cerr << d.part(i); if ( i < d.part.length - 1 ) cerr << ","; } cerr << " : " << d.small.basis << "\n" << "has weight enumerator " << as_poly(wts) << ".\n"; } if (auto_macaulay) { cerr << "generators for ideal: "; execute_macaulay(d.basic_small( )); } if ( !found ) { if ( pound_label_head == "" ) { WARNING( "This code does not appear in your list." ); } else { for ( k = 1; k < pound_label_ctr_first; k++ ) { String pound_labelk = pound_label_head + dec(k) + "]"; Pix p = home->label_to_Pix(pound_labelk, results); if ( isomorphic(d.basic_small( ), home->configs(p).small.basis) ) break; } if ( k == pound_label_ctr_first ) { String pound_label = pound_label_head + dec(pound_label_ctr++) + "]"; if ( pound_label_head == "$" ) terminals_m.append( d.basic_small( ) ); else { if (show_terminals) { cerr << "creating " << pound_label << " terminal " << d.basic_small( ) << ";\n"; } config c( home, d.basic_small( ) ); if ( auto_group_computation ) { pair pp = c.find_automorphism_group( ); c.aut = pp.first; } Pix j = home->merge_config(c); pixlist.append(j); home->labels.append( make_pair(pound_label, j) ); } if ( max_create > 0 && pound_label_ctr > max_create ) { cerr << "Terminating via building due " << "to max create bound.\n"; home->implications.append( make_pair(home->current, pixlist) ); time_used_by_build += time(0); home->set_current(0); return; } } } } get_out: uu = stack.first( ); /* nonzero (kludge) */ } if ( uu == 0 && yvar > 0 && ybound < wts(yvar) ) { if ( d.small.basis.nrows != home->dim ) { cerr << "Configuration [#" << ++config_count << "] "; for ( i = 0; i < d.part.length; i++ ) { cerr << d.part(i); if ( i < d.part.length - 1 ) cerr << ","; } cerr << " : " << d.small.basis << "\n" << "has weight enumerator " << as_poly(wts) << ".\n"; } ERROR("The constraint y" << yvar << " <= " << ybound << " is violated by this configuration."); } if ( uu == 0 ) { SLList listn3 = subdivide_wordtype_list( list, home, pix1, c, d, w, results, use_joint_variables, false ); stack.append( make_triple( config_core(d), compressed_wordtype_list(d.part, listn3), !listn3.empty( ) ) ); stack_can.append( canonical_form( config_core(d) ) ); if (show_all_configs) { cerr << "Configuration " << ++config_count << "\n" << " config "; for ( i = 0; i < d.part.length; i++ ) { cerr << d.part(i); if ( i < d.part.length - 1 ) cerr << ","; } cerr << " : " << d.small.basis << " : " << d.dualsmall.basis << "\n" << "has weight enumerator " << as_poly(wts) << "\nand will have <= " << listn3.length( ) << " configurations directly below it.\n"; } } } stack(q).second.b.set_size(0); stack(q).third = false; } if ( pound_label_head != "$" ) { home->implications.append( make_pair(home->current, pixlist) ); home->set_current(0); } time_used_by_build += time(0); } index_command(clean) void execute_clean( String commandx ) { String input_file_name, output_file_name; commandx = commandx.after("clean<"); static Regex var_pattern(var); input_file_name = take( commandx, var_pattern ); commandx = commandx.after(">"); output_file_name = take( commandx, var_pattern ); prevector avoids(0); if (!commandx.empty( )) avoids = unpack( String(commandx.after("(")).before(")") ); ifstream infile( input_file_name ); ofstream outfile( output_file_name ); DLList< pair > main; constraint c; Pix p, q, r, s, sa, i; // Read constraints. while( infile.peek( ) != EOF ) { infile >> c; main.append( make_pair( c, Rational(c.RHS) ) ); infile >> ws; } // skip over whitespace infile.close( ); // Eliminate equality constraints. forPix( p, main ) { if ( main(p).first.sense != '=' ) continue; term t; constraint& cc = main(p).first; term_sum& ts = cc.LHS; term_sum ts2; // Delete any leading terms which are zero. while(1) { if ( ts.length( ) == 0 ) { if ( main(p).second == Rational(0) ) goto tail; ERROR( "self-contradictory constraint" ); } if ( ts.front( ).coeff != Rational(0) ) break; ts.del_front( ); } // Find the nonzero term whose rank is highest // on the avoidance list. if ( avoids.length != 0 ) { Pix best_pix; int kk, best_rank = -1; forPix( i, ts ) { if ( ts(i).coeff == Rational(0) ) continue; for ( kk = 0; kk < avoids.length; kk++ ) { if ( ts(i).var == avoids(kk) ) { if ( kk > best_rank ) { best_rank = kk; best_pix = i; } break; } } if ( kk == avoids.length ) { best_pix = i; break; } } if ( best_pix != ts.first( ) ) swap( ts(best_pix), ts(ts.first( )) ); } t = ts.front( ); cerr << "eliminating " << t.var << " by replacing it by "; ts.del_front( ); ts2 = ts; forPix( i, ts2 ) ts2(i).coeff = -ts2(i).coeff / t.coeff; if ( ts2.length( ) != 0 ) cerr << ts2 << " + "; cerr << str( main(p).second / t.coeff ) << "\n"; forPix( q, main ) { if ( q == p ) continue; term_sum& tt = main(q).first.LHS; forPix( r, tt ) if ( tt(r).var == t.var ) break; if ( r != 0 ) { forPix( s, ts2 ) { forPix( sa, tt ) if ( ts2(s).var == tt(sa).var ) { tt(sa).coeff += ts2(s).coeff * tt(r).coeff; break; } if ( sa == 0 ) tt.append( term( ts2(s).coeff * tt(r).coeff, ts2(s).var ) ); } main(q).second -= tt(r).coeff * main(p).second / t.coeff; tt.del(r); // Delete terms with zero coefficient. forPix( sa, tt ) { repete: if ( tt(sa).coeff == Rational(0) ) { tt.del(sa); if ( sa == 0 ) break; goto repete; } } } } // If we've just hit a constraint // like "x = 7", replace it by "0 = 0". if ( ts.length( ) == 0 ) main(p).second = 0; else { if ( t.coeff > Rational(0) ) main(p).first.sense = '<'; else main(p).first.sense = '>'; } tail: continue; } // Test for constraints whose left hand side is zero. constraint d; Pix ww; forPix( p, main ) { repeat: d = main(p).first; forPix( ww, d.LHS ) if ( d.LHS(ww).coeff != Rational(0) ) break; if ( ww == 0 ) { if ( test ( 0, main(p).second, d.sense ) ) { main.del(p); if ( p == 0 ) break; goto repeat; } ERROR( "self-contradictory constraint found" ); } } // Change <= constraints if any into >= constraints. forPix( p, main ) { if ( main(p).first.sense == '<' ) { main(p).first.sense = '>'; main(p).second = -main(p).second; forPix( q, main(p).first.LHS ) main(p).first.LHS(q).coeff = -main(p).first.LHS(q).coeff; } } // Eliminate constraints whose left hand side is nonnegative // but whose right hand side is non-positive. forPix( p, main ) { repeet: if ( main(p).second > Rational(0) ) continue; forPix( q, main(p).first.LHS ) if ( main(p).first.LHS(q).coeff < Rational(0) ) break; if ( q == 0 ) { main.del(p); if ( p == 0 ) break; goto repeet; } } // Check to see if any constraint implies another constraint // according to the rule // c1v1 +...+ cnvn >= e --> c1'v1 +...+ cn'vn >= e' // if there exists r > 0 such that // c1' >= rc1, ..., cn' >= rcn, e' <= re. // Probably we should normalize first. Pix pp, qq; forPix( p, main ) forPix( q, main ) { next_q: if ( p == q ) continue; term_sum& p_LHS = main(p).first.LHS; term_sum& q_LHS = main(q).first.LHS; Rational rmin = 0, rmax = -1; //-1 stands for infinity Rational rmin_new, rmax_new; // Does main(p) imply main(q)? (Several steps.) if ( main(p).second == Rational(0) ) { if ( main(q).second > Rational(0) ) goto no_way; } else if ( main(p).second > Rational(0) ) { rmin_new = main(q).second / main(p).second; rmin = max( rmin, rmin_new ); } else { if ( main(q).second >= Rational(0) ) goto no_way; rmax_new = main(q).second / main(p).second; if ( rmax == Rational(-1) ) rmax = rmax_new; else rmax = min( rmax, rmax_new ); } // If there are any variables which have nonnegative // coefficients in main(p) but which have negative // coefficients in main(q), the answer is no. forPix( qq, q_LHS ) { if ( q_LHS(qq).coeff < Rational(0) ) { forPix( pp, p_LHS ) if ( q_LHS(qq).var == p_LHS(pp).var ) { if ( p_LHS(pp).coeff >= Rational(0) ) goto no_way; goto maybe; } goto no_way; } maybe: continue; } forPix( pp, p_LHS ) { if ( p_LHS(pp).coeff == Rational(0) ) continue; forPix( qq, q_LHS ) if ( q_LHS(qq).var == p_LHS(pp).var ) { if ( p_LHS(pp).coeff > Rational(0) ) { if ( q_LHS(qq).coeff == Rational(0) ) goto no_way; rmax_new = q_LHS(qq).coeff / p_LHS(pp).coeff; if (rmax == Rational(-1)) rmax = rmax_new; else rmax = min(rmax, rmax_new); if (rmax < rmin) goto no_way; } else { rmin_new = q_LHS(qq).coeff / p_LHS(pp).coeff; rmin = max( rmin, rmin_new ); if ( rmax != Rational(-1) && rmax < rmin ) goto no_way; } break; } if ( qq == 0 && p_LHS(pp).coeff > Rational(0) ) goto no_way; } main.del(q); if ( q == 0 ) break; goto next_q; no_way: continue; } // Write main constraints. forPix( p, main ) { d = main(p).first; // Normalize. constraint d2; Integer multiplier = main(p).second.denominator( ); Integer divider = main(p).second.numerator( ); forPixDef( j, d.LHS ) { multiplier = lcm( multiplier, d.LHS(j).coeff.denominator( ) ); divider = gcd( divider, d.LHS(j).coeff.numerator( ) ); } forPix( j, d.LHS ) d2.LHS.append( term ( (d.LHS(j).coeff.numerator( ) * multiplier) / (d.LHS(j).coeff.denominator( ) * divider), d.LHS(j).var ) ); d2.RHS = (main(p).second.numerator( ) * multiplier) / (main(p).second.denominator( ) * divider); d2.sense = d.sense; // Print the constraint. outfile << d2 << "\n"; } outfile.close( ); } #define LET(l) char('a' + l) index_command(macaulay) void execute_macaulay( const matrix& M ) { ofstream mac_in( calculations_dir + "/Split-mac-in" ); int i, j; mac_in << "ring R\n" << " 2 ;\n"; mac_in << " " << M.nrows << " ;\n"; mac_in << " " << "a-" << LET(M.nrows - 1) << " ;\n"; mac_in << " ;\n" << " ;\n\n"; mac_in << "ideal I\n"; mac_in << choose( M.nrows, 2 ) << "\n"; for ( i = 0; i < M.nrows; i++ ) for ( j = i + 1; j < M.nrows; j++ ) mac_in << LET(i) << "2" << LET(j) << "+" << LET(i) << LET(j) << "2\n"; mac_in << "std I I\n" << "qring I S\n"; mac_in << "mat M\n" << M.nrows << "\n" << M.ncols << "\n"; for ( i = 0; i < M.ncols; i++ ) for ( j = 0; j < M.nrows; j++ ) mac_in << M(j,i) << "\n"; mac_in << "" << calculations_dir << "/Split-mac-out\n"; mac_in.close( ); system( "Macaulay < " + calculations_dir + "/Split-mac-in " + "> " + calculations_dir + "/Split-mac-report" ); ifstream mac_out( calculations_dir + "/Split-mac-out" ); char d; while( mac_out.peek( ) != EOF ) { mac_out.get(d); cerr << d; } mac_out.close( ); } index_command(via varying) void execute_via_varying( String yi, prevector labels, codehome* home, bool gullible, codetable& results ) { if ( home->current == 0 ) ERROR("Current configuration not defined."); int i; prevector pixes(labels.length); for ( i = 0; i < labels.length; i++ ) pixes(i) = home->label_to_Pix(labels(i), results); prevector< pair< constraintlist, Integer > > work( labels.length ); for ( i = 0; i < labels.length; i++ ) { config& ci = home->configs(pixes(i)); if (!ci.basal( )) ERROR( labels(i) << " is not basal." ); work(i).first = ci.assumed_cons; forPixDef( p, work(i).first ) if ( work(i).first(p).simple_global( ) ) { constraint& r = work(i).first(p); if ( r.sense == '=' && r.LHS.front( ).var == yi ) { work(i).second = r.RHS; work(i).first.del(p); goto next_label; } } ERROR( labels(i) << " doesn't have a " << "constraint which fixes " << yi << "." ); next_label: continue; } sort_by_secondx( work ); for ( i = 1; i < work.length; i++ ) if ( work(i).second != work(i-1).second + 1 ) ERROR("Read the command definition again, please."); String dbl = String(dec(work(0).second)) + "<=" + yi + "<=" + dec(work(work.length-1).second); if ( !gullible && !home->show( constraintlist(dbl), results, false, constraintlist( ), false, true ) ) ERROR("I can't show that " << dbl << "."); for ( i = 0; i < labels.length; i++ ) { constraintlist forced(yi + "=" + dec(work(i).second)); if (!gullible && !home->show( work(i).first, results, true, forced, false, true )) ERROR("I can't deduce " << work(i).first << " from " << forced << "."); } home->implications.append( make_pair(home->current, make_listv(pixes)) ); home->set_current(0); } index_command(reduce variable set) void execute_reduce_variable_set( codehome* home, codetable& results ) { if ( home->current == 0 ) ERROR("Current configuration undefined."); config& c = home->configs(home->current); home->activate(true, results); pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; mawhometable& vt = home->active->vtable; prevector< pair< wordtype, bool > > adm( vt.length ); int i, j, a; wordtype wt; for ( i = 0; i < vt.length; i++ ) adm(i) = make_pair( vt(i).maw, true ); try_to_reduce_again: for ( i = 0; i < adm.length; i++ ) { if ( adm(i).second ) { for ( j = 0; j < c.aut.length; j++ ) { wt = adm(i).first; c.aut(j).act( wt ); a = vt.mfind( wt ); if ( a == -1 || !adm(a).second ) { adm(i).second = false; goto try_to_reduce_again; } } } } for ( i = 0; i < adm.length; i++ ) if ( !adm(i).second ) { constraint wt_eq_0 = adm(i).first.variable( ) + "=0"; c.con.merge( wt_eq_0 ); } home->deactivate( ); } index_command(round local variables) void execute_round_local( codehome* home, codetable& results ) { if ( home->current == 0 ) ERROR("The current configuration is undefined."); config& c = home->configs(home->current); home->activate(false, results); opt_table search(home); for ( int j = 1; j < home->active->vtable.length; j++ ) search.add( term_sum( home->active->vtable(j).maw.variable( ) ), "minmax" ); search.compute(results); if ( !search.feasible ) cerr << "Current configuration is infeasible.\n"; else { constraint cc; Rational eps(1,1000), low, high; forPixDef( i, search.data ) { low = search.data(i).min; high = search.data(i).max; if ( abs(low - Rational(round(low))) > eps ) { cc.LHS = search.data(i).var; cc.sense = '>'; cc.RHS = ceil(low); cerr << " " << cc << "\n"; c.con.append(cc); } if ( abs(high - Rational(round(high))) > eps ) { cc.LHS = search.data(i).var; cc.sense = '<'; cc.RHS = floor(high); cerr << " " << cc << "\n"; c.con.append(cc); } } } } index_method(joint_we) prevector< matrix > joint_we( const config_core& c ) { int i, j, k, n = c.part.n, wx, wy; prevector< matrix > y(n+1); for ( k = 0; k <= n; k++ ) { y(k).set_size(n+1, n+1); y(k).set_zero( ); } vector indx(c.smallbasis.nrows), sumx(c.smallbasis.ncols), sumy(c.smallbasis.ncols), sumxy(c.smallbasis.ncols); do { mul( indx, c.smallbasis, sumx ); wx = sumx * c.part; vector indy(c.smallbasis.nrows); do { mul( indy, c.smallbasis, sumy ); wy = sumy * c.part; if ( wx <= wy ) { for ( i = 0; i < c.smallbasis.ncols; i++ ) sumxy(i) = sumx(i) * sumy(i); ++y( sumxy * c.part )(wx, wy); } } while ( indy.advance( ) ); } while( indx.advance( ) ); return y; } index_method(execute_print_joint) void execute_print_joint( codehome* home ) { config& c = home->configs(home->current); prevector< matrix > y = joint_we(c); int i, j, k, n = home->n; int print_count = 0; for ( i = 0; i <= n; i++ ) // weight of one word for ( j = i; j <= n; j++ ) // weight of another word for ( k = 0; k <= n; k++ ) if ( y(k)(i,j) != 0 ) { int l = i + j - 2*k; // weight of their sum if ( j <= l ) { if ( l > 0 ) cerr << ", "; if (l > 0 && print_count++ % 4 == 0) cerr << "\n"; cerr << String("jy") + dec(i) + "y" + dec(j) << "y" << dec(l) << " = " << y(k)(i,j); } } cerr << "\n"; } index_command(random weight enumerator) void execute_random_we( short int n, short int k, short int div, short int modulus, Integer count ) { if ( div != 1 && div != 4 ) ERROR("Illegal value for div."); matrix M(k,n), Mred(k,n); vector w(n+1), wm(modulus); int j, l, m, bad_row_count; { for ( Integer i = 0; i < count; ++i ) { dependent: for ( j = 0; j < k; j++ ) { if ( div == 1 ) M(j).set_random( ); if ( div == 4 ) { matrix M0(j,n); for ( m = 0; m < j; m++ ) M0(m) = M(m); M0.reduce( ); matrix dual(n-j,n); M0.nullspace_equals(dual); vector col(n-j); bad_row_count = 0; bad_row: if (bad_row_count++ == 1000) goto dependent; col.set_random( ); mul( col, dual, M(j) ); if ( M(j).weight( ) % 4 != 0 ) goto bad_row; matrix M1(j+1,n); for ( m = 0; m < j + 1; m++ ) M1(m) = M(m); if ( M1.reduce( ) != j+1 ) goto bad_row; } } Mred = M; if ( Mred.reduce( ) != k ) goto dependent; w = M.enumerate_weights( ); wm.set_zero( ); for ( j = 0; j <= n; j++ ) wm( j % modulus ) += w(j); cerr << wm(0); for ( j = 1; j < modulus; j++ ) cerr << ", " << wm(j); cerr << "\n"; } } } index_method(random macaulay) void execute_random_macaulay( short int n, short int k, short int d, Integer count ) { matrix M(k,n); vector col(k); int c, j, v; for ( Integer i = 0; i < count; ++i ) { try_again: do { for ( c = 0; c < n; c++ ) { do { do col.set_random( ); while ( col.if_zero( ) ); for ( v = 0; v < c; v++ ) { for ( j = 0; j < k; j++ ) if ( M(j,v) != col(j) ) break; if ( j == k ) break; } } while ( v != c ); for ( j = 0; j < k; j++ ) M(j,c) = col(j); } } while ( M.reduce( ) != k ); vector y = M.enumerate_weights( ); for ( c = 1; c < d; c++ ) if ( y(c) != 0 ) goto try_again; cerr << M << "\n"; cerr << "weight enumerator: " << as_poly(y) << "\n"; cerr << "generators for ideal: "; execute_macaulay(M); } } index_method(is_cyclic_print) void is_cyclic_print( Permutation q, word v, word w ) { int i, j, k, n = q.length; String acp = q.as_cycle_product( ); if ( acp.length( ) == 0 ) return; String a = acp; a.gsub(")(", ","); a.gsub("(", 0); a.gsub(")", 0); vector av(a); String aplus = a; for ( i = 1; i <= n; i++ ) if ( !av.member(i) ) aplus += String(",") + dec(i); Permutation p(aplus); Permutation pi = p.inverse( ); pi.act(v); if ( w.length > 0 ) pi.act(w); SLList t; static Regex cycle_pat( "([0-9,]+)" ); do { String cycle = take( acp, cycle_pat ); t.append( cycle.freq( "," ) + 1 ); } while( acp.length( ) > 0 ); vector tv(t); // The following line does not work for some reason: // String prefix = "(" + String(tv) + ")-"; String prefix = String("(") + dec(int(tv(0))); for ( k = 1; k < tv.length; k++ ) prefix += String(",") + dec(int(tv(k))); prefix += ")-"; for ( k = 1; k < tv.length; k++ ) if ( tv(k) != tv(0) ) break; if ( k == tv.length && tv(0) * tv.length == q.length ) prefix = (tv.length == 1) ? String("") : dec(tv.length) + String("-"); cerr << "--> " << prefix << "cyclic {" << v; if ( w.length > 0 ) cerr << ", " << w; cerr << "}"; if (show_roots) { cerr << "\nroots:\n"; int place = 0; word vp(v); vp.resize(n); for ( i = 0; i < tv.length; i++ ) { polyF2 u( tv(i) ); for ( j = 0; j < tv(i); j++ ) u(j) = vp(place + j); place += tv(i); pair< int, vector > p = roots(u); cerr << "degree = " << p.first << "; logs = " << p.second << "\n"; } } } index_method(find cyclic codes) void execute_find_cyclic_codes( codehome* home, int q, codetable& results ) { config& cur = home->configs(home->current); constraintlist cnull; vector wts; int i, j, n = home->n, k = home->dim, qi; if ( n % q != 0 ) ERROR(q << " does not divide " << n << "."); Permutation sigma(n); for ( i = 0; i < n; i++ ) sigma(i) = ((i + q) % n) + 1; int r = n - k + 1, d = home->w.min( ), w; word gen(r), indx(k), v(n); SLList< matrix > cyclics; config_core c; c.part.set_all_ones(n); c.smallbasis.set_size(k, n); c.dualsmallbasis.set_size(0, n); constraintlist kn = cur.known_cons( ); config_core core(cur); forPixDef( p, kn ) if (kn(p).global( )) kn(p).LHS = core.simplify_global_vars( kn(p).LHS, cur.share->ww, home->dim ); do { w = gen.weight( ); if ( w < d ) continue; indx.set_zero( ); indx.advance( ); do { v.set_zero( ); for ( i = 0; i < k; i++ ) if ( indx(i) ) { if ( q == 1 ) { for ( j = 0; j < r; j++ ) v(i + j) += gen(j); } else { qi = q*i; for ( j = 0; j < r; j++ ) v((qi + j) % n) += gen(j); } } w = v.weight( ); if ( w < d ) goto next_gen; } while (indx.advance( ) != 0); c.smallbasis.set_zero( ); for ( i = 0; i < k; i++ ) { if ( q == 1 ) { for ( j = 0; j < r; j++ ) c.smallbasis(i, i + j) = gen(j); } else { qi = q*i; for ( j = 0; j < r; j++ ) c.smallbasis(i, (qi + j) % n) = gen(j); } } c.smallbasis.reduce( ); if ( !realizable(c, cnull, home, results) ) goto next_gen; if ( !iso_member( c.smallbasis, cyclics ) ) { cyclics.append(c.smallbasis); word vv(n); for ( i = 0; i < gen.length; i++ ) vv(i) = gen(i); is_cyclic_print( sigma, vv, word(0) ); cerr << " :: {"; vector we = c.smallbasis.enumerate_weights( ); bool first_nonzero = true; for ( i = 1; i <= n; i++ ) if ( we(i) != 0 ) { if (!first_nonzero) cerr << ", "; first_nonzero = false; cerr << String("y") << dec(i) << " = " << dec( we(i) ); } cerr << "}\n"; } next_gen: continue; } while( gen.advance( ) != 0 ); } index_command(is cyclic?) void execute_is_cyclic( codehome* home, bool extra_used, codetable& results ) { if (home->current == 0) ERROR("[current] is undefined."); config& d = home->configs(home->current); if ( !d.terminal( ) ) ERROR("Configuration must be terminal."); if (!extra_used) { config c( home, d.basic_small( ) ); pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); int i, j, k, l, n = home->n; Permutationlist q(n), classes(n); classes.find_conjugacy_classes( pp.first ); c.small.build( ); matrix M(home->dim, n); for ( j = 0; j < classes.length; j++ ) { for ( i = 0; i < c.small.x.nrows; i++ ) { M(0) = c.small.x(i); for ( l = 1; l < home->dim; l++ ) { M(l) = M(l-1); classes(j).act( M(l) ); } if ( M.reduce( ) == home->dim ) { is_cyclic_print(classes(j), c.small.x(i), word(0)); cerr << ";\n"; break; } } } } else { matrix A = d.basic_small( ); // We look at all codimension-one subcodes. We should only look // at one representative from each orbit, under the action of the // automorphism group of the given code. vector indx(A.nrows); indx.advance( ); do { matrix B(indx), C, D; B.nullspace_equals(C); mul( C, A, D ); D.reduce( ); codehome xhome( D.ncols, D.nrows, weightlist("1", D.ncols), results ); config c( &xhome, D ); pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); cerr << "subcode has " << pp.second << " automorphisms\n"; if ( pp.second == 1 ) continue; Permutationlist q(xhome.n), classes(xhome.n); int i, j, l; for ( i = 0; i < pp.first.length; i++ ) q.append(pp.first(i)); classes.generate(q); Permutation id(xhome.n); c.small.build( ); matrix M(xhome.dim, xhome.n); for ( j = 0; j < classes.length; j++ ) { if ( classes(j) == id || classes(j).order( ) < xhome.dim ) continue; for ( i = 0; i < c.small.x.nrows; i++ ) { M(0) = c.small.x(i); for ( l = 1; l < xhome.dim; l++ ) { M(l) = M(l-1); classes(j).act( M(l) ); } if ( M.reduce( ) == xhome.dim ) { word w; word perp_indx( indx.length ); for ( l = 0; l < indx.length; l++ ) if ( indx(l) ) break; perp_indx(l) = 1; mul( perp_indx, A, w ); is_cyclic_print(classes(j), c.small.x(i), w); cerr << ";\n"; } } } } while( indx.advance( ) != 0 ); } } index_method(matrix_by_orbits) pair matrix_by_orbits( matrix M, Permutationlist G, OSLList excluded_columns ) { int i, j, pj, k = M.nrows, n = M.ncols; // Convert the automorphisms to permutations of the columns. Permutationlist H(k); for ( i = 0; i < G.length; i++ ) { Permutation p = G(i); // ith generator matrix pM( k, n ); for ( int ir = 0; ir < k; ir++ ) for ( int ic = 0; ic < n; ic++ ) pM( ir, ic ) = M( ir, p(ic)-1 ); Permutation q(k); for ( j = 0; j < k; j++ ) { for ( pj = 0; pj < k; pj++ ) if ( M(j) == pM(pj) ) break; if ( pj == k ) INTERNAL_ERROR( "matrix_by_orbits" ); q(j) = pj + 1; } H.append(q); } // Determine the equivalence classes of the columns. EquivRelIntList e(n); for ( i = 0; i < G.length; i++ ) for ( j = 0; j < e.length; j++ ) e.join( j, G(i)(j) - 1 ); // Create a character array which displays this data. matrix Mpict( k, n + e.orbit_count( ) ); int col = 0; for ( i = 0; i < n; i++ ) { if ( !e.minimal(i) || excluded_columns.contains(i) ) continue; SLList L = e.orbit(i); forPixDef( pi, L ) { for ( j = 0; j < k; j++ ) Mpict( j, col ) = char( M( j, L(pi) ).x + '0' ); col++; } for ( j = 0; j < k; j++ ) Mpict( j, col ) = ' '; col++; } if ( col == 0 ) return make_pair( String(""), H ); Mpict.resize( Mpict.nrows, col ); for ( j = 0; j < k; j++ ) Mpict( j, col-1 ) = '\n'; // Pack it up. String answer; for ( i = 0; i < Mpict.nrows; i++ ) for ( j = 0; j < Mpict.ncols; j++ ) answer += Mpict( i, j ); return make_pair( answer, H ); } // Copy of cmp (groan). index_method(mcmp) int mcmp(const matrix& a, const matrix& b) { register int i, n = a.nrows; for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } // Copy of mul (groan). index_method(mmul) void mmul(const matrix& A, const matrix& B, matrix& P) { if ( A.ncols != B.nrows ) INTERNAL_ERROR("matrix multiplication"); P.set_size(A.nrows, B.ncols); int i, j, k; gf2 sum; for ( i = 0; i < P.nrows; i++ ) for ( j = 0; j < P.ncols; j++ ) { sum = 0; for ( k = 0; k < A.ncols; k++ ) sum += A(i,k) * B(k,j); P(i,j) = sum; } } TEX( ![ {\tt End}:\ Return an $\F_2$ basis for the vector space of matrices which commute with a given list of invertible matrices. This is a returned as a matrix, with one row for each basis element; the \th{(ni + j)}\ entry of the row corresponds to the \th{(i,j)}\ entry of a matrix. ]! ) index_method(End) matrix End( int n, prevector< matrix > Ms ) { // Let V = F_2^n, viewed as a G-module. Compute End(V). This involves // solving a system of Ms.length * n^2 equations in n^2 variables, // where the ij'th entry is the (n*i + j)'th variable. int i, j, k, l; matrix E; { bitmat MA_reds( 0, n * n ); { bitmat MA( n * n, n * n ); for ( l = 0; l < Ms.length; l++ ) { MA.set_zero( ); for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) { // Generate the row of MA corresponding to the equation // Ms(l) * A = A * Ms(l) // [where A is the matrix of variables]. int MArow = n * i + j; for ( k = 0; k < n; k++ ) { MA(MArow).add( n * k + j, Ms(l)(i, k) ); MA(MArow).add( n * i + k, Ms(l)(k, j) ); } } int rank = MA.reduce( ); MA_reds.resize( MA_reds.length + rank ); MA_reds.nrows += rank; for ( i = 0; i < rank; i++ ) MA_reds( MA_reds.length - rank + i ) = MA(i); MA_reds.reduce_nz( ); } } // Note. The following line was // matrix MAR( MA_reds ); // but ecgs 1.1 couldn't handle it. matrix MAR = MA_reds.operator matrix( ); MAR.nullspace_equals(E); } return E; } index_method(Aut) prevector< matrix > Aut( int n, prevector< matrix > Ms ) { matrix E = End( n, Ms ); int i, j, l, r = E.nrows; prevector< matrix > B( E.nrows ); for ( l = 0; l < r; l++ ) { B(l).set_size( n, n ); for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) B(l)(i, j) = E(l, n * i + j); } SLList< matrix > invertibles; word indx(r); do { matrix A( n, n ); for ( i = 0; i < r; i++ ) if ( indx(i) ) A = A + B(i); if ( A.invertible( ) ) invertibles.append(A); } while( indx.advance( ) ); SLList< matrix > gens; srandomx(1); prevector< matrix > inv(invertibles); while(1) { i = randomx( ) % inv.length; gens.append( inv(i) ); matrix I(n, n); for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) I(i, j) = (i == j); prevector< matrix > gensv(gens), G; orbit( gensv, I, G, mcmp, mmul ); if (G.length == inv.length) return prevector< matrix >(gens); } } index_method(subrep) prevector< matrix > subrep( prevector< matrix > Ms, matrix subspace ) { prevector< matrix > answer( Ms.length ); int k = subspace.nrows; for ( int i = 0; i < Ms.length; i++ ) { matrix A( k, k ); for ( int j = 0; j < k; j++ ) { word v; mul( Ms(i), subspace(j), v ); A.set_col( j, subspace.coord_vector(v) ); } answer(i) = A; } return answer; } // Make a change of basis so that a given representation decomposes. The // new basis is given by the rows of Q and the components of the decomposition // are given by summands. index_method(decompose_rep) void decompose_rep( int n, prevector< matrix > Ms0, prevector< prevector< matrix > >& summands, matrix& Q ) { int i, j, l; summands.set_size(0); srandomx(1); // Eliminate identity generators. SLList< matrix > Msl; for ( i = 0; i < Ms0.length; i++ ) { for ( j = 0; j < n; j++ ) for ( l = 0; l < n; l++ ) if ( Ms0(i)(j,l).x != (j == l) ) goto non_identity; goto identity; non_identity: Msl.append( Ms0(i) ); identity: continue; } prevector< matrix > Ms(Msl); // Compute the Endomorphism ring End(V). matrix R = End( n, Ms ); R.reduce( ); int r = R.nrows; // Determine if R is commutative. bool commutative = true; matrix B1(n,n), B2(n,n), B1B2, B2B1; for ( int l1 = 0; l1 < r; l1++ ) { int l2; for ( l2 = l1 + 1; l2 < r; l2++ ) { for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) { B1(i, j) = R(l1, n * i + j); B2(i, j) = R(l2, n * i + j); } mul(B1, B2, B1B2); mul(B2, B1, B2B1); if ( B1B2 != B2B1 ) { commutative = false; break; } } if ( l2 < r ) break; } // If not, we try to find a non-nilpotent nonunit B in R, and replace // R by F_2[B]. if ( !commutative ) { int ll = 0; while(1) { matrix B(n, n); word v(r), w(n*n); v.set_random( ); mul( v, R, w ); for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) B(i, j) = w(n * i + j); if ( ll++ >= 10 && !B.invertible( ) && B.nilpotent( ) ) { // We're having trouble. Perhaps B lies in the Jacobson // radical of R. If not, we'll find a non-nilpotent // nonunit anyway. int l1, l2; for ( l1 = 0; l1 < r; l1++ ) { for ( l2 = 0; l2 < r; l2++ ) { matrix R1(n,n), R2(n,n), R1BR2, R1B; for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) { R1(i, j) = R(l1, n * i + j); R2(i, j) = R(l2, n * i + j); } mul( R1, B, R1B ); mul( R1B, R2, R1BR2 ); if ( !R1BR2.nilpotent( ) ) { B = R1BR2; break; } } if ( l2 < r ) break; } if ( l1 == r ) return; } if ( !B.invertible( ) && !B.nilpotent( ) ) { // Compute F_2[B]. matrix C, D( 0, n*n ), Ctemp; C.set_identity(n); while(1) { for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) w(n * i + j) = C(i, j); if ( !D.rowspace_member(w) ) { D.resize( D.nrows+1, D.ncols ); D( D.nrows - 1 ) = w; D.reduce( ); } else break; mul( B, C, Ctemp ); C = Ctemp; } R = D; r = R.nrows; break; } } } // Compute the endomorphism L |-> L^2 of R. matrix Rsq( R.nrows, R.nrows ); for ( l = 0; l < R.nrows; l++ ) { matrix B(n,n), Bsq; word w(n*n); for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) B(i, j) = R( l, n * i + j ); mul( B, B, Bsq ); for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) w( n * i + j ) = Bsq(i, j); Rsq.set_col( l, R.coord_vector(w) ); } // Compute the idempotent elements of R. matrix Rid(Rsq), nidem, idem; for ( i = 0; i < R.nrows; i++ ) Rid(i, i) += 1; Rid.reduce_nz( ); Rid.nullspace_equals(nidem); mul( nidem, R, idem ); idem.reduce( ); if ( idem.nrows > 1 ) { // There is a nontrivial idempotent. Use it to split representation. for ( l = 0; l < idem.nrows; l++ ) { matrix id(n, n), ident; for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) id(i, j) = idem( l, n * i + j ); ident.set_identity(n); if ( id != ident ) { matrix space1 = transpose_of(id), space2; space1.reduce_nz( ); int k = space1.nrows; id.reduce_nz( ); id.nullspace_equals(space2); space2.reduce( ); // Decompose space1 and space2; combine. prevector< matrix > S1 = subrep(Ms0, space1); prevector< matrix > S2 = subrep(Ms0, space2); if ( S1.length == 0 || S2.length == 0 ) return; prevector< prevector< matrix > > summands1, summands2; matrix Q1, Q2; decompose_rep( k, S1, summands1, Q1 ); decompose_rep( n - k, S2, summands2, Q2 ); summands.set_size( summands1.length + summands2.length ); for ( i = 0; i < summands1.length; i++ ) summands(i) = summands1(i); for ( i = 0; i < summands2.length; i++ ) summands( i + summands1.length ) = summands2(i); matrix top, bot, Q0; mul( Q1, space1, top ); mul( Q2, space2, bot ); vcat( top, bot, Q0 ); vector leng( summands.length ); for ( i = 0; i < leng.length; i++ ) leng(i) = summands(i)(0).nrows; Permutation pl; leng.sort( &rcmp, pl ); Permutation pli = pl.inverse( ); int Q_i = 0, Q0_i; Q.set_size( n, n ); for ( i = 0; i < pli.length; i++ ) { l = pli(i) - 1; Q0_i = 0; for ( j = 0; j < l; j++ ) Q0_i += summands(j)(0).nrows; for ( j = 0; j < summands(l)(0).nrows; j++ ) Q( Q_i++ ) = Q0( Q0_i++ ); } // below effect: pl.act( summands ); prevector< prevector< matrix > > summandsx( summands.length ); for ( i = 0; i < summands.length; i++ ) summandsx( pl(i) - 1 ) = summands(i); summands = summandsx; return; } } } // Check for nilpotent elements in R. matrix mnil; Rsq.reduce_nz( ); Rsq.nullspace_equals(mnil); if ( mnil.nrows > 0 ) return; // Otherwise the representation is irreducible. summands.set_size(1); summands(0) = Ms0; Q.set_identity(n); return; } TEX( ![ Let $V$ and $W$ be semisimple representations of a finite group $G$ over $\F_2$. Determine if $V$ is isomorphic to $W$. ]! ) index_method(isomorphic) bool isomorphic( prevector< matrix > Ms1, prevector< matrix > Ms2, bool known_simple = false ) { if ( Ms1.length != Ms2.length || Ms1.length == 0 ) INTERNAL_ERROR( "Confused request to isomorphic." ); int i, j, k, l, n = Ms1(0).nrows; if ( n != Ms2(0).nrows ) return false; if (known_simple) { // Compute Hom(V, W) as G-modules. matrix MA( Ms1.length * n * n, n * n ), Hom; for ( l = 0; l < Ms1.length; l++ ) for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) { // Generate the row of MA corresponding to the equation // Ms2(l) * A = A * Ms1(l) // [where A is the matrix of variables]. int MArow = n * (n * l + i) + j; for ( k = 0; k < n; k++ ) { MA( MArow, n * k + j ) += Ms2(l)(i, k); MA( MArow, n * i + k ) += Ms1(l)(k, j); } } MA.reduce_nz( ); MA.nullspace_equals(Hom); return Hom.nrows > 0; } prevector< prevector< matrix > > summands1, summands2; matrix Q; decompose_rep( n, Ms1, summands1, Q ); decompose_rep( n, Ms2, summands2, Q ); if ( summands1.length == 0 || summands2.length == 0 ) ERROR( "I don't know how to tell if two representations are " << "isomorphic unless they are semisimple." ); int r = summands1.length; if ( r != summands2.length ) return false; prevector killed2(r); for ( i = 0; i < r; i++ ) { for ( j = 0; j < r; j++ ) if ( !killed2(j) && isomorphic( summands1(i), summands2(j), true ) ) { killed2(j) = true; break; } if ( j == r ) return false; } return true; } TEX( ![ \verb|advance( indx, bound )|:\ If you start with \verb|indx| = 0 and invoke \verb|advance| repeatedly until it fails, you will get \verb|indx| to cycle through all nonnegative integer vectors which are $\leq$ \verb|bound|. ]! ) index_method(advance) bool advance( vector& indx, vector bound ) { int i, j; for ( i = indx.length - 1; i >= 0; i-- ) if ( indx(i) != bound(i) ) break; if ( i == -1 ) return false; indx(i)++; for ( j = i+1; j < indx.length; j++ ) indx(j) = 0; return true; } TEX( ![ Form the direct sum of a list of matrices. ]! ) index_method(direct_sum) matrix direct_sum( prevector< matrix > summands ) { int i, j, k, nrows = 0, ncols = 0, current_row = 0, current_col = 0; for ( i = 0; i < summands.length; i++ ) { nrows += summands(i).nrows; ncols += summands(i).ncols; } matrix A(nrows, ncols); for ( i = 0; i < summands.length; i++ ) { for ( j = 0; j < summands(i).nrows; j++ ) for ( k = 0; k < summands(i).ncols; k++ ) A( j + current_row, k + current_col ) = summands(i)(j)(k); current_row += summands(i).nrows; current_col += summands(i).ncols; } return A; } // The following routine returns the approximate memory usage of the // calling process, in kilobytes. It should be possible to get this usage // with getrusage, but I couldn't get it to work on the Alpha. The information // about statm came from the readproc, in the source code for procps, found in // ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin. Or you could search for // "procps" on http://metalab.unc.edu, and choose something ending with ".lsm". index_method(mem_usage) int mem_usage( ) { size_t page_size = getpagesize( ); int thisproc = getpid( ); ifstream statm( String("/proc/") + dec(thisproc) + "/statm" ); long mempages; statm >> mempages; return mempages * page_size/1024; } index_command(print) void execute_print( String commandx, codehome* home, codetable& results, String code_label ) { commandx = commandx.after( "print" ); static Regex number_pattern( number_pat ); if ( commandx == "timeused" ) { cerr << setprecision(5) << (time(0) - total_time_used)/60.0 << " minutes real time used so far\n"; return; } if ( commandx == "memoryusage" ) { cerr << "Approximately " << mem_usage( ) << " kilobytes of memory " << "are presently in use by this process.\n"; return; } if ( home == 0 ) WARNRET( "The code type is not defined." ); if (home->current == 0) WARNRET("The current configuration is undefined."); config& c = home->configs(home->current); if ( commandx == "dualweightenumerator" ) { vector y = c.smallcode_we( ); cerr << as_poly( dual_of_we(y) ) << "\n"; } else if ( commandx == "intersectionweightenumerator" ) { matrix n, m = c.basic_small( ); intersect_dual(m, n); vector y = n.enumerate_weights( ); cerr << as_poly(y) << "\n"; } else if ( commandx == "jointweightenumerator" ) execute_print_joint(home); else if ( commandx == "config" ) cerr << c; else if ( commandx == "basis" ) cerr << c.basic_small( ) << "\n"; else if ( commandx == "reducedbasis" ) { matrix T, M = c.basic_small( ); M.transpose_equals(T); prevector cols(T.nrows); for ( int i = 0; i < cols.length; i++ ) cols(i) = T(i); cols.unique_sort(&cmp); matrix A( M.nrows, cols.length ); for ( int i = 0; i < cols.length; i++ ) A.set_col( i, cols(i) ); cerr << A << "\n"; } else if ( commandx == "dualbasis" ) { matrix D; c.basic_small( ).nullspace_equals(D); cerr << D << "\n"; } else if ( commandx == "intersectionbasis" ) { matrix n, m = c.basic_small( ); intersect_dual(m, n); cerr << n << "\n"; } else if ( commandx == "evensubcodebasis" ) { matrix M = c.basic_small( ); int i, j; for ( i = 0; i < M.nrows; i++ ) if ( odd( M(i).weight( ) ) ) break; if ( i == M.nrows ) { cerr << "The code itself is even. Here is its basis:\n"; cerr << M << "\n"; } else { if ( !odd( M( M.nrows-1 ).weight( ) ) ) M( M.nrows-1 ) += M(i); for ( j = 0; j < M.nrows-1; j++ ) if ( odd( M(j).weight( ) ) ) M(j) += M( M.nrows-1 ); M.resize( M.nrows-1, M.ncols ); M.reduce( ); cerr << M << "\n"; } } else if ( commandx == "puncturedcodes" ) { matrix M = c.basic_small( ); SLList< pair< int, matrix > > list = punctured_codes(M); forPixDef( p, list ) { vector y = list(p).second.enumerate_weights( ); cerr << list(p).second << "\n" << "weight enumerator: " << as_poly(y) << "\n"; } } else if ( commandx == "codewordorbits" ) { c.small.build( ); int i, j, class_count = 1; prevector cd(c.small.x.nrows); for ( i = 0; i < cd.length; i++ ) cd(i) = c.small.x(i); cd.sort(&cmp); EquivRelIntList e(cd.length); word w(c.part.length); for ( i = 0; i < c.aut.length; i++ ) for ( j = 0; j < cd.length; j++ ) { w = cd(j); c.aut(i).act(w); int k = cd.pos(w, &cmp); if ( k == -1 ) INTERNAL_ERROR("code word orbits"); e.join(j, k); } for ( i = 0; i < e.length; i++ ) { if ( e.minimal(i) ) { cerr << "class " << class_count++ << " (words of weight " << (cd(i) * c.part) << "):\n1. " << cd(i) << "\n"; j = i; int l = 2; while( (j = e(j)) != i ) cerr << l++ << ". " << cd(j) << "\n"; } } } else if ( commandx == "variableclasses" ) { home->activate(false, results); EquivRelIntList e = home->active->auto_equiv( ); int i, j, class_count = 1; for ( i = 0; i < e.length; i++ ) { if ( e.minimal(i) ) { cerr << "class " << class_count++ << ": "; mawhometable& vt = home->active->vtable; cerr << vt(i).maw.variable( ); j = i; while( (j = e(j)) != i ) cerr << ", " << vt(j).maw.variable( ); cerr << ";\n"; } } } else if ( commandx.contains("wordsofweight", 0) ) { commandx.del( "wordsofweight" ); if ( !commandx.contains( number_pattern, 0 ) ) WARNRET( "Weight doesn't make sense." ); int m = take_int(commandx, number_pattern); if ( commandx != ",showingorbitgroups" ) WARNRET( "Illegal print command." ); matrix M = c.basic_small( ); SLList wds; word indx(M.nrows); do { word v; mul( indx, M, v ); if ( v.weight( ) == m ) wds.append(v); } while( indx.advance( ) ); if ( wds.length( ) == 0 ) WARNRET( "There are no words of weight " << m << ".\n" ); matrix A( M.ncols, wds ); pair xxx = matrix_by_orbits( A, find_automorphism_group(M).first, OSLList( ) ); cerr << xxx.first; } else if ( commandx.contains("dualwordsofweight", 0) ) { commandx = commandx.after( "dualwordsofweight" ); if_no_match(commandx, number_pat) WARNRET( "Weight doesn't make sense." ); int m = as_int(commandx); matrix M = c.basic_small( ); SLList< vector > L = dual_words_of_given_weight(M, m); matrix D( L.length( ), M.ncols ); int count = 0; forPixDef( p, L ) { for ( int i = 0; i < m; i++ ) D( count, L(p)(i) ) = 1; count++; } for ( int i = 0; i < D.nrows; i++ ) cerr << D(i) << "\n"; } else if ( commandx == "automorphismgroupgenerators" ) { if ( !c.assumed_cons.joint( ) ) WARNRET( "Local variables are present in an assumed " << "constraint. Command ignored." ); pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); cerr << "Aut(current) has " << pp.second << " elements. " << "Generators are as follows:\n"; for ( int i = 0; i < pp.first.length; i++ ) cerr << " " << pp.first(i).as_cycle_product( ) << "\n"; } else if ( commandx == "automorphismgroup" ) { if ( !c.assumed_cons.joint( ) ) WARNRET( "Local variables are present in an assumed " << "constraint. Command ignored." ); pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); Permutationlist gp(c.part.length), gen(c.part.length); int i; for ( i = 0; i < pp.first.length; i++ ) gen.append( pp.first(i) ); gp.generate(gen); for ( i = 0; i < gp.length; i++ ) cerr << gp(i).as_cycle_product( ) << "\n"; } else if ( commandx.contains( "splitvariablesforweight", 0 ) ) { int m = take_int( commandx, number_pattern ); matrix M = c.basic_small( ); int i, j, n = M.ncols; pair< Permutationlist, Integer > pp = find_automorphism_group(M); SLList wds; word indx(M.nrows); do { word v; mul( indx, M, v ); if ( v.weight( ) == m ) wds.append(v); } while( indx.advance( ) ); if ( wds.length( ) == 0 ) WARNRET( "There are no words of weight " << m << ".\n" ); prevector cd(wds); cd.sort(&cmp); EquivRelIntList e(cd.length); word w(n); for ( i = 0; i < pp.first.length; i++ ) for ( j = 0; j < cd.length; j++ ) { w = cd(j); pp.first(i).act(w); int k = cd.pos(w, &cmp); if ( k == -1 ) INTERNAL_ERROR("code word orbits"); e.join(j, k); } SLList swes; for ( i = 0; i < e.length; i++ ) { if ( e.minimal(i) ) { word w = cd(i); matrix wt(n+1, n+1); wt.set_zero( ); indx.set_zero( ); do { word v; mul( indx, M, v ); int i1 = idot( v, w ); int i2 = v.weight( ) - i1; ++wt(i1,i2); } while( indx.advance( ) ); String swe; for ( int i1 = 0; i1 <= n; i1++ ) for ( int i2 = 0; i2 <= n; i2++ ) if ( wt(i1,i2) != 0 ) { if ( swe != "" ) swe += ", "; swe += String("x_") + dec(i1) + "_" + dec(i2) + " = " + dec(wt(i1,i2)); } forPixDef( p, swes ) if ( swes(p) == swe ) break; if ( p == 0 ) { cerr << swe << "\n"; swes.append(swe); } } } } else if (commandx.contains("dimensionofcodespannedbydualwordsofweight",0)) { commandx = commandx.after( "dimensionofcodespannedbydualwordsofweight" ); if_no_match(commandx, number_pat) WARNRET("Weight doesn't make sense."); int m = as_int(commandx); matrix M = c.basic_small( ); SLList< vector > L = dual_words_of_given_weight(M, m); matrix D( L.length( ), M.ncols ); int count = 0; forPixDef( p, L ) { for ( int i = 0; i < m; i++ ) D( count, L(p)(i) ) = 1; count++; } cerr << D.reduce( ) << "\n"; } else if ( commandx.contains("variablesofweight", 0) ) { commandx = commandx.after("variablesofweight"); if_no_match(commandx, number_pat) WARNRET("Weight doesn't make sense."); int m = as_int(commandx); home->activate(true, results); const mawhometable& me = home->active->vtable; bool first_variable = true; for ( int i = 0; i < me.length; i++ ) { bool first_in_class = true; forPixDef( p, me(i).w ) { wordtype alttype = me(i).maw; alttype.act( me(i).w(p) ); if ( sum(alttype) == m ) { if (!first_variable) { if (first_in_class) cerr << ", "; else cerr << " ~ "; } cerr << alttype.variable( ); first_variable = false; first_in_class = false; } } } cerr << "\n"; } else if ( commandx.contains("projectionsontowordsofweight", 0) ) { commandx = commandx.after("projectionsontowordsofweight"); if_no_match(commandx, number_pat) WARNRET("Weight doesn't make sense."); int m = as_int(commandx); matrix M = c.basic_small( ); code C; C.basis = M; C.build( ); pair< Permutationlist, Integer > pp = find_automorphism_group(M); Permutationlist aut = pp.first; c.small.build( ); int i, j, class_count = 1; prevector cd(C.x.nrows); for ( i = 0; i < cd.length; i++ ) cd(i) = C.x(i); cd.sort(&cmp); EquivRelIntList e(cd.length); word w(c.part.length); for ( i = 0; i < aut.length; i++ ) for ( j = 0; j < cd.length; j++ ) { w = cd(j); aut(i).act(w); int k = cd.pos(w, &cmp); if ( k == -1 ) INTERNAL_ERROR("print projections onto"); e.join(j, k); } SLList< matrix > projs; for ( i = 0; i < e.length; i++ ) { if ( e.minimal(i) && cd(i).weight( ) == m ) { matrix A = M.select_col( cd(i) ); A.reduce_nz( ); if ( !iso_member( A, projs ) ) { projs.append(A); vector y = A.enumerate_weights( ); cerr << A << "\n" << "weight enumerator: " << as_poly(y) << "\n"; } } } } else WARNRET("Unrecognized print option."); } void execute_help( String commandx ) { commandx = commandx.after( "help" ); if ( commandx.empty( ) ) { cerr << "The help command may be used to get information about a " << "particular command. It works by opening the Split report " << "at the appropriate page. To use it, you must " << "have xdvi and ghostscript (gs) installed on your " << "machine. Try \"help print;\" and \"help via;\" " << "to see how it works. The spacebar and backspace " << "key may be used to page forward and backward in " << "the report. Type \"q\" to exit xdvi.\n"; return; } ifstream idx( "tex/t.idxb" ); SLList< pair > plausibles; char* com; String comx, command_name, cname0, pl; while(1) { idx >> ws; // skip over whitespace if ( idx.peek( ) == EOF ) break; idx.gets(&com); comx = com; comx.gsub("$", "" ); if ( !idx ) ERROR("Input error."); comx.del( "\\indexentry{" ); command_name = comx.before("}"); cname0 = command_name; cname0.gsub(RXwhite,""); if ( cname0.contains( commandx, 0 ) ) { forPixDef( p, plausibles ) { pl = plausibles(p).first; pl.gsub(RXwhite,""); if ( pl == cname0 ) break; } if ( p != 0 ) continue; comx = comx.after("}{"); comx = comx.before("}"); plausibles.append( make_pair(command_name, comx) ); } delete com; } if ( plausibles.length( ) == 0 ) cerr << "I can't find an entry in the index which starts with \"" << commandx << "\". Perhaps you should try a shorter string.\n"; else if ( plausibles.length( ) > 1 ) { forPixDef( p, plausibles ) { if ( plausibles(p).first == commandx ) { system("xdvi +" + plausibles(p).second + " tex/t.dvi"); return; } } cerr << "I've found more than one index entry which " << "starts with \"" << commandx << "\". Please choose " << "from the following and use the help command again:\n"; forPix( p, plausibles ) cerr << plausibles(p).first << "\n"; } else system("xdvi +" + plausibles.front().second + " tex/t.dvi"); } void execute_test( int n, int k, int d, codetable& results, codehome* home, String& code_label, const constraintlist& test_mask ) { if ( d > n ) ERROR("Minimum weight exceeds length."); forPixDef( p, test_mask ) { Rational sum = 0; forPixDef( q, test_mask(p).LHS ) { const term& t = test_mask(p).LHS(q); if ( t.var == "n" ) sum += Integer(n) * t.coeff; else if ( t.var == "k" ) sum += Integer(k) * t.coeff; else if ( t.var == "d" ) sum += Integer(d) * t.coeff; else ERROR( "Illegal variable in test mask." ); } if ( !test( sum, test_mask(p).RHS, test_mask(p).sense ) ) return; } if (doubly_even_test) { if ( d % 4 != 0 ) return; String sss( dec(d) ); sss += "_4"; weightlist wt( sss, n ); if ( results.not_exist(n, k, wt) ) return; if ( no_test_if_classified && results.weakly_classified(codebase(n, k, wt)) ) return; if ( results.new_not_exist( n, k, d, 4, home, code_label, allowed_failures ) ) { results.kill( codebase(n, k, wt) ); WARNING( "There is no [" << n << ", " << k << ", " << d << "_4] code." ); } } else if ( results.not_exist(n-1, k, d) ) { weightlist wt( dec(d), n ); if ( no_test_if_classified && results.weakly_classified(codebase(n, k, wt)) ) return; if ( results.new_not_exist( n, k, d, 1, home, code_label, allowed_failures ) ) { results.kill(n, k, d); WARNING( "There is no [" << n << ", " << k << ", " << d << "] code." ); } } } index_method(set_numerical_parameter) void set_numerical_parameter( const String& parameter, const String& value, const String& mode ) { static Regex signed_number_pat( signed_number ); if ( !value.matches(signed_number_pat) ) ERROR( "Illegal parameter " << "value " << value << " for " << parameter << ".\n" ); #define INT_PARAM(uname,mename,low,high) \ if ( parameter == uname ) \ { extern int mename; \ static int mename##_save; \ if ( mode == "set" ) \ { mename = as_int(value); \ if ( mename < low || (high != 0 && mename > high) ) ERROR( \ "Illegal parameter value " << value << " for " << \ parameter << ".\n" ); }\ else if ( mode == "save" ) mename##_save = mename; \ else if ( mode == "restore" ) mename = mename##_save; \ return; } INT_PARAM("refactorizationrate", refactorization_rate, 0, 0) INT_PARAM("dualconstraintbound", dual_constraint_bound, -1, 0) INT_PARAM("totaldualconstraintbound", total_dual_constraint_bound, -1, 0) INT_PARAM("dcbdepthlimit", dcb_depth_limit, 0, 0) INT_PARAM("autojointsearch", auto_joint_search, 0, 0) INT_PARAM("autojointtest", auto_joint_test, 0, 0) INT_PARAM("usedualdualforjoint", use_dual_dual_for_joint, 0, 0) INT_PARAM("fillweight", fill_weight, 0, 0) INT_PARAM("pricerefinementcount", price_refinement_count, 0, 0) INT_PARAM("secondarykillmaxvars", secondary_kill_maxvars, 0, 0) INT_PARAM("partialpricing", partial_pricing, 0, 0) INT_PARAM("toldjpercent", toldj_percent, 0, 0) INT_PARAM("tolpivpercent", tolpiv_percent, 0, 0) INT_PARAM("allowedfailures", allowed_failures, 0, 0) INT_PARAM("nzvlengthmax", nzv_length_max, 1, 0) INT_PARAM("generatenonevenbounds", generate_noneven_bounds, 0, 0) INT_PARAM("dualtransformlengthlimit", dual_transform_length_limit, 1, 0) INT_PARAM("autotransformdepth", auto_transform_depth, 0, 0) INT_PARAM("iterationlimit", iteration_limit, 1000, 0) INT_PARAM("tupleorbitmax", tuple_orbit_max, 1, 0) INT_PARAM("nzvlengthmax2", nzv_length_max2, 0, 0) INT_PARAM("transformpasslevel", transform_pass_level, 0, 0) INT_PARAM("autodualcolumndeletion", auto_dual_column_deletion, 0, 2) INT_PARAM("startingtupleorbit", starting_tuple_orbit, 1, 0) INT_PARAM("findregulargroupelement", find_regular_group_element, 0, 0) INT_PARAM("i1low", i1low, 0, 0) INT_PARAM("i1high", i1high, 0, 0) INT_PARAM("i2low", i2low, 0, 0) INT_PARAM("i2high", i2high, 0, 0) INT_PARAM("groupsizelimit", group_size_limit, 0, 0) INT_PARAM("autodualresidualtransform", auto_dual_residual_transform, 0, 0) INT_PARAM("loadlimit", load_limit, 1, 0) INT_PARAM("autoenlargebydualword", auto_enlarge_by_dual_word, 0, 4) INT_PARAM("deletepairs", delete_pairs, 0, 0) INT_PARAM("deletetriples", delete_triples, 0, 0) INT_PARAM("seedcount", seed_count, 0, 0) INT_PARAM("perturbationcount", perturbation_count, 0, 0) INT_PARAM("eclengthlimit", ec_length_limit, 0, 0) INT_PARAM("autocyclictest", auto_cyclic_test, 0, 0) INT_PARAM("searchvectorweightmax", search_vector_weight_max, 0, 0) INT_PARAM("minvectorweight", min_vector_weight, 0, 0) INT_PARAM("viaconfigurationsearch!grouplevel", configuration_search_group_level, 0, 0) INT_PARAM("viaconfigurationsearch!groupsizecap", configuration_search_group_size_cap, 0, 0) INT_PARAM("startinglength", starting_length, 0, 0) INT_PARAM("randomdoublingprobability", random_doubling_probability, 0, 100) INT_PARAM("viabuilding!maxcreate", max_create, 0, 0) INT_PARAM("maxdoubles", max_doubles, 0, 0) INT_PARAM("precision", force_precision, 1, 0) INT_PARAM("precisionlock", precision_lock, 0, 0) INT_PARAM("trytokill!maxvars", try_to_kill_maxvars, 0, 0) INT_PARAM("verifyfeasibility", verify_feasibility, 0, 2) Integer ivalue = as_int(value); if (ivalue != 0 && ivalue != 1) ERROR( "Illegal parameter value " << value << " for " << parameter << ".\n" ); #define BOOL_PARAM(uname,mename) \ if ( parameter == uname ) \ { extern int mename; \ static int mename##_save; \ if ( mode == "set" ) mename = int(ivalue); \ else if ( mode == "save" ) mename##_save = mename; \ else if ( mode == "restore" ) mename = mename##_save; \ return; } BOOL_PARAM("gullible", gullible) BOOL_PARAM("optimal", optimal) BOOL_PARAM("nautyvocal", nauty_vocal) BOOL_PARAM("dumpcost", dump_cost) BOOL_PARAM("unresidue!showallconfigs", unresidue_show_all_configs) BOOL_PARAM("unresidue!showextrainfo", unresidue_show_extra_info) BOOL_PARAM("lowmemoryjointgeneration",low_memory_joint_generation) BOOL_PARAM("repeatloop", repeat_loop) BOOL_PARAM("purgejointsontypeexit", purge_joints_on_type_exit) BOOL_PARAM("adjoinextrabrouwerconstraints", adjoin_extra_brouwer_constraints) BOOL_PARAM("bound!dualsearch", bound_dual_search) BOOL_PARAM("show!quiet", show_quiet) BOOL_PARAM("status!quiet", status_quiet) BOOL_PARAM("vialp!quiet", via_lp_quiet) BOOL_PARAM("bound!quiet", bound_quiet) BOOL_PARAM("bound!verify", bound_verify) BOOL_PARAM("process!clearnewcodes", clear_newcodes) BOOL_PARAM("viaconfigurationsearch!gotoend", configuration_search_to_end) BOOL_PARAM("viaconfigurationsearch!showexample", configuration_search_show_example) BOOL_PARAM("viaconfigurationsearch!expandfinalcount", configuration_search_expand_final_count) BOOL_PARAM("viaconfigurationsearch!printfinallist", configuration_search_print_final_list) BOOL_PARAM("eval!inputform", input_form) BOOL_PARAM("debug", debug) BOOL_PARAM("showresidualdata", show_residual_data) BOOL_PARAM("fullreduction", full_reduction) BOOL_PARAM("randomsearch", random_search) BOOL_PARAM("forceimprovement", force_improvement) BOOL_PARAM("leveltwosearch", level_two_search) BOOL_PARAM("autoanalyzelocalrelations", auto_analyze_local_relations) BOOL_PARAM("autoanalyzelocalrelations!vocal", auto_analyze_local_relations_vocal) BOOL_PARAM("alternatequalitycriterion", alternate_quality_criterion) BOOL_PARAM("ecfill", ec_fill) BOOL_PARAM("notestifclassified", no_test_if_classified) BOOL_PARAM("findparametersonly", find_parameters_only) BOOL_PARAM("limitedsecondarykill", limited_secondary_kill) BOOL_PARAM("residualcheckforkill", residual_check_for_kill) BOOL_PARAM("fullsecondarykill", full_secondary_kill) BOOL_PARAM("homebrewfullreport", homebrew_full_report) BOOL_PARAM("homebrewdump", homebrew_dump) BOOL_PARAM("showdistanceoptimal", show_distance_optimal) BOOL_PARAM("warningsarefatal", warnings_are_fatal) BOOL_PARAM("autoprojection", auto_projection) BOOL_PARAM("autoprojection!showconstraints", auto_projection_show_constraints) BOOL_PARAM("autoprojection!showparameters", auto_projection_show_parameters) BOOL_PARAM("crazycodesearch", crazy_code_search) BOOL_PARAM("autojointlist", auto_joint_list) BOOL_PARAM("autotrytokilljvars", auto_try_to_kill_jvars) BOOL_PARAM("savebounds", save_bounds) BOOL_PARAM("showconfigcreation", show_config_creation) BOOL_PARAM("showevenifknown", show_even_if_known) BOOL_PARAM("lowerboundcheck", lower_bound_check) BOOL_PARAM("showroots", show_roots) BOOL_PARAM("doublyeventest", doubly_even_test) BOOL_PARAM("autodualtransform", auto_dual_transform) BOOL_PARAM("autoresidualtransform", auto_residual_transform) BOOL_PARAM("autogroupresidualtransformalt", auto_group_residual_transform_alt) BOOL_PARAM("autogroupresidualtransform", auto_group_residual_transform) BOOL_PARAM("autopuncturetransform", auto_puncture_transform) BOOL_PARAM("nocolumndeletion", no_column_deletion) BOOL_PARAM("limiteddeletion", limited_deletion) BOOL_PARAM("doublecolumnpairs", double_column_pairs) BOOL_PARAM("doublecolumntriples", double_column_triples) BOOL_PARAM("doublecolumngroups", double_column_groups) BOOL_PARAM("smartdual", smart_dual) BOOL_PARAM("showmatrix", show_matrix) BOOL_PARAM("showvariables", show_variables) BOOL_PARAM("autoorbittransform", auto_orbit_transform) BOOL_PARAM("matrixisomorphismsilent", matrix_isomorphism_silent) BOOL_PARAM("autoround", auto_round) BOOL_PARAM("homebrewspeedy", homebrew_speedy) BOOL_PARAM("silent", silent) BOOL_PARAM("gulliblesilent", gullible_silent) BOOL_PARAM("alternateextensionmethod", alternate_extension_method) BOOL_PARAM("secondaryecho", secondary_echo) BOOL_PARAM("viabuilding!automacaulay", auto_macaulay) BOOL_PARAM("viabuilding!depthfirst", depth_first) BOOL_PARAM("viabuilding!showterminals", show_terminals) BOOL_PARAM("viabuilding!showallconfigs", show_all_configs) BOOL_PARAM("viabuilding!usejointvariables", use_joint_variables) BOOL_PARAM(":=!ingredienttracking", ingredient_tracking) BOOL_PARAM("trytokill!vocal", try_to_kill_vocal) BOOL_PARAM("homebrew", force_homebrew) BOOL_PARAM("viabuilding!showextrainfo", via_building_show_extra_info) BOOL_PARAM("tablesonly", tables_only) BOOL_PARAM("sort", sort_flag) BOOL_PARAM("secondaryplus", secondary_plus) BOOL_PARAM("autogroupcomputation", auto_group_computation) BOOL_PARAM("automu1", auto_mu1) ERROR( "Unknown parameter -- \"" << parameter << "\"." ); } index_method(save_and_set_parameter) void save_and_set_parameters(String list) { String parameter, value; if_no_match( list, String("<") + ".*>" ) ERROR( "The syntax of the parameter list is incorrect." ); list = list.after("<"); list = list.before(">"); prevector opts = unpack(list); for ( int i = 0; i < opts.length; i++ ) { if ( !opts(i).contains("=") ) { parameter = opts(i); value = "1"; } else { parameter = opts(i).before("="); value = opts(i).after("="); } set_numerical_parameter(parameter, value, "save"); set_numerical_parameter(parameter, value, "set"); } } index_method(restore_parameters) void restore_parameters(String list) { String parameter, value; if_no_match( list, String("<") + ".*>" ) ERROR( "The syntax of the parameter list is incorrect." ); list = list.after("<"); list = list.before(">"); prevector opts = unpack(list); for ( int i = 0; i < opts.length; i++ ) { if ( !opts(i).contains("=") ) { parameter = opts(i); value = "1"; } else { parameter = opts(i).before("="); value = opts(i).after("="); } set_numerical_parameter(parameter, value, "restore"); } } index_command(type) void execute_type( String commandx, codehome*& home, codetable& results, String& code_label, bool fast, bool gullible ) { // First save the previous codehome, if there was one. if (home != 0) results.save( *home, code_label ); String set_pat( "{" + list_of( pos_number + orsign + pos_number + "\\.\\." + pos_number ) + "}" ); static Regex weightlist_pat( pos_number + orsign + pos_number + "_" + pos_number + orsign + set_pat + orsign + pos_number + "-" + set_pat + orsign + pos_number + "_" + pos_number + "-" + set_pat ); static Regex label_pattern( label_pat ); static Regex type_residual_pattern(pos_number + "," + number_pat + ",.*"); static Regex number_pattern( number_pat ); #define n_options 5 static Regex option1( "dual_may_be_code_of_design(t=2,k=" + number_pat + ",lambda=" + number_pat + ")" ); static Regex option2( "partition_of_word_by_dual_words(weight=" + number_pat + ",dual_weight=" + number_pat + ")" ); static Regex option3( "doubly_even_part_is_subcode" ); static Regex option4( "dualcoveringradius<=" + pos_number ); static Regex option5( "maybesubcodeof" + label_pat ); Regex* option_pats[n_options] = { &option1, &option2, &option3, &option4, &option5 }; code_label = ""; String defining_command = commandx; if ( commandx[0] == '[' ) code_label = take(commandx, label_pattern); // if (fast) code_label = ""; bool reenter = false; if ( code_label != "" ) { if ( code_label == "[current]" ) ERROR( "The code label [current] " << "refers to the current code type. It may not be " << "assigned." ); forPixDef( p, results.olabels ) if ( code_label == results.olabels(p).first ) { Pix hp = results.olabels(p).second; home = results.open(hp); if ( home->defining_command != defining_command ) ERROR( "If you reuse a codetype label, the defining " << "command must be identical (verbatim) to the " << "earlier command. The initial definition was " << home->defining_command << ", but now you've " << "used " << defining_command << "." ); results.open.del(hp); results.olabels.del(p); // forPixDef( q, results.olabels ) // { if ( code_label == results.olabels(q).first ) // { results.olabels.del(q); // break; } } home->current = home->base; reenter = true; if (fast) return; break; } } commandx = commandx.after("type["); if ( !commandx.matches(type_residual_pattern) ) ERROR("Incorrect syntax."); int n = take_int(commandx, number_pattern); commandx = commandx.after(","); int dim = take_int(commandx, number_pattern); if ( dim == 0 ) ERROR( "Do you need a computer to study zero-dimensional codes?" ); if ( dim > n ) ERROR("Dimension exceeds length."); commandx = commandx.after(","); weightlist w = weightlist( take(commandx, weightlist_pat), n ); weightlist dw( "1", n ); if ( commandx.contains( ',', 0 ) ) { commandx.del( ',' ); dw = weightlist( take(commandx, weightlist_pat), n ); } require_char(commandx, ']'); if (auto_mu1 && commandx == "") { if (gullible) results.kill(n-1, dim, w.min()); else { if ( results.new_not_exist( n-1, dim, w.min( ), 1, home, code_label, allowed_failures ) ) results.kill(n-1, dim, w.min()); else WARNRET( "The parameter \"auto mu1\" is set but I am unable" << " to show that there is no [" << n-1 << "," << dim << "," << w.min( ) << "] code." ); } } constraintlist assumed_cons; if_match( commandx, "{[^}]*}.*" ) { commandx = commandx.after("{"); String conx = commandx.before("}"); assumed_cons = constraintlist(conx); commandx = commandx.after("}"); } if ( dw != weightlist( "1", n ) ) { if ( dw.divisible(2) ) { assumed_cons.append( String("y") + dec(n) + "=1" ); for ( int i = 2; i <= n; i += 2 ) if ( !dw.contains(i) ) assumed_cons.append( String("mu") + dec(i) + "=0" ); } else for ( int i = 1; i <= n; i++ ) if ( !dw.contains(i) ) assumed_cons.append( String("mu") + dec(i) + "=0" ); } String options[n_options]; int i; if ( !commandx.empty( ) ) { require_char( commandx, '/' ); while(1) { for ( i = 0; i < n_options; i++ ) if ( commandx.contains(*option_pats[i], 0) ) { if (!options[i].empty( )) ERROR("Option used twice."); options[i] = take(commandx, *option_pats[i]); break; } if ( !commandx.empty( ) && commandx[0] != '/' ) require_char(commandx, ','); if (i == n_options) break; } if ( commandx != "/" ) ERROR("Illegal option or missing /."); } int radius = 0, radius_dim = 0, radius_length = 0; String subcode_of; if ( !options[3].empty( ) ) { int r = take_int( options[3], number_pattern ); radius = r; radius_dim = dim; radius_length = n; } if ( !options[4].empty( ) ) { options[4] = options[4].after( "maybesubcodeof" ); codehome* h = results.get_home( options[4], false ); subcode_of = options[4]; if ( h->n < n || h->dim < dim ) ERROR( "Your use of the maybe subcode of option " << "doesn't make sense." ); w = intersection(w, h->configs(h->base).share->ww); constraintlist cj = h->configs(h->base).share->ycon; forPixDef( p, cj ) { if ( cj(p).simple( ) && cj(p).LHS.front( ).var[0] == 'j' && cj(p).sense == '=' && cj(p).RHS == 0 ) { String var = cj(p).LHS.front( ).var; static Regex j_pattern( "jy" + number_pat + "y" + number_pat + "y" + number_pat ); if ( var.matches(j_pattern) ) { int i1, i2, i3; parse_j_var( var, i1, i2, i3 ); if ( (i1 + i2 + i3)/2 <= n ) assumed_cons.merge( cj(p) ); } } } if ( h->opt.dual_radius > 0 ) { if ( radius > 0 ) ERROR( "You can't use both the dual covering radius option " << "and the maybe subcode of option for a code type " << "which also has the dual covering radius option." ); radius = h->opt.dual_radius; radius_length = h->n; radius_dim = h->dim; } } if (reenter) { codehome* home2 = new codehome( n, dim, w, results, radius, radius_length, radius_dim, assumed_cons ); home->ww(home->base) = intersection( home->ww(home->base), home2->ww(home2->base) ); home->configs(home->base).share->ycon.merge( home2->configs(home2->base).share->ycon ); home->configs(home->base).share->wjv.set_size(0); delete home2; } else { if (fast) home = new codehome( n, dim, w, assumed_cons ); else home = new codehome( n, dim, w, results, radius, radius_length, radius_dim, assumed_cons ); } home->defining_command = defining_command; home->opt.dual_radius = radius; home->opt.dual_radius_length = radius_length; home->opt.dual_radius_dim = radius_dim; home->opt.maybe_subcode_of = subcode_of; forPixDef( p, assumed_cons ) { constraint d = home->assumed_cons(p); forPixDef( q, d.LHS ) home->configs(home->base).check_variable( d.LHS(q).var ); } if ( !options[0].empty( ) ) { home->opt.dual_may_be_code_of_design = true; options[0] = options[0].after("k="); int k = take_int(options[0], number_pattern); if ( k == 0 || k > n ) ERROR( "k value for dual_may_be_code_of_design " << "option doesn't make sense." ); home->opt.k = k; options[0] = options[0].after(",lambda="); int lambda = take_int(options[0], number_pattern); if ( lambda == 0 ) ERROR( "lambda value for " << "dual_may_be_code_of_design " << "option doesn't make sense." ); home->opt.lambda = lambda; } if ( !options[1].empty( ) ) { home->opt.partition_of_word_by_dual_words = true; options[1] = options[1].after("weight="); int wt = take_int(options[1], number_pattern); home->opt.w = wt; options[1] = options[1].after("weight="); int dwt = take_int(options[1], number_pattern); home->opt.d = dwt; if ( wt < 0 || wt > home->n || dwt < 0 || dwt > n || wt/dwt * dwt != wt ) ERROR("Values for weight and/or dual_weight " << "don't make sense."); } if ( !options[2].empty( ) ) home->opt.doubly_even_part_is_subcode = true; if ( !fast && auto_joint_list ) { config& c = home->configs(home->base); bool nan; forPix( p, home->assumed_cons ) { constraint d = home->assumed_cons(p); if ( d.global( ) ) c.add_constraint( d, results, nan ); } forPix( p, home->assumed_cons ) { constraint d = home->assumed_cons(p); if ( !d.global( ) ) c.add_constraint( d, results, nan ); } home->basic_joint_vars(&home->configs(home->base), results); home->deactivate( ); } } index_method(unpack_poly) vector unpack_poly( String s ) { SLList< pair > terms; do { bool stuff_found = false; Integer coeff = 1; int exp = 0; if ( s[0] == '+' ) s.del( '+' ); else if ( s[0] == '-' ) { s.del( '-' ); coeff = -1; } static Regex number_pattern( number_pat ); if ( s.contains( number_pattern, 0 ) ) { coeff *= Integer( take( s, number_pattern ) ); stuff_found = true; } static Regex t_power( "t^" + number_pat ); if ( s.contains( t_power, 0 ) ) { s.del( "t^" ); exp = take_int( s, number_pattern ); stuff_found = true; } else if ( s.contains( 't', 0 ) ) { s.del( 't' ); exp = 1; stuff_found = true; } if ( !stuff_found || (s.length( ) != 0 && s[0] != '+' && s[0] != '-') ) ERROR( "Illegal polynomial." ); terms.append( make_pair( coeff, exp ) ); } while( s.length( ) != 0 ); int max_exp = 0; forPixDef( p, terms ) max_exp = max( max_exp, terms(p).second ); vector answer( max_exp + 1 ); answer.set_zero( ); forPix( p, terms ) answer( terms(p).second ) += terms(p).first; return answer; } index_method(we_from_String) vector we_from_String( String s, int n, int k ) { vector we = unpack_poly(s); if ( we.length > n + 1 ) ERROR( "Illegal weight enumerator." ); int old_size = we.length; if ( we.length != n + 1 ) { we.resize( n + 1 ); for ( int i = old_size; i <= n; i++ ) we(i) = 0; } Integer sum = 0; for ( int j = 0; j <= n; j++ ) { if ( we(j) < 0 ) ERROR("Negative coefficient in weight enumerator."); sum += we(j); } if ( sum != Ipow(2, k) || we(0) != 1 ) ERROR("That weight enumerator doesn't make sense."); return we; } index_command(status) void execute_status( codehome* home, String commandx, DLList& command_queue, bool gullible, codetable& results ) { String set_pat( "{" + list_of( pos_number + orsign + pos_number + "\\.\\." + pos_number ) + "}" ); static Regex weightlist_pat( pos_number + orsign + pos_number + "_" + pos_number + orsign + set_pat + orsign + pos_number + "-" + set_pat + orsign + pos_number + "_" + pos_number + "-" + set_pat ); String wtlist; Pix entering_config = home->current; commandx = commandx.after( "status:" ); config& b = home->configs(home->base); while(1) { if ( commandx.empty( ) ) return; if ( commandx.contains( "classified", 0 ) ) { commandx = commandx.after( "classified" ); if (gullible) b.share->realizable = 1; else if ( b.share->realizable != 1 ) WARNING( "I don't know that the code type is realizable." ); if (gullible) home->classified = true; else if (!home->classified) ERROR( "The code type has not been classified." ); if ( commandx.empty( ) ) return; require_char( commandx, ',' ); } else if ( commandx[0] == 'w' ) { if ( !commandx.contains( "weights=", 0 ) ) ERROR( "Unrecognized status command." ); commandx = commandx.after( "weights=" ); if ( !commandx.contains( weightlist_pat, 0 ) ) ERROR( "Unrecognized status command." ); wtlist = take( commandx, weightlist_pat ); weightlist w(wtlist, home->n); OSLList w2 = diff( home->ww(home->base), w ); config& c = home->configs(home->base); bool nan; if (!gullible) { weightlist w1 = diff( w, home->ww(home->base) ); if ( !w1.empty( ) ) WARNING( "You should not have the " << "weights " << w1 << " in your weightlist." ); if ( !w2.empty( ) ) { // Perhaps the code type is classified. if ( home->dc.first == 'c' ) { weightlist bads; for ( int j = 0; j < home->dc.second.length; j++ ) { prevector cs = expand_config_list(home, home->dc.second(j)); for ( int i = 0; i < cs.length; i++ ) { config& c = home->configs( home->label_to_Pix( cs(i), results ) ); matrix M = c.basic_small( ); vector y = M.enumerate_weights( ); weightlist w3 = w2; forPixDef( l, w3 ) if ( y( w3(l) ) != 0 ) { w2.del( w3(l) ); bads.add( w3(l) ); } } } forPixDef( p, w2 ) c.add_constraint( String("y") + dec(w2(p)) + "=0", results, nan ); if ( bads.length( ) != 0 ) WARNING( "It would appear that weights " << bads << " cannot be eliminated." ); if ( commandx.empty( ) ) return; require_char( commandx, ',' ); continue; } vector v2(w2); bool something_changed; ordinary_kill: do { something_changed = false; for ( int i = v2.length-1; i >= 0; i-- ) { int wx = v2(i); if ( wx == 0 ) continue; String wxs = String("y") + dec(wx) + "=0"; if ( home->n == wx ) home->set_config(String(dec(wx)) + ":{1}", results); else home->set_config(String(dec(wx)) + "," + dec(home->n - wx) + ":{10}", results); home->configs(home->current). check_secondary_residuals(results); home->activate(true, results); if ( home->contradiction(true, results) ) { c.add_constraint( wxs, results, nan ); v2(i) = 0; something_changed = true; continue; } } } while(something_changed); home->set_current(home->base); for ( int i = v2.length-1; i >= 0; i-- ) { int wx = v2(i); if ( wx == 0 ) continue; home->deactivate( ); home->activate(true, results); constraintlist cl( String("y") + dec(wx) + "=0" ); set_numerical_parameter( "usedualdualforjoint", "5", "save" ); set_numerical_parameter( "usedualdualforjoint", "5", "set" ); bool answer = home->show(cl, results, true, constraintlist( ), true); set_numerical_parameter( "usedualdualforjoint", "5", "restore" ); if (answer) { String wxs = String("y") + dec(wx) + "=0"; c.add_constraint( wxs, results, nan ); home->ww(home->base).del(wx); v2(i) = 0; goto ordinary_kill; } } if ( !v2.if_zero( ) ) { String bads(v2); bads.gsub( ",0", "" ); bads.gsub( "{0,", "{" ); ERROR( "I can't get rid of the weights in the " << "list " << bads << "." ); } } } else { forPixDef( p, w2 ) c.add_constraint( String("y") + dec(w2(p)) + "=0", results, nan ); } home->set_current(entering_config); if ( commandx.empty( ) ) return; require_char( commandx, ',' ); } else if ( commandx[0] == 'e' ) { if ( !commandx.contains( "enumerator=", 0 ) ) ERROR( "Unrecognized status command." ); commandx = commandx.after( "enumerator=" ); String wes; if ( commandx.contains(',') ) { wes = commandx.before(','); commandx = commandx.after(','); } else { wes = commandx; commandx = ""; } vector we = we_from_String( wes, home->n, home->dim ); if (gullible) { bool weight_killed = false; for ( int i = 1; i <= home->n; i++ ) if (we(i) == 0) { home->ww(home->base).del(i); weight_killed = true; } else b.share->ycon.append( String("y") + dec(i) + "=" + dec(we(i)) ); if ( weight_killed && b.share->wjv.length != 0 ) { b.share->wjv.set_size(0); home->basic_joint_vars( &b, results ); } } else { home->set_current(home->base); int i; for ( i = 1; i <= home->n; i++ ) if (we(i) != 0 && !b.known ( String("y") + dec(i) + "=" + dec(we(i)) ) ) break; if ( i <= home->n ) { SLList vars0; for ( i = home->n; i >= 1; i-- ) { if ( we(i) == 0 && home->ww(home->base).contains(i) ) vars0.append( String("y") + dec(i) ); } bool work_required = !vars0.empty( ); if ( !work_required ) { for ( i = 1; i <= home->n; i++ ) { String y_eq = String("y") + dec(i) + "=" + dec(we(i)); if ( we(i) != 0 && !b.known(y_eq) ) { work_required = true; break; } } } if (work_required) { // Perhaps the code type is classified. if ( home->dc.first == 'c' ) { for ( int j = 0; j < home->dc.second.length; j++ ) { prevector cs = expand_config_list(home, home->dc.second(j)); for ( i = 0; i < cs.length; i++ ) { config& c = home->configs( home->label_to_Pix( cs(i), results ) ); matrix M = c.basic_small( ); vector y = M.enumerate_weights( ); if ( we != y ) ERROR( "It would " << "appear that you have the " << "wrong enumerator." ); } } work_required = false; } } if (work_required) { if ( !vars0.empty( ) ) { prevector vars(vars0); execute_kill_variable_by( home, vars, false, results ); } SLList var; SLList< pair > bound; for ( i = 1; i <= home->n; i++ ) { String y_eq = String("y") + dec(i) + "=" + dec(we(i)); if ( we(i) != 0 && !b.known(y_eq) && !home->show(y_eq, results, true) ) { var.append( String("y") + dec(i) ); bound.append(make_pair(we(i), we(i)));}} if ( var.length( ) != 0 ) { prevector< pair > boundv(bound); if ( !round_by_lp( b, var, boundv, false, true, 2, status_quiet, results ) ) ERROR( "I can't show that the weight " << "enumerator of the base " << "configuration " << "is " << as_poly(we) << "." ); } } } for ( i = 1; i <= home->n; i++ ) if (we(i) == 0) home->ww(home->base).del(i); } home->we_known = true; home->set_current(entering_config); if ( commandx.empty( ) ) return; require_char( commandx, ',' ); } else if ( commandx[0] == 'c' ) { if ( !commandx.contains( "constraints={", 0 ) ) ERROR( "Unrecognized status command." ); commandx = commandx.after("constraints={"); HIDE(![ static String less_op = left + "<" + orsign + "<=" + right; static String compound_constraint_pat = "[-]?" + number_pat + less_op + LHS_pat + less_op + "[-]?" + number_pat; static Regex constraint_list_pat( list_of( constraint_pat + orsign + var + "!=0" + orsign + compound_constraint_pat) ); ]!) if ( !commandx.contains( constraint_list_pat, 0 ) ) ERROR("Constraint list is garbled."); constraintlist cl( take( commandx, constraint_list_pat ) ); require_char( commandx, '}' ); if ( !cl.joint( ) ) ERROR("The constraints can involve only " << "global and joint variables."); constraintlist cl_left; forPixDef( p, cl ) { if (gullible) b.share->ycon.merge( cl(p) ); else if ( !b.known( cl(p) ) ) { // Perhaps the code type is classified. if ( home->dc.first == 'c' && cl(p).global( ) ) { for ( int j = 0; j < home->dc.second.length; j++ ) { prevector cs = expand_config_list(home, home->dc.second(j)); for ( int i = 0; i < cs.length; i++ ) { config& c = home->configs( home->label_to_Pix( cs(i), results ) ); matrix M = c.basic_small( ); vector y = M.enumerate_weights( ); if (!home->check_globals(cl(p), y, c)) ERROR( "It would appear that " << cl(p) << " does not hold." ); } } } else cl_left.append( cl(p) ); } } // Otherwise try to show the constraints are true. home->set_current(home->base); prevector var; prevector< pair > bound; reformat_constraintlist( cl_left, var, bound ); if ( !round_by_lp( b, var, bound, false, true, 2, status_quiet, results ) ) ERROR( "I couldn't show that the given constraints hold." ); if ( commandx.empty( ) ) return; require_char( commandx, ',' ); } else if ( commandx.contains( "unique", 0 ) ) { commandx = commandx.after( "unique" ); if (gullible) { home->unique = true; b.share->realizable = 1; } else if (!home->unique) ERROR( "The code type is not known to contain a unique code." ); if ( commandx.empty( ) ) return; require_char( commandx, ',' ); } else { if ( !commandx.contains( "realizable", 0 ) ) ERROR( "Unrecognized status command." ); commandx = commandx.after("realizable"); if (gullible) b.share->realizable = 1; else if ( b.share->realizable != 1 ) WARNING( "I don't know that the code type is realizable." ); if ( commandx.empty( ) ) return; require_char( commandx, ',' ); } } } index_method(expand_config_list) prevector expand_config_list( codehome* home, String s ) { HIDE( ![ static Regex config_list_pat(config_list); static Regex number_pattern( number_pat ); ]! ) static Regex config_list_piece_pat(config_list_piece); String s_save = s; if ( !s.matches( config_list_pat ) ) ERROR( "Syntax of configuration list " << s_save << " is wrong." ); prevector answer; SLList pass1, pass2, pass3, pass4, pass5; while( !s.empty( ) ) { pass1.append( take(s, config_list_piece_pat) ); if ( s.empty( ) ) break; s.del( "," ); } forPixDef( p, pass1 ) { String piece = pass1(p); if ( !piece.contains("{") ) pass2.append(piece); else { String front = piece.before("{"); piece = piece.after("{"); piece.del("]"); if ( !piece.contains("}", -1) ) ERROR( "Syntax of configuration list " << s_save << " is wrong." ); piece.del("}", -1); prevector segs = unpack(piece); for ( int i = 0; i < segs.length; i++ ) pass2.append( front + segs(i) + "]" ); } } if ( home != 0 ) { forPix( p, pass2 ) { String piece = pass2(p); if ( !piece.contains("*") ) pass3.append(piece); else { pass2(p).del("]", -1); if ( !pass2(p).contains("*", -1) ) ERROR( "Syntax of " << "configuration list " << s_save << " is wrong." ); pass2(p).del("*", -1); forPixDef( q, home->labels ) if ( home->labels(q).first.contains( pass2(p), 0 ) ) { String s = home->labels(q).first.after(pass2(p)); if ( s.contains( "!" ) ) continue; pass3.append( home->labels(q).first ); } } } } else pass3 = pass2; forPix( p, pass3 ) { String piece = pass3(p); if ( !piece.contains( ',' ) ) pass4.append(piece); else { prevector ps = unpack(piece); pass4.append( ps(0) + "]" ); for ( int i = 1; i < ps.length - 1; i++ ) pass4.append( "[" + ps(i) + "]" ); pass4.append( "[" + ps( ps.length - 1 ) ); } } forPix( p, pass4 ) { String piece = pass4(p); static Regex range( number_pat + "[" + "." + "][" + "." + "]" + number_pat ); if ( !piece.contains(range) ) pass5.append(piece); else { String first = piece.before(range); String middle = piece.at(range); String last = piece.after(range); int i1 = take_int( middle, number_pattern ); middle.del( ".." ); int i2 = as_int( middle ); if ( i1 > i2 ) ERROR( "Invalid .. range." ); for ( int i = i1; i <= i2; i++ ) pass5.append( first + dec(i) + last ); } } return prevector(pass5); } index_command(via unique wordtypes) void execute_via_unique_wordtypes( String label1, String label2, Pix pix1, Pix pix2, codehome* home, bool gullible ) { if (!gullible) { config& c1 = home->configs(pix1); config& c2 = home->configs(pix2); if ( !c2.terminal( ) ) ERROR(label2 << " is not terminal."); if ( !(home->configs(pix2).share->realizable == 1) ) ERROR( label2 << " is not known to be realizable" ); forPixDef( p, home->implications ) if ( home->implications(p).first == pix2 && home->implications(p).second.length( ) == 1 && home->implications(p).second.front( ) == pix1 ) break; if (p == 0) ERROR("I don't know that the realization of " << label2 << " is contained in the realization of " << label1 << "."); vector we = c1.smallcode_we( ); SLList unknowns; for ( int i = 1; i <= home->n; i++ ) { String con = String("y") + dec(i) + "=" + dec(we(i)); if ( !c1.known( con ) ) unknowns.append(con); } if ( unknowns.length( ) > 1 ) { cerr << "The following constraints are unknown:\n"; forPix( p, unknowns ) cerr << " " << unknowns(p) << "\n"; ERROR("At most one such constraint can be unknown."); } } home->implications.append(make_pair(pix1, make_list(pix2) )); home->set_current(0); } index_method(mask_satisfied) bool mask_satisfied( int n, int k, constraintlist mask ) { forPixDef( p, mask ) { Rational sum = 0; forPixDef( q, mask(p).LHS ) { term& t = mask(p).LHS(q); if ( t.var == "n" ) sum += Integer(n) * t.coeff; else if ( t.var == "k" ) sum += Integer(k) * t.coeff; else ERROR( "Illegal variable in mask." ); } if ( !test( sum, mask(p).RHS, mask(p).sense ) ) return false; } return true; } index_method(juxt) String juxt( String label1, String label2 ) { label1.del("]"); label2.del("["); return label1 + "." + label2; } index_method(iso_dual_words_of_given_weight) SLList< vector > iso_dual_words_of_given_weight( matrix M, int r ) { int i, j, k; SLList< vector > answer; SLList< vector > L = dual_words_of_given_weight(M, r); if ( L.length( ) == 0 ) return SLList< vector >( ); prevector< vector > Lv(L), Lv2(L.length( )); prevector Lw( Lv.length ); for ( j = 0; j < Lw.length; j++ ) { Lw(j).set_size( M.ncols ); for ( k = 0; k < r; k++ ) Lw(j)( Lv(j)(k) ) = 1; } // Sort Lw and then in effect apply the same permutation to Lv. Lw.sort(&cmp); for ( i = 0; i < Lw.length; i++ ) { vector x(r); int j = 0; for ( k = 0; k < M.ncols; k++ ) if ( Lw(i)(k) ) x(j++) = k; Lv(i) = x; } EquivRelIntList e(Lw.length); word w(M.ncols); pair pp = find_automorphism_group(M); for ( i = 0; i < pp.first.length; i++ ) for ( j = 0; j < Lw.length; j++ ) { w = Lw(j); pp.first(i).act(w); k = Lw.pos(w, &cmp); if ( k == -1 ) INTERNAL_ERROR("dual word orbits"); e.join(j, k); } for ( i = 0; i < e.length; i++ ) if ( e.minimal(i) ) answer.append( Lv(i) ); return answer; } index_method(bitlist) String bitlist(const word& w, bool short_form = false, int mult = 1 ) { String s = "{"; bool dotdot = false; int i; for ( i = 0; i < w.length; i++ ) { if ( w(i).x == 0 && dotdot ) { if ( i >= 2 && w(i-1) && w(i-2) ) { if ( i <= 2 || !w(i-3) ) s += String(",") + dec(mult*i); else s += String("..") + dec(mult*i); } dotdot = false; } else if ( w(i) && !dotdot ) { if ( s.length( ) != 1 ) s += ","; s += dec(mult*(i+1)); dotdot = true; } } if ( dotdot && i >= 2 && w(i-1) && w(i-2) ) { if ( i <= 2 || !w(i-3) ) s += String(",") + dec(mult*i); else s += String("..") + dec(mult*i); } s += "}"; if ( short_form && mult == 1 ) { bool even = true; for ( i = 0; i < w.length; i += 2 ) if ( w(i).x != 0 ) { even = false; break; } bool doubly_even = even; if (even) { for ( i = 1; i < w.length; i += 4 ) if ( w(i).x != 0 ) { doubly_even = false; break; } } if ( !even ) return s; for ( i = 0; i < w.length; i++ ) if ( w(i) != 0 ) break; if ( i == w.length ) return s; int d = i+1; if (doubly_even) { String s_alt = String(dec(d)) + "_4"; word v( w.length/4 ); for ( i = 0; i < v.length; i++ ) if ( 4*i+4 >= d && !w(4*i+3) ) v(i) = 1; s_alt += " - " + bitlist( v, false, 4 ); if ( s_alt.length( ) < s.length( ) ) return s_alt; } else { String s_alt = String(dec(d)) + "_2"; word v( w.length/2 ); for ( i = 0; i < v.length; i++ ) if ( 2*i+2 >= d && !w(2*i+1) ) v(i) = 1; s_alt += " - " + bitlist( v, false, 2 ); if ( s_alt.length( ) < s.length( ) ) return s_alt; } } return s; } index_method(enlarge_by_dual_word) SLList< matrix > enlarge_by_dual_word(const matrix& M, int r) { int i, j, n = M.ncols, k = M.nrows, d = min_distance(M, 0); // Make a list of all possible columns which could be added to M. vector< vector > admv( (int) Ipow( 2, k ) ); word v(k); int count = 0; do admv( count++ ) = v; while( v.advance( ) ); admv.sort(&cmp); // Compute the action of Aut(M) on these columns. // (code taken from list_extensions) Permutationlist genset = find_automorphism_group(M).first; Permutationlist genset2(count); genset2.set_size( genset.length ); matrix Mc, Q; vector rx; Permutation pp(count); for ( j = 0; j < genset.length; j++ ) { Mc = M; Mc.permute_columns( genset(j) ); Mc.reduce_i(Q); for ( i = 0; i < count; i++ ) { mul( Q, admv(i), rx ); int xp = admv.pos( rx, cmp ); HIDE( ![ if ( xp == -1 ) INTERNAL_ERROR("computation of genset2"); ]! ) pp(i) = xp + 1; } genset2(j) = pp; } // Determine the induced equivalence relation on the columns. EquivRelIntList e( count ); for ( i = 0; i < genset2.length; i++ ) { Permutation p = genset2(i); for ( j = 0; j < p.length; j++ ) e.join( j, p(j) - 1 ); } SLList< matrix > MAs1, MAs2; SLList min_words; word indx(k); word w(n); do { mul( indx, M, w ); int rr = w.weight( ); if ( rr == d || rr == d+1 ) min_words.append(indx); } while( indx.advance( ) ); word u(r); matrix A( k, r ); vector min_cl( admv.length ); for ( i = 0; i < admv.length; i++ ) min_cl(i) = e.min_in_class(i); if ( r == 3 ) { for ( int q1 = 0; q1 < admv.length; q1++ ) { if ( !e.minimal(q1) ) continue; A.set_col( 0, admv(q1) ); for ( int q2 = q1; q2 < admv.length; q2++ ) { if ( min_cl(q2) < q1 ) continue; A.set_col( 1, admv(q2) ); for ( i = 0; i < k; i++ ) A(i, 2) = A(i, 0) + A(i, 1); forPixDef( p, min_words ) { mul( min_words(p), A, u ); if ( u.if_zero( ) ) break; } if ( p == 0 ) { matrix MA; hcat( M, A, MA ); MA.reduce_nz( ); matrix MAc = canonical_form(MA); forPixDef( q, MAs1 ) if ( MAs1(q) == MAc ) break; if ( q == 0 ) { MAs1.append( MAc ); MAs2.append( MA ); } } } } } if ( r == 4 ) { for ( int q1 = 0; q1 < admv.length; q1++ ) { if ( !e.minimal(q1) ) continue; A.set_col( 0, admv(q1) ); for ( int q2 = q1; q2 < admv.length; q2++ ) { if ( min_cl(q2) < q1 ) continue; A.set_col( 1, admv(q2) ); for ( int q3 = q2; q3 < admv.length; q3++ ) { if ( min_cl(q3) < q1 ) continue; A.set_col( 2, admv(q3) ); for ( i = 0; i < k; i++ ) A(i, 3) = A(i, 0) + A(i, 1) + A(i, 2); forPixDef( p, min_words ) { mul( min_words(p), A, u ); if ( u.if_zero( ) ) break; } if ( p == 0 ) { matrix MA; hcat( M, A, MA ); MA.reduce_nz( ); matrix MAc = canonical_form(MA); forPixDef( q, MAs1 ) if ( MAs1(q) == MAc ) break; if ( q == 0 ) { MAs1.append( MAc ); MAs2.append( MA ); } } } } } } if ( r == 5 ) { for ( int q1 = 0; q1 < admv.length; q1++ ) { if ( !e.minimal(q1) ) continue; A.set_col( 0, admv(q1) ); for ( int q2 = q1; q2 < admv.length; q2++ ) { if ( min_cl(q2) < q1 ) continue; A.set_col( 1, admv(q2) ); for ( int q3 = q2; q3 < admv.length; q3++ ) { if ( min_cl(q3) < q1 ) continue; A.set_col( 2, admv(q3) ); for ( int q4 = q3; q4 < admv.length; q4++ ) { if ( min_cl(q4) > q1 ) continue; A.set_col( 3, admv(q4) ); for ( i = 0; i < k; i++ ) A(i,4) = A(i,0) + A(i,1) + A(i,2) + A(i,3); forPixDef( p, min_words ) { mul( min_words(p), A, u ); if ( u.if_zero( ) ) break; } if ( p == 0 ) { matrix MA; hcat( M, A, MA ); MA.reduce_nz( ); matrix MAc = canonical_form(MA); forPixDef( q, MAs1 ) if ( MAs1(q) == MAc ) break; if ( q == 0 ) { MAs1.append( MAc ); MAs2.append( MA ); } } } } } } } if ( r == 6 ) { for ( int q1 = 0; q1 < admv.length; q1++ ) { if ( !e.minimal(q1) ) continue; cerr << "trying " << q1 << "\n"; // XXX A.set_col( 0, admv(q1) ); for ( int q2 = q1; q2 < admv.length; q2++ ) { if ( min_cl(q2) < q1 ) continue; cerr << "sub - trying " << q2 << "\n"; // XXX A.set_col( 1, admv(q2) ); for ( int q3 = q2; q3 < admv.length; q3++ ) { if ( min_cl(q3) < q1 ) continue; A.set_col( 2, admv(q3) ); for ( int q4 = q3; q4 < admv.length; q4++ ) { if ( min_cl(q4) > q1 ) continue; A.set_col( 3, admv(q4) ); for ( int q5 = q4; q5 < admv.length; q5++ ) { if ( min_cl(q5 ) > q1 ) continue; A.set_col( 4, admv(q5) ); for ( i = 0; i < k; i++ ) A(i,5) = A(i,0) + A(i,1) + A(i,2) + A(i,3) + A(i,4); forPixDef( p, min_words ) { mul( min_words(p), A, u ); if ( u.if_zero( ) ) break; } if ( p == 0 ) { matrix MA; hcat( M, A, MA ); MA.reduce_nz( ); matrix MAc = canonical_form(MA); forPixDef( q, MAs1 ) if ( MAs1(q) == MAc ) break; if ( q == 0 ) { MAs1.append( MAc ); MAs2.append( MA ); } } } } } } } } return MAs2; } index_command(config) void execute_config_command( String commandx, String commandx_save, codehome* home, bool executing_secondary_command, codetable& results, constraintlist input_mask, String code_label ) { bool eq = false; HIDE( ![ static Regex bang_label_pattern( bang_label_pat ); static Regex label_pattern( label_pat ); ]! ) Pix oldp = home->current; if ( commandx[0] == '=' ) { commandx.del('='); if (oldp == 0) WARNRET("Current configuration is undefined."); eq = true; } String l = ""; if ( commandx[0] == '[' ) { l = take(commandx, bang_label_pattern); if ( (eq || !executing_secondary_command) && l[l.length( ) - 1] == '!' ) WARNRET( "Invalid configuration label." ); config dd = config(home, commandx.after("config")); home->set_config(dd, results, l); } else home->set_config( commandx.after("config"), results ); config& c = home->configs(home->current); if ( c.small.basis.nrows <= 5 ) { c.small.build( ); int max_wt = 0; for ( int i = 0; i < c.small.x.nrows; i++ ) max_wt = max( max_wt, c.small.x(i) * c.part ); weightlist w; w.add(0); int d = c.home->w.min( ); bool some_deleted = false; forPixDef( p, c.share->ww ) { int wt = c.share->ww(p); if ( wt == max_wt || 2 * home->n - wt - max_wt >= d ) w.add(wt); else some_deleted = true; } c.small.unbuild( ); if (some_deleted) { c.share->ww = w; if (c.share->wjv.length != 0) { c.share->wjv.set_size(0); home->basic_joint_vars(&c, results); } } } bool nan = false; forPixDef( p, c.assumed_cons ) if ( c.assumed_cons(p).global( ) ) c.add_constraint( c.assumed_cons(p), results, nan ); if ( c.part.length == 1 ) { constraintlist cshare = c.share->ycon; forPix( p, cshare ) c.add_constraint( cshare(p), results, nan ); forPix( p, c.assumed_cons ) if ( !c.assumed_cons(p).global( ) ) c.add_constraint( c.assumed_cons(p), results, nan ); } forPix( p, home->configs ) { if ( p == home->current ) continue; config& cf = home->configs(p); bool me = mostly_equal(cf, c); if ( ( cf.basal( ) || me ) && cf.assumed_cons <= c.assumed_cons ) { c.share->ww = intersection( c.share->ww, cf.share->ww ); if ( cf.share != c.share ) { forPixDef( q, cf.share->ycon ) c.add_constraint( cf.share->ycon(q), results, nan ); } // c.share->ycon.merge( cf.share->ycon ); if (me) c.con.merge( cf.con ); } } if (eq) { Pix curp = home->current; execute_equals( home, oldp, curp, gullible ); home->set_current(curp); } if (nan) home->deactivate( ); if ( auto_group_computation && !home->configs(home->base).no_auto && c.assumed_cons.global( ) ) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; } if ( c.title == "" ) { String title = commandx_save; take( title, label_pattern ); title.del( ":=" ); title.del( ";", -1 ); if ( title.contains( "::" ) ) title = title.before( "::" ); c.title = title; } String a_code_label = code_label; if ( a_code_label == "" ) a_code_label = String("[?") + dec(home->n) + "_" + dec(home->dim) + "_" + dec(home->w.min( )) + "]"; String a_config_label = (l != "") ? l : String("[?]"); String source = juxt( a_code_label, a_config_label ); if ( home->dim != c.small.basis.nrows || !mask_satisfied( home->n, home->dim, input_mask ) ) return; if (auto_orbit_transform) { if (auto_dual_column_deletion != 2) auto_orbit_search( c.basic_small( ), source, results, home ); if (auto_dual_column_deletion != 0) { matrix M = c.basic_small( ); SLList< pair< int, matrix > > L = punctured_codes(M); forPixDef( p, L ) { cerr << "deleting column " << L(p).first << "\n"; auto_orbit_search( L(p).second, source + "-col" + dec(L(p).first), results, home ); } } } if (auto_residual_transform) { SLList cd = codeword_orbits(c); forPixDef( p, cd ) { if ( cd(p).if_zero( ) ) continue; matrix A = c.small.basis; matrix B(A.nrows, A.ncols - cd(p).weight( )); int l = 0; for ( int k = 0; k < A.ncols; k++ ) { if ( cd(p)(k) ) continue; for ( int j = 0; j < A.nrows; j++ ) B(j, l) = A(j, k); l++; } process_new_matrix( home, B, source + " - columns " + bitlist( cd(p) ), results ); } } if (auto_dual_residual_transform) { matrix M = c.basic_small( ); bool dual_word_found = false; int i, j, k; for ( int dd = 1; dd <= home->n; dd++ ) { SLList< vector > L = iso_dual_words_of_given_weight(M,dd); if ( L.length( ) == 0 ) continue; SLList< pair< vector, matrix > > dels; int count = 0; uniq_matrix_list Ms; forPixDef( p, L ) { matrix M2 = M; M2.delete_columns( L(p) ); M2.reduce_nz( ); if ( Ms.add(M2) ) { if ( count++ > auto_dual_residual_transform ) break; dels.append( make_pair( L(p), M2 ) ); } } forPixDef( q, dels ) { if ( dels.length( ) == 1 && p == 0 ) process_new_matrix( home, dels(q).second, source + " - dual word of weight " + dec(dd), results ); else process_new_matrix( home, dels(q).second, source + " - columns " + String(dels(q).first + number(1)), results ); } break; } } if (auto_group_residual_transform) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); if ( pp.second >= 2 && pp.second <= group_size_limit ) { Permutationlist classes(c.part.length); classes.find_conjugacy_classes( pp.first ); OSLList wd_list; for ( int i = 0; i < classes.length; i++ ) { int j, k, n = home->n; Permutation p = classes(i); SLList pile[n]; for ( j = 0; j < n; j++ ) { int k = 0; int jp = j; while(1) { if ( p(jp) == j+1 ) { pile[k].append(j); break; } k++; jp = p(jp) - 1; } } SLList< SLList > piles; for ( j = 0; j < n; j++ ) if ( pile[j].length( ) != 0 ) piles.append( pile[j] ); prevector< SLList > pilesv(piles); if ( pilesv.length == 1 ) continue; word indx( pilesv.length ), wd(n); do { wd.set_zero( ); for ( j = 0; j < pilesv.length; j++ ) { if ( indx(j) ) { forPixDef( q, pilesv(j) ) wd( pilesv(j)(q) ) = 1; } } int n0 = wd.weight( ); if ( n0 <= 5 || n0 == n ) continue; if ( wd_list.contains(wd) ) continue; wd_list.add(wd); matrix B( home->dim, n0 ); int l = 0; for ( j = 0; j < n; j++ ) if ( wd(j) ) B.set_col(l++, c.small.basis.col(j)); process_new_matrix( home, B, source + " - columns " + bitlist( wd.complement( ) ), results ); } while( indx.advance( ) ); } } } if (find_regular_group_element >= 1 && c.part.length == c.home->n ) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); if (pp.second >= 2 && pp.second <= group_size_limit) { Permutationlist classes(c.part.length); classes.find_conjugacy_classes( pp.first ); int i, j; for ( i = 0; i < classes.length; i++ ) { int k, n = home->n; Permutation p = classes(i); prevector< prevector > pv = p.orbits( ); String pc = p.as_cycle_product( ); if ( pv(0).length != 0 ) continue; int r = pv(1).length; for ( j = 2; j < pv.length; j++ ) if ( pv(j).length != r ) break; if ( j != pv.length ) continue; if ( find_regular_group_element > 1 && find_regular_group_element != r ) continue; if (r == 2) { OSLList kernel, image, dkernel; matrix M = c.basic_small( ); word indx(M.nrows), v; cerr << "monogenic words:\n"; do { mul( indx, M, v ); for ( j = 1; j < n/2 + 1; j++ ) if ( v( pv(j)(0) ) && v( pv(j)(1) ) ) break; if ( j == pv.length ) { for (j = 1; j < n/2 + 1; j++) cerr << v( pv(j)(0) ) << v( pv(j)(1) ) << " "; cerr << "\n"; } word im( n/2 ); for ( j = 1; j <= n/2; j++ ) im(j) = v( pv(j)(0) ) + v( pv(j)(1) ); image.add(im); if ( im.if_zero( ) ) { dkernel.add(v); word ker( n/2 ); for (j = 1; j <= n/2; j++) ker(j) = v( pv(j)(0) ); kernel.add(ker); } } while( indx.advance( ) ); matrix k2( n/2, SLList(kernel) ); matrix dk2( n, SLList(dkernel) ); matrix i2( n/2, SLList(image) ); k2.reduce_nz( ); dk2.reduce_nz( ); i2.reduce_nz( ); pair pk2 = find_automorphism_group(k2); pair pi2 = find_automorphism_group(i2); cerr << "basis for kernel : full code\n"; for ( j = 0; j < dk2.nrows; j++ ) { word xxx(n); for ( int ll = 1; ll <= n/2; ll++ ) { xxx(2*ll - 2) = dk2( j, pv(ll)(0) ); xxx(2*ll - 1) = dk2( j, pv(ll)(1) ); } dk2(j) = xxx; } matrix dM = M; for ( j = 0; j < dM.nrows; j++ ) { word xxx(n); for ( int ll = 1; ll <= n/2; ll++ ) { xxx(2*ll - 2) = dM( j, pv(ll)(0) ); xxx(2*ll - 1) = dM( j, pv(ll)(1) ); } dM(j) = xxx; } cerr << dk2 << " :\n"; cerr << dM << "\n"; cerr << "kernel has type [" << n/2 << "," << k2.nrows << "," << min_distance( k2, 0 ) << "]{" << as_poly(k2.enumerate_weights( )) << "}|Aut| = " << pk2.second << " and "; cerr << "image has type [" << n/2 << "," << i2.nrows << "," << min_distance( i2, 0 ) << "]{" << as_poly(i2.enumerate_weights( )) << "}|Aut| = " << pi2.second << "\n"; cerr << "generators for Aut(kernel):\n"; for ( j = 0; j < pk2.first.length; j++ ) cerr << " " << pk2.first(j) << "\n"; } cerr << pc << "\n"; } } } if (auto_enlarge_by_dual_word) { int n = home->n, k = home->dim; int d = home->w.min( ); int r = auto_enlarge_by_dual_word; if ( r != 3 && r != 4 ) ERROR( "Illegal value for auto enlarge by dual word." ); results.recompute_lower_bound(n, k); // In some ways it would be better to remove the following "if", // because the program would then be more likely to find an // internal error, if it exists. if ( !results.not_exist( n+r, k, weightlist( dec(d + 2), n+r ) ) && results.lower_bound( n+r-1, k ) < d + 2 && results.lower_bound( n+r+1, k+1 ) < d + 2 ) { matrix M = c.basic_small( ); SLList< matrix > MAs = enlarge_by_dual_word(M, r); int count = 1; forPixDef( p, MAs ) { String call = source + " + dual word of weight " + r + " (#" + dec(count++) + ")"; process_new_matrix( home, MAs(p), call, results ); } } } if (auto_group_residual_transform_alt) { pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; if (pp.second >= 2 && pp.second <= group_size_limit) { Permutationlist classes(c.part.length); classes.find_conjugacy_classes( pp.first ); int i, j, k, n = home->n; for ( i = 0; i < classes.length; i++ ) { Permutation p = classes(i); prevector< prevector > pv = p.orbits( ); String pc = p.as_cycle_product( ); if ( pv.length == 1 ) continue; if ( pv.length > nzv_length_max ) continue; word indx( pv.length ), wd(n); do { wd.set_zero( ); for ( j = 0; j < pv.length; j++ ) { if ( indx(j) ) { for ( k = 0; k < pv(j).length; k++ ) wd( pv(j)(k) ) = 1; } } int n0 = wd.weight( ); if (!mask_satisfied(n0, home->dim, output_mask)) continue; if ( n0 == n ) continue; matrix B( home->dim, n0 ); int l = 0; for ( j = 0; j < n; j++ ) { if ( !wd(j) ) continue; for ( k = 0; k < home->dim; k++ ) B( k, l ) = c.small.basis( k, j ); l++; } B.reduce_nz( ); if (!mask_satisfied(B.ncols, B.nrows, output_mask)) continue; String call = source + " - columns " + bitlist( wd.complement( ) ); process_new_matrix( home, B, call, results ); } while( indx.advance( ) ); } } } if (auto_puncture_transform) { int i, j, k, n = home->n; matrix wes(n,n+1); wes.set_zero( ); c.small.build( ); for ( i = 0; i < c.small.x.nrows; i++ ) { int wt = c.small.x(i).weight( ); for ( j = 0; j < n; j++ ) wes(j, wt) += c.small.x(i)(j); } c.small.unbuild( ); SLList< SLList > bags; for ( i = 0; i < n; i++ ) { forPixDef( p, bags ) if ( wes( bags(p).front( ) ) == wes(i) ) { bags(p).append(i); break; } if ( p == 0 ) { SLList newbag; newbag.append(i); bags.append(newbag); } } prevector< SLList > pilesv(bags); if ( pilesv.length > 1 && pilesv.length <= 16 ) { word indx( pilesv.length ), wd(n); do { wd.set_zero( ); for ( j = 0; j < pilesv.length; j++ ) { if ( indx(j) ) { forPixDef( q, pilesv(j) ) wd( pilesv(j)(q) ) = 1; } } int n0 = wd.weight( ); if ( n0 <= 5 || n0 == n ) continue; matrix B( home->dim, n0 ); int l = 0; for ( j = 0; j < n; j++ ) { if ( !wd(j) ) continue; for ( k = 0; k < home->dim; k++ ) B( k, l ) = c.small.basis( k, j ); l++; } process_new_matrix(home, B, source + " * puncture ", results); } while( indx.advance( ) ); } } if (auto_dual_transform) { if (auto_dual_column_deletion != 2) auto_dual_search( c.basic_small( ), source, results, home ); if (auto_dual_column_deletion != 0) { matrix M = c.basic_small( ); SLList< pair< int, matrix > > L = punctured_codes(M); forPixDef( p, L ) { cerr << "deleting column " << L(p).first << "\n"; auto_dual_search( L(p).second, source + "-col" + dec(L(p).first), results, home ); } } } } index_method(codeword_orbits) SLList codeword_orbits( config& c ) { c.small.build( ); int i, j; prevector cd(c.small.x.nrows); for ( i = 0; i < cd.length; i++ ) cd(i) = c.small.x(i); cd.sort(&cmp); EquivRelIntList e(cd.length); word w(c.part.length); pair< Permutationlist, Integer > pp = c.find_automorphism_group( ); c.aut = pp.first; for ( i = 0; i < c.aut.length; i++ ) for ( j = 0; j < cd.length; j++ ) { w = cd(j); c.aut(i).act(w); int k = cd.pos(w, &cmp); if ( k == -1 ) INTERNAL_ERROR( "codeword_orbits" ); e.join(j, k); } SLList answer; for ( i = 0; i < cd.length; i++ ) if ( e.minimal(i) ) answer.append( cd(i) ); return answer; } index_command(process) void execute_process( String commandx, int low, codetable& results, codehome* home, String code_label, String commandx_save ) { if (clear_newcodes) newcodes.clear( ); if ( commandx.contains( "@1" ) && !commandx.contains( "@w1" ) ) { int count = 0; forPixDef( p, results.olabels ) { String hlabel = results.olabels(p).first; codehome* h = results.open(results.olabels(p).second); if ( !mask_satisfied(h->n, h->dim, input_mask )) continue; forPixDef( q, h->labels ) { String clabel = h->labels(q).first; config& c = h->configs(h->labels(q).second); if ( c.full( ) ) { String md = commandx; md.gsub( "@1", juxt( hlabel, clabel ) ); execute_process( md, count++, results, home, code_label, commandx_save ); } } } } else if ( commandx.contains( "@1" ) && commandx.contains( "@w1" ) ) { int count = 0; forPixDef( p, results.olabels ) { String hlabel = results.olabels(p).first; codehome* h = results.open(results.olabels(p).second); if ( !mask_satisfied(h->n, h->dim, input_mask )) continue; forPixDef( q, h->labels ) { String clabel = h->labels(q).first; config& c = h->configs(h->labels(q).second); SLList cd = codeword_orbits(c); if ( c.full( ) ) { count++; String md = commandx; md.gsub( "@1", juxt( hlabel, clabel ) ); forPixDef( r, cd ) { String md2 = md; word vv = c.small.basis.coord_vector( cd(r) ); if ( vv.if_zero( ) ) continue; md2.gsub( "@w1", String(vv) ); execute_process(md2, count, results, home, code_label, commandx_save); } } } } } else if ( commandx.contains( "@2" ) ) { int count = 0; forPixDef( p, results.olabels ) { String hlabel = results.olabels(p).first; codehome* h = results.open(results.olabels(p).second); if ( !mask_satisfied(h->n, h->dim, input_mask )) continue; forPixDef( q, h->labels ) { String clabel = h->labels(q).first; config& c = h->configs(h->labels(q).second); if ( c.full( ) ) { if ( count++ < low ) continue; String md = commandx; md.gsub( "@2", juxt( hlabel, clabel ) ); execute_process( md, 0, results, home, code_label, commandx_save ); } } } } else if ( commandx.contains( "@i1" ) ) { for ( int i = i1low; i <= i1high; i++ ) { String md = commandx; md.gsub( "@i1", dec(i) ); execute_process( md, 0, results, home, code_label, commandx_save ); } } else if ( commandx.contains( "@i2" ) ) { for ( int i = i2low; i <= i2high; i++ ) { String md = commandx; md.gsub( "@i2", dec(i) ); execute_process( md, 0, results, home, code_label, commandx_save ); } } else if ( commandx.contains( ",@v)" , -1 ) ) { commandx.del( ",@v)", -1 ); int i, j; for ( i = commandx.length( ) - 1; i >= 0; i-- ) if ( commandx.contains( "Act(", i ) ) break; if ( i < 0 ) ERROR( "Illegal use of Act." ); String gp = commandx.after( "Act(", i ); String hd = commandx.before( "Act(", i ); matrix header(0,0); SLList sources; if ( hd != "" ) { if ( hd[hd.length( ) - 1] != '|' ) ERROR("Illegal use of Act."); hd.del( "|", -1 ); header = evaluate_expression( hd, results, home, code_label, sources ); } int hncols = header.ncols; commandx_save = commandx_save.after( "process" ); generic_object g = evaluate_expression( gp, results, home, code_label, sources ); g.convert( "List(MatF2{invertible}){homogeneous}" ); prevector< matrix > ms = g; int n; n = ms(0).nrows; if ( header.nrows != 0 && header.nrows != n ) ERROR( "Header size doesn't make sense." ); int two_k = Ipow( 2, n ); // In the case of a random search, we include the zero column, which // for some reason may make the search work better. int sz = two_k; if (!random_search) sz--; prevector wds( sz ); word indx(n); if (!random_search) indx.advance( ); j = 0; do wds(j++) = indx; while( indx.advance( ) ); wds.sort( &cmp ); EquivRelIntList e(wds.length); for ( i = 0; i < ms.length; i++ ) { matrix M = ms(i); for ( j = 0; j < wds.length; j++ ) { word w; mul( M, wds(j), w ); int kc = wds.pos( w, &cmp ); if ( kc == -1 ) INTERNAL_ERROR("xpos problem"); e.join( j, kc ); } } SLList< prevector > orbits; for ( int j1 = 0; j1 < wds.length; j1++ ) if (e.minimal(j1) && wds(j1).weight( ) >= min_vector_weight) { int k1 = e.size(j1); if ( hncols + k1 > dual_transform_length_limit ) continue; int e_ptr = j1; SLList orbit; for ( i = 0; i < k1; i++ ) { orbit.append( wds(e_ptr) ); e_ptr = e(e_ptr); } prevector orbitv(orbit); orbits.append(orbitv); } prevector< prevector > orbitsv(orbits); String title_head = commandx_save.before( "@v" ); if (random_search) random_code_search( n, orbitsv, results, title_head, 2, vector(0), int(0), home, header ); else code_search( n, orbitsv, results, title_head, 2, vector(0), int(0), home, header ); } else { SLList sources; packed_matrix_list M = evaluate_expression( commandx, results, home, code_label, sources ); forPixDef( p, M.third ) { matrix N = unpack( M.third(p).x, M.first, M.second ); if ( mask_satisfied( N.ncols, N.nrows, input_mask ) ) process_new_matrix( home, N, commandx, results ); } } } set_compile_file(execute3.cc) HIDE( ![ #include "homedefs.h" #include "bitvec.h" #include "codetable.h" #include "graph.h" extern int unresidue_show_all_configs, unresidue_show_extra_info, auto_joint_list, warnings_are_fatal; Permutation get_canonical(vertex_colored_graph&, int); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); matrix subdivide_matrix(const matrix&, const partition&, const wordtype&, bool, bool = true); SLList subdivide_wordtype_list(SLList, codehome*, Pix, config&, config&, wordtype, codetable&, bool, bool); int rcmp(const number&, const number&); void mul( const vector&, const matrix&, vector&); prevector< triple< int, int, prevector< pair > > > sblv_triple_maker(const partition&, const partition&, const wordtype&, wordtype&, int = 0); bool realizable(config_core&, constraintlist&, codehome*, codetable&); prevector< prevector< prevector > > joint_adm_table( config* c, codetable& results); ]! ) TEX( ![ \verb|extend_residual_code|: Attempt to reconstruct a code $C$ from its residual code $D$ \WRT\ some word. Input to the routine consists primarily of a matrix {\tt R}, the generator matrix for $D$, a codehome {\tt home}, and a basal configuration {\tt clabel} for it. Output consists of all the codes in {\tt home} which have $D$ as their residual code, up to isomorphism, and which satisfy the constraints of {\tt clabel}. Here are a few remarks about the method. Let $R_0$ denote the matrix obtained from $R$ by adding a zero row at the bottom. In the very roughest sense, the program proceeds by systematically considering all matrices $M$ whose first row is the all ones vector and which after adding rows at the bottom could be horizonally concatenated with $R_0$ to yield a generator matrix for the code type. There are some subtleties regarding the sense in which such matrices $M$ are tracked. First, permutations of the columns of $M$ should be ignored. Second, complementation of rows (beyond the first row) should be ignored. Third, we contract repeated columns of $M$ (yielding $\oM$) and place the information thus lost into a multiplicity vector $m$. In fact, we do not just track the pairs $(\oM,m)$. For each $(\oM,m)$, we also keep a list of pairs $(w,j)$, corresponding to wordtypes $w$ which could (conceivably) ``be'' the \th{j} row of an extension of $M$. ]! ) index_method(extend_residual_code) prevector< matrix > extend_residual_code( codehome* home, String clabel, matrix R, codetable& results, Integer stop_after ) { bool show_all_configs = unresidue_show_all_configs; bool depth_first = false; SLList< matrix > terminals; constraintlist bass; Pix p, q; config& basal = home->configs( home->label_to_Pix( clabel, results ) ); if ( !basal.basal( ) ) ERROR( "Unresidue can only be applied to a basal configuration." ); forPix( p, home->assumed_cons ) if ( home->assumed_cons(p).joint( ) ) bass.append( home->assumed_cons(p) ); forPix( p, basal.assumed_cons ) if ( basal.assumed_cons(p).joint( ) ) bass.append( basal.assumed_cons(p) ); int i, j, k, r = R.ncols, n = home->n; if ( n <= r ) ERROR( "There is nothing to extend." ); int mind = home->w.min( ); if ( n-r >= 2*mind ) ERROR( "I can't do that safely." ); R.reduce_nz( ); if ( R.nrows != home->dim - 1 ) ERROR( "The rank of the matrix fed to Unresidue must be one less " << "than the dimension of the code type fed to it." ); String basscon( basal.assumed_cons ); basscon.gsub( " ", "" ); config b = config( home, String(dec(n-r)) + "," + dec(r) + ":{10}::{" + basscon + "}" ); bool projective = b.known( constraint("mu1=0") ) && b.known( constraint("mu2=0") ); home->set_config( b, results ); SLList< quadruped< config_core, SLList< pair< wordtype, OSLList > >, SLList, bool > > stack; SLList< pair< partition, matrix > > stack_can; int config_count = 0, terminal_config_count = 0; // Determine the weights below the parts. home->activate( true, results, false ); mawhometable& m = home->active->vtable; weightlist ww1; for ( int l = 0; l < m.length; l++ ) { int x = m(l).maw(0); ww1.add( x ); ww1.add( n - r - x ); } codehome h0( n - r, home->dim, ww1 ); config b0( &h0, String(dec(n-r)) + ":{1}" ); // Reformat the table of admissible variables. bool adm[n+1][n+1]; for ( i = 0; i <= n; i++ ) for ( j = 0; j <= n; j++) adm[i][j] = false; for ( int l = 0; l < m.length; l++ ) { adm[ m(l).maw(0) ][ m(l).maw(1) ] = true; adm[ n - r - m(l).maw(0) ][ m(l).maw(1) ] = true; } // Compute list0 and list0x. SLList< pair< wordtype, OSLList > > list0; SLList list0x; bool warnflag = false; for ( int l = 0; l < m.length; l++ ) { if ( m(l).maw(0) == 0 && m(l).maw(1) != 0 && !warnflag ) { WARNING( "The results of this calculation are unreliable " << "unless I know that every codeword disjoint from" << " a codeword of weight " << n-r << " is zero." ); warnflag = true; } vector wv( m(l).maw ); wv.resize( wv.length - 1 ); wordtype w0(wv); w0.c = &b0; forPix( p, list0 ) if ( list0(p).first == w0 ) break; if ( p == 0 && w0(0) != 0 ) { OSLList some; for ( i = 1; i < R.nrows; i++ ) if ( adm[w0(0)][R(i).weight( )] ) some.add(i); list0.append( make_pair(w0, some) ); if ( adm[w0(0)][R(0).weight( )] ) list0x.append(w0); } } stack.append( make_quadruped( config_core(b0), list0, list0x, true ) ); if (show_all_configs) cerr << "\nConfiguration " << ++config_count << "\n" << b << "will have <= " << list0x.length( ) << " configurations directly below it.\n\n"; while(1) { // Check to see if we're done and count nodes. int nodes = 0; int stack_length = 0; forPix( p, stack ) if ( stack(p).fourth ) { nodes += stack(p).third.length( ); stack_length++; } if ( nodes == 0 ) break; if (unresidue_show_extra_info) cerr << "\nThere are now " << stack_length << " configurations " << "in the stack. When these are processed, there may be " << "as many as " << nodes << " configurations in the " << "stack, but in all likelihood there will not be so " << "many, because some of them will be isomorphic.\n\n"; TEX( ![ \begin{quotea} Find a stack element with a wordtype list of minimal length, unless \verb|depth_first| is set. \end{quotea} ]! ) if ( !depth_first ) { int lenx = -1; forPix( p, stack ) if ( stack(p).fourth && (lenx < 0 || stack(p).third.length( ) < lenx ) ) { q = p; lenx = stack(p).third.length( ); } } else { int dimx = -1, lenx; forPix( p, stack ) if ( stack(p).fourth ) { if ( stack(p).first.smallbasis.nrows > dimx ) { q = p; dimx = stack(p).first.smallbasis.nrows; lenx = stack(p).third.length( ); } else if ( stack(p).first.smallbasis.nrows == dimx && stack(p).third.length( ) < lenx ) { q = p; lenx = stack(p).third.length( ); } } } config c; c.home = &h0; c.part = stack(q).first.part; c.small.basis = stack(q).first.smallbasis; matrix cb = c.small.basis; c.small.basis.reduce( ); c.dualsmall.basis.set_size(0, c.part.length); c.leading1s = c.small.basis.leading_ones( ); c.small.build( ); SLList list = stack(q).third; SLList< pair< wordtype, OSLList > > listx = stack(q).second; forPix( p, list ) { TEX( ![ \begin{quotebneg} Subdivide to get a new configuration. If the new configuration is terminal, we force its dual small code to be zero. \end{quotebneg} ]! ) list(p).c = &c; wordtype w = list(p); config d; d.home = c.home; d.part = subdivide_partition( c.part, w ); int s = d.part.length; d.small.basis = subdivide_matrix( cb, c.part, w, true, false); matrix db = d.small.basis; d.small.basis.reduce( ); d.dualsmall.basis.set_size( 0, s ); d.leading1s = d.small.basis.leading_ones( ); vector dpv(d.part); Permutation fix; dpv.sort( rcmp, fix ); partition ep( dpv, d.part.n ); matrix eb(db); eb.permute_columns(fix); // Compute the automorphism group of (ep, eb), in the // following sense. Two such pairs are deemed equivalent if // after permuting columns and complementing rows, we can // get from one pair to the other. Since the first row of // eb is the all ones row, it may be ignored in this process. // To compute the automorphism group, we assign a graph. // To that end, we delete row one, and double all the other // rows, replacing each copy by its complement. In terms // of this new matrix we define a graph, which has one // vertex for each column and one vertex for each row. // The columns are colored by the partition elements. The // rows are colored by assigning one new color to each // pair of rows. Add edges according to the matrix. vertex_colored_graph g( eb.ncols + 2 * (eb.nrows-1) ); for ( i = 0; i < eb.ncols; i++ ) g.c(i) = ep(i); for ( i = 0; i < eb.nrows-1; i++ ) g.c(eb.ncols + 2*i) = g.c(eb.ncols + 2*i + 1) = n + i + 1; for ( i = 0; i < eb.ncols; i++ ) for ( j = 0; j < eb.nrows-1; j++ ) { g.a(i).set( eb.ncols + 2*j, eb(j + 1, i) ); g.a( eb.ncols + 2*j ).set( i, eb(j + 1, i) ); if ( eb(j + 1, i) == 0 ) { g.a(i).set( eb.ncols + 2*j + 1, 1 ); g.a( eb.ncols + 2*j + 1 ).set( i, 1 ); } } pair pp = g.find_automorphism_group( ); Permutationlist pl(ep.length); for ( i = 0; i < pp.first.length; i++ ) { Permutation qq(ep.length); for ( j = 0; j < ep.length; j++ ) qq(j) = pp.first(i)(j); pl.append(qq); } Permutationlist aut(ep.length); aut.generate(pl); // Convert to canonical form. Permutation qi = get_canonical( g, eb.ncols ); qi.act(ep); eb.permute_columns(qi); forPixDef( uu, stack_can ) { if ( stack_can(uu).first == ep && stack_can(uu).second.nrows == eb.nrows ) { matrix& M = stack_can(uu).second; for ( i = 1; i < eb.nrows; i++ ) { if ( M(i) != eb(i) ) { for ( j = 0; j < eb.ncols; j++ ) if ( M(i,j) + eb(i,j) == 0 ) break; if ( j != eb.ncols ) break; } } if ( i == eb.nrows ) break; } } if ( uu != 0 ) continue; stack_can.append( make_pair( ep, eb ) ); if ( d.small.basis.nrows == home->dim ) { int RX = R.ncols, DX = d.small.basis.ncols; matrix R0 = R, Z(1, RX), ZR0, dplus, dplus0; R0.resize( db.nrows - 1, RX ); vcat( Z, R0, ZR0 ); hcat( db, ZR0, dplus ); config_core dc; dc.part.set_size( d.part.length + R.ncols ); for ( i = 0; i < d.part.length; i++ ) dc.part(i) = d.part(i); for ( i = d.part.length; i < dc.part.length; i++ ) dc.part(i) = 1; dc.part.n = n; dc.smallbasis = dplus; dc.smallbasis.reduce( ); matrix M = dc.basic_small( ); if ( realizable( dc, bass, home, results ) ) { forPixDef( tp, terminals ) if ( isomorphic( terminals(tp), M ) ) break; if ( tp == 0 ) { terminals.append(M); cerr << "Terminal configuration [#" << ++terminal_config_count << "] "; for ( i = 0; i < dc.part.length; i++ ) { cerr << dc.part(i); if ( i < dc.part.length - 1 ) cerr << ","; } cerr << " : " << dplus << ".\n"; vector yy = dc.smallcode_we( ); cerr << "enumerator = " << as_poly(yy) << "\n"; if ( stop_after != 0 && terminal_config_count == stop_after ) return terminals; } } } else { SLList listn4; SLList< pair< wordtype, OSLList > > listn5; // Let RX = # of columns in R. // Let DX = # of columns in d.smallbasis. int RX = R.ncols, DX = d.small.basis.ncols; matrix R0 = R, dplus; R0.resize( db.nrows-2, R.ncols ); matrix db0 = db.submatrix(db.nrows-2, db.ncols, 1, 0); hcat( db0, R0, dplus ); matrix dplusx[R.nrows]; prevector dpxs[R.nrows]; bool wordtype_found[R.nrows]; for ( int ll = db.nrows-1; ll < R.nrows; ll++ ) { wordtype_found[ll] = false; dplusx[ll].set_size( int(Ipow(2, dplus.nrows)), DX + RX ); word indx(dplus.nrows); i = 0; do mul( indx, dplus, dplusx[ll](i++) ); while ( indx.advance( ) != 0 ); for ( i = 0; i < dplusx[ll].nrows; i++ ) { for ( j = 0; j < DX; j++ ) dplusx[ll](i)(j) += db(db.nrows-1)(j); for ( j = 0; j < RX; j++ ) dplusx[ll](i)(DX + j) += R(ll)(j) + R(db.nrows-2)(j); } dpxs[ll].set_size( dplusx[ll].nrows ); for ( i = 0; i < dpxs[ll].length; i++ ) { dpxs[ll](i) = 0; for ( j = DX; j < DX + RX; j++ ) if ( dplusx[ll](i)(j) ) ++dpxs[ll](i); } } word dpw(DX + RX); forPixDef( qo, listx ) { wordtype v = listx(qo).first; partition P = d.part; wordtype vnew = vector(P.length); vnew.c = &d; int pmax = 0; if ( projective && d.small.basis.nrows == home->dim-2 ) pmax = 2; prevector< triple< int, int, prevector< pair > > > t = sblv_triple_maker( P, c.part, v, vnew, pmax ); vector indx( t.length ); for ( i = 0; i < t.length; i++ ) { if ( t(i).third.length == 0 ) break; vnew(t(i).first) = t(i).third(0).first; vnew(t(i).first + 1) = t(i).third(0).second; } if ( i < t.length ) continue; int N = Ipow(2, dplus.nrows); int Sum = 0; for ( i = 0; i < P.length; i++ ) Sum += vnew(i); while(1) { forPixDef( llp, listx(qo).second ) { int ll = listx(qo).second(llp); register int* dpxsx = dpxs[ll].x; for ( j = 0; j < N; j++ ) { register int sum = Sum; register gf2* dpjx = dplusx[ll](j).x; for (register int kk = 0; kk < DX; kk++) { if ( dpjx[kk].x ) sum += d.part.x[kk].x - 2*vnew.x[kk].x; } if ( !adm[sum][dpxsx[j]] ) break; } if ( j == N ) { wordtype_found[ll] = true; // Add to listn4. if ( ll == db.nrows - 1 ) { forPixDef( rr, listn4 ) if (listn4(rr) == vnew) break; if ( rr == 0 ) { wordtype altf = vnew; fix.act(altf); forPix( rr, listn4 ) { wordtype wf = listn4(rr); fix.act(wf); int l; for (l = 0; l < aut.length; l++) { wordtype wfa = wf; aut(l).act(wfa); if (altf == wfa) break; } if ( l != aut.length ) break; } } if ( rr == 0 ) listn4.append(vnew); continue; } // Add to listn5. forPixDef( rr, listn5 ) { if ( listn5(rr).first == vnew ) { listn5(rr).second.add(ll); break; } } if ( rr == 0 ) { OSLList single; single.append(ll); listn5.append( make_pair( vnew, single ) ); } } } for ( i = t.length - 1; i >= 0; i-- ) if ( indx(i) < t(i).third.length - 1 ) break; if ( i < 0 ) break; for ( j = t.length - 1; j > i; j-- ) { indx(j) = 0; vnew(t(j).first) = t(j).third(0).first; vnew(t(j).first + 1) = t(j).third(0).second;} ++indx(i); vnew(t(i).first) = t(i).third(indx(i)).first; vnew(t(i).first + 1) = t(i).third(indx(i)).second; } } int ll; for ( ll = db.nrows-1; ll < R.nrows; ll++ ) if ( !wordtype_found[ll] ) break; if ( ll != R.nrows ) listn4.clear( ); config_core dcc; dcc.part = d.part; dcc.smallbasis = db; dcc.dualsmallbasis.set_size( 0, s ); if ( listn4.empty( ) ) listn5.clear( ); stack.append( make_quadruped( dcc, listn5, listn4, !listn4.empty( ) ) ); if (show_all_configs) { cerr << "Configuration " << ++config_count << "\n" << " config "; for ( i = 0; i < d.part.length; i++ ) { cerr << d.part(i); if ( i < d.part.length - 1 ) cerr << ","; } cerr << " : " << db << "\n"; matrix R0 = R, Z(1, RX), ZR0, dplus, dplus0; R0.resize( db.nrows - 1, RX ); vcat( Z, R0, ZR0 ); hcat( db, ZR0, dplus ); config_core dc; dc.part.set_size( d.part.length + R.ncols ); for ( i = 0; i < d.part.length; i++ ) dc.part(i) = d.part(i); for ( i = d.part.length; i < dc.part.length; i++ ) dc.part(i) = 1; dc.part.n = n; dc.smallbasis = dplus; dc.smallbasis.reduce( ); vector yy = dc.smallcode_we( ); cerr << " has weight enumerator " << as_poly(yy) << "\nand will have <= " << listn4.length( ) << " configurations directly below it.\n"; } } } stack(q).second.clear( ); stack(q).third.clear( ); stack(q).fourth = false; } return terminals; } set_compile_file(web.cc) HIDE( ![ ifelse(UNAME,Openstep,![#include ]!) #include #include #include #include #include #include "homedefs.h" #include "state.h" #include "bitvec.h" #include "codetable.h" #include "opt.h" matrix canonical_form(matrix); vector pack(matrix); #include "uniq.h" extern int warnings_are_fatal, auto_macaulay, fill_weight; extern int dual_transform_length_limit, auto_joint_list, auto_group_computation, auto_dual_column_deletion, auto_residual_transform, group_size_limit, auto_dual_residual_transform, auto_group_residual_transform, auto_group_residual_transform_alt, auto_puncture_transform, find_regular_group_element, auto_dual_transform, gullible, auto_orbit_transform, nzv_length_max, i1low, i1high, i2low, i2high, show_roots, auto_enlarge_by_dual_word, random_search, auto_cyclic_test, min_vector_weight; extern constraintlist input_mask, output_mask; extern "C" int isdigit(int); Integer round_down_to_power_of_2(Integer); Integer round_up_to_power_of_2(Integer); int griesmer(int, int); void code_search(int, prevector< prevector >, codetable&, String, int, vector, int, codehome*, matrix = matrix(0,0)); void random_code_search(int, prevector< prevector >, codetable&, String, int, vector, int, codehome*, matrix = matrix(0,0)); bool iso_member(const matrix&, const SLList< matrix >&); bool realizable(config_core&, constraintlist&, codehome*, codetable&); vector dual_of_we(vector, bool = false); void log2(const Integer&, Integer&, Integer&); typedef vector polyF2; inline int deg( const polyF2& f ) { int i; for ( i = f.length-1; i >= 0; i-- ) if ( f(i).x != 0 ) break; return i; } polyF2 remainder(polyF2, const polyF2&); pair< int, vector > roots(polyF2); int yno(String); int rcmp(const number&, const number&); int rcmp(const int&, const int&); int take_int(String&, const Regex&); int String_cmp(const String&, const String&); SLList< pair< int, matrix > > punctured_codes(const matrix&); SLList< vector > dual_words_of_given_weight(matrix, int); prevector< vector > tuple_orbits(matrix, int); String list_of(const String&, const String& = ","); typedef triple< int, int, OSLList< vector > > packed_matrix_list; matrix unpack(char*, int, int); void sort_by_secondx( prevector< pair >& ); int min_distance(const matrix&, int); extern long time_used_by_build; extern int allowed_failures, doubly_even_test, no_test_if_classified; extern int auto_mu1; extern String LHS_pat, label_pat, bang_label_pat, gen_label_pat, config_list, config_list_piece; void auto_orbit_search(matrix, String, codetable&, codehome*); int process_new_matrix(codehome*, matrix, String, codetable&, int = 0, bool = false, int = 0, bool = false); prevector< triple< int, int, prevector< pair > > > sblv_triple_maker(const partition&, const partition&, const wordtype&, wordtype&, int = 0); SLList codeword_orbits(config&); void auto_dual_search(matrix, String, codetable&, codehome*); void execute_macaulay(const matrix&); void execute_equals(codehome*, Pix, Pix, bool); void execute_kill_variable_by(codehome*, prevector, bool, codetable&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); inline bool test(const Rational& a, const Rational& b, char sense) { if ( sense == '=' ) return a == b; if ( sense == '<' ) return a <= b; return a >= b; } matrix subdivide_matrix(const matrix&, const partition&, const wordtype&, bool, bool = true); pair< Permutationlist, Integer > find_automorphism_group(const matrix&); config_core canonical_form( config_core, bool = false ); pair matrix_by_orbits(matrix, Permutationlist, OSLList); String bitlist(const word&, bool=false, int=1); void mul( const vector&, const matrix&, vector&); ]! ) index_method(as_html_poly) String as_html_poly(const vector& v) { String p = "1"; for ( int i = 1; i < v.length; i++ ) if ( v(i) != 0 ) { p += " + "; if ( v(i) != 1 ) p += dec(v(i)); p += (String("t") + dec(i) + ""); } return p; } index_method(pretty_print) void pretty_print( const matrix& M, String filename, bool nofold = false ) { String Mstring(M); ofstream f( filename ); f << "\n" << "
\n";
     if (nofold)
     {    Mstring.gsub(",", ",\n ");
          f << Mstring;    }
     else
     {    for ( int i = 0; i < Mstring.length( ); i++ )
          {    if ( i != 0 && i % 80 == 0 ) f << "\n";
               f << Mstring[i];    }    }
     f << "\n
\n"; f.close( ); } TEX( ![ \verb|is_cyclic|:\ Determine if a given permutation group is cyclic. It takes as input generators for the group and the size of the group. ]! ) index_method(is_cyclic) bool is_cyclic( const Permutationlist& gen, Integer N ) { if ( N <= 3 ) return true; if ( N > gen.n ) return false; Permutationlist gp(gen.n); gp.generate(gen); for ( int i = 0; i < gp.length; i++ ) if ( gp(i).order( ) == N ) return true; return false; } index_method(is_abelian) bool is_abelian( const Permutationlist& gen ) { for ( int i = 0; i < gen.length; i++ ) for ( int j = i + 1; j < gen.length; j++ ) if ( gen(i) * gen(j) != gen(j) * gen(i) ) return false; return true; } TEX( ![ \verb|find_perm_rep|:\ Let a $k \times n$ matrix $M$ over $\F_2$ be given, with distinct rows. Its $n$ columns define a subset $S$ of $\F_2^k$. Let a permutation group $G$ also be given, of degree $n$, which acts on $S$. Reformulate it as a degree $k$ permutation group, and describe the action on $S$. ]! ) index_method(find_perm_rep) String find_perm_rep( matrix M, Permutationlist G ) { int i, j, pj, k = M.nrows, n = M.ncols; // Determine if Choose(k, i) is a submatrix of M, for any i. OSLList cols; SLList ch; for ( i = 0; i <= k; i++ ) { OSLList found; SLList found_no; for ( j = 0; j < n; j++ ) if ( !cols.contains(j) && M.col(j).weight( ) == i ) if ( found.add( M.col(j) ) ) found_no.append(j); if ( found.length( ) == choose( k, i ) ) { ch.append(i); forPixDef( p, found_no ) cols.add( found_no(p) ); i--; } } String answer = "\n" "
\n"
          "After permuting columns, the matrix is\n\n";
     if ( ch.length( ) != 0 )
     {    vector chv(ch);
          answer += String("Choose( ") + dec(k) + ", " + String(chv) 
               + " ) |\n\n";    }
     pair< String, Permutationlist > xxx = matrix_by_orbits( M, G, cols );
     answer += xxx.first;
     Permutationlist H = xxx.second;
     answer += String("\nThe column groups shown are orbits under the ")
          + "permutation group generated by:\n\n";
     for ( i = 0; i < H.length; i++ )
          if ( H(i).order( ) != 1 ) answer += H(i).as_cycle_product( ) + "\n";
     answer += "
\n"; return answer; } TEX( ![ \verb|analyze_matrix(M, k1, k2)|:\ Given a matrix $M$ over $\F_2$ with $k_1 + k_2$ rows, try to find a pattern, and return the conclusion as a string, together with an integer which measures the quality of the description found. ]!) index_method(analyze_matrix) pair analyze_matrix( matrix M, int k1, int k2, Permutationlist G ) { int r, n = M.ncols, k = M.nrows; OSLList special_col_numbers; String answer = "\n" "
\n"
          "After permuting columns, the generator matrix"
          " has the following structure:\n\n";
     bool something_changed;
     do
     {    something_changed = false;
          for ( int i1 = 0; i1 <= k1; i1++ )
               for ( int i2 = 0; i2 <= k2; i2++ )
               {    Integer expected_size = choose(k1, i1) * choose(k2, i2);
                    if (expected_size > n - special_col_numbers.length( )) 
                         continue;
                    OSLList col_numbers;
                    OSLList cols;
                    for ( r = 0; r < n; r++ )
                    {    if ( special_col_numbers.contains(r) ) continue;
                         int w1 = 0;
                         for ( int c1 = 0; c1 < k1; c1++ )
                              if ( M(c1, r) ) w1++;
                         if ( w1 != i1 ) continue;
                         int w2 = 0;
                         for ( int c2 = k1; c2 < k; c2++ )
                              if ( M(c2, r) ) w2++;
                         if ( w2 != i2 ) continue;
                         if ( cols.add( M.col(r) ) ) col_numbers.add(r);    }
                    if ( col_numbers.length( ) != expected_size ) continue;
                    forPixDef( p, col_numbers )
                         special_col_numbers.add( col_numbers(p) );
                    something_changed = true;
                    answer += String("Choose(") + dec(k1) + "," + dec(i1) + 
                         ") # Choose(" + dec(k2) + "," + dec(i2) + 
                         ") |\n";    }    }
     while( something_changed );
     answer += "\n";
     int i, j, pj;
     // Convert the automorphisms to permutations of the columns.
     Permutationlist H(k);
     for ( i = 0; i < G.length; i++ )
     {    Permutation p = G(i);   // ith generator 
          matrix pM( k, n );
          for ( int ir = 0; ir < k; ir++ )
               for ( int ic = 0; ic < n; ic++ )
                    pM( ir, ic ) = M( ir, p(ic)-1 );
          Permutation q(k);
          for ( j = 0; j < k; j++ )
          {    for ( pj = 0; pj < k; pj++ )
                    if ( M(j) == pM(pj) ) break;
               if ( pj == k ) INTERNAL_ERROR( "analyze_matrix" );
               q(j) = pj + 1;    }
          H.append(q);    }
     // Determine the equivalence classes of the columns.
     EquivRelIntList e(n);
     for ( i = 0; i < G.length; i++ )
          for ( j = 0; j < e.length; j++ )
               e.join( j, G(i)(j) - 1 );
     // Create a character array which displays this data.
     matrix Mpict( k, n + e.orbit_count( ) );
     int col = 0;
     int quality = 0;
     for ( i = 0; i < n; i++ )
     {    if ( !e.minimal(i) || special_col_numbers.contains(i) ) continue;
          quality++;
          SLList L = e.orbit(i);
          forPixDef( pi, L )
          {    for ( j = 0; j < k; j++ )
                    Mpict( j, col ) = char( M( j, L(pi) ).x + '0' );
               col++;    }
          for ( j = 0; j < k; j++ )
               Mpict( j, col ) = ' ';
          col++;    }
     if ( col == 0 ) return make_pair( answer, quality );
     Mpict.resize( Mpict.nrows, col );
     for ( j = 0; j < k; j++ )
          Mpict( j, col-1 ) = '\n';
     for ( i = 0; i < Mpict.nrows; i++ )
          for ( j = 0; j < Mpict.ncols; j++ )
               answer += Mpict( i, j );
     answer += String( "\n\nThe column groups shown are orbits under the "
          "permutation group generated by:\n\n" );
     for ( i = 0; i < H.length; i++ )
          if ( H(i).order( ) != 1 ) answer += H(i).as_cycle_product( ) + "\n";
     return make_pair( answer, quality );    }

index_method(red_quote)
String red_quote(String s)
{    if ( s[s.length( ) - 1] == '\n' ) s.del( '\n', -1 );
     s.gsub('\n', "
\n"); return String("
") + s + ".
"; } index_method(is_graph_matrix) bool is_graph_matrix( const matrix& M ) { int k = M.nrows, n = M.ncols; for ( int w = 2; w <= k-3; w++ ) { OSLList cols; int count = 0; for ( int i = 0; i < n; i++ ) { word col = M.col(i); if ( col.weight( ) == w ) { count++; cols.add(col); } } if ( cols.length( ) != count ) return false; if ( count != 0 && count != int( choose( k, w ) ) ) return false; } return true; } index_method(make_reference) void make_reference( String middle, String nm ) { static OSLList nms; static bool first_call(true); if ( !nms.contains( nm ) ) { nms.add( nm ); ofstream html_file( "webcodes/binary/" + nm + ".html" ); html_file << "\n"; html_file << "\n"; html_file.close( ); if (first_call) { first_call = false; ifelse(UNAMEM,alpha, ![ system( "rcp src/REF cpthree:/tmp" ); system( "rsh cpthree \"cd /tmp; tibdex -p INDEX REF\"" ); ]!, ![ system( "cd tex; tibdex -p INDEX ../src/REF" ); ]! ) } ofstream ref_file( "tex/ref_file" ); ref_file << "\\magnification 2000\n" << "\\hsize 3.5in\n" << "\\tolerance=10000\n" << "% " << middle << "\n" << "\\nopagenumbers\n" << ".[]\n" << "\\end\n"; ref_file.close( ); system( "cd tex; sh makeref" ); system( "cp tex/r001.gif webcodes/binary/" + nm + ".gif" ); } } index_method(credit_to_html) String credit_to_html( String s, int levels = 0 ) { static Regex ref_pat( "\\[\\.[^.]*\\.\\]" ); static Regex ref_pats( "\\[\\..*\\.\\]" ".*" "\\[\\..*\\.\\]" ); // Case 1: ref_pat occurs zero times if ( !s.contains( ref_pat ) ) return s; // Case 2: ref_pat occurs >= 2 times if ( s.contains( ref_pats ) ) { while( s.contains(ref_pat) ) { String first = s.before( ref_pat ); String middle = s.at( ref_pat ); String last = s.after( ref_pat ); String nm = middle; nm.gsub( '[', "" ); nm.gsub( ']', "" ); nm.gsub( '.', "" ); nm.gsub( ' ', '_' ); make_reference(middle, nm); s = first + "" + "" + "" + last; } s.gsub( "{\\ }", " " ); s.gsub( "\\ ", " " ); return s; } // Case 3: ref_pat occurs 1 time String first = s.before( ref_pat ); if ( first.length( ) > 0 && first[ first.length( ) - 1 ] == ' ' ) first.del( ' ', -1 ); String middle = s.at( ref_pat ); String last = s.after( ref_pat ); String nm = middle; nm.gsub( '[', "" ); nm.gsub( ']', "" ); nm.gsub( '.', "" ); nm.gsub( ' ', '_' ); make_reference(middle, nm); String answer = "" + first + ""; } index_method(config_to_web) void config_to_web( int n, int k, codehome* h, codetable& results, String label, String where ) { String nkfhead = where + "/" + dec(n) + "/" + dec(k) + "/"; int i, j; ofstream nkf2( nkfhead + label + ".html" ); config& c = h->configs( h->label_to_Pix( label, results ) ); matrix M = c.basic_small( ); vector Mp = M.enumerate_weights( ); nkf2 << "\n"; nkf2 << "n = " << n << ", k = " << k << "
\n"; String title = c.title; String comp_title = title; comp_title.gsub(RXwhite,""); // delete white space static Regex zero_one_matrix_pat( "{" + list_of( "[01]+" ) + "}" ); if ( comp_title.matches( zero_one_matrix_pat ) ) title = ""; if ( title != "" ) { nkf2 << "The code " << label << " has the formal description " << red_quote(title); if ( c.credit_e != "" ) nkf2 << "It was found by " << credit_to_html(c.credit_e, 2) << ". "; if ( c.alt_title != "" ) nkf2 << "An isomorphic code is given by the formal description " << red_quote(c.alt_title); nkf2 << "A generator matrix is"; } else if ( c.credit_e == "" ) nkf2 << "A generator matrix for code " << label << " is"; else nkf2 << "Code " << label << " was found by " << credit_to_html(c.credit_e, 2) << ". A generator matrix is"; nkf2 << " here. Its weight enumerator is " << "
" << as_html_poly( Mp ) << ".
\n"; pretty_print( M, nkfhead + label + "@gen.html" ); vector dMp = dual_of_we( Mp, true ); for ( i = 1; i <= n; i++ ) if ( dMp(i) != 0 ) break; nkf2 << "The dual code has minimum distance " << i << " and has " << dMp(i) << " word"; if ( dMp(i) > 1 ) nkf2 << "s"; nkf2 << " of weight " << i << ".
\n"; static Regex first_in_list( "\\[[a-zA-Z_]+1\\]" ); if ( label.matches( first_in_list ) ) { forPixDef( p, h->notes_to_config_lists ) { String labelx = label.before( "]" ); pair ln = h->notes_to_config_lists(p); if ( ln.first.contains( labelx ) ) { nkf2 << "
Note to " << ln.first << ": " << ln.second << "
\n"; } } } if ( k > 14 || h->configs(h->base).no_auto ) { nkf2.close( ); return; } pair< Permutationlist, Integer > pp = find_automorphism_group(M); bool cyc = is_cyclic( pp.first, pp.second ); bool ab = is_abelian( pp.first ); if ( pp.second == 1 ) nkf2 << "Its automorphism group is trivial.\n"; else if (cyc) nkf2 << "Its automorphism group is cyclic of order " << pp.second << ".\n"; else if (ab) nkf2 << "Its automorphism group is abelian of order " << pp.second << ", but is not cyclic.\n"; else nkf2 << "Its automorphism group is nonabelian and has order " << pp.second << ".\n"; EquivRelIntList ec( n ); for ( j = 0; j < pp.first.length; j++ ) for ( i = 0; i < n; i++ ) ec.join( i, pp.first(j)(i) - 1 ); if ( ec.orbit_count( ) == 1 ) { nkf2 << "This group acts transitively on the coordinates.\n"; cerr << "n = " << n << ", k = " << k << ", label = " << label << ": the automorphism group acts transitively\n"; } else if ( pp.second > 1 ) { nkf2 << "Under the action of this group, the coordinates are " << "divided into " << ec.orbit_count( ) << " orbits.\n"; if ( ec.orbit_count( ) <= 5 ) { prevector sz( ec.orbit_count( ) ); nkf2 << "These have sizes "; j = 0; for ( i = 0; i < n; i++ ) if ( ec.minimal(i) ) sz(j++) = ec.orbit(i).length( ); sz.sort(&rcmp); for ( i = 0; i < sz.length; i++ ) { nkf2 << sz(i); if ( i < sz.length - 1 && sz.length != 2 ) nkf2 << ", "; if ( i == sz.length - 2 ) nkf2 << "and "; } nkf2 << ".\n"; } } nkf2 << "

\n"; code C; C.basis = M; C.build( ); if ( pp.second < auto_cyclic_test && pp.second >= k && !title.contains("cyclic") && !c.alt_title.contains("cyclic") ) { Permutationlist classes(n); classes.find_conjugacy_classes( pp.first ); matrix MC(k, n); for ( j = 0; j < classes.length; j++ ) { for ( i = 0; i < C.x.nrows; i++ ) { MC(0) = C.x(i); for ( int l = 1; l < k; l++ ) { MC(l) = MC(l-1); classes(j).act( MC(l) ); } if ( MC.reduce( ) == k ) { cerr << "n = " << n << ", k = " << k << ", label = " << label << " is generalized-cyclic.\n"; break; } } if ( i != C.x.nrows ) break; } } if ( cyc ) { nkf2.close( ); return; } word if_basis(n+1); for ( i = 1; i <= n; i++ ) if ( Mp(i) == k || Mp(i) == k + 1 ) { word indx(k); matrix gen( (int) Mp(i), n ); j = 0; do { word w; mul( indx, M, w ); if ( w.weight( ) == i ) gen(j++) = w; } while( indx.advance( ) ); matrix gens = gen; if ( gen.reduce( ) == k ) { if_basis(i) = 1; if ( Mp(i) == k ) nkf2 << "The words of weight " << i << " comprise a basis for the code.\n"; else nkf2 << "The " << k+1 << " words of weight " << i << " generate the code.\n"; ofstream nkf3(nkfhead + label + "@gen" + dec(i) + ".html"); nkf3 << find_perm_rep( gens, pp.first ); nkf3.close( ); if ( is_graph_matrix(gens) ) cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has a graph-matrix generating set.\n"; else cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has an interesting generating set.\n"; } } for ( int i1 = 1; i1 <= n; i1++ ) for ( int i2 = i1 + 1; i2 <= n; i2++ ) { if ( if_basis(i1) || if_basis(i2) ) continue; int mi1 = int( Mp(i1) ), mi2 = int( Mp(i2) ); if ( mi1 != 0 && mi2 != 0 && ( mi1 + mi2 >= k && mi1 + mi2 <= k + 2 ) ) { word indx(k); int total = mi1 + mi2; matrix gen( total, n ); int j1 = 0, j2 = mi1; do { word w; mul( indx, M, w ); if ( w.weight( ) == i1 ) gen(j1++) = w; else if ( w.weight( ) == i2 ) gen(j2++) = w; } while( indx.advance( ) ); matrix gens = gen; if ( gen.reduce( ) == k ) { if ( total == k ) nkf2 << "The words of weight " << i1 << " and " << i2 << " comprise a basis for the code.\n"; else nkf2 << "The " << total << " words of weight " << i1 << " and " << i2 << " generate the code.\n"; ofstream nkfg( nkfhead + label + "@gen" + dec(i1) + "_" + dec(i2) + ".html" ); nkfg << analyze_matrix( gens, mi1, mi2, pp.first ).first; nkfg.close( ); cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has an interesting generating set.\n"; } } } prevector cd(C.x.nrows); for ( i = 0; i < cd.length; i++ ) cd(i) = C.x(i); cd.sort(&cmp); EquivRelIntList e(cd.length); word w(n); for ( i = 0; i < pp.first.length; i++ ) for ( j = 0; j < cd.length; j++ ) { w = cd(j); pp.first(i).act(w); int l = cd.pos(w, &cmp); if ( l == -1 ) INTERNAL_ERROR("xcode word orbits"); e.join(j, l); } SLList< SLList > orbits; for ( i = 0; i < e.length; i++ ) { if ( e.minimal(i) ) { SLList orbit; orbit.append( cd(i) ); j = i; int l = 2; while( (j = e(j)) != i ) orbit.append( cd(j) ); orbits.append(orbit); } } prevector< prevector > orbitsv( orbits.length( ) ); i = 0; forPixDef( q, orbits ) orbitsv(i++) = orbits(q); prevector orbit_gen( orbitsv.length ); for ( i = 0; i < orbitsv.length; i++ ) { orbit_gen(i) = false; prevector v = orbitsv(i); if ( v.length < k || v.length > k+2 ) continue; int wt = v(0).weight( ); if ( v.length == int( Mp(wt) ) ) continue; matrix Mv(v.length, n); for ( j = 0; j < v.length; j++ ) Mv(j) = v(j); matrix Mvs = Mv; if ( Mv.reduce( ) == k ) { orbit_gen(i) = true; if ( v.length == k ) nkf2 << "An invariant set of words of " << "weight " << wt << " comprise a basis for the code.\n"; else nkf2 << "An invariant set of " << v.length << " words of weight " << wt << " generate the code.\n"; ofstream nkf3( nkfhead + label + "@geni" + dec(i) + ".html" ); nkf3 << find_perm_rep( Mvs, pp.first ); nkf3.close( ); if ( is_graph_matrix(Mvs) ) cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has a special graph-matrix generating set.\n"; else cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has a special interesting generating set.\n"; } } SLList< triple< pair, String, pair< String, matrix > > > descrips; for ( i = 0; i < orbitsv.length; i++ ) { if ( orbit_gen(i) ) continue; prevector v1 = orbitsv(i); if ( v1.length > k + 1 ) continue; int wt1 = v1(0).weight( ); if ( v1.length == int( Mp(wt1) ) ) continue; for ( j = i+1; j < orbitsv.length; j++ ) { if ( orbit_gen(j) ) continue; prevector v2 = orbitsv(j); if ( v2.length > k + 1 ) continue; int wt2 = v2(0).weight( ); if ( v2.length == int( Mp(wt2) ) ) continue; int vl = v1.length + v2.length; if ( vl < k || vl > k+2 ) continue; matrix Mv(vl, n); int l; for ( l = 0; l < v1.length; l++ ) Mv(l) = v1(l); for ( l = 0; l < v2.length; l++ ) Mv(l + v1.length) = v2(l); matrix Mvs = Mv; if ( Mv.reduce( ) == k ) { String wts = String("weights ") + dec(wt1) + " and " + dec(wt2); if ( wt1 == wt2 ) wts = String("weight ") + dec(wt1); String title; if ( vl == k ) title = "An invariant set of words of " + wts + " comprise a basis for the code.\n"; else title = String("An invariant set of ") + vl + " words of " + wts + " generate the code.\n"; descrips.append( make_triple( analyze_matrix(Mvs, v1.length, v2.length, pp.first), dec(i) + String(".") + dec(j), make_pair(title, Mvs) ) ); } } } int best_quality = 10000; forPix(q, descrips) best_quality = min( best_quality, descrips(q).first.second ); int count = 0; forPix(q, descrips) if ( descrips(q).first.second == best_quality ) { if ( count++ > 6 ) break; nkf2 << descrips(q).third.first; ofstream nkf3( nkfhead + label + "@geni" + descrips(q).second + ".html" ); nkf3 << descrips(q).first.first; nkf3.close( ); if ( is_graph_matrix( descrips(q).third.second ) ) cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has a very special graph-matrix generating" << " set.\n"; else cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has a " << "very special interesting generating set.\n"; } descrips.clear( ); for ( i = 0; i < orbitsv.length; i++ ) { if ( orbit_gen(i) ) continue; prevector v1 = orbitsv(i); if ( v1.length > k + 1 ) continue; int wt1 = v1(0).weight( ); if ( v1.length == int( Mp(wt1) ) ) continue; for ( int i2 = 1; i2 <= n; i2++ ) { if ( i2 == wt1 ) continue; if ( if_basis(i2) ) continue; int mi2 = int( Mp(i2) ); int vl = v1.length + mi2; if ( vl < k || vl > k + 2 ) continue; matrix Mv(vl, n); int l; for ( l = 0; l < v1.length; l++ ) Mv(l) = v1(l); word indx(k); do { word w; mul( indx, M, w ); if ( w.weight( ) == i2 ) Mv(l++) = w; } while( indx.advance( ) ); matrix Mvs = Mv; if ( Mv.reduce( ) == k ) { String wts = String("weights ") + dec(wt1) + ", together with all words of weight " + dec(i2); String title; if ( vl == k ) title = "An invariant set of words of " + wts + " comprise a basis for the code.\n"; else title = "An invariant set of words of " + wts + " comprise a " + dec(vl) + "-element generating set for the code.\n"; descrips.append( make_triple( analyze_matrix(Mvs, v1.length, mi2, pp.first), dec(i) + String(".") + dec(i2), make_pair(title, Mvs) ) ); } } } best_quality = 10000; forPix(q, descrips) best_quality = min( best_quality, descrips(q).first.second ); count = 0; forPix(q, descrips) if ( descrips(q).first.second == best_quality ) { if ( count++ > 6 ) break; nkf2 << descrips(q).third.first; ofstream nkf3( nkfhead + label + "@genj" + descrips(q).second + ".html" ); nkf3 << descrips(q).first.first; nkf3.close( ); if ( is_graph_matrix( descrips(q).third.second ) ) cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has a very special graph-matrix generating" << " set.\n"; else cerr << "n = " << n << ", k = " << k << ", label = " << label << " (|Aut(C)| = " << pp.second << ") has a " << "very special interesting generating set.\n"; } nkf2.close( ); } index_method(hidden) String hidden( String name, String value ) { return ""; } index_method(get_input) String get_input( String name, int size ) { return "";} index_method(build_web_core) String build_web_core( codehome* h, int l, String href, String nkfhead, int n, int k, codetable& results ) { String answer; String codehome_name = results.get_codehome_name(h); for ( int j = 0; j < l; j++ ) { String cn = h->dc.second(j); static Regex ln( "\\[[0-9a-zA-Z]*[a-zA-Z]" + pos_number + "\\]" ); if ( cn.matches(ln) ) { static Regex lnh( "\\[[0-9a-zA-Z]*[a-zA-Z]" ); String cnh = cn.at(lnh); String cnt = cn.after(lnh); static Regex number_pattern( number_pat ); int cnf = take_int(cnt, number_pattern); int ll; if ( j + 15 >= l ) goto reg; for ( ll = 1; ll < 15; ll++ ) if ( h->dc.second(j + ll) != cnh + dec( ll + cnf ) + "]" ) goto reg; for ( ll = 1; ll < l - j; ll++ ) if ( h->dc.second(j + ll) != cnh + dec( ll + cnf ) + "]" ) break; // Now we have ll labels in order. ofstream plus( nkfhead + "/" + cn + "plus.html" ); plus << "\n"; plus << "n = " << n << ", k = " << k << "
\n"; if ( ll > 200 && codehome_name != "" ) { static Regex lnhp( "\\[[0-9a-zA-Z]*[a-zA-Z]" + pos_number ); int maxl = 0; Pix bestq; String tag; forPixDef( q, h->config_lists ) { String& xn = h->config_lists(q).title; if ( xn.at(lnhp) == cnh + dec(cnf) ) { String xnt = xn.after(lnhp); int xnf = take_int(xnt, number_pattern); if ( xnf - cnf > maxl ) { maxl = xnf - cnf + 1; tag = xn; bestq = q; } } } if (maxl > 200) { String Split_prog = String("unset auto joint list;\n") + "set gullible;\n" + h->defining_command + ";\n" + tag + " := " + h->config_lists(bestq).descrip + ";\n" + "build web directory for " + codehome_name.before("]") + "." + cnh.after( "[" ) + "$$1];"; String return_loc = dec(n) + String("/") + dec(k) + "/" + cnh + "$$1].html"; answer += href + cn + "plus.html\">" + tag + ""; if ( j + maxl != l ) answer += ", "; plus << "This is a collection of " << maxl << " codes." << " The web pages for these are created on the " << "fly." << " Enter below a number between " << cnf << " and " << cnf + maxl - 1 << ".

\n"; int digits = String(dec(cnf+maxl-1)).length( ); plus << "
Show me code " << "" << cnh << get_input("arg1", digits) << "]. " << hidden( "body", Split_prog ) << hidden( "return_loc", return_loc ) << // "" << "

\n"; plus << "It may be necessary to push " << "reload to get a given page to " << "show up.\n"; j += maxl - 1; continue; } if ( maxl > 0 ) ll = maxl; } String fulltag = cnh + dec(cnf) + ".." + dec(cnf+ll-1) + "]"; answer += href + cn + "plus.html\">" + fulltag + ""; if ( j + ll != l ) answer += ", "; for ( int aa = 0; aa < ll; aa++ ) { String cnp = cnh + dec(aa+1) + "]"; plus << "" << cnp << ""; if ( aa != ll-1 ) plus << ", "; config_to_web( n, k, h, results, cnp, "webcodes/binary" ); } plus << "\n"; j += ll - 1; continue; } reg: answer += href + cn + ".html\">" + cn + ""; if ( j != l-1 ) answer += ", "; config_to_web( n, k, h, results, cn, "webcodes/binary" ); } return answer; } index_command(build web directory) void execute_build_web( String commandx, codetable& results ) { commandx = commandx.after( "buildwebdirectoryfor" ); static Regex number_pattern( number_pat ); int n0 = take_int(commandx, number_pattern); commandx = commandx.after("<=n<="); int n1 = take_int(commandx, number_pattern); commandx.del(","); int k0 = take_int(commandx, number_pattern); if ( k0 < 1 ) ERROR("k0 is too small"); commandx = commandx.after("<=k<="); int k1 = take_int(commandx, number_pattern); if ( results.upper_bound.nrows <= n1 || results.upper_bound.ncols <= k1 ) WARNRET( "I don't think I know enough to generate this table." ); results.recompute_lower_bound(n1, min(k1, n1-1)); mkdir( "webcodes/binary", 00777 ); for ( int n = n0; n <= n1; n++ ) { cerr << "working on n = " << n << "\n"; String dir_n = String("webcodes/binary/") + dec(n); mkdir( &(dir_n[0]), 00777 ); for ( int k = k0; k <= k1; k++ ) { if ( k >= n ) continue; String dir_nk = String("webcodes/binary/") + dec(n) + "/" + dec(k); mkdir( dir_nk, 00777 ); int d = results.upper_bound(n,k); weightlist w = results.possible_weights(n,k,d,false); word ww(n); forPixDef( p, w ) if ( w(p) > 0 ) ww( w(p) - 1 ) = 1; ww(0) = 1; String hw = " has weights in the set " + bitlist(ww); hw.gsub( "{1", "{0" ); bool hw_triv = ( hw == String(" has weights in the set {0,") + dec(d) + ".." + dec(n) + "}" ) || ( hw == String(" has weights in the set {0..") + dec(n) + "}" ); String nkfhead = String("webcodes/binary/") + dec(n) + "/" + dec(k) + "/"; ofstream nkfile( nkfhead + "/@main" ); nkfile << "There is no binary [" << n << "," << k << "," << d+1 << "] code. "; String nkd = String("[") + dec(n) + "," + dec(k) + "," + dec(d) + "]"; // Find known [n,k,d] codes. // Do a first pass through the codehomes to determine if there // is a "disjoint" or "classification of" command. forPix( p, results.open ) { codehome* h = results.open(p); if ( h->n != n || h->dim != k ) continue; int i; int dh = h->w.min( ); if ( dh != d ) continue; for ( i = dh; i <= n; i++ ) if ( !h->w.contains(i) ) break; if ( i == n + 1 && h->assumed_cons.empty( ) && h->opt.none_chosen( ) && (h->dc.first == 'd' || h->dc.first == 'c') ) break; } bool dc = (p != 0); // Now check to see if the weight enumerator of an [n,k,d] code // is known. String if_exists; forPix( p, results.open ) { codehome* h = results.open(p); if ( h->n != n || h->dim != k ) continue; int i; int dh = h->w.min( ); if ( dh != d ) continue; for ( i = dh; i <= n; i++ ) if ( !h->w.contains(i) ) break; if ( i == n + 1 && h->assumed_cons.empty( ) && h->opt.none_chosen( ) && h->we_known ) { vector we(n+1); we.set_zero( ); we(0) = 1; for ( int j = 1; j <= n; j++ ) if ( w.contains(j) ) { Integer low = 0, high = -1; h->configs(h->base).evaluate( String("y") + dec(j), low, high ); if ( low != high ) { PRINT(n); PRINT(k); cerr << low << " <= y" << j << " <= " << high << "\n"; INTERNAL_ERROR( "I've encountered " << "a code type for which the weight " << "enumerator is supposed to be " << "known, but it isn't." ); } we(j) = low; } if_exists = " has weight enumerator " + as_html_poly(we) + ". "; break; } } if ( p == 0 && !hw_triv ) if_exists = hw + ". "; int dl = results.lower_bound(n, k); // Now do the main pass. String note; forPix( p, results.open ) { codehome* h = results.open(p); if ( h->n != n || h->dim != k ) continue; String credit = credit_to_html( h->configs(h->base).credit_e ); String credit_u = credit_to_html( h->configs(h->base).credit_u ); String credit_c = credit_to_html( h->configs(h->base).credit_c ); // If existence credit has been assigned for the // code type, and a unique terminal configuration has // been defined, we assign the same existence credit // to the terminal configuration. if ( credit != "" ) { int full_count = 0; Pix cp_save; forPixDef( q, h->labels ) { String label = h->labels(q).first; Pix cp = h->labels(q).second; config& c = h->configs(cp); if ( c.full( ) ) { if ( full_count == 0 ) cp_save = cp; if ( ++full_count == 2 ) break; } } if ( full_count == 1 ) { config& c = h->configs(cp_save); if ( c.credit_e == "" ) c.credit_e = credit; } } note = h->configs(h->base).note; int i, j, dh = h->w.min( ); if ( dh < dl ) continue; for ( i = dh; i <= n; i++ ) if ( !h->w.contains(i) ) break; String nkdh = String("[") + dec(n) + "," + dec(k) + "," + dec(dh) + "]"; String href = String("assumed_cons.empty( ) && h->opt.none_chosen( ) ) { int l = h->dc.second.length; if ( h->dc.first == 'd' && l > 1 ) { if ( dh == d ) { if ( credit != "" ) nkfile << "There exists an " << nkd << " code, as was discovered by " << credit << ". "; if (!hw_triv) nkfile << "Every " << nkd << " code" << if_exists; } else { if (!hw_triv) nkfile << "If a " << nkd << " code exists, it" << if_exists; if ( credit != "" ) nkfile << "There exists an " << nkdh << " code, as was discovered by " << credit << ". "; } triple tri = make_triple(n, k, dh); forPixDef( ppp, results.ignore ) if ( results.ignore(ppp) == tri ) break; if ( ppp == 0 ) nkfile << "I know of " << l << " nonisomorphic " << nkdh << " codes: "; else nkfile << "I have stopped keeping track of " << nkdh << " codes, but here are " << l << " nonisomorphic ones: "; nkfile << build_web_core( h, l, href, nkfhead, n, k, results ); break; } if ( h->dc.first == 'c' ) { if ( dh != d ) continue; if ( l == 1 ) { if ( credit != "" && credit_u == "" ) nkfile << "There exists an " << nkd << " code, as was discovered by " << credit << ". In fact there " << "is a unique one: "; else if ( credit == "" && credit_u == "" ) nkfile << "There is a unique " << nkd << " code: "; else if ( credit != "" && credit_u != "" ) nkfile << "There exists an " << nkd << " code, as was discovered by " << credit << ". This code was " << "shown to be unique by " << credit_u << ". It is: "; else if ( credit == "" && credit_u != "" ) nkfile << "It has been shown by " << credit_u << " that there is a " << "unique " << nkd << " code: "; String label = h->dc.second(0); nkfile << label << ". "; Pix px = h->label_to_Pix( label, results ); config& c = h->configs(px); matrix MM = c.basic_small(); if ( c.title != "" ) { nkfile << "It has the formal " << "description " << red_quote(c.title); if ( c.credit_e != "" ) nkfile << "It was found by " << credit_to_html(c.credit_e) << ". "; if ( c.alt_title != "" ) nkfile << "An isomorphic code is " << "given by the formal " << "description " << red_quote(c.alt_title); nkfile << "A generator matrix for it " << "is"; } else if ( c.credit_e == "" ) nkfile << "A generator matrix for it " << "is"; else nkfile << "It was found by " << credit_to_html(c.credit_e) << ". " << "A generator matrix is"; nkfile << " here. " << "Its weight enumerator is " << "
" << as_html_poly(MM.enumerate_weights( )) << ".
\n"; if (k <= 14 && !h->configs(h->base).no_auto) { pair< Permutationlist, Integer > pp = find_automorphism_group(MM); nkfile << "Its automorphism group has " << pp.second << " elements"; } pretty_print( MM, nkfhead + label + "@gen" + ".html" ); break; } if ( credit != "" ) nkfile << "There exists an " << nkd << " code, as was discovered by " << credit << ". "; if (!hw_triv) nkfile << "Every " << nkd << " code" << if_exists; if ( credit_c != "" ) nkfile << "It has been shown by " << credit_c << " that there "; else nkfile << "There "; nkfile << "are exactly " << l << " nonisomorphic " << nkd << " codes: "; nkfile << build_web_core( h, l, href, nkfhead, n, k, results ); break; } if (dc) continue; forPixDef( q, h->labels ) { String label = h->labels(q).first; Pix cp = h->labels(q).second; config& c = h->configs(cp); if ( c.full( ) ) { if (!hw_triv) nkfile << "Every " << nkd << " code" << if_exists; if ( credit != "" ) nkfile << "There exists an " << nkdh << " code, as was discovered by " << credit << ". "; nkfile << "I know of one " << nkdh << " code: " << href << label << ".html\">" << label << ""; config_to_web( n, k, h, results, label, "webcodes/binary" ); break; } } if ( q != 0 ) break; } } if ( p == 0 ) { if ( d == dl ) { nkfile << "There does exist a " << nkd << " code"; if ( !hw_triv ) nkfile << ", and I also know " << "that every such code" << if_exists; else nkfile << ". "; } else if ( d < dl ) INTERNAL_ERROR( "Contradiction found by execute_build_web." ) else { if (!hw_triv) nkfile << "If a " << nkd << " code exists, it" << if_exists; nkfile << "There does exist a [" << n << "," << k << "," << dl << "] code."; } nkfile << "\n"; } else nkfile << ".\n"; int gr = 0; for ( int i = 0; i < k; i++ ) gr += int( ceil( Rational( d, Ipow(2, i) ) ) ); if ( gr == n && d <= int(Ipow(2, k-1)) ) nkfile << "

Codes with parameters " << nkd << " are at the Griesmer bound. According to a theorem " << "of " << credit_to_html( "Helleseth [.helleseth characterization 1981.]" ) << ", they are either " << credit_to_html( "Solomon-Stiffler codes [.solomon stiffler.]" ) << " or " << credit_to_html( "Belov codes [.belov griesmer.]" ) << ". In " << "those cases where the codes are known to be unique, " << "this follows from Helleseth's result, or (in " << "some cases) from the earlier results of " << credit_to_html( "van Tilborg [.tilborg griesmer 1980.]" ) << ".\n"; if ( note != "" ) nkfile << "

Note: " << credit_to_html(note) << "\n"; nkfile.close( ); } } } set_compile_file(code.c) #include "signal.h" index_method(abort_handler) void abort_handler(int sig) { cerr << "\n\nSystem abort received. One possible reason for this is that " << "the system may\nhave run out of memory. Note that by default, " << "Split sets the maximum\nmemory usage to 40% of the total " << "system memory.\n"; exit(1); } HIDE( ![ pair< Permutationlist, Integer > find_automorphism_group(const matrix&); SLList< vector > dual_words_of_given_weight(matrix, int); bool mask_satisfied(int, int, constraintlist); bool iso_member(const matrix&, const SLList< matrix >&); typedef vector polyF2; pair< int, vector > roots(polyF2); extern String juxt(String, String); prevector expand_config_list(codehome*, String); void round_variable(String, Integer&, Integer&, int, int, const config&, codetable&); void execute_infer_command(codehome*, config&, constraint, codetable&, bool); void execute_incorporate_command(codehome*, String, String, String, String, String, Pix, Pix, codetable&, bool); String execute_classification_of(codehome*, String, String&, prevector, String, bool, codetable&); void execute_via_lp_command(codehome*, String, bool, codetable&, bool, prevector, bool, bool = false); void execute_via_extension(codehome*, String, prevector, bool, bool, codetable&, String, int&); void execute_dump(codehome*); void execute_try_to_kill_current(codehome*, codetable&, bool); void execute_disjoint(codehome*, prevector, bool, const codetable&); void execute_infer_from_local_variables(codehome*, constraint, bool); void execute_via_variable_split(codehome*, String, prevector, bool, const codetable&); void execute_implies(codehome*, String, String, Pix, Pix, bool); void execute_equals(codehome*, Pix, Pix, bool); void execute_via_dual_word(codehome*, String, Pix, bool); void execute_via_configuration_search(codehome*, String, String, Pix, Pix, bool); void execute_load_constraints(codehome*, codetable&, String, Pix); void execute_projection_onto(codehome*, word, String, Pix, codetable&, bool, int); void execute_realizable(codehome*, prevector, bool, codetable&); void execute_automorphism(codehome*, String, Permutation, bool, codetable&); void execute_via_dual_nonexistence(codehome*, codetable&, bool); void execute_report_group_size(codehome*, prevector); String execute_deduce(codehome*, String&, prevector&, bool, const codetable&, bool); void execute_via_building(codehome*, int, int, bool, String, prevector, bool, bool, codetable&, String, int&, SLList< matrix >&); void execute_known(codehome*, constraintlist, bool); void execute_clean(String); void execute_reduce_variable_set(codehome*, codetable&); void execute_print_joint(codehome*); void execute_config_from(codehome*, String, String, bool, codetable&); void execute_round_local(codehome*, codetable&); void execute_random_we(short int, short int, short int, short int, Integer); void execute_random_macaulay(short int, short int, short int, Integer); void execute_is_cyclic(codehome*, bool, codetable&); void execute_print(String, codehome* home, codetable&, String); void execute_help(String); void execute_test(int,int,int,codetable&,codehome*, String&, const constraintlist&); void execute_type(String, codehome*&, codetable&, String&, bool, bool); void execute_status(codehome*, String, DLList&, bool, codetable&); void execute_via_unique_wordtypes(String, String, Pix, Pix, codehome*, bool); void execute_config_command(String, String, codehome*, bool, codetable&, constraintlist, String); void execute_build_web(String, codetable&); void execute_process(String, int, codetable&, codehome*, String, String); void execute_colon_equals(String, codehome*, String, String, bool, codetable&); void execute_other_commands(bool&, String, codehome*, codetable&, String, String, String, bool); void set_numerical_parameter(const String&, const String&, const String&); void save_and_set_parameters(String); void restore_parameters(String); void parse_j_var(String, int&, int&, int&); bool isomorphic(const matrix&, const matrix&, prevector = prevector( ) ); int griesmer(int, int); ]! ) TEX( \block{Main program}\label{main-program-section} ) HIDE(![ #include #include #include ]!) int warnings_are_fatal = 1; index_method(pack) vector pack( matrix M ) { int i, j, n = M.ncols, k = M.nrows; int nbytes = (n * k - 1)/8 + 1; vector raw(nbytes); for ( i = 0; i < nbytes; i++ ) raw(i) = 0; for ( i = 0; i < k; i++ ) for ( j = 0; j < n; j++ ) { int bit_no = n * i + j; int rbn = bit_no % 8; int byte_no = bit_no / 8; if ( M(i,j) ) raw(byte_no) |= (1 << rbn); } return raw; } HIDE( ![ typedef triple< int, int, OSLList< vector > > packed_matrix_list; matrix unpack(char*, int, int); #include "generic.h" generic_object evaluate_expression(String, codetable&, codehome*, String&, SLList&); inline bool test(const Rational& a, const Rational& b, char sense) { if ( sense == '=' ) return a == b; if ( sense == '<' ) return a <= b; return a >= b; } vector dual_of_we(vector, bool = false); ]! ) // The following shouldn't be needed. inline int cmp(const vector& a, const vector& b) { register int i, n = a.length; for ( i = 0; i < n; i++ ) { if ( a(i) > b(i) ) return 1; if ( a(i) < b(i) ) return -1; } return 0; } TEX( ![ \verb|min_distance|:\ Compute the minimum distance of the code defined by the rowspace of the given matrix {\tt M}. But if we find a nonzero codeword of weight less than the given value {\tt d0}, halt and return $0$. ]! ) index_method(min_distance) int min_distance( const matrix& M, int d0 ) { int d = M.ncols; if ( M.nrows <= 31 ) { bitmat A(M); unsigned long X = Ipow(2, M.nrows); bitvec sum(M.ncols); for ( unsigned long i = 0; i < X - 1; i++ ) { sum += A.x[ gray(i) ]; d = min( d, sum.weight( ) ); if ( d < d0 ) return 0; } } else // This should be replaced! { vector indx(M.nrows), sum(M.ncols); indx.advance( ); register gf2* Mk; register int tl; do { register int j, k; sum.set_zero( ); for ( k = 0; k < indx.length; k++ ) if ( indx(k).x ) { Mk = M.x[k].x; tl = sum.length; for ( j = 0; j < tl; j++ ) sum(j).x ^= Mk[j].x; } d = min( d, sum.weight( ) ); if ( d < d0 ) return 0; } while( indx.advance( ) != 0 ); } return d; } index_method(check_mask) bool check_mask( const constraintlist& test_mask, int n, int k, int d ) { forPixDef( p, test_mask ) { Rational sum = 0; forPixDef( q, test_mask(p).LHS ) { const term& t = test_mask(p).LHS(q); if ( t.var == "n" ) sum += Integer(n) * t.coeff; else if ( t.var == "k" ) sum += Integer(k) * t.coeff; else if ( t.var == "d" ) sum += Integer(d) * t.coeff; else ERROR( "Illegal variable in test mask." ); } if ( !test( sum, test_mask(p).RHS, test_mask(p).sense ) ) return false; } return true; } index_command(n =) void execute_n_equals( codetable& results, DLList& command_queue, short int n, short int k, String inv, const constraintlist& test_mask ) { static Regex number_pattern( number_pat ); prevector vs = unpack(inv); vector v0(vs.length), v1(vs.length); int i; for ( i = 0; i < vs.length; i++ ) { if ( vs(i).matches(number_pattern) ) { v0(i) = v1(i) = as_int( vs(i) ); continue; } if ( vs(i)[0] != '-' ) v0(i) = as_int( take( vs(i), pos_number_pattern ) ); else v0(i) = 1; if ( vs(i) != "-" ) v1(i) = as_int( vs(i).after("-") ); else v1(i) = n; } if ( k + v0.length - 1 >= n ) ERROR( "This command is not for [n,k] codes with k >= n." ); for ( i = v0.length - 1; i >= 0; i-- ) { bool d0gul = !check_mask( test_mask, n, k + i, v0(i) ); bool d0pgul = !check_mask( test_mask, n, k + i, v0(i) + 1 ); bool d1gul = !check_mask( test_mask, n, k + i, v1(i) ); bool d1pgul = !check_mask( test_mask, n, k + i, v1(i) + 1 ); if ( !gullible && !d0pgul ) { if (optimal && lower_bound_check) command_queue.append( String("test yes[") + dec(n) + "," + dec(k+i) + "," + dec( v0(i).x + 1) + "]" ); } if ( !gullible && !d1gul ) { if ( optimal && even(int(v1(i))) ) command_queue.append( String("test[") + dec(n) + "," + dec(k+i) + "," + dec( v1(i).x ) + "]" ); } if (lower_bound_check) { if ( gullible || d0gul ) results.update_lower_bound(n, k+i, v0(i).x); else command_queue.append( String("yes[") + dec(n) + "," + dec(k+i) + "," + dec( v0(i).x ) + "]" ); } if ( v1(i) != n ) { if ( gullible || d1pgul ) { results.kill( n, k+i, v1(i)+1 ); if ( odd( v1(i) + 1 ) ) results.kill( n+1, k+i, v1(i)+2 ); } else command_queue.append( String("no[") + dec(n) + "," + dec(k+i) + "," + dec( v1(i) + 1 ) + "]" ); } } } index_class(IEquivRelIntList) // IEquivRelIntList is the same as EquivRelIntList, except that we use // class "int" instead of class "number" for the entries. class IEquivRelIntList : public vector { public: IEquivRelIntList(int n) : vector(n) { for ( int i = 0; i < length; i++ ) (*this)(i) = i; } IEquivRelIntList(const vector&, bool); // use equality as the // relation on a given list }; TEX( ![ Find orbit representatives for $r$-tuples of column indices of a matrix $M$, under the action of $\Aut(M)$. ]! ) index_method(tuple_orbits) prevector< vector > tuple_orbits( matrix M, int r ) { int i, j; vector< vector > Ctuplev; vector tuple(r); IEquivRelIntList e(1); for ( i = 0; i < r; i++ ) tuple(i) = i; { SLList< vector > Ctuple; while(1) { Ctuple.append(tuple); for ( i = r-1; i >= 0; i-- ) if ( tuple(i) < M.ncols - (r-i) ) break; if ( i == -1 ) break; ++tuple(i); for ( j = i+1; j < r; j++ ) tuple(j) = tuple(j-1) + 1; } Ctuplev = Ctuple; } pair< Permutationlist, Integer > pp = find_automorphism_group(M); Permutationlist au = pp.first; e = IEquivRelIntList(Ctuplev.length); // The following gives a canonical element of an e-equivalence class. // If i is a canonical element, e_size(i) is the size of its // equivalence class. prevector e_can(Ctuplev.length), e_size(Ctuplev.length); for ( i = 0; i < Ctuplev.length; i++ ) { e_can(i) = i; e_size(i) = 1; } for ( int pass = 1; pass <= 2; pass++ ) { for ( i = 0; i < au.length; i++ ) { for ( int j1 = 0; j1 < Ctuplev.length; j1++ ) { if ( pass == 1 && j1 != e_can(j1) ) continue; vector p( Ctuplev(j1) ), p2(r); for ( int kk = 0; kk < r; kk++ ) p2(kk) = au(i)( p(kk) ) - 1; p2.sort( &rcmp ); int j2 = Ctuplev.pos( p2, &cmp ); if ( j2 == -1 ) INTERNAL_ERROR("Ctuplev broken"); // In effect do "e.join( j1, j2 );", but also update e_can // and e_size. int ec1 = e_can(j1), ec2 = e_can(j2); int es1 = e_size(ec1), es2 = e_size(ec2); if ( ec1 != ec2 ) { if ( es2 <= es1 ) { int z = j2; do { e_can(z) = ec1; z = e(z); } while ( z != j2 ); e_size(ec1) = es1 + es2; } else { int z = j1; do { e_can(z) = ec2; z = e(z); } while ( z != j1 ); e_size(ec2) = es1 + es2; } int a = e(j1); e(j1) = e(j2); e(j2) = a; } } } } SLList< vector > answer; for ( int j1 = 0; j1 < Ctuplev.length; j1++ ) if ( j1 == e_can(j1) ) answer.append( Ctuplev(j1) ); return prevector< vector >(answer); } constraintlist test_mask, input_mask, output_mask; long int command_start_time; set_compile_file(codesearch.cc) HIDE( ![ #include #include "homedefs.h" #include #include "bitvec.h" #include "codetable.h" extern int no_column_deletion, debug, delete_pairs, delete_triples, limited_deletion, double_column_pairs, double_column_triples, show_distance_optimal, find_parameters_only, show_even_if_known, show_matrix, crazy_code_search, nzv_length_max, nzv_length_max2, dual_transform_length_limit, transform_pass_level, double_column_groups, ec_fill, ec_length_limit, seed_count, perturbation_count, alternate_quality_criterion, force_improvement, search_vector_weight_max, starting_length, random_doubling_probability, max_doubles; extern int level_two_search; extern constraintlist input_mask; bool mask_satisfied(int, int, constraintlist); int rcmp(const number&, const number&); int rcmp(const int&, const int&); int min_distance(const matrix&, int); SLList< vector > dual_words_of_given_weight(matrix, int); bool iso_member(const matrix&, const SLList< matrix >&); prevector< vector > tuple_orbits(matrix, int); int String_cmp(const String&, const String&); template void sort_by_second( prevector< pair >&); void mul( const vector&, const matrix&, vector&); ]! ) index_method(orbits) prevector< prevector > orbits( prevector< matrix > Ms ) { int i, j, r = Ms.length; if ( r == 0 ) ERROR( "No matrices supplied." ); int n = Ms(0).nrows; for ( i = 0; i < r; i++ ) { if ( Ms(i).nrows != n || Ms(i).ncols != n ) ERROR( "The matrices must all be square, of the same size." ); matrix B = Ms(i); if ( B.reduce( ) != n ) ERROR( "The matrices must be invertible." ); } int two_k = Ipow( 2, n ); prevector wds( two_k ); word indx(n); j = 0; do wds(j++) = indx; while( indx.advance( ) ); wds.sort( &cmp ); EquivRelIntList e(wds.length); for ( int u = 0; u < r; u++ ) { for ( j = 0; j < wds.length; j++ ) { word w; mul( Ms(u), wds(j), w ); int kc = wds.pos( w, &cmp ); if ( kc == -1 ) INTERNAL_ERROR("xpos problem"); e.join( j, kc ); } } SLList< prevector > orbits; for ( int j1 = 0; j1 < wds.length; j1++ ) if ( e.minimal(j1) ) { int k1 = e.size(j1); int e_ptr = j1; SLList orbit; for ( i = 0; i < k1; i++ ) { orbit.append( wds(e_ptr) ); e_ptr = e(e_ptr); } prevector orbitv(orbit); orbits.append(orbitv); } return orbits; } TEX( ![ \verb|isomorphic| accepts as input (what should be) two partitions of $\F_2^n$. Determine if there exists a linear automorphism of $\F_2^n$ which moves one partition to the other. ]! ) index_method(isomorphic) bool isomorphic( prevector< prevector > *vorig ) { int i, j, k; if ( vorig[0].length != vorig[1].length ) return false; int r = vorig[0].length; int n = vorig[0](0)(0).length; if ( n != vorig[1](0)(0).length ) return false; // Are vorig[0] and vorig[1] isomorphic as partitions? prevector len[2]; for ( i = 0; i < 2; i++ ) { len[i].set_size(r); for ( j = 0; j < r; j++ ) len[i](j) = vorig[i](j).length; len[i].sort(&rcmp); } if ( len[0] != len[1] ) return false; prevector< prevector > v[2]; for ( i = 0; i < 2; i++ ) v[i] = vorig[i]; prevector wesv[2], wesvs[2]; for ( i = 0; i < 2; i++ ) { wesv[i].set_size(r); for ( j = 0; j < r; j++ ) { matrix M( n, v[i](j).length ); for ( k = 0; k < v[i](j).length; k++ ) M.set_col( k, v[i](j)(k) ); M.reduce_nz( ); if (M.nrows > 0) wesv[i](j) = as_poly(M.enumerate_weights( )); else wesv[i](j) = "0"; } wesvs[i] = wesv[i]; wesvs[i].sort(&String_cmp); } if ( wesvs[0] != wesvs[1] ) return false; if (debug) { cerr << "in isomorphic, partition = " << len[0] << "\n"; cerr << "enumerators = " << wesvs[0] << "\n"; } // We make a change of basis which we believe will be advantageous. First // look for those partition elements whose weight enumerators are unique. SLList< pair > uniq; for ( i = 0; i < r; i++ ) { if ( wesv[0](i) == "0" ) continue; for ( j = 0; j < r; j++ ) if ( i != j && wesv[0](i) == wesv[0](j) ) break; if ( j == r ) uniq.append( make_pair(i, v[0](i).length) ); } prevector< pair > uniqv(uniq); sort_by_second( uniqv ); if ( uniqv.length > 0 ) { matrix N( 0, n ), A(0, n); // I can't explain why, but the reverse order given below // seems advantageous. for ( k = uniqv.length - 1; k >= 0; k-- ) { i = uniqv(k).first; for ( j = 0; j < v[0](i).length; j++ ) if ( !A.rowspace_member( v[0](i)(j) ) ) { A.resize( A.nrows + 1, n ); A( A.nrows - 1 ) = v[0](i)(j); A.reduce( ); N.resize( N.nrows + 1, n ); N( N.nrows - 1 ) = v[0](i)(j); } } for ( i = 0; i < r; i++ ) for ( j = 0; j < v[0](i).length; j++ ) if ( !A.rowspace_member( v[0](i)(j) ) ) { A.resize( A.nrows + 1, n ); A( A.nrows - 1 ) = v[0](i)(j); A.reduce( ); N.resize( N.nrows + 1, n ); N( N.nrows - 1 ) = v[0](i)(j); } // for ( j = 0; j < n; j++ ) // { word e(n); // e(j) = 1; // if ( !A.rowspace_member(e) ) // { A.resize( A.nrows + 1, n ); // A( A.nrows - 1 ) = e; // N.resize( N.nrows + 1, n ); // N( N.nrows - 1 ) = e; // A.reduce( ); } } matrix B = transpose_of(N).inverse( ); for ( i = 0; i < v[0].length; i++ ) for ( j = 0; j < v[0](i).length; j++ ) { word w; mul( B, v[0](i)(j), w ); v[0](i)(j) = w; } for ( j = 0; j < r; j++ ) { matrix M( n, v[0](j).length ); for ( k = 0; k < v[0](j).length; k++ ) M.set_col( k, v[0](j)(k) ); M.reduce_nz( ); if (M.nrows > 0) wesv[0](j) = as_poly(M.enumerate_weights( )); else wesv[0](j) = "0"; } } // Can ith part possibly map to jth part? matrix allow(r, r); for ( i = 0; i < r; i++ ) for ( j = 0; j < r; j++ ) allow(i, j) = ( wesv[0](i) == wesv[1](j) ); // Set L[i](j) = the unique k such that v[i](k) contains the jth // vector in F_2^n. prevector L[2]; for ( i = 0; i < 2; i++ ) { L[i].set_size( int( Ipow(2, n) ) ); word ix(n); int mm = 0; do { for ( j = 0; j < r; j++ ) { for ( k = 0; k < v[i](j).length; k++ ) { if ( v[i](j)(k) == ix ) { L[i](mm) = j; break; } } if ( k < v[i](j).length ) break; } mm++; } while( ix.advance( ) ); } prevector indx(n); for ( i = 0; i < n; i++ ) indx(i).set_size(n); int pos = 0; while(1) { // Test for plausibility of current assignment e_i |-> indx(i), // i = 0,...,pos. First test for injectivity. matrix M( pos+1, n ); for ( i = 0; i <= pos; i++ ) M(i) = indx(i); if ( M.reduce( ) == pos + 1 ) { // Main test. bool fail = false; word iy(pos + 1); vector fromto(r); for ( i = 0; i < r; i++ ) fromto(i) = -1; int is0, is1, from, to; word sum(n); do { is0 = 0; is1 = 0; for ( i = pos; i >= 0; i-- ) { if ( iy(i) ) is0++; if ( i > 0 ) is0 += is0; } sum.set_zero( ); for ( i = 0; i <= pos; i++ ) if ( iy(i) ) sum += indx(i); for ( i = n-1; i >= 0; i-- ) { if ( sum(i) ) is1++; if ( i > 0 ) is1 += is1; } from = L[0](is0); to = L[1](is1); if ( fromto(from) == -1 ) fromto(from) = to; else if ( fromto(from) != to ) { fail = true; break; } if ( !allow( from, to ) ) { fail = true; break; } } while( iy.advance( ) ); if ( !fail ) { if ( ++pos == n ) return true; indx(pos).set_zero( ); } } // Advance to next candidate. while(1) { if ( indx(pos).advance( ) ) break; if ( --pos == -1 ) return false; } } } index_method(process_new_matrix) TEX( ![ \verb|process_new_matrix(B,s,results,desc,sort)|:\ Let {\tt B} be a binary matrix, not necessarily in \RREF, with description given by the string {\tt s}. Let $C$ be the rowspace of {\tt B}. Print it if not known to {\tt results}, and if not already printed. Return the deviance $\delta d$ of the minimum distance of $C$ from the best known minimum distance. (If $\delta d$ is negative, $C$ beats the known bound.) Upon entry the allowed descrepancy {\tt desc} is to be a nonnegative integer. If $\delta d > \verb|desc|$, return $\verb|desc| + 1$ instead of $\delta d$. (This allows us to avoid computing the minimum distance of $C$ in many cases.) If the {\tt sort} flag is set, the columns of {\tt B} may be lexicographically sorted. ]!) SLList< matrix > newcodes; int process_new_matrix( codehome* home, matrix B, String s, codetable& results, int desc = 0, bool sort = false, int d_if_known = 0, bool dont_delete_columns = false ) { static SLList< triple > found_parameters; if (no_column_deletion) dont_delete_columns = true; matrix B_save = B; B.reduce_nz( ); int n = B.ncols; int k = B.nrows; if ( !mask_satisfied( n, k, input_mask ) || k <= 1 ) return desc + 1; static int n0(0), k0(0); if ( n+1 >= results.lower_bound.nrows || k+1 >= results.lower_bound.ncols ) results.update_lower_bound(n,k,1); // Force table resizing. int d00 = results.lower_bound(n,k); int d0 = d00 - desc; int d; if ( d_if_known != 0 ) d = d_if_known; else d = min_distance( B, d0 ); if ( d <= 2 ) return desc + 1; if ( d < d00 - 1 ) return d00 - d; if (debug) // XXX cerr << "{" << n << "," << k << "," << d << "}, d00 = " << // XXX d00 << ", s = " << s << "\n"; // XXX results.update_lower_bound(n,k,d); if ( n > n0 || k > k0 || d > d00 ) { results.recompute_lower_bound(n, k); d00 = results.lower_bound(n,k); if ( d < d00 - 1 ) return d00 - d; n0 = max(n,n0); k0 = max(k,k0); } int i, j; if (debug) cerr << "contemplating sort\n"; // XXX if (sort) { B = B_save; prevector columns(B.ncols); for ( j = 0; j < B.ncols; j++ ) columns(j).set_size(B.nrows); for ( i = 0; i < B.nrows; i++ ) for ( j = 0; j < B.ncols; j++ ) columns(j)(i) = B(i)(j); columns.sort(&cmp); for ( i = 0; i < B.nrows; i++ ) for ( j = 0; j < B.ncols; j++ ) B(i)(j) = columns(j)(i); B.reduce_nz( ); } TEX( ![ \begin{quote} Create a matrix $M$ whose rows are the minimum weight codewords. \end{quote} ]! ) if (debug) cerr << "creating min_words\n"; // XXX SLList min_words; word indx(k), w(n); do { mul( indx, B, w ); if ( w.weight( ) == d ) min_words.append(w); } while( indx.advance( ) != 0 ); matrix M( n, min_words ); bool improvable = false; TEX( ![ \begin{quote} Look for columns $i$ of $M$ which are all zero vectors. These can be removed to give a better code. If these exist, we look for maximal sets of columns which can be deleted to give a better code. Don't do any of this if a column has already been doubled. \end{quote} ]! ) if ( !s.contains("+ column") && !dont_delete_columns ) { SLList to_remove; for ( i = 0; i < n; i++ ) { for ( j = 0; j < M.nrows; j++ ) if ( M(j,i).x == 1 ) break; if ( j == M.nrows ) to_remove.append(i); } if ( !to_remove.empty( ) ) { prevector tdv(to_remove); prevector< OSLList< vector > > deletables(n+1); // Set up deletable sets of size 1. for ( i = 0; i < tdv.length; i++ ) { vector item(1); item(0) = tdv(i); deletables(1).add(item); } // Inductively find deletable sets of size i+1. for ( i = 1; i <= n-1; i++ ) { forPixDef( p, deletables(i) ) { vector st = deletables(i)(p); for ( j = 0; j < tdv.length; j++ ) { if ( st.member(tdv(j)) ) continue; vector stp(st); stp.resize(i+1); stp(i) = tdv(j); stp.sort(&rcmp); if (deletables(i+1).contains(stp)) continue; matrix B2( k, n-(i+1) ); int cx = 0; for ( int lc = 0; lc < n; lc++ ) { if ( stp.member(lc) ) continue; for ( int lr = 0; lr < k; lr++ ) B2(lr,cx) = B(lr,lc); cx++; } if ( min_distance(B2, d) == d ) deletables(i+1).add(stp); } } } // Delete non-maximal deletable sets. for ( i = 2; i <= n; i++ ) { forPixDef( p, deletables(i) ) { SLList non_max; forPixDef( q, deletables(i-1) ) if ( subset ( deletables(i-1)(q), deletables(i)(p) ) ) non_max.append(q); forPix( q, non_max ) deletables(i-1).del( deletables(i-1)(non_max(q)) ); } } if (debug) // XXX { cerr << "maximal sets of deletable columns:\n"; // XXX for ( i = 1; i <= n; i++ ) // XXX { forPixDef( p, deletables(i) ) // XXX cerr << deletables(i)(p) << "\n"; } } // XXX // Generate matrices and invoke process_new_matrix. for ( i = 1; i <= n; i++ ) { forPixDef( p, deletables(i) ) { vector st = deletables(i)(p); matrix B2( k, n-i ); int cx = 0; for ( int lc = 0; lc < n; lc++ ) { if ( st.member(lc) ) continue; for ( int lr = 0; lr < k; lr++ ) B2(lr,cx) = B(lr,lc); cx++; } String ss = s; for ( j = 0; j < st.length; j++ ) ss += String(" - column ") + dec(st(j) + 1 - j); if (debug) cerr << "using " << st << "\n"; // XXX process_new_matrix( home, B2, ss, results, desc, false, d, true ); if (limited_deletion) return d00 - d; } } return d00 - d; } else { // Look for pairs of columns whose deletion results in a // of the minimum distance by only one. int del_count = 0; if ( delete_pairs > 0 && results.lower_bound(n-2,k) <= d-1 ) { for ( i = 0; i < n; i++ ) { for ( j = i+1; j < n; j++ ) { int l; for ( l = 0; l < M.nrows; l++ ) if ( M(l,i) && M(l,j) ) break; if ( l == M.nrows ) { matrix B2 = B; B2.delete_column(i); B2.delete_column(j-1); String ss = s; ss += String(" - column ") + dec(i+1) + String(" - column ") + dec(j); process_new_matrix( home, B2, ss, results, desc, false, d-1 ); if ( ++del_count >= delete_pairs ) goto dpf; } } } } // Consider deleting dual words of weight 3. if ( delete_triples > 0 && del_count == 0 && results.lower_bound(n-3,k) <= d-2 ) { SLList< vector > Bt = dual_words_of_given_weight(B, 3); del_count = 0; forPixDef( p, Bt ) { matrix B2 = B; B2.delete_columns( Bt(p) ); // The following two lines were associated with // a spurious bus error. So I replaced them with // the subsequent five lines. // String ss = s + " - columns " + // String( Bt(p) + number(1) ); String ss = s; ss += String( " - columns " ); for ( i = 0; i < 3; i++ ) ++(Bt(p)(i)); ss += String( Bt(p) ); process_new_matrix( home, B2, ss, results, desc ); if ( ++del_count >= delete_triples ) break; } } } } TEX( ![ \begin{quote} Look for columns $i$ which are all ones vectors. These can be doubled to give a better code. \end{quote} ]! ) dpf: if (debug) cerr << "trying to double columns\n"; // XXX SLList to_double; for ( i = 0; i < n; i++ ) { for ( j = 0; j < M.nrows; j++ ) if ( M(j,i).x == 0 ) break; if ( j == M.nrows ) to_double.append(i); } if ( !to_double.empty( ) ) { improvable = true; prevector tdv(to_double); EquivRelIntList e(tdv.length); for ( i = 0; i < tdv.length; i++ ) { int ii = tdv(i); matrix B2( k, n+1 ); for ( j = 0; j <= ii; j++ ) for ( int l = 0; l < k; l++ ) B2(l,j) = B(l,j); for ( j = ii; j < n; j++ ) for ( int l = 0; l < k; l++ ) B2(l,j+1) = B(l,j); process_new_matrix( home, B2, s + " + column " + dec(ii+1), results, desc, false, d+1 ); } } TEX( ![ \begin{quote} Look for pairs of columns whose union is the all ones vector. These can be doubled to give (possibly) a good code. To speed this up, I've put a weight enumerator filter on this. So some new codes may be missed. \end{quote} ]! ) bool double_column_pair_succeeded = false; static SLList< triple< int, int, vector > > wes; if ( !improvable && double_column_pairs ) { if (debug) cerr << "attempting to double column pairs\n"; // XXX for ( i = 0; i < n; i++ ) { for ( j = i; j < n; j++ ) { int l; for ( l = 0; l < M.nrows; l++ ) if ( M(l,i).x == 0 && M(l,j).x == 0 ) break; if (l == M.nrows) break; } if ( j < n ) break; } if ( i < n ) { if (debug) cerr << "it is possible\n"; // XXX double_column_pair_succeeded = true; // Check to see if weight enumerator has already been // encountered or if it looks like the automorphism // group computer will hang on the matrix. vector w = B.enumerate_weights( ); for ( j = 0; j < w.length; j++ ) if (odd(j) && (w(j) == 128 || w(j) == 256 || w(j) == 512 )) break; forPixDef( p, wes ) if ( wes(p).first == n && wes(p).second == k && wes(p).third == w ) break; if ( j == w.length && p == 0 ) { wes.append(make_triple(n, k, w)); prevector< vector > Ct = tuple_orbits(B, 2); for ( int ee = 0; ee < Ct.length; ee++ ) { i = Ct(ee)(0); j = Ct(ee)(1); int l; for ( l = 0; l < M.nrows; l++ ) if ( M(l,i).x == 0 && M(l,j).x == 0 ) break; if (l == M.nrows) { matrix B2( k, n+2 ); int cc; for ( cc = 0; cc <= i; cc++ ) for ( l = 0; l < k; l++ ) B2(l,cc) = B(l,cc); for ( cc = i; cc <= j; cc++ ) for ( l = 0; l < k; l++ ) B2(l,cc+1) = B(l,cc); for ( cc = j; cc < n; cc++ ) for ( l = 0; l < k; l++ ) B2(l,cc+2) = B(l,cc); process_new_matrix( home, B2, s + " + column " + dec(i+1) + " + column " + dec(j+2), results, desc, false, d+1 ); } } } } } if ( !improvable && double_column_triples && !double_column_pair_succeeded ) { if (debug) cerr << "attempting to double column triples\n"; // XXX int h; for ( i = 0; i < n; i++ ) { for ( j = i; j < n; j++ ) { for ( h = j; h < n; h++ ) { int l; for ( l = 0; l < M.nrows; l++ ) if ( M(l,i).x == 0 && M(l,j).x == 0 && M(l,h).x == 0 ) break; if (l == M.nrows) break; } if ( h < n ) break; } if ( j < n ) break; } if ( i < n ) { if (debug) cerr << "it is possible\n"; // XXX vector w = B.enumerate_weights( ); for ( j = 0; j < w.length; j++ ) if (odd(j) && (w(j) == 128 || w(j) == 256 || w(j) == 512 )) break; forPixDef( p, wes ) if ( wes(p).first == n && wes(p).second == k && wes(p).third == w ) break; if ( j == w.length && p == 0 ) { wes.append(make_triple(n, k, w)); prevector< vector > Ct = tuple_orbits(B, 3); for ( int ee = 0; ee < Ct.length; ee++ ) { i = Ct(ee)(0); j = Ct(ee)(1); h = Ct(ee)(2); int l; for ( l = 0; l < M.nrows; l++ ) if ( M(l,i).x == 0 && M(l,j).x == 0 && M(l,h).x == 0 ) break; if (l == M.nrows) { matrix B2( k, n+3 ); int cc; for ( cc = 0; cc <= i; cc++ ) for ( l = 0; l < k; l++ ) B2(l,cc) = B(l,cc); for ( cc = i; cc <= j; cc++ ) for ( l = 0; l < k; l++ ) B2(l,cc+1) = B(l,cc); for ( cc = j; cc <= h; cc++ ) for ( l = 0; l < k; l++ ) B2(l,cc+2) = B(l,cc); for ( cc = h; cc < n; cc++ ) for ( l = 0; l < k; l++ ) B2(l,cc+3) = B(l,cc); process_new_matrix( home, B2, s + " + column " + dec(i+1) + " + column " + dec(j+2) + " + column " + dec(h+3), results, desc, false, d+1 ); } } } } } if ( improvable || d < d00 ) return d00 - d; if ( !show_distance_optimal ) { if ( results.lower_bound( n-1, k ) >= d ) return 0; if ( results.lower_bound( n+1, k+1 ) >= d ) return 0; } // Add parity check. bool parity_check = odd(d); if (parity_check) { matrix Bp = B; Bp.resize( B.nrows, B.ncols+1 ); for ( j = 0; j < B.nrows; j++ ) if ( odd( B(j).weight( ) ) ) Bp( j, B.ncols ) = 1; B = Bp; n++; d++; d00 = results.lower_bound(n,k); } if ( !show_distance_optimal ) { if ( results.lower_bound( n+1, k ) >= d+1 ) return 0; } forPixDef( p, results.ignore ) if ( results.ignore(p).first == n && results.ignore(p).second == k && results.ignore(p).third == d ) return 0; if ( find_parameters_only ) { triple param = make_triple(n,k,d); forPix( p, found_parameters ) if ( found_parameters(p) == param ) return 0; found_parameters.append(param); } String label; if ( d == d00 && !show_even_if_known ) { if ( results.is_unique(n, k, d) || results.identify(B, label, home) ) return 0; } if ( d == d00 && iso_member(B, newcodes) ) return 0; newcodes.append(B); cerr << "found: a [" << n << "," << k << "," << d << "] code"; if ( d == d00 && show_even_if_known ) { if ( results.identify(B, label, home) ) { if ( label != "" ) cerr << ", previously known as " << label; else cerr << ", previously known but unlabelled"; } } cerr << "\n" << s; if (parity_check) cerr << " + check"; cerr << "\n"; if (show_matrix) cerr << B << "\n"; cerr << "weight enumerator = " << as_poly(B.enumerate_weights( )) << "\n"; return d00 - d; } index_method(code_search_core) int code_search_core( int ss, int k, prevector< prevector > ec, vector w, int title_type, String title_head, vector tu, int rp, matrix& B, String& s, int desc, codehome* home, codetable& results, int d, matrix header ) { matrix A(ss - header.ncols, k); int er = 0; for ( int ew = 0; ew < w.length; ew++ ) { int mm = w(ew); for ( int xy = 0; xy < ec(mm).length; xy++ ) { A(er) = ec(mm)(xy); er++; } } A.transpose_equals(B); if (title_type == 1) { s = title_head + "{"; int i, j; for ( i = 0; i < w.length; i++ ) { s += dec( int(w(i))/rp ) + String("_{"); int res = w(i) % rp; for ( j = 0; j < tu.length; j++ ) { if ( res % 2 ) s += dec(tu(j)+1); else s += dec(-(tu(j)+1)); if ( j != tu.length - 1 ) s += ","; res /= 2; } s += "}"; if ( i != w.length - 1 ) s += ","; } s += "}"; } else if (title_type == 2) { s = title_head + "{"; int i; for ( i = 0; i < w.length; i++ ) { s += ec(w(i))(0); if ( i != w.length-1 ) s += ","; } s += "}"; } if ( header.ncols != 0 ) { matrix Bplus; hcat( header, B, Bplus ); B = Bplus; } return process_new_matrix(home, B, s, results, desc, true, d); } TEX( ![ Given a matrix, and given an equivalence relation on its codewords, look for new good codes whose generator matrices have as their columns the codewords lying in some of the equivalence classes of the codewords. The equivalence classes of codewords are given as the argument {\tt ec}. The arguments \verb|title_head|, \verb|title_type|, \verb|tu|, and \verb|rp| are part of an ad hoc mechanism for titling the new codes. ]! ) index_method(code_search) void code_search( int k, prevector< prevector > ec, codetable& results, String title_head, int title_type, vector tu, int rp, codehome* home, matrix header = matrix(0,0) ) { int i, j, l; int hncols = header.ncols; if ( header.ncols != 0 && k != header.nrows ) INTERNAL_ERROR( "code_search: header has wrong size" ); Integer dim_low = 0, dim_high = -1; input_mask.evaluate( "k", dim_low, dim_high ); SLList nz; vector nzv; int dual_length_low = 1; if (crazy_code_search) { for ( j = 0; j < ec.length; j++ ) { if ( ec(j).length >= 2 ) { nz.append(j); if ( nz.length( ) >= nzv_length_max ) break; } } nzv = nz; } else { too_long: nz.clear( ); for ( j = 0; j < ec.length; j++ ) if ( ec(j).length >= dual_length_low && hncols + ec(j).length <= dual_transform_length_limit ) nz.append(j); nzv = nz; if ( nzv.length > nzv_length_max ) { dual_length_low += 1; goto too_long; } } cerr << "nzv has length " << nzv.length << "\n"; if ( nzv.length == 0 ) return; TEX( ![ \begin{quote} Let $k = \verb|M.nrows|$. We create a matrix {\tt ecwt} which has one row for each element of $\F_2^k - \setof{0}$. Recall that for each $j$, $\verb|ec|(j)$ is of type \verb|prevector| -- which we think of now as a matrix $N_j$, with each {\tt word} comprising a row. Considering now what the \th{i} row of \verb|ecwt| is to be, let $v_i$ be the element of $\F_2^k$ corresponding to $i$. Then $\verb|ecwt|(i,j) = \abs{N_j v_i}$. \end{quote} ]! ) matrix ecwt( (int) (Ipow(2,k) - 1), ec.length); word indx(k); indx.advance( ); i = 0; do { for ( j = 0; j < ec.length; j++ ) for ( l = 0; l < ec(j).length; l++ ) ecwt(i,j) += int(ec(j)(l) * indx); i++; } while( indx.advance( ) ); vector hdwt( (int) (Ipow(2,k) - 1) ); hdwt.set_zero( ); if ( header.ncols != 0 ) { indx.set_zero( ); indx.advance( ); i = 0; do { word v; mul( indx, header, v ); hdwt(i++) = v.weight( ); } while( indx.advance( ) ); } SLList nz2; vector nzv2; int dual_length_low2 = 1; too_long2: nz2.clear( ); for ( j = 0; j < ec.length; j++ ) if ( ec(j).length >= dual_length_low2 && ec(j).length < dual_length_low ) nz2.append(j); nzv2 = nz2; if ( nzv2.length > nzv_length_max2 ) { dual_length_low2 += 1; goto too_long2; } if ( nzv2.length != 0 ) cerr << "nzv2 has length " << nzv2.length << "\n"; vector ix(nzv.length); ix.advance( ); vector w; Integer count = 0; Integer count_max = Ipow(2, nzv.length); long int loop_start_time = time(0); do { ++count; if ( count % 1000000 == 0 ) { cerr << "[" << setprecision(3) << double(Rational(count*100, count_max)) << "% done in "; long time_used = time(0) - loop_start_time; cerr << time_used/60.0 << " minutes]\n"; } if ( search_vector_weight_max > 0 && ix.weight( ) > search_vector_weight_max ) continue; int ss = hncols, ff = 0, ee; w.set_size(ix.weight( )); for ( ee = 0; ee < nzv.length; ee++ ) { if ( ix(ee) ) { w(ff) = nzv(ee); ss += ec(w(ff)).length; if ( ss > dual_transform_length_limit ) break; ff++; } } if ( ee != nzv.length ) continue; if ( ss <= k ) continue; int desc = transform_pass_level; if ( nzv_length_max2 == 0 ) desc = 0; if ( ss+1 >= results.lower_bound.nrows || k+1 >= results.lower_bound.ncols ) results.update_lower_bound(ss,k,1); // Force table resizing. int d0x = results.lower_bound(ss, k) - desc; int d = ss; for ( i = 0; i < ecwt.nrows; i++ ) { int sum = hdwt(i); for ( j = 0; j < w.length; j++ ) sum += ecwt(i)(w(j)); if (sum == 0 && k == dim_low) break; if (sum > 0) d = min(d, sum); if (d < d0x) break; } if ( i != ecwt.nrows ) continue; matrix B0; String s; int delta_d = code_search_core( ss, k, ec, w, title_type, title_head, tu, rp, B0, s, desc, home, results, d, header ); if ( delta_d > desc || header.ncols != 0 ) continue; // Now we try to double existing column groups. word ixd(w.length); vector wd; do { if ( !double_column_groups && !ixd.if_zero( ) ) break; int ssd = ss; ff = 0; wd.set_size(ixd.weight( )); for ( ee = 0; ee < w.length; ee++ ) { if ( ixd(ee) ) { wd(ff) = w(ee); ssd += ec(wd(ff)).length; ff++; } } if ( ssd > dual_transform_length_limit ) continue; matrix Ad(ssd-ss, k), Bd, BdB; int er = 0; for ( int ew = 0; ew < wd.length; ew++ ) { int mm = wd(ew); for ( int xy = 0; xy < ec(mm).length; xy++ ) { Ad(er) = ec(mm)(xy); er++; } } Ad.transpose_equals(Bd); hcat( B0, Bd, BdB ); matrix B = BdB; matrix B00 = B; String sd; if (title_type == 1) { sd = s; sd.del("}", -1); sd += ","; for ( i = 0; i < wd.length; i++ ) { sd += dec( int(wd(i))/rp ) + String("_{"); int res = wd(i) % rp; for ( j = 0; j < tu.length; j++ ) { if ( res % 2 ) sd += dec(tu(j)+1); else sd += dec(-(tu(j)+1)); if ( j != tu.length - 1 ) sd += ","; res /= 2; } sd += "}"; if ( i != wd.length - 1 ) sd += ","; } sd += "}"; } else if (title_type == 2) { sd = s; sd.del("}", -1); sd += ","; for ( i = 0; i < wd.length; i++ ) { sd += ec(wd(i))(0); if ( i != wd.length-1 ) sd += ","; } sd += "}"; } if ( !ixd.if_zero( ) ) delta_d = process_new_matrix( home, B, sd, results, desc, true); if ( delta_d > desc || nzv2.length == 0 ) continue; vector ix2(nzv2.length); ix2.advance( ); vector w2; do { int ss2 = ssd; ff = 0; w2.set_size(ix2.weight( )); for ( ee = 0; ee < nzv2.length; ee++ ) { if ( ix2(ee) ) { w2(ff) = nzv2(ee); ss2 += ec(w2(ff)).length; ff++; } } if ( ss2 > dual_transform_length_limit ) continue; matrix A2(ss2-ssd, k), B2, B2B; er = 0; for ( int ew = 0; ew < w2.length; ew++ ) { int mm = w2(ew);