RANDPOLY.TEX 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. \documentstyle[11pt]{article}
  2. \title{RANDPOLY: A Random Polynomial Generator}
  3. \author{Francis J. Wright \\
  4. School of Mathematical Sciences \\
  5. Queen Mary and Westfield College \\
  6. University of London \\
  7. Mile End Road, London E1 4NS, UK. \\
  8. Email: {\tt F.J.Wright@QMW.ac.uk}}
  9. \date{14 July 1994}
  10. \begin{document}
  11. \maketitle
  12. \begin{abstract}
  13. This package is based on a port of the Maple random polynomial
  14. generator together with some support facilities for the generation
  15. of random numbers and anonymous procedures.
  16. \end{abstract}
  17. \section{Introduction}
  18. The operator {\tt randpoly} is based on a port of the Maple random
  19. polynomial generator. In fact, although by default it generates a
  20. univariate or multivariate polynomial, in its most general form it
  21. generates a sum of products of arbitrary integer powers of the
  22. variables multiplied by arbitrary coefficient expressions, in which
  23. the variable powers and coefficient expressions are the results of
  24. calling user-supplied functions (with no arguments). Moreover, the
  25. ``variables'' can be arbitrary expressions, which are composed with
  26. the underlying polynomial-like function.
  27. The user interface, code structure and algorithms used are essentially
  28. identical to those in the Maple version. The package also provides an
  29. analogue of the Maple {\tt rand} random-number-generator generator,
  30. primarily for use by {\tt randpoly}. There are principally two
  31. reasons for translating these facilities rather than designing
  32. comparable facilites anew: (1) the Maple design seems satisfactory and
  33. has already been ``proven'' within Maple, so there is no good reason
  34. to repeat the design effort; (2) the main use for these facilities is
  35. in testing the performance of other algebraic code, and there is an
  36. advantage in having essentially the same test data generator
  37. implemented in both Maple and REDUCE\@. Moreover, it is interesting
  38. to see the extent to which a facility can be translated without change
  39. between two systems. (This aspect will be described elsewhere.)
  40. Sections \ref{sec:Basic} and \ref{sec:Advanced} describe respectively
  41. basic and more advanced use of {\tt randpoly}; \S\ref{sec:Subsidiary}
  42. describes subsidiary functions provided to support advanced use of
  43. {\tt randpoly}; \S\ref{sec:Examples} gives examples; an appendix gives
  44. some details of the only non-trivial algorithm, that used to compute
  45. random sparse polynomials. Additional examples of the use of {\tt
  46. randpoly} are given in the test and demonstration file {\tt
  47. randpoly.tst}.
  48. \section{Basic use of {\tt randpoly}}
  49. \label{sec:Basic}
  50. The operator {\tt randpoly} requires at least one argument
  51. corresponding to the polynomial variable or variables, which must be
  52. either a single expression or a list of expressions.%
  53. \footnote{If it is a single expression then the univariate code is
  54. invoked; if it is a list then the multivariate code is invoked, and in
  55. the special case of a list of one element the multivariate code is
  56. invoked to generate a univariate polynomial, but the result should be
  57. indistinguishable from that resulting from specifying a single
  58. expression not in a list.} %
  59. In effect, {\tt randpoly} replaces each input expression by an
  60. internal variable and then substitutes the input expression for the
  61. internal variable in the generated polynomial (and by default expands
  62. the result as usual), although in fact if the input expression is a
  63. REDUCE kernel then it is used directly. The rest of this document
  64. uses the term ``variable'' to refer to a general input expression or
  65. the internal variable used to represent it, and all references to the
  66. polynomial structure, such as its degree, are with respect to these
  67. internal variables. The actual degree of a generated polynomial might
  68. be different from its degree in the internal variables.
  69. By default, the polynomial generated has degree 5 and contains 6
  70. terms. Therefore, if it is univariate it is dense whereas if it is
  71. multivariate it is sparse.
  72. \subsection{Optional arguments}
  73. Other arguments can optionally be specified, in any order, after the
  74. first compulsory variable argument. All arguments receive full
  75. algebraic evaluation, subject to the current switch settings etc. The
  76. arguments are processed in the order given, so that if more than one
  77. argument relates to the same property then the last one specified
  78. takes effect. Optional arguments are either keywords or equations
  79. with keywords on the left.
  80. In general, the polynomial is sparse by default, unless the keyword
  81. {\tt dense} is specified as an optional argument. (The keyword {\tt
  82. sparse} is also accepted, but is the default.) The default degree can
  83. be changed by specifying an optional argument of the form
  84. \begin{center}
  85. {\tt degree = {\it natural number}}.
  86. \end{center}
  87. In the multivariate case this is the total degree, i.e.\ the sum of
  88. the degrees with respect to the individual variables. The keywords
  89. {\tt deg} and {\tt maxdeg} can also be used in place of {\tt degree}.
  90. More complicated monomial degree bounds can be constructed by using
  91. the coefficient function described below to return a monomial or
  92. polynomial coefficient expression. Moreover, {\tt randpoly} respects
  93. internally the REDUCE ``asymptotic'' commands {\tt let}, {\tt weight}
  94. etc.\ described in \S10.4 of the \REDUCE 3.6 manual, which can be used
  95. to exercise additional control over the polynomial generated.
  96. In the sparse case (only), the default maximum number of terms
  97. generated can be changed by specifying an optional argument of the
  98. form
  99. \begin{center}
  100. {\tt terms = {\it natural number}}.
  101. \end{center}
  102. The actual number of terms generated will be the minimum of the value
  103. of {\tt terms} and the number of terms in a dense polynomial of the
  104. specified degree, number of variables, etc.
  105. \section{Advanced use of {\tt randpoly}}
  106. \label{sec:Advanced}
  107. The default order (or minimum or trailing degree) can be changed by
  108. specifying an optional argument of the form
  109. \begin{center}
  110. {\tt ord = {\it natural number}}.
  111. \end{center}
  112. The keyword is {\tt ord} rather than {\tt order} because {\tt order}
  113. is a reserved command name in REDUCE\@. The keyword {\tt mindeg} can
  114. also be used in place of {\tt ord}. In the multivariate case this is
  115. the total degree, i.e.\ the sum of the degrees with respect to the
  116. individual variables. The order normally defaults to 0.
  117. However, the input expressions to {\tt randpoly} can also be
  118. equations, in which case the order defaults to 1 rather than 0. Input
  119. equations are converted to the difference of their two sides before
  120. being substituted into the generated polynomial. The purpose of this
  121. facility is to easily generate polynomials with a specified zero -- for
  122. example
  123. \begin{center}\tt
  124. randpoly(x = a);
  125. \end{center}
  126. generates a polynomial that is guaranteed to vanish at $x = a$, but is
  127. otherwise random.
  128. Order specification and equation input are extensions of the current
  129. Maple version of {\tt randpoly}.
  130. The operator {\tt randpoly} accepts two further optional arguments in
  131. the form of equations with the keywords {\tt coeffs} and {\tt expons}
  132. on the left. The right sides of each of these equations must evaluate
  133. to objects that can be applied as functions of no variables. These
  134. functions should be normal algebraic procedures (or something
  135. equivalent); the {\tt coeffs} procedure may return any algebraic
  136. expression, but the {\tt expons} procedure must return an integer
  137. (otherwise {\tt randpoly} reports an error). The values returned by
  138. the functions should normally be random, because it is the randomness
  139. of the coefficients and, in the sparse case, of the exponents that
  140. makes the constructed polynomial random.
  141. A convenient special case is to use the function {\tt rand} on the
  142. right of one or both of these equations; when called with a single
  143. argument {\tt rand} returns an anonymous function of no variables that
  144. generates a random integer. The single argument of {\tt rand} should
  145. normally be an integer range in the form $a~..~b$, where $a$, $b$ are
  146. integers such that $a < b$. The spaces around (or at least before)
  147. the infix operator ``..'' are necessary in some cases in REDUCE and
  148. generally recommended. For example, the {\tt expons} argument might
  149. take the form
  150. \begin{center}\tt
  151. expons = rand(0~..~n)
  152. \end{center}
  153. where {\tt n} will be the maximum degree with respect to each variable
  154. {\em independently}. In the case of {\tt coeffs} the lower limit will
  155. often be the negative of the upper limit to give a balanced
  156. coefficient range, so that the {\tt coeffs} argument might take the
  157. form
  158. \begin{center}\tt
  159. coeffs = rand(-n~..~n)
  160. \end{center}
  161. which will generate random integer coefficients in the range $[-n,n]$.
  162. \section{Subsidiary functions: rand, proc, random}
  163. \label{sec:Subsidiary}
  164. \subsection{Rand: a random-number-generator generator}
  165. The first argument of {\tt rand} must be either an integer range in
  166. the form $a~..~b$, where $a$, $b$ are integers such that $a < b$, or a
  167. positive integer $n$ which is equivalent to the range $0~..~n-1$. The
  168. operator {\tt rand} constructs a function of no arguments that calls
  169. the REDUCE random number generator function {\tt random} to return a
  170. random integer in the range specified; in the case that the first
  171. argument of {\tt rand} is a single positive integer $n$ the function
  172. constructed just calls {\tt random($n$)}, otherwise the call of {\tt
  173. random} is scaled and shifted.
  174. As an additional convenience, if {\tt rand} is called with a second
  175. argument that is an identifier then the call of {\tt rand} acts
  176. exactly like a procedure definition with the identifier as the
  177. procedure name. The procedure generated can then be called with an
  178. empty argument list by the algebraic processor.
  179. [Note that {\tt rand()} with no argument is an error in REDUCE and
  180. does not return directly a random number in a default range as it does
  181. in Maple -- use instead the REDUCE function {\tt random} (see below).]
  182. \subsection{Proc: an anonymous procedure generator}
  183. The operator {\tt proc} provides a generalization of {\tt rand}, and
  184. is primarily intended to be used with expressions involving the {\tt
  185. random} function (see below). Essentially, it provides a mechanism to
  186. prevent functions such as {\tt random} being evaluated when the
  187. arguments to {\tt randpoly} are evaluated, which is too early. {\tt
  188. Proc} accepts a single argument which is converted into the body of an
  189. anonymous procedure, which is returned as the value of {\tt proc}.
  190. (If a named procedure is required then the normal REDUCE {\tt
  191. procedure} statement should be used instead.) Examples are given in
  192. the following sections, and in the file {\tt randpoly.tst}.
  193. \subsection{Random: a generalized interface}
  194. As an additional convenience, this package extends the interface to
  195. the standard REDUCE {\tt random} function so that it will directly
  196. accept either a natural number or an integer range as its argument,
  197. exactly as for the first argument of {\tt rand}. Hence effectively
  198. \begin{center}\tt
  199. rand(X) = proc random(X)
  200. \end{center}
  201. although {\tt rand} is marginally more efficient. However, {\tt proc}
  202. and the generalized {\tt random} interface allow expressions such as
  203. the following anonymous random fraction generator to be easily
  204. constructed:
  205. \begin{center}\tt
  206. proc(random(-99~..~99)/random(1~..~99))
  207. \end{center}
  208. \subsection{Further support for procs}
  209. {\tt Rand} is a special case of {\tt proc}, and (for either) if the
  210. switch {\tt comp} is {\tt on} (and the compiler is available) then the
  211. generated procedure body is compiled.
  212. {\tt Rand} with a single argument and {\tt proc} both return as their
  213. values anonymous procedures, which if they are not compiled are Lisp
  214. lambda expressions. However, if compilation is in effect then they
  215. return only an identifier that has no external significance%
  216. \footnote{It is not interned on the oblist.} %
  217. but which can be applied as a function in the same way as a lambda
  218. expression.
  219. It is primarily intended that such ``proc expressions'' will be used
  220. immediately as input to {\tt randpoly}. The algebraic processor is
  221. not intended to handle lambda expressions. However, they can be
  222. output or assigned to variables in algebraic mode, although the output
  223. form looks a little strange and is probably best not displayed. But
  224. beware that lambda expressions cannot be evaluated by the algebraic
  225. processor (at least, not without declaring some internal Lisp
  226. functions to be algebraic operators). Therefore, for testing purposes
  227. or curious users, this package provides the operators {\tt showproc}
  228. and {\tt evalproc} respectively to display and evaluate ``proc
  229. expressions'' output by {\tt rand} or {\tt proc} (or in fact any
  230. lambda expression), in the case of {\tt showproc} provided they are
  231. not compiled.
  232. \section{Examples}
  233. \label{sec:Examples}
  234. The file {\tt randpoly.tst} gives a set of test and demonstration
  235. examples.
  236. The following additional examples were taken from the Maple {\tt
  237. randpoly} help file and converted to REDUCE syntax by replacing [~] by
  238. \{~\} and making the other changes shown explicitly:
  239. \begin{verbatim}
  240. randpoly(x);
  241. 5 4 3 2
  242. - 54*x - 92*x - 30*x + 73*x - 69*x - 67
  243. randpoly({x, y}, terms = 20);
  244. 5 4 4 3 2 3 3
  245. 31*x - 17*x *y - 48*x - 15*x *y + 80*x *y + 92*x
  246. 2 3 2 2 4 3 2
  247. + 86*x *y + 2*x *y - 44*x + 83*x*y + 85*x*y + 55*x*y
  248. 5 4 3 2
  249. - 27*x*y + 33*x - 98*y + 51*y - 2*y + 70*y - 60*y - 10
  250. randpoly({x, sin(x), cos(x)});
  251. 4 3 3
  252. sin(x)*( - 4*cos(x) - 85*cos(x) *x + 50*sin(x)
  253. 2
  254. - 20*sin(x) *x + 76*sin(x)*x + 96*sin(x))
  255. % randpoly(z, expons = rand(-5..5)); % Maple
  256. % A generalized random "polynomial"!
  257. % Note that spaces are needed around .. in REDUCE.
  258. on div; off allfac;
  259. randpoly(z, expons = rand(-5 .. 5));
  260. 4 3 -3 -4 -5
  261. - 39*z + 14*z - 77*z - 37*z - 8*z
  262. off div; on allfac;
  263. % randpoly([x], coeffs = proc() randpoly(y) end); % Maple
  264. randpoly({x}, coeffs = proc randpoly(y));
  265. 5 5 5 4 5 3 5 2 5 5
  266. 95*x *y - 53*x *y - 78*x *y + 69*x *y + 58*x *y - 58*x
  267. 4 5 4 4 4 3 4 2 4
  268. + 64*x *y + 93*x *y - 21*x *y + 24*x *y - 13*x *y
  269. 4 3 5 3 4 3 3 3 2
  270. - 28*x - 57*x *y - 78*x *y - 44*x *y + 37*x *y
  271. 3 3 2 5 2 4 2 3 2 2
  272. - 64*x *y - 95*x - 71*x *y - 69*x *y - x *y - 49*x *y
  273. 2 2 5 4 3 2
  274. + 77*x *y + 48*x + 38*x*y + 93*x*y - 65*x*y - 83*x*y
  275. 5 4 3 2
  276. + 25*x*y + 51*x + 35*y - 18*y - 59*y + 73*y - y + 31
  277. % A more conventional alternative is ...
  278. % procedure r; randpoly(y)$ randpoly({x}, coeffs = r);
  279. % or, in fact, equivalently ...
  280. % randpoly({x}, coeffs = procedure r; randpoly(y));
  281. randpoly({x, y}, dense);
  282. 5 4 4 3 2 3 3
  283. 85*x + 43*x *y + 68*x + 87*x *y - 93*x *y - 20*x
  284. 2 2 2 2 4 3 2
  285. - 74*x *y - 29*x *y + 7*x + 10*x*y + 62*x*y - 86*x*y
  286. 5 4 3 2
  287. + 15*x*y - 97*x - 53*y + 71*y - 46*y - 28*y + 79*y + 44
  288. \end{verbatim}
  289. \appendix
  290. \newfont{\SYM}{msbm10 scaled\magstephalf} % AMS "blackboard bold" etc
  291. \newcommand{\N}{\mbox{\SYM N}} %%% {{\bf N}}
  292. \newcommand{\th}{\mbox{$^{\it th}$}}
  293. \newtheorem{prop}{Proposition}
  294. \newenvironment{proof}%
  295. {\par\addvspace\baselineskip\noindent{\bf Proof~}}%
  296. {\hspace*{\fill}$\Box$\par\addvspace\baselineskip}
  297. \section{Algorithmic background}
  298. The only part of this package that involves any mathematics that is
  299. not completely trivial is the procedure to generate a sparse set of
  300. monomials of specified maximum and minimum total degrees in a
  301. specified set of variables. This involves some combinatorics, and the
  302. Maple implementation calls some procedures from the Maple
  303. Combinatorial Functions Package {\tt combinat} (of which I have
  304. implemented restricted versions in REDUCE).
  305. Given the maximum possible number $N$ of terms (in a dense
  306. polynomial), the required number of terms (in the sparse polynomial)
  307. is selected as a random subset of the natural numbers up to $N$, where
  308. each number indexes a term. In the univariate case these indices are
  309. used directly as monomial exponents, but in the multivariate case they
  310. are converted to monomial exponent vectors using a lexicographic
  311. ordering.
  312. \subsection{Numbers of polynomial terms}
  313. By explicitly enumerating cases with 1, 2, etc.\ variables, as
  314. indicated by the inductive proof below, one deduces that:
  315. \begin{prop}
  316. In $n$ variables, the number of distinct monomials having total
  317. degree precisely $r$ is $^{r+n-1}C_{n-1}$, and the maximum number of
  318. distinct monomials in a polynomial of maximum total degree $d$ is
  319. $^{d+n}C_n$.
  320. \end{prop}
  321. \begin{proof}
  322. Suppose the first part of the proposition is true, namely that there
  323. are at most
  324. \[
  325. N_h(n,r) = {}^{r+n-1}C_{n-1}
  326. \]
  327. distinct monomials in an $n$-variable {\em homogeneous\/}
  328. polynomial of total degree $r$. Then there are at most
  329. \[
  330. N(d,r) = \sum_{r=0}^d {}^{r+n-1}C_{n-1} = {}^{d+n}C_n
  331. \]
  332. distinct monomials in an $n$-variable polynomial of maximum total
  333. degree $d$.
  334. The sum follows from the fact that
  335. \[
  336. {}^{r+n}C_n = \frac{(r+n)^{\underline n}}{n!}
  337. \]
  338. where $x^{\underline n} = x(x-1)(x-2)\cdots(x-n+1)$ denotes a
  339. falling factorial, and
  340. \[
  341. \sum_{a \leq x < b} x^{\underline n} =
  342. \left. \frac{x^{\underline{n+1}}}{n+1} \right|_a^b.
  343. \]
  344. (See, for example, D. H. Greene \& D. E. Knuth, {\it Mathematics
  345. for the Analysis of Algorithms}, Birkh\"auser, Second Edn.\ 1982,
  346. equation (1.37)). Hence the second part of the proposition follows
  347. from the first.
  348. The proposition holds for 1 variable ($n = 1$), because there is
  349. clearly 1 distinct monomial of each degree precisely $r$ and hence
  350. at most $d+1$ distinct monomials in a polynomial of maximum degree
  351. $d$.
  352. Suppose that the proposition holds for $n$ variables, which are
  353. represented by the vector $X$. Then a homogeneous polynomial of
  354. degree $r$ in the $n+1$ variables $X$ together with the single
  355. variable $x$ has the form
  356. \[
  357. x^r P_0(X) + x^{r-1} P_1(X) + \cdots + x^0 P_r(X)
  358. \]
  359. where $P_s(X)$ represents a polynomial of maximum total degree $s$
  360. in the $n$ variables $X$, which therefore contains at most
  361. $^{s+n}C_n$ distinct monomials. The homogeneous polynomial of
  362. degree $r$ in $n+1$ terms therefore contains at most
  363. \[
  364. \sum_{s=0}^r {}^{s+n}C_n = {}^{r+n+1}C_{n+1}
  365. \]
  366. distinct monomials.
  367. Hence the proposition holds for $n+1$ variables, and therefore by
  368. induction it holds for all $n$.
  369. \end{proof}
  370. \subsection{Mapping indices to exponent vectors}
  371. The previous proposition is also the basis of the algorithm to map
  372. term indices $m \in \N$ to exponent vectors $v \in \N^n$, where $n$ is
  373. the number of variables.
  374. Define a norm $\|\cdot\|$ on exponent vectors by $\|v\| = \sum_{i=1}^n
  375. v_i$, which corresponds to the total degree of the monomial. Then,
  376. from the previous proposition, the number of exponent vectors of
  377. length $n$ with norm $\|v\| \leq d$ is $N(n,d) = {}^{d+n}C_n$. The
  378. elements of the $m\th$ exponent vector are constructed recursively by
  379. applying the algorithm to successive tail vectors, so let a subscript
  380. denote the length of the vector to which a symbol refers.
  381. The aim is to compute the vector of length $n$ with index $m = m_n$.
  382. If this vector has norm $d_n$ then the index and norm must satisfy
  383. \[
  384. N(n,d_n-1) \leq m_n < N(n,d_n),
  385. \]
  386. which can be used (as explained below) to compute $d_n$ given $n$ and
  387. $m_n$. Since there are $N(n,d_n-1)$ vectors with norm less than
  388. $d_n$, the index of the $(n-1)$-element tail vector must be given by
  389. $m_{n-1} = m_n - N(n,d_n-1)$, which can be used recursively to compute
  390. the norm $d_{n-1}$ of the tail vector. From this, the first element
  391. of the exponent vector is given by $v_1 = d_n - d_{n-1}$.
  392. The algorithm therefore has a natural recursive structure that
  393. computes the norm of each tail subvector as the recursion stack is
  394. built up, but can only compute the first term of each tail subvector
  395. as the recursion stack is unwound. Hence, it constructs the exponent
  396. vector from right to left, whilst being applied to the elements from
  397. left to right. The recursion is terminated by the observation that
  398. $v_1 = d_1 = m_1$ for an exponent vector of length $n = 1$.
  399. The main sub-procedure, given the required length $n$ and index $m_n$
  400. of an exponent vector, must return its norm $d_n$ and the index of its
  401. tail subvector of length $n-1$. Within this procedure, $N(n,d)$ can
  402. be efficiently computed for values of $d$ increasing from 0, for which
  403. $N(n,0) = {}^nC_n = 1$, until $N(n,d) > m$ by using the observation
  404. that
  405. \[
  406. N(n,d) = {}^{d+n}C_n = \frac{(d+n)(d-1+n)\cdots(1+n)}{d!}.
  407. \]
  408. \end{document}