library(caracas)
SymPy
directlyFirst we get the SymPy
object:
<- get_sympy() sympy
$diff("2*a*x", "x")
sympy#> 2*a
$solve("x**2 - 1", "x")
sympy#> [[1]]
#> -1
#>
#> [[2]]
#> 1
How can we minimise the amount of material used to produce a cylindric tin can that contains 1 litre. The cylinder has diameter \(d\) and height \(h\). The question is therefore: What is \(d\) and \(h\)?
We introduce the variables d
(diameter) and h
(height):
<- sympy$symbols('d')
d <- sympy$symbols('h') h
The problem is a constrained optimisation problem, and we solve it by a Lagrange multiplier, and therefore we introduce lam
(the Lagrange multiplier):
<- sympy$symbols('lam') lam
We now set up the problem:
<- "Pi/2 * d**2 + Pi * h * d"
area_str <- "Pi/4 * d**2 * h"
vol_str <- paste0("(", area_str, ") - lam*((", vol_str, ") - 1)")
lap_str <- sympy$parsing$sympy_parser$parse_expr(
lap
lap_str,local_dict = list('d' = d, 'h' = h, 'lam' = lam))
We can now find the gradient:
<- sympy$derive_by_array(lap, list(d, h, lam))
grad
grad#> [-Pi*d*h*lam/2 + Pi*d + Pi*h, -Pi*d**2*lam/4 + Pi*d, -Pi*d**2*h/4 + 1]
And find the critical points:
<- sympy$solve(grad, list(d, h, lam), dict = TRUE)
sol
sol#> [[1]]
#> [[1]]$d
#> 2**(2/3)/Pi**(1/3)
#>
#> [[1]]$h
#> 2**(2/3)/Pi**(1/3)
#>
#> [[1]]$lam
#> 2*2**(1/3)*Pi**(1/3)
#>
#>
#> [[2]]
#> [[2]]$d
#> 2**(2/3)*(-1 + sqrt(3)*I)/(2*Pi**(1/3))
#>
#> [[2]]$h
#> 2**(2/3)*(-1 + sqrt(3)*I)/(2*Pi**(1/3))
#>
#> [[2]]$lam
#> -2**(1/3)*Pi**(1/3) - 2**(1/3)*sqrt(3)*I*Pi**(1/3)
#>
#>
#> [[3]]
#> [[3]]$d
#> -2**(2/3)*(1 + sqrt(3)*I)/(2*Pi**(1/3))
#>
#> [[3]]$h
#> -2**(2/3)*(1 + sqrt(3)*I)/(2*Pi**(1/3))
#>
#> [[3]]$lam
#> -2**(1/3)*Pi**(1/3) + 2**(1/3)*sqrt(3)*I*Pi**(1/3)
We take the one with the real solution:
1]]
sol[[#> $d
#> 2**(2/3)/Pi**(1/3)
#>
#> $h
#> 2**(2/3)/Pi**(1/3)
#>
#> $lam
#> 2*2**(1/3)*Pi**(1/3)
We now have a short helper function to help getting appropriate R
expressions (such a function will be included in later versions of this package):
<- function(x) {
to_r <- as.character(x)
x <- gsub("Pi", "pi", x, fixed = TRUE)
x <- gsub("**", "^", x, fixed = TRUE)
x <- parse(text = x)
x return(x)
}
<- to_r(sol[[1]]$d)
sol_d
sol_d#> expression(2^(2/3)/pi^(1/3))
eval(sol_d)
#> [1] 1.083852
<- to_r(sol[[1]]$h)
sol_h
sol_h#> expression(2^(2/3)/pi^(1/3))
eval(sol_h)
#> [1] 1.083852
(It is left as an exercise to the reader to show that the critical point indeed is a minimum.)
<- sympy$symbols('x')
x $assumptions0
x#> $commutative
#> [1] TRUE
<- sympy$symbols('x', positive = TRUE)
x $assumptions0
x#> $positive
#> [1] TRUE
#>
#> $extended_nonnegative
#> [1] TRUE
#>
#> $commutative
#> [1] TRUE
#>
#> $negative
#> [1] FALSE
#>
#> $extended_nonzero
#> [1] TRUE
#>
#> $extended_positive
#> [1] TRUE
#>
#> $zero
#> [1] FALSE
#>
#> $extended_negative
#> [1] FALSE
#>
#> $imaginary
#> [1] FALSE
#>
#> $nonnegative
#> [1] TRUE
#>
#> $extended_nonpositive
#> [1] FALSE
#>
#> $complex
#> [1] TRUE
#>
#> $real
#> [1] TRUE
#>
#> $nonpositive
#> [1] FALSE
#>
#> $nonzero
#> [1] TRUE
#>
#> $infinite
#> [1] FALSE
#>
#> $hermitian
#> [1] TRUE
#>
#> $extended_real
#> [1] TRUE
#>
#> $finite
#> [1] TRUE
<- sympy$parsing$sympy_parser$parse_expr("x**2 - 1",
eq local_dict = list('x' = x))
$solve(eq, x, dict = TRUE)
sympy#> [[1]]
#> [[1]]$x
#> 1
<- sympy$symbols('x', positive = TRUE)
x <- sympy$parsing$sympy_parser$parse_expr("x**3/3 - x",
eq local_dict = list('x' = x))
eq#> x**3/3 - x
<- sympy$derive_by_array(eq, x)
grad
grad#> x**2 - 1
$solve(grad, x, dict = TRUE)
sympy#> [[1]]
#> [[1]]$x
#> 1