-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.Rmd
254 lines (192 loc) · 6.85 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
---
title: "The 'ratioOfQsprays' package"
author: "Stéphane Laurent"
date: "`r Sys.Date()`"
output: github_document
---
***Fractions of multivariate polynomials with rational coefficients.***
<!-- badges: start -->
[![R-CMD-check](https://github.com/stla/ratioOfQsprays/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/stla/ratioOfQsprays/actions/workflows/R-CMD-check.yaml)
<!-- badges: end -->
___
The [**qspray** package](https://github.com/stla/qspray) allows arithmetic
(and more) on multivariate polynomials with rational coefficients. Based on
this one, the **ratioOfQsprays** package allows to manipulate *fractions* of
multivariate polynomials with rational coefficients.
These notes about the **ratioOfQsprays** package assume that the reader is a
bit familiar with the **qspray** package.
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = TRUE, message = FALSE)
```
## Creating a `ratioOfQsprays`
A `ratioOfQsprays` object represents a fraction of two multivariate
polynomials with rational coefficients. Such polynomials are represented by
`qspray` objects. The easiest way to create a `ratioOfQsprays` is to introduce
the variables of the polynomials with the `qlone` function (from the **qspray**
package), and then to build a `qspray` numerator and a `qspray` denominator
with the arithmetic operations. For example:
```{r}
library(ratioOfQsprays)
f <- function(x1, x2, x3) {
(2*x1^2 + x2*x3) / (4*x1 - 3*x3 + 1)
}
# variables:
x1 <- qlone(1)
x2 <- qlone(2)
x3 <- qlone(3)
# the 'ratioOfQsprays':
( roq <- f(x1, x2, x3) )
```
The denominator of a `ratioOfQsprays` fraction of polynomials is always *monic*.
That means it is a polynomial whose leading coefficient is 1.
Arithmetic on `ratioOfQsprays` objects is available:
```{r}
roq^2
roq - roq
1 / roq
2*roq + (x2 + x3)/x1
```
You don't like my quotient bar `%//%`? Be patient, we will see how to change
it later. I adopted this large quotient bar because it is more easy to find
it than a single slash `/` in a `ratioOfQsprays` having a long expression.
Rational numbers and `qspray` polynomials are coercible to
`ratioOfQsprays` objects, and then you can also perform arithmetic operations
between a `ratioOfQsprays` and such an object:
```{r}
2 * roq
"1/2" * roq
roq + gmp::as.bigq("7/3")
x1 + roq + x3^2
```
The result of an arithmetic operation is always an irreducible fraction.
To perform this step, the C++ library **CGAL** is used to compute a greatest
common divisor of the numerator and the denominator of the possibly non-reduced
fraction resulting from the arithmetic operation, and then to divide both of
them by this greatest common divisor. This is very efficient in general.
## Evaluating a `ratioOfQsprays`
Use `evalRatioOfQsprays` to evaluate a `ratioOfQsprays`. This function returns
a `bigq` number:
```{r}
library(gmp) # rational numbers
x <- c("4", "3", "2/5")
evalRatioOfQsprays(roq, x)
x <- as.bigq(x)
evalRatioOfQsprays(roq, x)
f(x[1], x[2], x[3])
```
It is also possible to substitute some values to only a subset of the
variables, with the help of the function `substituteRatioOfQsprays`. You have
to indicate the variables you don't want to replace with `NA`:
```{r}
x <- c(NA, "3", "2/5")
substituteRatioOfQsprays(roq, x)
x <- as.bigq(x)
f(x1, x[2], x[3])
```
And it is possible to convert a `ratioOfQsprays` to a function which is
evaluated by **Ryacas**:
```{r}
fyac <- as.function(roq)
fyac("4", "3", "2/5") # = evalRatioOfQsprays(roq, c("4", "3", "2/5"))
```
Actually you can pass some literal variables to this function:
```{r}
fyac("x", "3", "2/5") # = substituteRatioOfQsprays(roq, c(NA, "3", "2/5"))
fyac("x", "y", "z") # = roq
fyac("x", "x", "x")
```
Complex numbers are allowed; the imaginary unit is denoted by `I`. See the
[**Yacas** documentation](https://yacas.readthedocs.io/en/latest/) for more
information.
```{r}
fyac("Sqrt(2)", "2 + 2*I", "3")
```
You can get numerical approximations by setting the option `N=TRUE` in
`as.function`:
```{r}
fyacN <- as.function(roq, N = TRUE)
fyacN("4", "3", "2/5")
fyacN("x", "3", "2/5")
fyacN("Sqrt(2)", "2 + 2*I", "3")
```
Let us also mention the `substituteSomeRatioOfQsprays` function. This function
allows to substitute the variables of a `ratioOfQsprays` fraction of polynomials
with some `ratioOfQsprays` objects.
## Querying a `ratioOfQsprays`
A couple of functions to query a `ratioOfQsprays` are available:
```{r}
getNumerator(roq)
getDenominator(roq)
numberOfVariables(roq)
isConstant(roq)
isConstant(roq / roq)
isUnivariate(roq)
isUnivariate(x1 / (x1^2 + 1))
isPolynomial(roq)
isPolynomial((x1^2 - x2^2) / (x1 - x2))
```
## Showing a `ratioOfQsprays`
As you have seen, the variables of `roq` are denoted by `x`, `y`, `z`. This is
the default way of printing a `ratioOfQsprays` which has no more than three
variables. If it has more than three variables, then they are denoted by
`x1`, `x2`, `x3`, ...:
```{r}
x4 <- qlone(4)
roq / x4
```
It is possible to control the way a `ratioOfQsprays` is printed. For example,
let's say you want to print `roq` by using `a1`, `a2`, `a3` for the variables
and you want to change the symbol for the quotient bar:
```{r}
showRatioOfQspraysOption(roq, "x") <- "a"
showRatioOfQspraysOption(roq, "quotientBar") <- " / "
roq
```
Now, if you perform an arithmetic operation between `roq` *at first position*
and an another `ratioOfQsprays`, these show options are passed to the result if
possible:
```{r}
roq + (x1 + 1)/x2
```
If you perform an arithmetic operation between `roq` and an object coercible to
a `ratioOfQsprays` object but which is not a `ratioOfQsprays` object, such as a
`bigq` number or a `qspray` object, the show options of `roq` are passed to
the result, even if `roq` is not at the first position:
```{r}
x1 * roq
```
An obvious example of a situation in which it is not always possible to
transfer the show options is when you use three letters for the variables, e.g.
```{r}
showRatioOfQspraysOption(roq, "showQspray") <- showQsprayXYZ(c("A", "B", "C"))
roq
```
but then you add to `roq` a `ratioOfQsprays` containing the fourth variable:
```{r}
roq + x4/(x4 + 1)
```
Obviously it is not possible to denote the resulting fraction of polynomials
with the letters `A`, `B` and `C`. The solution I adopted consists in
taking the first of these letters and to index it. The same method is used
for the `qspray` polynomials.
## Transforming a `ratioOfQsprays`
Let's take a `ratioOfQsprays` fraction of polynomials:
```{r}
f <- function(x, y, z) {
(2*x^2 + y*z) / (4*x - 3*z + 1)
}
x <- qlone(1); y <- qlone(2); z <- qlone(3)
roq <- f(x, y, z)
```
You can differentiate it:
```{r}
derivRatioOfQsprays(roq, 2) # derivative w.r.t. y
```
You can permute its variables:
```{r}
swapVariables(roq, 2, 3) == f(x, z, y)
```
You can perform some polynomial changes of its variables:
```{r}
changeVariables(roq, list(x+1, y^2, x+y+z)) == f(x+1, y^2, x+y+z)
```