# How much pizza and how much frozen yogurt? …with Gröbner bases

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

In a recent blog post I tried to get `yacas` to solve a system of polynomial equations.
Unfortunately it could not do that, so I solved it numerically instead.
Now it is possible – together with many other systems of polynomial equations thanks to
fixing a small error in `yacas`.
It has now been fixed, also in `Ryacas` (development version), so
hurry up and update `Ryacas` to the latest version `0.9.0.9122`.

First I will show how to do it directly in `Ryacas` (and afterwards show what happens behind the curtains).

``library(Ryacas)``

## Solving a system of equations

We define the system from the recent blog post in `R`:

``````L <- "x^2 * (y/4) - a*(3*x + 3*y/2 - 45)"
eq1 <- paste0("D(x) ", L) %>% yac_str()
eq2 <- paste0("D(y) ", L) %>% yac_str()
eq3 <- paste0("D(a) ", L) %>% yac_str()
eqs <- c(eq1, eq2, eq3)
eqs
##  "(x*y)/2-3*a"      "x^2/4-(3*a)/2"    "45-(3*x+(3*y)/2)"``````

As known from the theory of Gröbner bases,
instead of finding roots in this entangled system,
we can find the Gröbner bases and find roots for those instead:

``````eq_str <- paste0("{", paste0(eqs, " == 0", collapse = ", "), "}") %>%
y_fn("Solve", "{x, y, a}")
eq_str
##  "Solve({(x*y)/2-3*a == 0, x^2/4-(3*a)/2 == 0, 45-(3*x+(3*y)/2) == 0}, {x, y, a})"
sol_all <- eq_str %>% yac_str()
sol_all
##  "{{x==0,y==30,a==0},{x==10,y==10,a==50/3}}"``````

As seen, we get two solutions. The solution \(a = 0\) is not feasible in our case (read the recent blog post) so we just pick the second:

``````sol_elible_vars <- sol_all %>% y_fn("Nth", 2) %>% yac_str()
sol_elible_vars
##  "{x==10,y==10,a==50/3}"``````

We have now finally arrived at the answer:
\[
(x, y, a) = (10, 10, 50/3) .
\]

It is also possible to postprocess the answer a bit if that is needed:

``````# Remove variable names if wanted:
sol_elible <- sol_elible_vars %>% y_rmvars() %>% yac_str()
sol_elible
##  "{10,10,50/3}"
# And maybe convert to numbers:
sol_elible %>% yac_expr()
## expression(c(10, 10, 50/3))
# ...maybe even evaluated:
sol_elible %>% yac_expr() %>% eval()
##  10.00000 10.00000 16.66667``````

## Enter Gröbner bases

We could actually have solved the system manually earlier using Gröbner bases.

As known from the theory of Gröbner bases (but I will not start trying to explain it because
I do not know them nearly as well as I should),
instead of finding roots in this entangled system,
we can find the Gröbner bases and find roots for those instead:

``````fs <- paste0("{", paste0(eqs, collapse = ", "), "}")
fs
##  "{(x*y)/2-3*a, x^2/4-(3*a)/2, 45-(3*x+(3*y)/2)}"
gs <- fs %>% y_fn("Groebner") %>% yac_str() %>% as_r()
gs
##  "(x*y)/2-3*a"            "x^2/4+((-3)*a)/2"
##  "(-3)*x+((-3)*y)/2+45"   "9*y*a-90*a"
##  "15*y-y^2/2-6*a"         "(-6)*a^2+100*a"
##  "((-15)*y)/2+(-9)*a+225"``````

As seen the system is now “triangulated”. So we proceed:

``````yac_str("Solve((-6)*a^2+100*a == 0, a)")
##  "{a==0,a==50/3}"``````

As mentioned, the solution \(a = 0\) is not feasible in our case (read the recent blog post), so we use \(a = 50/3\) and obtain:

``````yac_str("WithValue(a, 50/3, Solve(9*y*a-90*a == 0, y))")
##  "{y==10}"``````

So \(y = 10\). And we get

``````yac_str("WithValue({a, y}, {50/3, 10}, Solve((x*y)/2-3*a == 0, x))")
##  "{x==10}"``````

We have now finally arrived at the answer:
\[
(x, y, a) = (10, 10, 50/3) .
\]

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.