From 4c245be6302d265a9ac1567f4c0fe2fb3755dbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Mon, 22 Dec 2025 14:17:54 +0100 Subject: [PATCH 01/14] remove unnecessary calls to srand(time(0)) and let the user inputs a seed for RNG --- doc/msolve-tutorial.tex | 242 +++++++++++++++++++++------------------- src/fglm/fglm_core.c | 2 - src/msolve/lifting-gb.c | 27 +++-- src/msolve/main.c | 27 ++++- src/msolve/msolve.c | 116 ++++++++++--------- 5 files changed, 220 insertions(+), 194 deletions(-) diff --git a/doc/msolve-tutorial.tex b/doc/msolve-tutorial.tex index 4b2ce928..ee88287a 100644 --- a/doc/msolve-tutorial.tex +++ b/doc/msolve-tutorial.tex @@ -142,7 +142,7 @@ pdfborder = {0 0 0}% % Style de bordure : ici, pas de bordure ]{hyperref}% % Utilisation de HyperTeX \fi - + \hypersetup{ linkcolor=blue!60!black, citecolor=red, %OrangeRed, %Emerald, %OliveGreen, @@ -303,7 +303,7 @@ \section{Introduction} -\msolve~is a C library for solving multivariate polynomial systems of equations. +\msolve~is a C library for solving multivariate polynomial systems of equations. It relies on computer algebra, a.k.a.\ symbolic computation, algorithms to compute \emph{algebraic} representations of the solution set from which many, if not all, informations can be extracted. @@ -329,7 +329,7 @@ \section{Introduction} where binaries (for \texttt{x86} processors runing Linux operating systems) and source files are provided. -\msolve~is designed for $64$ bit architectures, with \texttt{AVX2} instructions. +\msolve~is designed for $64$ bit architectures, with \texttt{AVX2} instructions. \msolve allows you to: \begin{itemize} @@ -337,47 +337,47 @@ \section{Introduction} coefficients and finitely many complex solutions; \item compute Gr\"obner bases of polynomial systems with coefficients which are either rational numbers or in a prime field $\mathbb{Z}/p\mathbb{Z}$ with $p < - 2^{31}$; + 2^{31}$; \item compute parametrizations of the solutions of polynomial systems with coefficients which are either rational numbers or in a prime field $\mathbb{Z}/p\mathbb{Z}$ with $p < 2^{31}$ (assuming that the system has finitely many solutions with coordinates in an algebraic closure of the field - generated by the input coefficients). + generated by the input coefficients). \end{itemize} -\msolve is based on Gr\"obner bases computations. When launching \msolve on -an input polynomial system (see the file format in~\cref{sec:input}), a Gr\"obner -basis computation starts and allows \msolve to determine if the number of solutions -to the system is infinite or finite in an algebraic closure of the base field +\msolve is based on Gr\"obner bases computations. When launching \msolve on +an input polynomial system (see the file format in~\cref{sec:input}), a Gr\"obner +basis computation starts and allows \msolve to determine if the number of solutions +to the system is infinite or finite in an algebraic closure of the base field (the complex numbers when the input coefficients are rational numbers). -When the number of solutions is finite, one says that the system (or the ideal -generated by the input equations) has dimension zero at most. Else it has positive -dimension. -\Cref{sec:dim} shows how \msolve behaves when the input system has positive dimension -or when there is no solution at all in an algebraic closure of the base field (over -the complex numbers when the input coefficients are rational numbers). - -When the system has dimension at most zero, \msolve can compute the real solutions -or, as said above, compute a Gr\"obner basis (when the base field is a prime field) -or compute a parametrization of the solutions. -\Cref{sec:solvingreals} shows how to use \msolve for solving polynomial -systems over the reals when they have dimension at most zero. -\Cref{sec:grobner} shows how to use \msolve for computing -Gr\"obner bases over prime fields (with some restriction on the bit size of the -considered prime). \Cref{sec:param} shows how to use \msolve for computing rational -parametrizations of solutions to polynomial systems which have dimension at most -zero. Finally, \cref{sec:flags} summarizes some options which can be used rational -parametrizations of solutions to polynomial systems which have dimension at most -zero. Finally, \cref{sec:flags} summarizes some options which can be used. - -The \msolve library is described in \cite{msolve} with implementation details on -the algorithms used therein. All computations performed over the rational numbers -(e.g. for computing real roots) are based on multi-modular computations with a -probabilistic stopping criterion. Unless explicitely requested by the user (see the -\verb+-l+ flag in \cref{sec:flags}), all computations of Gr\"obner bases -in prime fields use deterministic -algorithms. Change of order algorithms which are used are deterministic +When the number of solutions is finite, one says that the system (or the ideal +generated by the input equations) has dimension zero at most. Else it has positive +dimension. +\Cref{sec:dim} shows how \msolve behaves when the input system has positive dimension +or when there is no solution at all in an algebraic closure of the base field (over +the complex numbers when the input coefficients are rational numbers). + +When the system has dimension at most zero, \msolve can compute the real solutions +or, as said above, compute a Gr\"obner basis (when the base field is a prime field) +or compute a parametrization of the solutions. +\Cref{sec:solvingreals} shows how to use \msolve for solving polynomial +systems over the reals when they have dimension at most zero. +\Cref{sec:grobner} shows how to use \msolve for computing +Gr\"obner bases over prime fields (with some restriction on the bit size of the +considered prime). \Cref{sec:param} shows how to use \msolve for computing rational +parametrizations of solutions to polynomial systems which have dimension at most +zero. Finally, \cref{sec:flags} summarizes some options which can be used rational +parametrizations of solutions to polynomial systems which have dimension at most +zero. Finally, \cref{sec:flags} summarizes some options which can be used. + +The \msolve library is described in \cite{msolve} with implementation details on +the algorithms used therein. All computations performed over the rational numbers +(e.g. for computing real roots) are based on multi-modular computations with a +probabilistic stopping criterion. Unless explicitely requested by the user (see the +\verb+-l+ flag in \cref{sec:flags}), all computations of Gr\"obner bases +in prime fields use deterministic +algorithms. Change of order algorithms which are used are deterministic when the input ideal is radical. \section{Input file format}\label{sec:input} @@ -404,9 +404,9 @@ \section{Input file format}\label{sec:input} Hence the structure of input files to \msolve is as follows: \begin{enumerate} \item the first line contains the variables of the input system, separated with - a comma (no comma at end of line); + a comma (no comma at end of line); \item the second line contains the characteristic of the field over which - computations are performed; + computations are performed; \item the next lines contain polynomials, in expanded form, separated by a comma and with a line break (no comma or line break for the last one). \end{enumerate} @@ -453,7 +453,7 @@ \section{Solving over the reals (finitely many solutions)}\label{sec:solvingreal The basic functionality \msolve allows you to perform is real root isolation for polynomial systems with rational coefficients and {\em with finitely many complex solutions}. This latter requirement is automatically -tested by \msolve. +tested by \msolve. For instance, consider the following input to \msolve written in a file \verb+in.ms+. @@ -461,10 +461,10 @@ \section{Solving over the reals (finitely many solutions)}\label{sec:solvingreal Then, typing the following command line \begin{tcolorbox} % examples/reals_dim0.sh \begin{verbatim} - ./msolve -f in.ms -o out.ms + ./msolve -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} -will display in the \verb+out.ms+ file the following content. +will display in the \verb+out.ms+ file the following content. \begin{tcolorbox} % examples/reals_dim0.res \begin{lstlisting} [0, [1, @@ -482,9 +482,9 @@ \section{Solving over the reals (finitely many solutions)}\label{sec:solvingreal list (this will be the usual case); \item the next are $\ell$ lists $L_1, \ldots, L_\ell$ which encode the solutions to the input system; each of them containing boxes isolating a single real - solution. + solution. \end{itemize} -For instance, from the above output, we deduce that the box defined by +For instance, from the above output, we deduce that the box defined by \[ \left \{ \begin{array}{l} @@ -506,7 +506,7 @@ \section{Solving over the reals (finitely many solutions)}\label{sec:solvingreal follows. \begin{tcolorbox} % examples/reals_dim0_prec256.sh \begin{verbatim} - ./msolve -p 256 -f in.ms -o out.ms + ./msolve -p 256 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} We obtain in \verb+out.ms+ the following @@ -533,7 +533,7 @@ \section{Computing Gr\"obner bases}\label{sec:grobner} command: \begin{tcolorbox} % examples/grevlex_char1073741827.sh \begin{verbatim} - ./msolve -g 2 -f in.ms -o out.ms + ./msolve -g 2 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} where the \verb+-g+ flag indicates that one aims at computing a Gr\"obner @@ -561,7 +561,7 @@ \section{Computing Gr\"obner bases}\label{sec:grobner} (which is a way smaller output), one simply uses the \verb+-g 1+ flag as follows \begin{tcolorbox} % examples/grevlex_lm_char1073741827.sh \begin{verbatim} - ./msolve -g 1 -f in.ms -o out.ms + ./msolve -g 1 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} and we obtain: @@ -584,7 +584,7 @@ \section{Computing Gr\"obner bases}\label{sec:grobner} \end{tcolorbox} Note that from this list of monomials, one can deduce the Hilbert series of the ideal generated by the input equations and then its dimension and its degree -(see~\cite{CLO}). +(see~\cite{CLO}). Note that when the \verb+-g 1+ flag is used in characteristic $0$, the result is always probabilistic: the leading monomials are deduced from two computations @@ -597,9 +597,9 @@ \section{Computing Gr\"obner bases}\label{sec:grobner} there are $8$ monomials in $z_1, z_2, z_3$ which are not divisible by the above leading monomials. -\msolve also allows you to perform Gröbner bases computations using +\msolve also allows you to perform Gröbner bases computations using \emph{one-block elimination monomial order} -thanks to the \verb+-e+ flag. The following command +thanks to the \verb+-e+ flag. The following command \begin{tcolorbox} % examples/elim_char1073741827.sh \begin{verbatim} ./msolve -e 1 -g 2 -f in.ms -o out.ms @@ -679,7 +679,7 @@ \section{Parametrizations of (finitely many) solutions} Assume that the input polynomials have coefficients in some field $\K$ with variables $x_1, \ldots, x_n$. In the case of polynomial systems of dimension $0$, \msolve computes by default a zero-dimensional parametrization of the -solution set. The user can obtain such an encoding using the \verb+-P+ flag +solution set. The user can obtain such an encoding using the \verb+-P+ flag (see below). Let us recall what a rational parametrization is. @@ -699,21 +699,21 @@ \section{Parametrizations of (finitely many) solutions} -\frac{v_n(\vartheta)}{w'(\vartheta)}\right ) \st w(\vartheta) = 0 \right\}. \] -In algebraic words, the polynomials \(w' x_i + v_i\) belong to the radical of the +In algebraic words, the polynomials \(w' x_i + v_i\) belong to the radical of the ideal generated by the input equations and the form \(\lambda_1 x_1 + \cdots + -\lambda_n x_n + t\). +\lambda_n x_n + t\). \msolve outputs univariate polynomials as an array \verb+[deg,L]+ where \verb+deg+ is the degree of the polynomial under consideration and \verb+L+ is -the array of its coefficients in the monomial basis by increasing degree and -\verb+c+ is a denominator to all coefficients. For instance, the polynomial -\(x^2+3x-2\) is encoded by +the array of its coefficients in the monomial basis by increasing degree and +\verb+c+ is a denominator to all coefficients. For instance, the polynomial +\(x^2+3x-2\) is encoded by \begin{verbatim} [2, [-2, 3, 1]] \end{verbatim} -We first explain \msolve's output in the case where the input coefficients are +We first explain \msolve's output in the case where the input coefficients are rational numbers (the characteristic zero case). For an input in the file \verb+in.ms+ \msolveinput{examples/param_simple.ms} @@ -726,9 +726,9 @@ \section{Parametrizations of (finitely many) solutions} \msolve outputs is \begin{tcolorbox} % examples/param_simple.res \begin{lstlisting} -[0, [0, -3, -4, +[0, [0, +3, +4, ['z1', 'z2', 'A'], [-119/576,69/576,5/576], [1, @@ -767,14 +767,14 @@ \section{Parametrizations of (finitely many) solutions} \begin{verbatim} ['z1', 'z2', 'A'] \end{verbatim} -where \verb+A+ is a new variable. +where \verb+A+ is a new variable. \item \texttt{form} is the list of coefficients for the linear form $\ell$ when it does not coincide with one of the input variables (else it is an empty list); In our example, this is a list of three rational numbers, - say \verb+[-119/576,69/576,5/576]+, - indicating that the linear form used to compute the rational parametrization is + say \verb+[-119/576,69/576,5/576]+, + indicating that the linear form used to compute the rational parametrization is \begin{verbatim} -119/576*z1+69/576*z2+5/576*A \end{verbatim} @@ -782,24 +782,24 @@ \section{Parametrizations of (finitely many) solutions} \item \verb+lw+ is the encoding of the eliminating polynomial $w$; \item \verb+lwp+ is the encoding of the denominator used in the rational parametrization; -\item \verb+param+ is the list of the output parametrizations, there are $n-1$ where - $n$ is the number of elements in \verb+vars+ ; - they are encoded as follows \verb+[[deg, L], c]+ where \verb+c+ is - an integer which divides the polynomial encoded by \verb+[deg, L]+. - - The first one corresponds to the first variable in \verb+vars+, the - second parametrization corresponds to the second variable in \verb+vars+ - and so on. Hence, the variable which is used to parametrize the solution +\item \verb+param+ is the list of the output parametrizations, there are $n-1$ where + $n$ is the number of elements in \verb+vars+ ; + they are encoded as follows \verb+[[deg, L], c]+ where \verb+c+ is + an integer which divides the polynomial encoded by \verb+[deg, L]+. + + The first one corresponds to the first variable in \verb+vars+, the + second parametrization corresponds to the second variable in \verb+vars+ + and so on. Hence, the variable which is used to parametrize the solution set is always the last one. \end{itemize} We illustrate now how the output looks like on input file \verb+in.ms+ \msolveinput{examples/param_char0.ms} -Using \verb+./msolve -P 2 -f in.ms+ the output is +Using \verb+./msolve -P 2 -f in.ms+ the output is \begin{tcolorbox} % examples/param_char0.res \begin{lstlisting} -[0, [0, -3, -4, +[0, [0, +3, +4, ['z1', 'z2', 'z3'], [0, 0, 1], [1, @@ -813,22 +813,22 @@ \section{Parametrizations of (finitely many) solutions} ]]]]]: \end{lstlisting} \end{tcolorbox} -On this example, all variables are parametrized by the variable \verb+z3+. +On this example, all variables are parametrized by the variable \verb+z3+. -The polynomial $w$ is $-116 - 210 z_3 + 1484 z_3^2 -344 z_3^3 + 53 z_3^4$. -The polynomials $v_1$ and $v_2$ are respectively +The polynomial $w$ is $-116 - 210 z_3 + 1484 z_3^2 -344 z_3^3 + 53 z_3^4$. +The polynomials $v_1$ and $v_2$ are respectively \[ - v_1 = 1894 + 162 z_3 - 1636 z_3^2 + 192 z_3^3 \quad \text{ and } + v_1 = 1894 + 162 z_3 - 1636 z_3^2 + 192 z_3^3 \quad \text{ and } \quad v_2 = -146 -620 z_3 - 3118 z_3^2 + 314 z_3^3. \] Note that we can get both the parametrization and the real roots. -For instance, using the command +For instance, using the command \verb+./msolve -P 1 -f in.ms+, one obtains \begin{tcolorbox} % example/param_and__reals_char0.res \begin{lstlisting} -[0, [0, -3, -4, +[0, [0, +3, +4, ['z1', 'z2', 'z3'], [0, 0, 1], [1, @@ -845,15 +845,15 @@ \section{Parametrizations of (finitely many) solutions} \end{lstlisting} \end{tcolorbox} -We end this section with the same example as above but seeing the coefficients in +We end this section with the same example as above but seeing the coefficients in \(\Z/65521\Z\). \msolveinput{examples/param_char65521.ms} The call \verb+./msolve -P 2 -f in.ms+ then outputs \begin{tcolorbox} % examples/param_char65521.res \begin{lstlisting} -[0, [65521, -3, -4, +[0, [65521, +3, +4, ['z1', 'z2', 'z3'], [0, 0, 1], [1, @@ -886,7 +886,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} A Gr\"obner basis for the \emph{grevlex order} can be computed in the former case with an input file containg $f_1,\ldots,f_m,\varphi$ and -called with the flag \verb+-S+ to use the F4SAT algorithm. Note that this option +called with the flag \verb+-S+ to use the F4SAT algorithm. Note that this option is at the moment restricted to 32 bit prime fields. For instance, consider the following input to \msolve written in a file @@ -895,10 +895,10 @@ \section{Saturation and colon ideals}\label{sec:f4sat} Then, typing the following command line \begin{tcolorbox} % examples/saturate_char1073741827.sh \begin{verbatim} - ./msolve -S -g 2 -f in.ms -o out.ms + ./msolve -S -g 2 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} -will display in the \verb+out.ms+ file the following content. +will display in the \verb+out.ms+ file the following content. \begin{tcolorbox} \begin{lstlisting} #Reduced Groebner basis data @@ -932,7 +932,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % coerce these coefficients into rational numbers. There, using continued % fractions is quite useful as it allows one to obtain reliable approximations % with integers of small \emph{height} (hence small length when represented with -% bits). +% bits). % All in all, one ends up with polynomial equations in the polynomial ring % $\Q[x_1, \ldots, x_n]$, i.e. the set of polynomials with coefficients in $\Q$ @@ -972,7 +972,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % Note also that this encoding loses the number of solutions counted with % \emph{multiplicities} ; this number is called the \emph{degree} of the input -% system (which always dominates the number of complex solutions). +% system (which always dominates the number of complex solutions). % For systems in $\Q[x_1, \ldots, x_n]$, \msolve~is able to decide if they have % finitely many complex solutions and, in that case, returns a rational @@ -985,7 +985,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % ; this is a family of polynomials which is obtained by taking appropriate % algebraic combinations of the input polynomials and from which one can extract % several properties of the solution set, in particular its \emph{dimension} and -% its \emph{degree} (see Section~\ref{sec:posdim}). +% its \emph{degree} (see Section~\ref{sec:posdim}). % For applications in cryptology and/or coding theory, polynomial systems lie in % some polynomial ring $\bF[x_1, \ldots, x_n]$ where $\bF$ is some finite field. In @@ -994,7 +994,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % have dimension at most $0$ when they have finitely many solutions in % $\overline{\bF}^n$, else they have positive dimension. For systems of dimension % at most zero, a rational parametrization as above can be computed when the -% characteristic of the field is large enough. +% characteristic of the field is large enough. % \section{Solving polynomial systems of dimension at most zero}\label{sec:zerodim} @@ -1031,7 +1031,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % % many solutions); % % \item \texttt{deg} is the number of solutions counted with multiplicities in % % $\overline{\K}^n$; -% % \item \texttt{nbsols} is the number of solutions in $\overline{\K}^n$; +% % \item \texttt{nbsols} is the number of solutions in $\overline{\K}^n$; % % \item \texttt{form} is the linear form $t$; % % \item \texttt{vars} is the list of the variables which are parametrized; % % \item \texttt{lw} is the encoding of the eliminating polynomial $w$; @@ -1040,7 +1040,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % % \item \texttt{param} is the list of the output parametrizations as described % % above ; the $i$th one corresponds to the $i$th element of \texttt{vars}. % % % \textcolor{magenta}{I am not sure this is still the case, maybe I used a reverse -% % % ordering.} +% % % ordering.} % % \end{itemize} % \begin{verbatim} % [dim, nbvar, deg, varstr, linform, lw, lwp, param] @@ -1052,7 +1052,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % \item \texttt{nbvar} is the number of variables; % \item \texttt{deg} is the number of solutions counted with multiplicities in % $\overline{\K}^n$; -% % \item \texttt{nbsols} is the number of solutions in $\overline{\K}^n$; +% % \item \texttt{nbsols} is the number of solutions in $\overline{\K}^n$; % \item \texttt{varstr} is the list of the variables which are parametrized; % \item \texttt{linform} is the linear form $t$, it is empty if there is none; % \item \texttt{lw} is the encoding of the eliminating polynomial $w$ @@ -1062,7 +1062,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % \item \texttt{param} is the list of the output parametrizations as described % above ; the $i$th one corresponds to the $i$th element of \texttt{varstr}. % % \textcolor{magenta}{I am not sure this is still the case, maybe I used a reverse -% % ordering.} +% % ordering.} % \end{itemize} % \begin{verbatim} % [char, nbvar, elim, den, param] @@ -1080,7 +1080,7 @@ \section{Saturation and colon ideals}\label{sec:f4sat} % \item \texttt{param} is the list of the output parametrizations as described % above ; the $i$th one corresponds to the $i$th element of \texttt{vars}. % % \textcolor{magenta}{I am not sure this is still the case, maybe I used a reverse -% % ordering.} +% % ordering.} % \end{itemize} @@ -1101,7 +1101,7 @@ \section{More flags and options}\label{sec:flags} \hfill \verb+Default value: 1+ -\item The flag \verb+-p + controls the binary precision of the output of the +\item The flag \verb+-p + controls the binary precision of the output of the univariate real root solver (default value may be automatically increased by \msolve when needed). @@ -1113,12 +1113,12 @@ \section{More flags and options}\label{sec:flags} \hfill \verb+Default value:0+ -\item The flag \verb+-P + tells \msolve to output the -rational parametrization computed for solving zero-dimensional polynomial +\item The flag \verb+-P + tells \msolve to output the +rational parametrization computed for solving zero-dimensional polynomial systems (those with finitely many solutions in an algebraic closure of the base field). -When +\verb+-P 0+ is set, such a parametrization is not returned, when \verb+-P 1+ is -set, the parametrization is returned and, in the charactersitic zero case (rational -coefficients), real solutions are returned, when +\verb+-P 2+ is set, only the +When \verb+-P 0+ is set, such a parametrization is not returned, when \verb+-P 1+ is +set, the parametrization is returned and, in the charactersitic zero case (rational +coefficients), real solutions are returned, when \verb+-P 2+ is set, only the rational parametrization is returned. \hfill \verb+Default value:0+ @@ -1130,17 +1130,29 @@ \section{More flags and options}\label{sec:flags} allowed to change the order of the variables if needed and quits if after these changes, the genericity requirements are not satisfied, when \verb++ is \verb+2+ \msolve is allowed to introduce a new variable and a - linear form until the genericity requirements are satisfied. + linear form until the genericity requirements are satisfied. In + positive characteristic, this linear have random coefficients, while + in characteristic $0$, it is deterministically chosen, depending on + the input. \hfill \verb+Default value:2+ \item The flag \verb+-d + tells \msolve how to handle further genericity requirements when the staircase is not generic enough by computing some normal forms: \verb++ can go from \verb+0+ (no normal form computations are computed) to - \verb+4+ (all the normal forms are computed). + \verb+4+ (all the normal forms are computed). \hfill \verb+Default value:2+ - + +\item The flag \verb+-a + tells \msolve which seed must be used + to initialize the pseudo-random generator: \verb+0+ means that + \verb+time(0)+ is used so that the seed is based on current time, + otherwise, for any positive integer \verb+N+, \verb+N+ will be the seed. The + latter option is for debug purpose only as the lack of randomization + can lead to failures on some input. + + \hfill \verb+Default value:0+ + \end{itemize} \section{Julia interface to \msolve} @@ -1189,22 +1201,22 @@ \section{Maple interface to \msolve} In order to compute Gr\"obner bases, you can also the function -\texttt{MSolveGroebner}. +\texttt{MSolveGroebner}. You may consult the source code for optional arguments which allow you to better control the output format, the names of used files, verbosity, etc. \section{Sage interface to \msolve} -There is now an interface between \href{https://www.sagemath.org/}{SageMath} -and \msolve. +There is now an interface between \href{https://www.sagemath.org/}{SageMath} +and \msolve. -You can have a look at +You can have a look at \url{https://github.com/sagemath/sage/blob/develop/src/sage/rings/polynomial/msolve.py} -and +and \url{https://github.com/sagemath/sage/blob/develop/src/sage/rings/polynomial/multi_polynomial_ideal.py} -\hfill Many thanks to the SageMath development team, in particular to Marc +\hfill Many thanks to the SageMath development team, in particular to Marc Mezzarobba who initiated this interface. %The Sage interface to \msolve can be found on the \msolve homepage or in the @@ -1234,9 +1246,9 @@ \section{Credits} Mohab Safey El Din. It relies on original implementations of Faugère's \Fquatre algorithm~\cite{F4} as well as Faug\`ere and Mou's Sparse-FGLM algorithm~\cite{SparseFGLM}. We are grateful to Huu Phuoc Le and Jorge -García Fontán for a +García Fontán for a preliminary version of the Maple interface as well as Rémi Prébet for a -preliminary version of the Sage interface. +preliminary version of the Sage interface. If you use \msolve, you may cite: \begin{verbatim} diff --git a/src/fglm/fglm_core.c b/src/fglm/fglm_core.c index 87f61455..7bb52c6d 100644 --- a/src/fglm/fglm_core.c +++ b/src/fglm/fglm_core.c @@ -1490,7 +1490,6 @@ static inline long initialize_fglm_data(sp_matfglm_t *matrix, if(matrix->dense_mat[i]==0) nb++; } - srand(time(0)); for(szmat_t i = 0; i < matrix->ncols; i++){ data->vecinit[i] = (CF_t)rand() % prime; } @@ -1511,7 +1510,6 @@ static inline long initialize_fglm_colon_data(sp_matfglmcol_t *matrix, if(matrix->dense_mat[i]==0) nb++; } - srand(time(0)); for(szmat_t i = 0; i < matrix->ncols; i++){ data->vecinit[i] = (CF_t)rand() % prime; data->vecinit[i] += (CF_t)rand() % prime; diff --git a/src/msolve/lifting-gb.c b/src/msolve/lifting-gb.c index ac26c31a..18f7ef5b 100644 --- a/src/msolve/lifting-gb.c +++ b/src/msolve/lifting-gb.c @@ -168,7 +168,7 @@ static inline void gb_modpoly_init(gb_modpoly_t modgbs, uint32_t alloc, int32_t *lens, bs_t *bs, int nv, uint32_t ld, - int32_t *lm, + int32_t *lm, md_t *st){ modgbs->alloc = alloc; modgbs->nprimes = 0; @@ -606,7 +606,7 @@ static inline int32_t *array_of_lengths(int32_t *bexp_lm, len_t len, int32_t *lens = calloc(len, sizeof(int32_t)); for(len_t i = 0; i < len; i++){ len_t idx = bs->lmps[i]; - lens[i] = bs->hm[idx][LENGTH]-1; + lens[i] = bs->hm[idx][LENGTH]-1; } return lens; } @@ -1023,7 +1023,7 @@ static inline void set_recdata(data_lift_t dl, rrec_data_t rd1, rrec_data_t rd2, static inline int ratrecon_lift_modgbs(gb_modpoly_t modgbs, data_lift_t dl, int32_t start, int32_t end, mpz_t mod_p, rrec_data_t rd1, rrec_data_t rd2){ - + mpz_t rnum, rden; mpz_init(rnum); mpz_init(rden); @@ -1263,7 +1263,7 @@ long max_bit_size_gb(gb_modpoly_t modgbs){ /* - - returns 0 if the computation went ok + - returns 0 if the computation went ok - returns 1 in case of failure @@ -1277,8 +1277,8 @@ gb_modpoly_t *core_groebner_qq( bs_t *bs, mstrace_t msd, md_t *st, - int32_t *errp, - const len_t fc, + int32_t *errp, + const len_t fc, const int print_gb ) { @@ -1303,7 +1303,6 @@ gb_modpoly_t *core_groebner_qq( uint32_t prime = 0; uint32_t primeinit = 0; uint32_t lprime = 1303905299; - srand(time(0)); prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); while(fc == 0 && is_lucky_prime_ui(prime, bs)){ @@ -1322,7 +1321,7 @@ gb_modpoly_t *core_groebner_qq( int success = 1; - int32_t maxbitsize = maxbitsize_generators(bs); + int32_t maxbitsize = maxbitsize_generators(bs); int learn = 1, apply = 1, nprimes = 0; double stf4 = 0; @@ -1412,7 +1411,7 @@ gb_modpoly_t *core_groebner_qq( free_rrec_data(recdata2); fprintf(stdout, "Something went wrong in the learning phase, msolve restarts."); - return core_groebner_qq(modgbsp, bs, msd, st, errp, fc, print_gb); + return core_groebner_qq(modgbsp, bs, msd, st, errp, fc, print_gb); } /* duplicate data for multi-threaded multi-mod computation */ duplicate_data_mthread_gbtrace(st->nthrds, bs, st, msd->num_gb, @@ -1542,7 +1541,7 @@ gb_modpoly_t *core_groebner_qq( gb_modpoly_without_hash_table_clear((*modgbsp)); free_rrec_data(recdata1); free_rrec_data(recdata2); - return core_groebner_qq(modgbsp, bs, msd, st, errp, fc, print_gb); + return core_groebner_qq(modgbsp, bs, msd, st, errp, fc, print_gb); } @@ -1660,7 +1659,7 @@ uint64_t export_results_from_groebner_qq( nterms += nlen; } - int32_t *exp = (int32_t *)(*mallocp)( + int32_t *exp = (int32_t *)(*mallocp)( ((uint64_t)nterms) * ((uint64_t) nve) * sizeof(int32_t)); memset(exp, 0, (unsigned long)nterms * nve * sizeof(int32_t)); @@ -1722,7 +1721,7 @@ uint64_t export_results_from_groebner_qq( } gb_modpoly_t *groebner_qq( - data_gens_ff_t *gens, + data_gens_ff_t *gens, msflags_t flags) { int32_t *dim_ptr = &flags->dim; @@ -1919,7 +1918,7 @@ int64_t export_groebner_qq( const int32_t reduce_gb, const int32_t pbm_file, const int32_t truncate_lifting, - const int32_t info_level + const int32_t info_level ) { /* timings */ @@ -1956,7 +1955,7 @@ int64_t export_groebner_qq( int err = 0; gb_modpoly_t *modgbsp = malloc(sizeof(gb_modpoly_t)); - modgbsp = core_groebner_qq(modgbsp, bs, msd, md, &err, field_char, + modgbsp = core_groebner_qq(modgbsp, bs, msd, md, &err, field_char, 2/* if set to 1, only the LM of the Gbs are correct */); if (err) { printf("Problem with groebner_qq, stopped computation.\n"); diff --git a/src/msolve/main.c b/src/msolve/main.c index 87607fee..87bb1285 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -71,6 +71,11 @@ static inline void display_help(char *str){ fprintf(stdout, " 0 - Nothing is printed. (default)\n"); fprintf(stdout, " 1 - Leading ideal is printed.\n"); fprintf(stdout, " 2 - Full reduced Groebner basis is printed.\n"); + fprintf(stdout, "-a SEED Random seed to initialize the pseudo"); + fprintf(stdout, " random generator\n"); + fprintf(stdout, " 0 - time(0) will be used (default)\n"); + fprintf(stdout, " Any positive integer - should be used for\n"); + fprintf(stdout, " debug purpose only\n"); fprintf(stdout, "-c GEN Handling genericity: If the staircase is not generic\n"); fprintf(stdout, " enough, msolve can automatically try to fix this\n"); fprintf(stdout, " situation via first trying a change of the order of\n"); @@ -174,6 +179,7 @@ static void getoptions( int32_t *refine, int32_t *isolate, int32_t *generate_pbm_files, + int32_t *seed, int32_t *info_level, files_gb *files){ int opt, errflag = 0, fflag = 1; @@ -182,7 +188,7 @@ static void getoptions( char *out_fname = NULL; char *bin_out_fname = NULL; opterr = 1; - char options[] = "hf:N:F:v:l:t:e:o:O:u:iI:p:P:L:q:g:c:s:SCr:R:m:M:n:d:Vf:"; + char options[] = "hf:N:F:v:l:t:e:o:O:u:iI:p:P:L:q:g:c:s:SCr:R:m:M:n:d:Vf:a:"; while((opt = getopt(argc, argv, options)) != -1) { switch(opt) { case 'N': @@ -319,6 +325,12 @@ static void getoptions( *normal_form_matrix = 0; } break; + case 'a': + *seed = strtol(optarg, NULL, 10); + if (*seed < 0) { + *seed = 0; + } + break; default: errflag++; break; @@ -374,6 +386,7 @@ int main(int argc, char **argv){ int32_t precision = 64; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ + int32_t seed = 0; files_gb *files = malloc(sizeof(files_gb)); if(files == NULL) exit(1); @@ -385,7 +398,15 @@ int main(int argc, char **argv){ &elim_block_len, &la_option, &use_signatures, &update_ht, &reduce_gb, &print_gb, &truncate_lifting, &genericity_handling, &unstable_staircase, &saturate, &colon, &normal_form, &normal_form_matrix, &is_gb, &lift_matrix, &get_param, - &precision, &refine, &isolate, &generate_pbm, &info_level, files); + &precision, &refine, &isolate, &generate_pbm, + &seed, &info_level, files); + + /* srand initialization */ + if (seed == 0) { + srand(time(0)); + } else { + srand(seed); + } FILE *fh = fopen(files->in_file, "r"); FILE *bfh = fopen(files->bin_file, "r"); @@ -452,7 +473,7 @@ int main(int argc, char **argv){ initial_hts, max_pairs, elim_block_len, update_ht, generate_pbm, reduce_gb, print_gb, truncate_lifting, get_param, genericity_handling, unstable_staircase, saturate, colon, normal_form, - normal_form_matrix, is_gb, lift_matrix, precision, + normal_form_matrix, is_gb, lift_matrix, precision, files, gens, ¶m, mpz_paramp, &nb_real_roots, &real_roots, &real_pts); diff --git a/src/msolve/msolve.c b/src/msolve/msolve.c index 4f2623c9..bc50ec3f 100644 --- a/src/msolve/msolve.c +++ b/src/msolve/msolve.c @@ -688,7 +688,6 @@ static int add_random_linear_form_to_input_system(data_gens_ff_t *gens, printf("(lowest w.r.t. monomial order)\n"); printf("[coefficients of linear form are randomly chosen]\n"); } - srand(time(0)); /* gens->random_linear_form = malloc(sizeof(int32_t)*(nvars_new)); */ gens->random_linear_form = realloc(gens->random_linear_form, sizeof(int32_t) * (nvars_new)); @@ -1674,7 +1673,7 @@ static int32_t *initial_modular_step( leadmons[0], md, bs->ht->nv, fc, unstable_staircase, - md->info_level, + md->info_level, files); if(*bmatrix == NULL){ @@ -1944,10 +1943,10 @@ static inline int is_lucky_matmul_prime_ui(uint32_t prime, } -static void free_msolve_trace_qq_secondary_data(mpz_param_t tmp_mpz_param, - trace_det_fglm_mat_t trace_det, mpz_t modulus, mpz_t prod_crt, mpq_t result, - mpq_t test, mpz_t rnum, mpz_t rden, mpz_upoly_t numer, mpz_upoly_t denom, - int16_t *check_lift, mpz_t guessed_num, mpz_t guessed_den, int *is_lifted, +static void free_msolve_trace_qq_secondary_data(mpz_param_t tmp_mpz_param, + trace_det_fglm_mat_t trace_det, mpz_t modulus, mpz_t prod_crt, mpq_t result, + mpq_t test, mpz_t rnum, mpz_t rden, mpz_upoly_t numer, mpz_upoly_t denom, + int16_t *check_lift, mpz_t guessed_num, mpz_t guessed_den, int *is_lifted, rrec_data_t recdata){ mpz_param_clear(tmp_mpz_param); trace_det_clear(trace_det); @@ -1966,14 +1965,14 @@ static void free_msolve_trace_qq_secondary_data(mpz_param_t tmp_mpz_param, free_rrec_data(recdata); } -static void free_msolve_trace_qq_initial_data(int *invalid_gens, md_t *st, primes_t *lp, - bs_t *bs_qq, bs_t **bs, param_t **nmod_params, uint32_t *bad_primes, - sp_matfglm_t **bmatrix, int32_t **bdiv_xn, int32_t **blen_gb_xn, - int32_t **bstart_cf_gb_xn, long**bextra_nf, int32_t **blens_extra_nf, - int32_t **bexps_extra_nf, int32_t **bcfs_extra_nf, fglm_data_t **bdata_fglm, - fglm_bms_data_t **bdata_bms, int32_t *num_gb, int32_t **leadmons_ori, - int32_t **leadmons_current, nvars_t *bnlins, nvars_t **blinvars, - nvars_t *linvars, uint32_t **lineqs_ptr, nvars_t **bsquvars, nvars_t *squvars, +static void free_msolve_trace_qq_initial_data(int *invalid_gens, md_t *st, primes_t *lp, + bs_t *bs_qq, bs_t **bs, param_t **nmod_params, uint32_t *bad_primes, + sp_matfglm_t **bmatrix, int32_t **bdiv_xn, int32_t **blen_gb_xn, + int32_t **bstart_cf_gb_xn, long**bextra_nf, int32_t **blens_extra_nf, + int32_t **bexps_extra_nf, int32_t **bcfs_extra_nf, fglm_data_t **bdata_fglm, + fglm_bms_data_t **bdata_bms, int32_t *num_gb, int32_t **leadmons_ori, + int32_t **leadmons_current, nvars_t *bnlins, nvars_t **blinvars, + nvars_t *linvars, uint32_t **lineqs_ptr, nvars_t **bsquvars, nvars_t *squvars, int32_t *lmb_ori, uint32_t field_char){ free(invalid_gens); free_lucky_primes(&lp); @@ -2047,7 +2046,7 @@ void update_initial_primes(primes_t **binit_primes, uint32_t fc){ else{ (*binit_primes)->old = (*binit_primes)->ld; (*binit_primes)->ld++; - (*binit_primes)->p = (uint32_t *)realloc((*binit_primes)->p, + (*binit_primes)->p = (uint32_t *)realloc((*binit_primes)->p, (unsigned long)((*binit_primes)->ld) * sizeof(uint32_t)); (*binit_primes)->p[(*binit_primes)->ld - 1] = fc; } @@ -2129,7 +2128,7 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, len_t i; - + /* initialize stuff */ md_t *st = allocate_meta_data(); @@ -2206,7 +2205,6 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, uint32_t primeinit = 0; /* max prime "lprime" : this is previous_prime(1303905301) */ uint32_t lprime = 1303905299; - srand(time(0)); /* choose next_prime of some random number between 1<<30 and 1303905301 */ /* (roughly, there are ~ 10**7 such primes) */ prime = next_prime(rand() % (1303905301 - (1 << 30) + 1) + (1 << 30)); @@ -2311,7 +2309,7 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, if (gens->rand_linear) { *minpolydeg_ptr = (*nmod_params)->degsqfrelimpol; return 3; - } + } if (*dim_ptr == 0 && success && *dquot_ptr > 0 && print_gb == 0) { if (nmod_params[0]->degsqfrelimpol != *minpolydeg_ptr && nmod_params[0]->elim->length - 1 != *dquot_ptr) { @@ -2329,10 +2327,10 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, if (lmb_ori == NULL || success == 0 || print_gb || gens->field_char) { if (print_gb) { - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); return 0; } @@ -2347,10 +2345,10 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, } (*nmod_param) = par; } - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); return 0; } @@ -2358,35 +2356,35 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, if (info_level) { fprintf(stdout, "Positive dimensional Grobner basis\n"); } - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); return 0; } if (*dquot_ptr == 0) { - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); return 0; } if (*dquot_ptr > 0) { if (success && *minpolydeg_ptr == (*nmod_params)->degsqfrelimpol) { /* same degree as with a random linear form */ - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); return 0; } else { - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); if (*minpolydeg_ptr == -1 && squares == 0) { return 2; @@ -2662,13 +2660,13 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, } nbadprimes++; if (nbadprimes > nprimes) { - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); - free_msolve_trace_qq_secondary_data(tmp_mpz_param, trace_det, modulus, - prod_crt, result, test, rnum, rden, numer, denom, check_lift, + free_msolve_trace_qq_secondary_data(tmp_mpz_param, trace_det, modulus, + prod_crt, result, test, rnum, rden, numer, denom, check_lift, guessed_num, guessed_den, is_lifted, recdata); return -4; } @@ -2723,13 +2721,13 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, fprintf(stdout, "-----------------------------------------\n"); fflush(stdout); } - free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, - bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, - blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, - num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, + free_msolve_trace_qq_initial_data(invalid_gens, st, lp, bs_qq, bs, nmod_params, + bad_primes, bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bextra_nf, + blens_extra_nf, bexps_extra_nf, bcfs_extra_nf, bdata_fglm, bdata_bms, + num_gb, leadmons_ori, leadmons_current, bnlins, blinvars, linvars, lineqs_ptr, bsquvars, squvars, lmb_ori, field_char); - free_msolve_trace_qq_secondary_data(tmp_mpz_param, trace_det, modulus, - prod_crt, result, test, rnum, rden, numer, denom, check_lift, + free_msolve_trace_qq_secondary_data(tmp_mpz_param, trace_det, modulus, + prod_crt, result, test, rnum, rden, numer, denom, check_lift, guessed_num, guessed_den, is_lifted, recdata); return 0; } @@ -4423,7 +4421,7 @@ int core_msolve( gens, initial_hts, unstable_staircase, nr_threads, max_pairs, elim_block_len, update_ht, - la_option, use_signatures, lift_matrix, + la_option, use_signatures, lift_matrix, &init_primes, info_level, print_gb, generate_pbm, precision, files, round, get_param); if(print_gb){ @@ -4436,7 +4434,7 @@ int core_msolve( real_pts_ptr, info_level); - if (b == 1) {// computation failed + if (b == 1) {// computation failed free(bld); bld = NULL; free(blen); @@ -4732,7 +4730,6 @@ int core_msolve( /* initialize tracer */ trace_t *trace = initialize_trace(bs_qq, st); - srand(time(0)); uint32_t prime = next_prime(1<<30); prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); while(is_lucky_prime_ui(prime, bs_qq)){ @@ -4917,7 +4914,6 @@ int core_msolve( st->tr = trace; - srand(time(0)); uint32_t prime = next_prime(1<<30); prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); while(is_lucky_prime_ui(prime, bs_qq)){ @@ -5097,7 +5093,7 @@ int core_msolve( gens, initial_hts, unstable_staircase, nr_threads, max_pairs, elim_block_len, update_ht, - la_option, use_signatures, lift_matrix, + la_option, use_signatures, lift_matrix, &init_primes, info_level, print_gb, generate_pbm, precision, files, round, get_param); @@ -5247,7 +5243,7 @@ int core_msolve( } } } - + free(bld); free(blen); free(bexp); From 784484873542d56d0fbd051fbc631d678a7300b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Mon, 22 Dec 2025 14:35:35 +0100 Subject: [PATCH 02/14] fix bug making quit when a random linear form in positive characteristic is introduced --- src/msolve/msolve.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/msolve/msolve.c b/src/msolve/msolve.c index bc50ec3f..05e1ad33 100644 --- a/src/msolve/msolve.c +++ b/src/msolve/msolve.c @@ -2306,7 +2306,7 @@ int msolve_trace_qq(mpz_param_t *mpz_paramp, files, &success); - if (gens->rand_linear) { + if (gens->field_char == 0 && gens->rand_linear) { *minpolydeg_ptr = (*nmod_params)->degsqfrelimpol; return 3; } @@ -3684,6 +3684,7 @@ int real_msolve_qq(mpz_param_t *mpz_paramp, param_t **nmod_param, int *dim_ptr, 0 if comp. is ok 1 if comp. failed 2 if more genericity is required + 3 if computation with a random linear form succeeded -2 if charac is > 0 -3 if meta data are corrupted -4 if bad prime @@ -4419,7 +4420,7 @@ int core_msolve( real_roots_ptr, real_pts_ptr, gens, - initial_hts, unstable_staircase, nr_threads, max_pairs, + initial_hts, unstable_staircase, nr_threads, max_pairs, elim_block_len, update_ht, la_option, use_signatures, lift_matrix, &init_primes, info_level, print_gb, @@ -5203,7 +5204,7 @@ int core_msolve( /* same degree for both random linear forms */ if (info_level > 0) { printf ("\nRestarting with a non-random linear form"); - } + } /* set back the base coefficient to its previous form before introducing the random linear form. Only for value larger than 1 @@ -5229,7 +5230,7 @@ int core_msolve( minpolydeg = -1; if (info_level > 0) { printf ("\nRestarting with another random linear form"); - } + } /* set back the base coefficient to its previous form before introducing the random linear form. Only for value larger than 1 From 14c76929a543bf9cf19924dce492db7a1c6cf81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Mon, 22 Dec 2025 15:40:31 +0100 Subject: [PATCH 03/14] info level now prints the seed for later debugging --- src/msolve/main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index 87bb1285..1ecf6247 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -403,9 +403,12 @@ int main(int argc, char **argv){ /* srand initialization */ if (seed == 0) { - srand(time(0)); - } else { - srand(seed); + seed = time(0); + } + srand(seed); + if (info_level) { + fprintf (stdout,"Initial seed for pseudo-random number generator "); + fprintf (stdout,"is %d\n",seed); } FILE *fh = fopen(files->in_file, "r"); From c68e486b362cd406244c712e79b272ccc3675915 Mon Sep 17 00:00:00 2001 From: jerebertho <94358310+jerebertho@users.noreply.github.com> Date: Mon, 22 Dec 2025 20:58:14 +0100 Subject: [PATCH 04/14] Update help text for -a option Co-authored-by: Vincent Neiger --- src/msolve/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index 1ecf6247..cb4b453c 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -74,8 +74,8 @@ static inline void display_help(char *str){ fprintf(stdout, "-a SEED Random seed to initialize the pseudo"); fprintf(stdout, " random generator\n"); fprintf(stdout, " 0 - time(0) will be used (default)\n"); - fprintf(stdout, " Any positive integer - should be used for\n"); - fprintf(stdout, " debug purpose only\n"); + fprintf(stdout, " Any positive integer - use at your own risks; this\n"); + fprintf(stdout, " is intended for developers and debug purposes only\n"); fprintf(stdout, "-c GEN Handling genericity: If the staircase is not generic\n"); fprintf(stdout, " enough, msolve can automatically try to fix this\n"); fprintf(stdout, " situation via first trying a change of the order of\n"); From bf559c26d274ee99ab39d260ec944ba0d0e5770c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Tue, 23 Dec 2025 10:36:21 +0100 Subject: [PATCH 05/14] change seed to int64_t as POSIX.1-2024 requires time_t to be 64 bits wide --- src/msolve/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index cb4b453c..7521f550 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -179,7 +179,7 @@ static void getoptions( int32_t *refine, int32_t *isolate, int32_t *generate_pbm_files, - int32_t *seed, + int64_t *seed, int32_t *info_level, files_gb *files){ int opt, errflag = 0, fflag = 1; @@ -386,7 +386,7 @@ int main(int argc, char **argv){ int32_t precision = 64; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ - int32_t seed = 0; + int64_t seed = 0; files_gb *files = malloc(sizeof(files_gb)); if(files == NULL) exit(1); @@ -408,7 +408,7 @@ int main(int argc, char **argv){ srand(seed); if (info_level) { fprintf (stdout,"Initial seed for pseudo-random number generator "); - fprintf (stdout,"is %d\n",seed); + fprintf (stdout,"is %ld\n",seed); } FILE *fh = fopen(files->in_file, "r"); From fb76a08e1c6cc81c704272b5650085eb21358769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Tue, 6 Jan 2026 17:43:06 +0100 Subject: [PATCH 06/14] changes seed back to int32_t, introduces long options and makes seed options as long option only --- src/msolve/main.c | 62 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index 7521f550..df7b0952 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -179,18 +179,58 @@ static void getoptions( int32_t *refine, int32_t *isolate, int32_t *generate_pbm_files, - int64_t *seed, + int32_t *seed, int32_t *info_level, files_gb *files){ int opt, errflag = 0, fflag = 1; + int digit_optind = 0; char *filename = NULL; char *bin_filename = NULL; char *out_fname = NULL; char *bin_out_fname = NULL; opterr = 1; - char options[] = "hf:N:F:v:l:t:e:o:O:u:iI:p:P:L:q:g:c:s:SCr:R:m:M:n:d:Vf:a:"; - while((opt = getopt(argc, argv, options)) != -1) { + /* char short_options[] = "hf:N:F:v:l:t:e:o:O:u:iI:p:P:L:q:g:c:s:SCr:R:m:M:n:d:Vf:"; */ + char short_options[] = "c:Cd:e:f:F:g:hiI:l:L:m:M:n:N:o:O:p:P:q:r:R:s:St:u:v:V"; + + struct option long_options[] = { + {"elim", required_argument, NULL, 'e'}, + {"elimation", required_argument, NULL, 'e'}, + {"file", required_argument, NULL, 'f'}, + {"gb", required_argument, NULL, 'g'}, + {"groebner_basis", required_argument, NULL, 'g'}, + {"input_file", required_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, + {"isolate", required_argument, NULL, 'I'}, + {"linear_algebra", required_argument, NULL, 'l'}, + {"linalg", required_argument, NULL, 'l'}, + {"lifting_mulmat", required_argument, NULL, 'L'}, + {"output", required_argument, NULL, 'o'}, + {"output_file", required_argument, NULL, 'o'}, + {"precision", required_argument, NULL, 'p'}, + {"parametrization", required_argument, NULL, 'P'}, + {"randomseed", required_argument, seed, 1}, + {"reduced_gb", required_argument, NULL, 'r'}, + {"verbose", required_argument, NULL, 'v'}, + {"version", no_argument, NULL, 'V'}, + {NULL,0,NULL,0} + }; + + while(1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + opt = getopt_long(argc, argv, short_options, long_options, &option_index); + if (opt == -1) { + /* processed all command-line options */ + break; + } + switch(opt) { + case 0: + /* no short equivalent */ + if (*seed < 0) { + *seed = 0; + } + break; case 'N': *truncate_lifting = strtol(optarg, NULL, 10); break; @@ -325,12 +365,12 @@ static void getoptions( *normal_form_matrix = 0; } break; - case 'a': - *seed = strtol(optarg, NULL, 10); - if (*seed < 0) { - *seed = 0; - } - break; + /* case 'a': */ + /* *seed = strtol(optarg, NULL, 10); */ + /* if (*seed < 0) { */ + /* *seed = 0; */ + /* } */ + /* break; */ default: errflag++; break; @@ -386,7 +426,7 @@ int main(int argc, char **argv){ int32_t precision = 64; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ - int64_t seed = 0; + int32_t seed = 0; files_gb *files = malloc(sizeof(files_gb)); if(files == NULL) exit(1); @@ -408,7 +448,7 @@ int main(int argc, char **argv){ srand(seed); if (info_level) { fprintf (stdout,"Initial seed for pseudo-random number generator "); - fprintf (stdout,"is %ld\n",seed); + fprintf (stdout,"is %d\n",seed); } FILE *fh = fopen(files->in_file, "r"); From 33f76ee96bca633142ce4ed8be40ede4f645fce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Tue, 6 Jan 2026 22:50:20 +0100 Subject: [PATCH 07/14] add long options in help text --- src/msolve/main.c | 211 +++++++++++++++++++++++----------------------- 1 file changed, 104 insertions(+), 107 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index df7b0952..0d716f12 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -35,17 +35,17 @@ static inline void display_help(char *str){ fprintf(stdout, "FILE1 and FILE2 are respectively the input and output files\n\n"); fprintf(stdout, "Standard options\n\n"); - fprintf(stdout, "-f FILE File name (mandatory).\n\n"); - fprintf(stdout, "-h Prints this help.\n"); - fprintf(stdout, "-o FILE Name of output file.\n"); - fprintf(stdout, "-t THR Number of threads to be used.\n"); - fprintf(stdout, " Default: 1.\n"); - fprintf(stdout, "-v n Level of verbosity, 0 - 2\n"); - fprintf(stdout, " 0 - no output (default).\n"); - fprintf(stdout, " 1 - global information at the start and\n"); - fprintf(stdout, " end of the computation.\n"); - fprintf(stdout, " 2 - detailed output for each step of the\n"); - fprintf(stdout, " algorithm, e.g. matrix sizes, #pairs, ...\n"); + fprintf(stdout, "-f, --file FILE File name (mandatory).\n\n"); + fprintf(stdout, "-h, --help Prints this help.\n"); + fprintf(stdout, "-o, --output-file FILE Name of output file.\n"); + fprintf(stdout, "-t, --threads THR Number of threads to be used.\n"); + fprintf(stdout, " Default: 1.\n"); + fprintf(stdout, "-v, --verbose VERB Level of verbosity, 0 - 2\n"); + fprintf(stdout, " 0 - no output (default).\n"); + fprintf(stdout, " 1 - global information at the start and\n"); + fprintf(stdout, " end of the computation.\n"); + fprintf(stdout, " 2 - detailed output for each step of the\n"); + fprintf(stdout, " algorithm, e.g. matrix sizes, #pairs, ...\n"); fprintf(stdout, "Input file format:\n"); fprintf(stdout, "\t - first line: variables separated by a comma\n"); @@ -64,93 +64,93 @@ static inline void display_help(char *str){ fprintf(stdout, "\nAdvanced options:\n\n"); - fprintf(stdout, "-F FILE File name encoding parametrizations in binary format.\n\n"); - fprintf(stdout, "-g GB Prints reduced Groebner bases of input system for\n"); - fprintf(stdout, " first prime characteristic w.r.t. grevlex ordering.\n"); - fprintf(stdout, " One element per line is printed, commata separated.\n"); - fprintf(stdout, " 0 - Nothing is printed. (default)\n"); - fprintf(stdout, " 1 - Leading ideal is printed.\n"); - fprintf(stdout, " 2 - Full reduced Groebner basis is printed.\n"); - fprintf(stdout, "-a SEED Random seed to initialize the pseudo"); - fprintf(stdout, " random generator\n"); - fprintf(stdout, " 0 - time(0) will be used (default)\n"); - fprintf(stdout, " Any positive integer - use at your own risks; this\n"); - fprintf(stdout, " is intended for developers and debug purposes only\n"); - fprintf(stdout, "-c GEN Handling genericity: If the staircase is not generic\n"); - fprintf(stdout, " enough, msolve can automatically try to fix this\n"); - fprintf(stdout, " situation via first trying a change of the order of\n"); - fprintf(stdout, " variables and finally adding a random linear form\n"); - fprintf(stdout, " with a new variable (smallest w.r.t. DRL)\n"); - fprintf(stdout, " 0 - Nothing is done, msolve quits.\n"); - fprintf(stdout, " 1 - Change order of variables.\n"); - fprintf(stdout, " 2 - Change order of variables, then try adding a\n"); - fprintf(stdout, " random linear form. (default)\n"); - fprintf(stdout, "-d GEN Handling genericity further: If the staircase is not generic\n"); - fprintf(stdout, " enough, msolve can still try to perform the full computation\n"); - fprintf(stdout, " by computing some normal forms and build the multiplication matrix,\n"); - fprintf(stdout, " before fixing the situation via option -c\n"); - fprintf(stdout, " 0 - No normal forms are computed.\n"); - fprintf(stdout, " 1 - Few normal forms are computed.\n"); - fprintf(stdout, " 2 - Some normal forms are computed. (default)\n"); - fprintf(stdout, " 3 - Lots of normal forms are computed.\n"); - fprintf(stdout, " 4 - All the normal forms are computed.\n"); - fprintf(stdout, "-C Use sparse-FGLM-col algorithm:\n"); - fprintf(stdout, " Given an input file with k polynomials\n"); - fprintf(stdout, " compute the quotient of the ideal\n"); - fprintf(stdout, " generated by the first k-1 polynomials\n"); - fprintf(stdout, " with respect to the kth polynomial.\n"); - fprintf(stdout, "-e ELIM Define an elimination order: msolve supports two\n"); - fprintf(stdout, " blocks of variables, each block using the degree reverse\n"); - fprintf(stdout, " lexicographical monomial order. ELIM has to be a number\n"); - fprintf(stdout, " between 1 and #variables-1, and gives the number of\n"); - fprintf(stdout, " eliminated variables. The basis with the first block of\n"); - fprintf(stdout, " ELIM variables eliminated is then computed.\n"); - fprintf(stdout, "-I Isolates the real roots (provided some univariate data)\n"); - fprintf(stdout, " without re-computing a Gröbner basis\n"); - fprintf(stdout, " Default: 0 (no).\n"); - fprintf(stdout, "-l LIN Linear algebra variant to be applied:\n"); - fprintf(stdout, " 1 - exact sparse / dense\n"); - fprintf(stdout, " 2 - exact sparse (default)\n"); - fprintf(stdout, " 42 - sparse / dense linearization (probabilistic)\n"); - fprintf(stdout, " 44 - sparse linearization (probabilistic)\n"); - fprintf(stdout, "-m MPR Maximal number of pairs used per matrix.\n"); - fprintf(stdout, " Default: 0 (unlimited).\n"); - fprintf(stdout, "-n NF Given n input generators compute normal form of the last NF\n"); - fprintf(stdout, " elements of the input w.r.t. a degree reverse lexicographical\n"); - fprintf(stdout, " Gröbner basis of the first (n - NF) input elements.\n"); - fprintf(stdout, " At the moment this only works for prime field computations.\n"); - fprintf(stdout, " Combining this option with the \"-i\" option assumes that the\n"); - fprintf(stdout, " first (n - NF) elements generate already a degree reverse\n"); - fprintf(stdout, " lexicographical Gröbner basis.\n"); - fprintf(stdout, "-p PRE Precision (in bits) on the output of real root isolation.\n"); - fprintf(stdout, " Default is 128.\n"); - fprintf(stdout, "-P PAR Get also rational parametrization of solution set.\n"); - fprintf(stdout, " Default is 0. For a detailed description of the output\n"); - fprintf(stdout, " format please see the general output data format section\n"); - fprintf(stdout, " above.\n"); - fprintf(stdout, "-L LIF Controls lifting of multplication matrices over the rationals.\n"); - fprintf(stdout, " Default is 0 (no lifting). \n"); - fprintf(stdout, " Matrices are lifted when LIF is 1.\n"); - fprintf(stdout, " Warning: when activated, this option may cause higher memory consumption.\n"); - fprintf(stdout, "-q Q Uses signature-based algorithms.\n"); - fprintf(stdout, " Default: 0 (no).\n"); - fprintf(stdout, "-r RED Reduce Groebner basis.\n"); - fprintf(stdout, " Default: 1 (yes).\n"); + fprintf(stdout, "-F FILE File name encoding parametrizations in binary format.\n\n"); + fprintf(stdout, "-g, --groebner-basis GB Prints reduced Groebner bases of input system for\n"); + fprintf(stdout, " first prime characteristic w.r.t. grevlex ordering.\n"); + fprintf(stdout, " One element per line is printed, commata separated.\n"); + fprintf(stdout, " 0 - Nothing is printed. (default)\n"); + fprintf(stdout, " 1 - Leading ideal is printed.\n"); + fprintf(stdout, " 2 - Full reduced Groebner basis is printed.\n"); + fprintf(stdout, " --random_seed SEED Random seed to initialize the pseudo\n"); + fprintf(stdout, " random generator\n"); + fprintf(stdout, " 0 - time(0) will be used (default)\n"); + fprintf(stdout, " N>0 - use at your own risks; this\n"); + fprintf(stdout, " is intended for developers and debug purposes only\n"); + fprintf(stdout, "-c GEN Handling genericity: If the staircase is not generic\n"); + fprintf(stdout, " enough, msolve can automatically try to fix this\n"); + fprintf(stdout, " situation via first trying a change of the order of\n"); + fprintf(stdout, " variables and finally adding a random linear form\n"); + fprintf(stdout, " with a new variable (smallest w.r.t. DRL)\n"); + fprintf(stdout, " 0 - Nothing is done, msolve quits.\n"); + fprintf(stdout, " 1 - Change order of variables.\n"); + fprintf(stdout, " 2 - Change order of variables, then try adding a\n"); + fprintf(stdout, " random linear form. (default)\n"); + fprintf(stdout, "-d GEN Handling genericity further: If the staircase is not generic\n"); + fprintf(stdout, " enough, msolve can still try to perform the full computation\n"); + fprintf(stdout, " by computing some normal forms and build the multiplication matrix,\n"); + fprintf(stdout, " before fixing the situation via option -c\n"); + fprintf(stdout, " 0 - No normal forms are computed.\n"); + fprintf(stdout, " 1 - Few normal forms are computed.\n"); + fprintf(stdout, " 2 - Some normal forms are computed. (default)\n"); + fprintf(stdout, " 3 - Lots of normal forms are computed.\n"); + fprintf(stdout, " 4 - All the normal forms are computed.\n"); + fprintf(stdout, "-C Use sparse-FGLM-col algorithm:\n"); + fprintf(stdout, " Given an input file with k polynomials\n"); + fprintf(stdout, " compute the quotient of the ideal\n"); + fprintf(stdout, " generated by the first k-1 polynomials\n"); + fprintf(stdout, " with respect to the kth polynomial.\n"); + fprintf(stdout, "-e, --elimination ELIM Define an elimination order: msolve supports two\n"); + fprintf(stdout, " blocks of variables, each block using the degree reverse\n"); + fprintf(stdout, " lexicographical monomial order. ELIM has to be a number\n"); + fprintf(stdout, " between 1 and #variables-1, and gives the number of\n"); + fprintf(stdout, " eliminated variables. The basis with the first block of\n"); + fprintf(stdout, " ELIM variables eliminated is then computed.\n"); + fprintf(stdout, "-I, --isolate ISOL Isolates the real roots (provided some univariate data)\n"); + fprintf(stdout, " without re-computing a Gröbner basis\n"); + fprintf(stdout, " Default: 0 (no).\n"); + fprintf(stdout, "-l, --linear-algebra LIN Linear algebra variant to be applied:\n"); + fprintf(stdout, " 1 - exact sparse / dense\n"); + fprintf(stdout, " 2 - exact sparse (default)\n"); + fprintf(stdout, " 42 - sparse / dense linearization (probabilistic)\n"); + fprintf(stdout, " 44 - sparse linearization (probabilistic)\n"); + fprintf(stdout, "-m MPR Maximal number of pairs used per matrix.\n"); + fprintf(stdout, " Default: 0 (unlimited).\n"); + fprintf(stdout, "-n, --normal-form NF Given n input generators compute normal form of the last NF\n"); + fprintf(stdout, " elements of the input w.r.t. a degree reverse lexicographical\n"); + fprintf(stdout, " Gröbner basis of the first (n - NF) input elements.\n"); + fprintf(stdout, " At the moment this only works for prime field computations.\n"); + fprintf(stdout, " Combining this option with the \"-i\" option assumes that the\n"); + fprintf(stdout, " first (n - NF) elements generate already a degree reverse\n"); + fprintf(stdout, " lexicographical Gröbner basis.\n"); + fprintf(stdout, "-p, --precision PRE Precision (in bits) on the output of real root isolation.\n"); + fprintf(stdout, " Default is 128.\n"); + fprintf(stdout, "-P, --parametrization PAR Get also rational parametrization of solution set.\n"); + fprintf(stdout, " Default is 0. For a detailed description of the output\n"); + fprintf(stdout, " format please see the general output data format section\n"); + fprintf(stdout, " above.\n"); + fprintf(stdout, "-L, --lifting-mulmat LIF Controls lifting of multplication matrices over the rationals.\n"); + fprintf(stdout, " 0 - no lifting (default). \n"); + fprintf(stdout, " 1 - matrices are lifted.\n"); + fprintf(stdout, " Warning: when activated, this option may cause higher memory consumption.\n"); + fprintf(stdout, "-q Q Uses signature-based algorithms.\n"); + fprintf(stdout, " Default: 0 (no).\n"); + fprintf(stdout, "-r, --reduced-gb RED Reduce Groebner basis.\n"); + fprintf(stdout, " Default: 1 (yes).\n"); /* fprintf(stdout, "-R Refinement fo real roots.\n"); */ /* fprintf(stdout, " (not implemented yet).\n"); */ - fprintf(stdout, "-s HTS Initial hash table size given\n"); - fprintf(stdout, " as power of two. Default: 17.\n"); - fprintf(stdout, "-S Use f4sat saturation algorithm:\n"); - fprintf(stdout, " Given an input file with k polynomials\n"); - fprintf(stdout, " compute the saturation of the ideal\n"); - fprintf(stdout, " generated by the first k-1 polynomials\n"); - fprintf(stdout, " with respect to the kth polynomial.\n"); - fprintf(stdout, " Note: At the moment restricted to 32 bit\n"); - fprintf(stdout, " prime fields.\n"); - fprintf(stdout, "-u UHT Number of steps after which the\n"); - fprintf(stdout, " hash table is newly generated.\n"); - fprintf(stdout, " Default: 0, i.e. no update.\n"); - fprintf(stdout, "-V Prints msolve's version\n"); + fprintf(stdout, "-s HTS Initial hash table size given\n"); + fprintf(stdout, " as power of two. Default: 17.\n"); + fprintf(stdout, "-S Use f4sat saturation algorithm:\n"); + fprintf(stdout, " Given an input file with k polynomials\n"); + fprintf(stdout, " compute the saturation of the ideal\n"); + fprintf(stdout, " generated by the first k-1 polynomials\n"); + fprintf(stdout, " with respect to the kth polynomial.\n"); + fprintf(stdout, " Note: At the moment restricted to 32 bit\n"); + fprintf(stdout, " prime fields.\n"); + fprintf(stdout, "-u UHT Number of steps after which the\n"); + fprintf(stdout, " hash table is newly generated.\n"); + fprintf(stdout, " Default: 0, i.e. no update.\n"); + fprintf(stdout, "-V, --version Prints msolve's version\n"); } static void getoptions( @@ -193,23 +193,20 @@ static void getoptions( char short_options[] = "c:Cd:e:f:F:g:hiI:l:L:m:M:n:N:o:O:p:P:q:r:R:s:St:u:v:V"; struct option long_options[] = { - {"elim", required_argument, NULL, 'e'}, {"elimation", required_argument, NULL, 'e'}, {"file", required_argument, NULL, 'f'}, - {"gb", required_argument, NULL, 'g'}, - {"groebner_basis", required_argument, NULL, 'g'}, - {"input_file", required_argument, NULL, 'f'}, + {"groebner-basis", required_argument, NULL, 'g'}, {"help", no_argument, NULL, 'h'}, {"isolate", required_argument, NULL, 'I'}, - {"linear_algebra", required_argument, NULL, 'l'}, - {"linalg", required_argument, NULL, 'l'}, - {"lifting_mulmat", required_argument, NULL, 'L'}, - {"output", required_argument, NULL, 'o'}, - {"output_file", required_argument, NULL, 'o'}, + {"linear-algebra", required_argument, NULL, 'l'}, + {"lifting-mulmat", required_argument, NULL, 'L'}, + {"normal-form", required_argument, NULL, 'L'}, + {"output-file", required_argument, NULL, 'o'}, {"precision", required_argument, NULL, 'p'}, {"parametrization", required_argument, NULL, 'P'}, - {"randomseed", required_argument, seed, 1}, - {"reduced_gb", required_argument, NULL, 'r'}, + {"random-seed", required_argument, seed, 1}, + {"reduced-gb", required_argument, NULL, 'r'}, + {"threads", required_argument, NULL, 't'}, {"verbose", required_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {NULL,0,NULL,0} From f5cbb45f6f2d179c758cab41183778609d9990b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Wed, 7 Jan 2026 15:21:13 +0100 Subject: [PATCH 08/14] new display help functions to take long options into account --- src/msolve/main.c | 256 +++++++++++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 107 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index 0d716f12..e0dcd1d3 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -24,6 +24,40 @@ #define DEBUGBUILDMATRIX 0 #define IO_DEBUG 0 +#define LONG_OPT_LENGTH 15 +#define ARG_OPT_LENGTH 4 + +static inline void display_option_help(char short_opt, char *long_opt, + char *arg_opt, char* str) { + int long_opt_non_empty= strcmp (long_opt, ""); + + if (short_opt == '\0') { + fprintf (stdout, " "); + } else { + fprintf (stdout, "-%c", short_opt); + if (long_opt_non_empty) { + fprintf (stdout, ", "); + } else { + fprintf (stdout, " "); + } + } + + if (long_opt_non_empty) { + fprintf (stdout, "--"); + } else { + fprintf (stdout, " "); + } + fprintf (stdout, "%-*s ", + LONG_OPT_LENGTH, long_opt); + fprintf (stdout, "%-*s ", + ARG_OPT_LENGTH, arg_opt); + fprintf (stdout, "%s", str); +} + +static inline void display_option_help_noopt(char* str) { + display_option_help ('\0', "", "", str); +} + static inline void display_help(char *str){ fprintf(stdout, "\nmsolve library for polynomial system solving, version %s\n", VERSION); fprintf(stdout, "implemented by J. Berthomieu, C. Eder, M. Safey El Din\n"); @@ -35,17 +69,18 @@ static inline void display_help(char *str){ fprintf(stdout, "FILE1 and FILE2 are respectively the input and output files\n\n"); fprintf(stdout, "Standard options\n\n"); - fprintf(stdout, "-f, --file FILE File name (mandatory).\n\n"); - fprintf(stdout, "-h, --help Prints this help.\n"); - fprintf(stdout, "-o, --output-file FILE Name of output file.\n"); - fprintf(stdout, "-t, --threads THR Number of threads to be used.\n"); - fprintf(stdout, " Default: 1.\n"); - fprintf(stdout, "-v, --verbose VERB Level of verbosity, 0 - 2\n"); - fprintf(stdout, " 0 - no output (default).\n"); - fprintf(stdout, " 1 - global information at the start and\n"); - fprintf(stdout, " end of the computation.\n"); - fprintf(stdout, " 2 - detailed output for each step of the\n"); - fprintf(stdout, " algorithm, e.g. matrix sizes, #pairs, ...\n"); + display_option_help('f', "file", "FILE", "File name (mandatory).\n\n"); + display_option_help('h', "help", "", "Prints this help.\n"); + display_option_help('o', "output-file", "FILE", "Name of output file.\n"); + display_option_help('t', "threads", "THR", "Number of threads to be used.\n"); + display_option_help_noopt("1 - one thread (default).\n"); + display_option_help_noopt("THR > 1 - THR threads.\n"); + display_option_help('v', "verbose", "VERB", "Level of verbosity, 0 - 2\n"); + display_option_help_noopt("0 - no output (default).\n"); + display_option_help_noopt("1 - global information at the start and\n"); + display_option_help_noopt(" end of the computation.\n"); + display_option_help_noopt("2 - detailed output for each step of the\n"); + display_option_help_noopt(" algorithm, e.g. matrix sizes, #pairs, ...\n"); fprintf(stdout, "Input file format:\n"); fprintf(stdout, "\t - first line: variables separated by a comma\n"); @@ -64,93 +99,98 @@ static inline void display_help(char *str){ fprintf(stdout, "\nAdvanced options:\n\n"); - fprintf(stdout, "-F FILE File name encoding parametrizations in binary format.\n\n"); - fprintf(stdout, "-g, --groebner-basis GB Prints reduced Groebner bases of input system for\n"); - fprintf(stdout, " first prime characteristic w.r.t. grevlex ordering.\n"); - fprintf(stdout, " One element per line is printed, commata separated.\n"); - fprintf(stdout, " 0 - Nothing is printed. (default)\n"); - fprintf(stdout, " 1 - Leading ideal is printed.\n"); - fprintf(stdout, " 2 - Full reduced Groebner basis is printed.\n"); - fprintf(stdout, " --random_seed SEED Random seed to initialize the pseudo\n"); - fprintf(stdout, " random generator\n"); - fprintf(stdout, " 0 - time(0) will be used (default)\n"); - fprintf(stdout, " N>0 - use at your own risks; this\n"); - fprintf(stdout, " is intended for developers and debug purposes only\n"); - fprintf(stdout, "-c GEN Handling genericity: If the staircase is not generic\n"); - fprintf(stdout, " enough, msolve can automatically try to fix this\n"); - fprintf(stdout, " situation via first trying a change of the order of\n"); - fprintf(stdout, " variables and finally adding a random linear form\n"); - fprintf(stdout, " with a new variable (smallest w.r.t. DRL)\n"); - fprintf(stdout, " 0 - Nothing is done, msolve quits.\n"); - fprintf(stdout, " 1 - Change order of variables.\n"); - fprintf(stdout, " 2 - Change order of variables, then try adding a\n"); - fprintf(stdout, " random linear form. (default)\n"); - fprintf(stdout, "-d GEN Handling genericity further: If the staircase is not generic\n"); - fprintf(stdout, " enough, msolve can still try to perform the full computation\n"); - fprintf(stdout, " by computing some normal forms and build the multiplication matrix,\n"); - fprintf(stdout, " before fixing the situation via option -c\n"); - fprintf(stdout, " 0 - No normal forms are computed.\n"); - fprintf(stdout, " 1 - Few normal forms are computed.\n"); - fprintf(stdout, " 2 - Some normal forms are computed. (default)\n"); - fprintf(stdout, " 3 - Lots of normal forms are computed.\n"); - fprintf(stdout, " 4 - All the normal forms are computed.\n"); - fprintf(stdout, "-C Use sparse-FGLM-col algorithm:\n"); - fprintf(stdout, " Given an input file with k polynomials\n"); - fprintf(stdout, " compute the quotient of the ideal\n"); - fprintf(stdout, " generated by the first k-1 polynomials\n"); - fprintf(stdout, " with respect to the kth polynomial.\n"); - fprintf(stdout, "-e, --elimination ELIM Define an elimination order: msolve supports two\n"); - fprintf(stdout, " blocks of variables, each block using the degree reverse\n"); - fprintf(stdout, " lexicographical monomial order. ELIM has to be a number\n"); - fprintf(stdout, " between 1 and #variables-1, and gives the number of\n"); - fprintf(stdout, " eliminated variables. The basis with the first block of\n"); - fprintf(stdout, " ELIM variables eliminated is then computed.\n"); - fprintf(stdout, "-I, --isolate ISOL Isolates the real roots (provided some univariate data)\n"); - fprintf(stdout, " without re-computing a Gröbner basis\n"); - fprintf(stdout, " Default: 0 (no).\n"); - fprintf(stdout, "-l, --linear-algebra LIN Linear algebra variant to be applied:\n"); - fprintf(stdout, " 1 - exact sparse / dense\n"); - fprintf(stdout, " 2 - exact sparse (default)\n"); - fprintf(stdout, " 42 - sparse / dense linearization (probabilistic)\n"); - fprintf(stdout, " 44 - sparse linearization (probabilistic)\n"); - fprintf(stdout, "-m MPR Maximal number of pairs used per matrix.\n"); - fprintf(stdout, " Default: 0 (unlimited).\n"); - fprintf(stdout, "-n, --normal-form NF Given n input generators compute normal form of the last NF\n"); - fprintf(stdout, " elements of the input w.r.t. a degree reverse lexicographical\n"); - fprintf(stdout, " Gröbner basis of the first (n - NF) input elements.\n"); - fprintf(stdout, " At the moment this only works for prime field computations.\n"); - fprintf(stdout, " Combining this option with the \"-i\" option assumes that the\n"); - fprintf(stdout, " first (n - NF) elements generate already a degree reverse\n"); - fprintf(stdout, " lexicographical Gröbner basis.\n"); - fprintf(stdout, "-p, --precision PRE Precision (in bits) on the output of real root isolation.\n"); - fprintf(stdout, " Default is 128.\n"); - fprintf(stdout, "-P, --parametrization PAR Get also rational parametrization of solution set.\n"); - fprintf(stdout, " Default is 0. For a detailed description of the output\n"); - fprintf(stdout, " format please see the general output data format section\n"); - fprintf(stdout, " above.\n"); - fprintf(stdout, "-L, --lifting-mulmat LIF Controls lifting of multplication matrices over the rationals.\n"); - fprintf(stdout, " 0 - no lifting (default). \n"); - fprintf(stdout, " 1 - matrices are lifted.\n"); - fprintf(stdout, " Warning: when activated, this option may cause higher memory consumption.\n"); - fprintf(stdout, "-q Q Uses signature-based algorithms.\n"); - fprintf(stdout, " Default: 0 (no).\n"); - fprintf(stdout, "-r, --reduced-gb RED Reduce Groebner basis.\n"); - fprintf(stdout, " Default: 1 (yes).\n"); - /* fprintf(stdout, "-R Refinement fo real roots.\n"); */ - /* fprintf(stdout, " (not implemented yet).\n"); */ - fprintf(stdout, "-s HTS Initial hash table size given\n"); - fprintf(stdout, " as power of two. Default: 17.\n"); - fprintf(stdout, "-S Use f4sat saturation algorithm:\n"); - fprintf(stdout, " Given an input file with k polynomials\n"); - fprintf(stdout, " compute the saturation of the ideal\n"); - fprintf(stdout, " generated by the first k-1 polynomials\n"); - fprintf(stdout, " with respect to the kth polynomial.\n"); - fprintf(stdout, " Note: At the moment restricted to 32 bit\n"); - fprintf(stdout, " prime fields.\n"); - fprintf(stdout, "-u UHT Number of steps after which the\n"); - fprintf(stdout, " hash table is newly generated.\n"); - fprintf(stdout, " Default: 0, i.e. no update.\n"); - fprintf(stdout, "-V, --version Prints msolve's version\n"); + display_option_help('F', "", "FILE", "File name encoding parametrizations in binary format.\n\n"); + display_option_help('g', "groebner-basis", "GB", "Prints reduced Groebner bases of input system for\n"); + display_option_help_noopt("first prime characteristic w.r.t. grevlex ordering.\n"); + display_option_help_noopt("One element per line is printed, commata separated.\n"); + display_option_help_noopt("0 - Nothing is printed. (default)\n"); + display_option_help_noopt("1 - Leading ideal is printed.\n"); + display_option_help_noopt("2 - Full reduced Groebner basis is printed.\n"); + display_option_help('c',"", "GEN", "Handling genericity: If the staircase is not generic\n"); + display_option_help_noopt("enough, msolve can automatically try to fix this\n"); + display_option_help_noopt("situation via first trying a change of the order of\n"); + display_option_help_noopt("variables and finally adding a random linear form\n"); + display_option_help_noopt("with a new variable (smallest w.r.t. DRL)\n"); + display_option_help_noopt("0 - Nothing is done, msolve quits.\n"); + display_option_help_noopt("1 - Change order of variables.\n"); + display_option_help_noopt("2 - Change order of variables, then try adding a\n"); + display_option_help_noopt(" random linear form. (default)\n"); + display_option_help('d', "", "GEN", "Handling genericity further: If the staircase is not generic\n"); + display_option_help_noopt("enough, msolve can still try to perform the full computation\n"); + display_option_help_noopt("by computing some normal forms and build the multiplication matrix,\n"); + display_option_help_noopt("before fixing the situation via option -c\n"); + display_option_help_noopt("0 - No normal forms are computed.\n"); + display_option_help_noopt("1 - Few normal forms are computed.\n"); + display_option_help_noopt("2 - Some normal forms are computed. (default)\n"); + display_option_help_noopt("3 - Lots of normal forms are computed.\n"); + display_option_help_noopt("4 - All the normal forms are computed.\n"); + display_option_help('C', "", "", "Use sparse-FGLM-col algorithm:\n"); + display_option_help_noopt("Given an input file with k polynomials\n"); + display_option_help_noopt("compute the quotient of the ideal\n"); + display_option_help_noopt("generated by the first k-1 polynomials\n"); + display_option_help_noopt("with respect to the kth polynomial.\n"); + display_option_help('e', "elimination", "ELIM", "Define an elimination order: msolve supports two\n"); + display_option_help_noopt("blocks of variables, each block using the degree reverse\n"); + display_option_help_noopt("lexicographical monomial order. ELIM has to be a number\n"); + display_option_help_noopt("between 1 and #variables-1, and gives the number of\n"); + display_option_help_noopt("eliminated variables. The basis with the first block of\n"); + display_option_help_noopt("ELIM variables eliminated is then computed.\n"); + display_option_help('I', "isolate", "ISOL", "Isolates the real roots (provided some univariate data)\n"); + display_option_help_noopt("without re-computing a Gröbner basis\n"); + display_option_help_noopt("0 - no (default).\n"); + display_option_help_noopt("1 - yes.\n"); + display_option_help('l', "linear-algebra", "LIN", "Linear algebra variant to be applied:\n"); + display_option_help_noopt(" 1 - exact sparse / dense\n"); + display_option_help_noopt(" 2 - exact sparse (default)\n"); + display_option_help_noopt("42 - sparse / dense linearization (probabilistic)\n"); + display_option_help_noopt("44 - sparse linearization (probabilistic)\n"); + display_option_help('m', "", "MPR", "Maximal number of pairs used per matrix.\n"); + display_option_help_noopt("0 - unlimited (default).\n"); + display_option_help('n', "normal-form", "NF", "Given n input generators compute normal form of the last NF\n"); + display_option_help_noopt("elements of the input w.r.t. a degree reverse lexicographical\n"); + display_option_help_noopt("Gröbner basis of the first (n - NF) input elements.\n"); + display_option_help_noopt("At the moment this only works for prime field computations.\n"); + display_option_help_noopt("Combining this option with the \"-i\" option assumes that the\n"); + display_option_help_noopt("first (n - NF) elements generate already a degree reverse\n"); + display_option_help_noopt("lexicographical Gröbner basis.\n"); + display_option_help('p', "precision", "PRE", "Precision (in bits) on the output of real root isolation.\n"); + display_option_help_noopt("128 (default).\n"); + display_option_help('P', "parametrization", "PAR", "Get also rational parametrization of solution set.\n"); + display_option_help_noopt("0 (default). For a detailed description of the output\n"); + display_option_help_noopt("format please see the general output data format section\n"); + display_option_help_noopt("above.\n"); + display_option_help('L', "lifting-mulmat", "LIF", "Controls lifting of multplication matrices over the rationals.\n"); + display_option_help_noopt("0 - no lifting (default). \n"); + display_option_help_noopt("1 - matrices are lifted.\n"); + display_option_help_noopt("Warning: when activated, this option may cause higher memory consumption.\n"); + display_option_help('q', "", "Q", "Uses signature-based algorithms.\n"); + display_option_help_noopt("0 - no (default).\n"); + display_option_help_noopt("1 - yes.\n"); + display_option_help('\0', "random_seed", "SEED", "Random seed to initialize the pseudo\n"); + display_option_help_noopt("random generator\n"); + display_option_help_noopt("0 - time(0) will be used (default)\n"); + display_option_help_noopt("SEED > 0 - use at your own risks;\n"); + display_option_help_noopt(" this is intended for developers and\n"); + display_option_help_noopt(" debug purposes only\n"); + display_option_help('r', "reduce-gb", "RED", "Reduce Groebner basis.\n"); + display_option_help_noopt("0 - no.\n"); + display_option_help_noopt("1 - yes (default).\n"); + /* display_option_help('R', "", "REF", "Refinement fo real roots.\n"); */ + /* display_option_help_noopt("(not implemented yet).\n"); */ + display_option_help('s', "", "HTS", "Initial hash table size given\n"); + display_option_help_noopt("as power of two.\n"); + display_option_help_noopt("17 (default).\n"); + display_option_help('S', "", "", "Use f4sat saturation algorithm:\n"); + display_option_help_noopt("Given an input file with k polynomials\n"); + display_option_help_noopt("compute the saturation of the ideal\n"); + display_option_help_noopt("generated by the first k-1 polynomials\n"); + display_option_help_noopt("with respect to the kth polynomial.\n"); + display_option_help_noopt("Note: At the moment restricted to 32 bit\n"); + display_option_help_noopt("prime fields.\n"); + display_option_help('u', "", "UHT", "Number of steps after which the\n"); + display_option_help_noopt("hash table is newly generated.\n"); + display_option_help_noopt("0 - no update (default).\n"); + display_option_help('V', "version", "", "Prints msolve's version\n"); } static void getoptions( @@ -183,7 +223,6 @@ static void getoptions( int32_t *info_level, files_gb *files){ int opt, errflag = 0, fflag = 1; - int digit_optind = 0; char *filename = NULL; char *bin_filename = NULL; char *out_fname = NULL; @@ -192,20 +231,21 @@ static void getoptions( /* char short_options[] = "hf:N:F:v:l:t:e:o:O:u:iI:p:P:L:q:g:c:s:SCr:R:m:M:n:d:Vf:"; */ char short_options[] = "c:Cd:e:f:F:g:hiI:l:L:m:M:n:N:o:O:p:P:q:r:R:s:St:u:v:V"; + int random_seed_flag = 0; struct option long_options[] = { - {"elimation", required_argument, NULL, 'e'}, + {"elimination", required_argument, NULL, 'e'}, {"file", required_argument, NULL, 'f'}, {"groebner-basis", required_argument, NULL, 'g'}, {"help", no_argument, NULL, 'h'}, {"isolate", required_argument, NULL, 'I'}, {"linear-algebra", required_argument, NULL, 'l'}, {"lifting-mulmat", required_argument, NULL, 'L'}, - {"normal-form", required_argument, NULL, 'L'}, + {"normal-form", required_argument, NULL, 'n'}, {"output-file", required_argument, NULL, 'o'}, {"precision", required_argument, NULL, 'p'}, {"parametrization", required_argument, NULL, 'P'}, - {"random-seed", required_argument, seed, 1}, - {"reduced-gb", required_argument, NULL, 'r'}, + {"random-seed", required_argument, &random_seed_flag, 1}, + {"reduce-gb", required_argument, NULL, 'r'}, {"threads", required_argument, NULL, 't'}, {"verbose", required_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, @@ -222,10 +262,12 @@ static void getoptions( } switch(opt) { - case 0: - /* no short equivalent */ - if (*seed < 0) { - *seed = 0; + case 0: /* no short option equivalent */ + if (random_seed_flag == 1) { + *seed = strtol(optarg, NULL, 10); + if (*seed < 0) { + *seed = 0; + } } break; case 'N': From 842ea038cef3d609b846509db68c44cb5cdaa0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Wed, 7 Jan 2026 15:35:46 +0100 Subject: [PATCH 09/14] allows negative random-seed, clean code --- src/msolve/main.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index e0dcd1d3..4baf6f13 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -265,9 +265,6 @@ static void getoptions( case 0: /* no short option equivalent */ if (random_seed_flag == 1) { *seed = strtol(optarg, NULL, 10); - if (*seed < 0) { - *seed = 0; - } } break; case 'N': @@ -404,12 +401,6 @@ static void getoptions( *normal_form_matrix = 0; } break; - /* case 'a': */ - /* *seed = strtol(optarg, NULL, 10); */ - /* if (*seed < 0) { */ - /* *seed = 0; */ - /* } */ - /* break; */ default: errflag++; break; From 3ee43321c5a45f52d8c3f0344c694d2d8d645f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Wed, 7 Jan 2026 15:40:59 +0100 Subject: [PATCH 10/14] update doc for long options --- doc/msolve-tutorial.tex | 43 ++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/doc/msolve-tutorial.tex b/doc/msolve-tutorial.tex index ee88287a..7a89e182 100644 --- a/doc/msolve-tutorial.tex +++ b/doc/msolve-tutorial.tex @@ -1091,36 +1091,39 @@ \section{Saturation and colon ideals}\label{sec:f4sat} \section{More flags and options}\label{sec:flags} \begin{itemize} -\item The flag \verb+-h+ displays some documentation +\item The flag \verb+-h+ or \verb+--help+ displays some documentation -\item The flag \verb+-v + controls the verbosity +\item The flag \verb+-v + or \verb+--verbose + controls the verbosity \hfill \verb+Default value: 0+ -\item The flag \verb+-t + controls the number of threads used +\item The flag \verb+-t + or \verb+--threads + + controls the number of threads used \hfill \verb+Default value: 1+ -\item The flag \verb+-p + controls the binary precision of the output of the - univariate real root - solver (default value may be automatically increased by \msolve when needed). - - \hfill \verb+Default value:128+ -\item The flag \verb+-g + tells \msolve to output the leading monomial of +\item The flag \verb+-p + or \verb+--precision + controls the binary + precision of the output of the + univariate real root + solver (default value may be automatically increased by \msolve when needed). + + \hfill \verb+Default value:128+ +\item The flag \verb+-g + or \verb+--groebner-basis+ tells \msolve to output + the leading monomial of the ideal generated by the input polynomials (when \verb++ is \verb+1+) or the minimal reduced Gr\"obner basis (when \verb++ is \verb+2+ and a prime characteristic is indicated). - + \hfill \verb+Default value:0+ -\item The flag \verb+-P + tells \msolve to output the -rational parametrization computed for solving zero-dimensional polynomial -systems (those with finitely many solutions in an algebraic closure of the base field). -When \verb+-P 0+ is set, such a parametrization is not returned, when \verb+-P 1+ is -set, the parametrization is returned and, in the charactersitic zero case (rational -coefficients), real solutions are returned, when \verb+-P 2+ is set, only the -rational parametrization is returned. - +\item The flag \verb+-P + or \verb+--precision + tells \msolve to output the + rational parametrization computed for solving zero-dimensional polynomial + systems (those with finitely many solutions in an algebraic closure of the base field). + When \verb+-P 0+ is set, such a parametrization is not returned, when \verb+-P 1+ is + set, the parametrization is returned and, in the charactersitic zero case (rational + coefficients), real solutions are returned, when \verb+-P 2+ is set, only the + rational parametrization is returned. + \hfill \verb+Default value:0+ @@ -1144,10 +1147,10 @@ \section{More flags and options}\label{sec:flags} \hfill \verb+Default value:2+ -\item The flag \verb+-a + tells \msolve which seed must be used +\item The flag \verb+--random-seed + tells \msolve which seed must be used to initialize the pseudo-random generator: \verb+0+ means that \verb+time(0)+ is used so that the seed is based on current time, - otherwise, for any positive integer \verb+N+, \verb+N+ will be the seed. The + otherwise, for any integer \verb+N+, \verb+N+ will be the seed. The latter option is for debug purpose only as the lack of randomization can lead to failures on some input. From 4d31f965497af59f237ebf938487f2a4957c9965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Wed, 7 Jan 2026 16:24:39 +0100 Subject: [PATCH 11/14] seed is changed to uint32_t and some spaces are modified --- src/msolve/main.c | 8 ++++---- src/msolve/msolve.c | 50 ++++++++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index 4baf6f13..05805afc 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -219,7 +219,7 @@ static void getoptions( int32_t *refine, int32_t *isolate, int32_t *generate_pbm_files, - int32_t *seed, + uint32_t *seed, int32_t *info_level, files_gb *files){ int opt, errflag = 0, fflag = 1; @@ -264,7 +264,7 @@ static void getoptions( switch(opt) { case 0: /* no short option equivalent */ if (random_seed_flag == 1) { - *seed = strtol(optarg, NULL, 10); + *seed = strtoul(optarg, NULL, 10); } break; case 'N': @@ -456,7 +456,7 @@ int main(int argc, char **argv){ int32_t precision = 64; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ - int32_t seed = 0; + uint32_t seed = 0; files_gb *files = malloc(sizeof(files_gb)); if(files == NULL) exit(1); @@ -478,7 +478,7 @@ int main(int argc, char **argv){ srand(seed); if (info_level) { fprintf (stdout,"Initial seed for pseudo-random number generator "); - fprintf (stdout,"is %d\n",seed); + fprintf (stdout,"is %u\n",seed); } FILE *fh = fopen(files->in_file, "r"); diff --git a/src/msolve/msolve.c b/src/msolve/msolve.c index 05e1ad33..c4a9b6be 100644 --- a/src/msolve/msolve.c +++ b/src/msolve/msolve.c @@ -4420,7 +4420,7 @@ int core_msolve( real_roots_ptr, real_pts_ptr, gens, - initial_hts, unstable_staircase, nr_threads, max_pairs, + initial_hts, unstable_staircase, nr_threads, max_pairs, elim_block_len, update_ht, la_option, use_signatures, lift_matrix, &init_primes, info_level, print_gb, @@ -5201,30 +5201,30 @@ int core_msolve( if (oldminpolydeg == -1 || oldminpolydeg < minpolydeg) { oldminpolydeg = minpolydeg; // need to run a 2nd time } else if (oldminpolydeg == minpolydeg) { - /* same degree for both random linear forms */ - if (info_level > 0) { - printf ("\nRestarting with a non-random linear form"); - } - /* set back the base coefficient to its previous form - before introducing the random linear form. - Only for value larger than 1 - */ - if (gens->linear_form_base_coef > 1) { - gens->linear_form_base_coef--; - } - /* set back the base coefficient to the - original one if a non random linear form had - been introduced before. - Only for value larger than 1 - */ - if (gens->linear_form_base_coef > 1) { - gens->linear_form_base_coef--; - } - /* set back the random linear form flag to 0 */ - gens->rand_linear=0; - if (add_linear_form_to_input_system(gens, info_level)) { - goto restart; - } + /* same degree for both random linear forms */ + if (info_level > 0) { + printf ("\nRestarting with a non-random linear form"); + } + /* set back the base coefficient to its previous form + before introducing the random linear form. + Only for value larger than 1 + */ + if (gens->linear_form_base_coef > 1) { + gens->linear_form_base_coef--; + } + /* set back the base coefficient to the + original one if a non random linear form had + been introduced before. + Only for value larger than 1 + */ + if (gens->linear_form_base_coef > 1) { + gens->linear_form_base_coef--; + } + /* set back the random linear form flag to 0 */ + gens->rand_linear=0; + if (add_linear_form_to_input_system(gens, info_level)) { + goto restart; + } } /* else oldminpolydeg > minpoly deg so need to run another 2nd time */ minpolydeg = -1; From 3893e764e4e4c2cb86519ddbbfbaad38c6b042df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Wed, 7 Jan 2026 22:23:21 +0100 Subject: [PATCH 12/14] random-seed default behavior (based on time(0)) is now obtained with argument -1, any nonnegative 32-bit integer can be a seed now --- doc/msolve-tutorial.tex | 4 ++-- src/msolve/main.c | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/doc/msolve-tutorial.tex b/doc/msolve-tutorial.tex index 7a89e182..04eb0761 100644 --- a/doc/msolve-tutorial.tex +++ b/doc/msolve-tutorial.tex @@ -1148,9 +1148,9 @@ \section{More flags and options}\label{sec:flags} \hfill \verb+Default value:2+ \item The flag \verb+--random-seed + tells \msolve which seed must be used - to initialize the pseudo-random generator: \verb+0+ means that + to initialize the pseudo-random generator: \verb+-1+ means that \verb+time(0)+ is used so that the seed is based on current time, - otherwise, for any integer \verb+N+, \verb+N+ will be the seed. The + otherwise, for any nonnegetive integer \verb+N+, \verb+N+ will be the seed. The latter option is for debug purpose only as the lack of randomization can lead to failures on some input. diff --git a/src/msolve/main.c b/src/msolve/main.c index 05805afc..724b0d0d 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -168,8 +168,8 @@ static inline void display_help(char *str){ display_option_help_noopt("1 - yes.\n"); display_option_help('\0', "random_seed", "SEED", "Random seed to initialize the pseudo\n"); display_option_help_noopt("random generator\n"); - display_option_help_noopt("0 - time(0) will be used (default)\n"); - display_option_help_noopt("SEED > 0 - use at your own risks;\n"); + display_option_help_noopt("-1 - time(0) will be used (default)\n"); + display_option_help_noopt("SEED ≥ 0 - use at your own risks;\n"); display_option_help_noopt(" this is intended for developers and\n"); display_option_help_noopt(" debug purposes only\n"); display_option_help('r', "reduce-gb", "RED", "Reduce Groebner basis.\n"); @@ -219,7 +219,7 @@ static void getoptions( int32_t *refine, int32_t *isolate, int32_t *generate_pbm_files, - uint32_t *seed, + int64_t *seed, int32_t *info_level, files_gb *files){ int opt, errflag = 0, fflag = 1; @@ -264,7 +264,7 @@ static void getoptions( switch(opt) { case 0: /* no short option equivalent */ if (random_seed_flag == 1) { - *seed = strtoul(optarg, NULL, 10); + *seed = strtol(optarg, NULL, 10); } break; case 'N': @@ -456,7 +456,7 @@ int main(int argc, char **argv){ int32_t precision = 64; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ - uint32_t seed = 0; + int64_t seed = -1; files_gb *files = malloc(sizeof(files_gb)); if(files == NULL) exit(1); @@ -472,13 +472,16 @@ int main(int argc, char **argv){ &seed, &info_level, files); /* srand initialization */ - if (seed == 0) { - seed = time(0); + uint32_t true_seed; + if (seed < 0) { + true_seed = time(0); + } else { + true_seed = (int32_t) seed; } - srand(seed); + srand(true_seed); if (info_level) { fprintf (stdout,"Initial seed for pseudo-random number generator "); - fprintf (stdout,"is %u\n",seed); + fprintf (stdout,"is %u\n",true_seed); } FILE *fh = fopen(files->in_file, "r"); From b7d1d1a990f17b5b9cadaf0803fa044e28c4dd22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Berthomieu?= Date: Thu, 8 Jan 2026 10:22:53 +0100 Subject: [PATCH 13/14] correcting typo strtoll for int64_t random-seed --- src/msolve/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index 724b0d0d..28c295ae 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -264,7 +264,7 @@ static void getoptions( switch(opt) { case 0: /* no short option equivalent */ if (random_seed_flag == 1) { - *seed = strtol(optarg, NULL, 10); + *seed = strtoll(optarg, NULL, 10); } break; case 'N': From de702c0f24693ad6d66d297abb096330688be8c5 Mon Sep 17 00:00:00 2001 From: jerebertho <94358310+jerebertho@users.noreply.github.com> Date: Thu, 8 Jan 2026 11:58:36 +0100 Subject: [PATCH 14/14] Correcting cast from seed Co-authored-by: Vincent Neiger --- src/msolve/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/msolve/main.c b/src/msolve/main.c index 28c295ae..25d9bed0 100644 --- a/src/msolve/main.c +++ b/src/msolve/main.c @@ -476,7 +476,7 @@ int main(int argc, char **argv){ if (seed < 0) { true_seed = time(0); } else { - true_seed = (int32_t) seed; + true_seed = (uint32_t) seed; } srand(true_seed); if (info_level) {