{"id":25059890,"url":"https://github.com/stla/qspray","last_synced_at":"2025-04-14T14:24:34.588Z","repository":{"id":64683123,"uuid":"577334188","full_name":"stla/qspray","owner":"stla","description":"Multivariate polynomials with rational coefficients.","archived":false,"fork":false,"pushed_at":"2024-08-28T03:25:50.000Z","size":509,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T03:24:24.390Z","etag":null,"topics":["gmp","polynomials","r"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stla.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-12T14:06:06.000Z","updated_at":"2024-08-28T03:25:53.000Z","dependencies_parsed_at":"2024-02-22T13:28:28.244Z","dependency_job_id":"689ec560-e783-4247-b671-d9c2cff5f649","html_url":"https://github.com/stla/qspray","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqspray","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqspray/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqspray/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stla%2Fqspray/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stla","download_url":"https://codeload.github.com/stla/qspray/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248550619,"owners_count":21122934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gmp","polynomials","r"],"created_at":"2025-02-06T15:55:32.677Z","updated_at":"2025-04-14T14:24:34.555Z","avatar_url":"https://github.com/stla.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\ntitle: \"The 'qspray' package\"\noutput: github_document\n---\n\n\u003c!-- badges: start --\u003e\n[![R-CMD-check](https://github.com/stla/qspray/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/stla/qspray/actions/workflows/R-CMD-check.yaml)\n[![R-CMD-check-valgrind](https://github.com/stla/qspray/actions/workflows/R-CMD-check-valgrind.yaml/badge.svg)](https://github.com/stla/qspray/actions/workflows/R-CMD-check-valgrind.yaml)\n\u003c!-- badges: end --\u003e\n\n***R package to deal with multivariate polynomials with rational coefficients.***\n\n___\n\nThis package is strongly inspired by Robin Hankin's **spray** package. \nThe C++ implementations are very similar.\n\n```{r setup, include=FALSE}\nknitr::opts_chunk$set(echo = TRUE, collapse = TRUE, message = FALSE)\n```\n\n```{r}\nlibrary(qspray)\n```\n\nThe **qspray** package provides the `qspray` objects, which represent \nmultivariate polynomials whose coefficients are rational numbers.\n\n\n## Creating a `qspray` polynomial and arithmetic\n\nThe easiest way to build a multivariate polynomial with **qspray** is to start \nby introducing the generating variables with the help of the `qlone` function \nand then to combine them with arithmetic operations:\n\n```{r}\nx \u003c- qlone(1); y \u003c- qlone(2); z \u003c- qlone(3)\n( pol \u003c- 4*x^2 + \"1/2\"*y - 5*x*y*z/3 )\n```\n\nI often like to use a function like this:\n\n```{r}\nf \u003c- function(x, y, z) {\n  4*x^2 + y/2 - 5*x*y*z/3\n}\nf(x, y, z)\n```\n\nOr maybe you prefer to define the polynomial by giving it as a string:\n\n```{r}\nqsprayMaker(string = \"4 x^(2) + 1/2 x^(0, 1) - 5/3 x^(1, 1, 1)\")\n```\n\nAs you want, but this method is not highly robust. And it is not very easy to \nfigure out what is the monomial represented by a string such as `\"x^(i,j,k)\"`\n(this is `x^i*y^j*z^k`).\n\nSome arithmetic on this polynomial:\n\n```{r}\n-pol\n2 * pol\npol / 2\n\"5/3\" * pol\npol + 5\npol - gmp::as.bigq(\"2/5\")\npol^2\n```\n\nTwo polynomials can be added and multiplied:\n\n```{r}\npol1 \u003c- pol\npol2 \u003c- pol\npol1 + pol2\npol1 - pol2\npol1 * pol2\n```\n\n\n## Evaluating a `qspray` \n\nUse `evalQspray` to evaluate a polynomial for some values of the variables:\n\n```{r}\nevalQspray(pol, c(\"1\", \"2\", \"3/2\"))\n```\n\nAlternatively, you can convert the polynomial to a function:\n\n```{r}\ng \u003c- as.function(pol)\ng(\"1\", \"2\", \"3/2\")\n```\n\nYou can pass the strings you want as the arguments of this function:\n\n```{r}\ng(\"x\", \"y\", \"z\")\ng(\"x+1\", \"2*x\", \"y^2\")\n```\n\nThe output of `g(\"x+1\", \"2*x\", \"y^2\")` is the expression of a bivariate \npolynomial. You can get it as a `qspray` polynomial with the help of the \nfunction `changeVariables` (see section **Transforming a `qspray`**).\n\nIf you want a function returning numerical approximations, use the \noption `N=TRUE`:\n\n```{r}\nh \u003c- as.function(pol, N = TRUE)\nh(\"1\", \"2\", \"3/2\")\nh(\"x\", \"y\", \"z\")\nh(\"x+1\", \"2*x\", \"y^2\")\n```\n\n\nYou can also perform \"partial evaluation\" of a `qspray`, that is to say \nreplacing only certain variables. This is done by using the function\n`substituteQspray` and indicating the variables to be kept with `NA`:\n\n```{r}\nsubstituteQspray(pol, c(\"1\", NA, \"3/2\"))\nf(gmp::as.bigq(1), y, gmp::as.bigq(\"3/2\"))\ng(\"1\", \"y\", \"3/2\")\nh(\"1\", \"y\", \"3/2\")\n```\n\n\n## Showing a `qspray`\n\nYou can control the way of printing a `qspray` with the help of the function \n`showQsprayOption\u003c-`. By default, the monomials of a `qspray` are printed in\nthe style of `x^2.y.z^3` if there are no more than three variables, otherwise \nthey are printed in the style of `x1^2.x2.x3^3`: \n\n```{r}\nset.seed(3141)\n( qspray \u003c- rQspray() ) # a random qspray\nqspray + qlone(4)^99\n```\n\nIf you want to always use the second way, you can do:\n\n```{r}\nshowQsprayOption(qspray, \"x\") \u003c- \"x\"\nqspray\n```\n\nIf you want to restore the way `qspray` objects were printed in previous \nversions, you can do\n\n```{r}\nshowQsprayOption(qspray, \"showMonomial\") \u003c- showMonomialOld()\nqspray\n```\n\nThere are three possible show options that can be passed to \n`showQsprayOption`:\n\n- The most general show option is `\"showQspray\"`. A `showQspray` function, that \nis to say a function appropriate for the `\"showQspray\"` option, must be\na function which transforms a `qspray` to a string. The package provides \nsome helper functions to built such functions, like `showQsprayXYZ` and \n`showQsprayX1X2X3`. With `showQsprayXYZ`, you can choose the letters you want \nto denote the variables:\n\n```{r}\nf \u003c- showQsprayXYZ(c(\"A\", \"B\", \"C\"))\nf(qspray)\n```\n\nWith `showQsprayX1X2X3`, you choose only one letter for the variables and they\nwill be appended with a digit:\n\n```{r}\nf \u003c- showQsprayX1X2X3(\"X\")\nf(qspray)\n```\n\nOnce you have constructed such a function, you pass it as a show option by \ndoing `showQsprayOption(qspray, \"showQspray\") \u003c- f`.\n\n- The second possible show option is `\"showMonomial\"`, to control the way the \nmonomials are printed. Actually in the two above examples of `showQsprayXYZ` \nand `showQsprayX1X2X3` we only changed the way the monomials are printed. \nIndeed, these two commands are equivalent:\n```{r}\nshowQsprayOption(qspray, \"showQspray\") \u003c- showQsprayXYZ(c(\"A\", \"B\", \"C\"))\nshowQsprayOption(qspray, \"showMonomial\") \u003c- showMonomialXYZ(c(\"A\", \"B\", \"C\"))\n```\nand these two commands are equivalent as well:\n```{r}\nshowQsprayOption(qspray, \"showQspray\") \u003c- showQsprayX1X2X3(\"X\")\nshowQsprayOption(qspray, \"showMonomial\") \u003c- showMonomialX1X2X3(\"X\")\n```\nBut the `showQspray` functions allow finer control, e.g. they allow to control \nthe multiplication symbol which separates a coefficient and a monomial within a \nterm.\n\n- Finally there is the show option `\"x\"`. Setting this option to a letter `x`:\n```{r, eval=FALSE}\nshowQsprayOption(qspray, \"x\") \u003c- x\n```\nis equivalent to:\n```{r, eval=FALSE}\nshowQsprayOption(qspray, \"showMonomial\") \u003c- showMonomialX1X2X3(x)\n```\nBut `showMonomialX1X2X3` also allows to control the way the individual \npowers are collapsed, e.g. `\"x^2.y.z^3\"` (the default) or `\"x^2*y*z^3\"`, or \n`\"x^2yz^3\"`. If the dot is nice for you, use the `\"x\"` option, that's less code \nto type.\n\nBy the way, a `qspray` object is an S4 object with two slots: `powers` and \n`coeffs`. The `powers` slot is a list of vector of exponents and the `coeffs` \nslot is a character vector, whose each element is coercable to a `bigq` \nnumber by an application of the function `gmp::as.bigq`. The `showMonomial` \nfunctions act only on the `powers` slot.\n\nWhen an arithmetic operation is performed between two `qspray` objects, \nthe show options of the first one are passed to the result, *if possible*:\n\n```{r}\nqspray + qlone(4)^99\n```\n\nFor example, this is not possible if you specify only three letters \nfor the variables and you perform an operation with a `qspray` involving the \nfourth variable:\n\n```{r}\nshowQsprayOption(qspray, \"showMonomial\") \u003c- showMonomialXYZ(c(\"a\", \"b\", \"c\"))\nqspray\nqspray + qlone(4)^99\n```\n\n\n## Exact integration over a simplex\n\nThe package provides a function which returns the exact value of the \nintegral of a polynomial with rational coefficients over a simplex whose \nvertices have rational Cartesian coordinates:\n\n```{r}\n# variables\nx \u003c- qlone(1); y \u003c- qlone(2); z \u003c- qlone(3)\n# polynomial\nP \u003c- x^4 + y + 2*x*y^2 - 3*z\n# simplex (tetrahedron) vertices\nv1 \u003c- c(1, 1, 1)\nv2 \u003c- c(2, 2, 3)\nv3 \u003c- c(3, 4, 5)\nv4 \u003c- c(3, 2, 1)\n# simplex\nS \u003c- rbind(v1, v2, v3, v4)\n# integral\nintegratePolynomialOnSimplex(P, S)\n```\n\n\n## Transforming a `qspray` \n\nLet's take a `qspray` polynomial:\n\n```{r}\nf \u003c- function(x, y, z) {\n  4*x^2 + y/2 - 5*x*y*z/3\n}\nx \u003c- qlone(1); y \u003c- qlone(2); z \u003c- qlone(3)\nP \u003c- f(x, y, z)\n```\n\nYou can get a derivative of this polynomial:\n\n```{r}\nderivQspray(P, i = 2) # derivative w.r.t y\n```\n\nYou can permute the variables of this polynomial:\n\n```{r}\nswapVariables(P, 1, 3) == f(z, y, x)\n```\n\nYou can perform a change of variables on this polynomial:\n\n```{r}\nchangeVariables(P, list(x+1, 2*x, y^2)) == f(x+1, 2*x, y^2)\n```\n\n\n## Gröbner bases\n\nFinally, let us mention the `groebner` function, which computes a Gröbner \nbasis of the ideal generated by a list of `qspray` polynomials:\n\n```{r}\nf \u003c- qsprayMaker(string = \"x^(3) - 2 x^(1,1)\")\ng \u003c- qsprayMaker(string = \"x^(2,1) - 2 x^(0,2) + x^(1)\")\ngroebner(list(f, g))\n```\n\nAs an application of Gröbner bases, there is the function `isPolynomialOf`. \nThis function checks whether a polynomial can be obtained by \nsubstituting the variables of a polynomial with some given polynomials: given a\n`qspray` polynomial `Q` and some `qspray` polynomials `P1`, ..., `Pn`, does \nthere exist a polynomial function `f` such that `Q = f(P1, ..., Pn)`? If this \nis true, the `isPolynomialOf` function also returns `f`.\n\n\n## Packages using 'qspray'\n\nThere are packages depending on the **qspray** package (some of them are not \non CRAN yet):\n\n- [**polyhedralCubature**](https://github.com/stla/polyhedralCubature): this package uses the `integratePolynomialOnSimplex` function to get the exact integral of a multivariate polynomial over a polytope.\n\n- [**jack**](https://github.com/stla/jackR): Jack polynomials.\n\n- [**resultant**](https://github.com/stla/resultant): resultant, subresultants, and \ngreatest common divisor of two `qspray` polynomials.\n\n- [**ratioOfQsprays**](https://github.com/stla/ratioOfQsprays): fractions of \n`qspray` polynomials.\n\n- [**symbolicQspray**](https://github.com/stla/symbolicQspray): multivariate \npolynomials whose coefficients are `ratioOfQsprays` fractions of polynomials; \nthey represent multivariate polynomials with parameters.\n\n\n## Using the C++ code in another package\n\nThe three packages **jack**, **ratioOfQsprays** and **symbolicQspray** use some \nC++ code based on the header file of the C++ code of **qspray**. If you want \nto use it in your package too, include the following instruction in the \nDESCRIPTION file:\n\n```yaml\nLinkingTo: Rcpp, RcppArmadillo, qspray\n```\n\nAnd include the following instruction in your C++ code:\n\n```cpp\n#include \"qspray.h\"\n```\n\nThen you can use the **qspray** header file in your C++ code by using the\nnamespace `QSPRAY`.\n\nThe header file provides the templated class `Qspray`. An object of type \n`Qspray\u003cT\u003e` represents a multivariate polynomials whose coefficients are \nrepresented by the objects of the type `T`. For example, multivariate \npolynomials with numeric coefficients can be represented by the objects of \ntype `Qspray\u003cdouble\u003e` (so I should have chosen another name since `Q` is here \nto indicate the field of rational numbers). The class `Qspray` provides the\noperators `==`, `!=`, `+`, `-`, `*` and the power for the objects of type\n`Qspray\u003cT\u003e` as long as the operators `==`, `!=`, `+`, `-` and `*` are available\nfor the type `T`. So you don't have to implement the comparison operators nor\nthe arithmetic operations for the `Qspray\u003cdouble\u003e` polynomials if you \ninstantiate this type. The class `Qspray` also provides a function to \ncalculate derivatives. This class is included in the namespace `QSPRAY` which \nalso includes a function performing the division of two multivariate \npolynomials but it is restricted to polynomials with rational coefficients.\nAnyway it would not be a good idea to use the algorithm performed by this \nfunction for polynomials whose coefficients type is not an \"exact type\", \nsuch as `double`. If you want to use `Qspray\u003cT\u003e` with an exact type `T` and \nif you need the division, send me a few words about your use case and I will \nsee whether I can help. I will probably remove the division from the namespace \n`QSPRAY`. I originally included it to use it in the **ratioOfQsprays** \npackage, but I finally used the division provided by the **CGAL** library \ninstead, which is faster.\n\nA few words about the implementation. The class `Qspray\u003cT\u003e` has only one \nmember object: an object of type `Polynomial\u003cT\u003e`, which is an alias of \nthe type `std::unordered_map\u003cstd::vector\u003cint\u003e, T\u003e` (plus a template argument \nfor the hasher). So a `Polynomial\u003cT\u003e` object is a map whose keys are \n`std::vector\u003cint\u003e` objects and whose values are `T` objects. An element of this \nmap represents a term of the polynomial: a key represents a monomial, e.g. the\nvector `{2,1,3}` represents the monomial `x^2*y*z^3`, and the value attached to\nthis key represents the coefficient of this monomial.\nThis way to represent a multivariate polynomial has been copied from Robin \nHankin's **spray** package, without which the **qspray** package would have \nnever existed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstla%2Fqspray","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstla%2Fqspray","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstla%2Fqspray/lists"}