I have system of equations
x + y - xy = c1
x + z - xz = c2
ay + bz = c3
(a,b, c1,c2 and c3 are known)
I want to know if this set of equation have a closed form solution. Or is optim best way to solve it accurately in R?
I'd recommend rSymPy, the R port of the awesome python library for symbolic math.
library(rSymPy)
sympy("var('x,y,a,b,z,c1,c2,c3')") # declare vars
sympy("solve([Eq(x+y-x*y,c1),Eq(x+z-x*z,c2),Eq(a*y-b*z,c3)],[x,y,z])",
retclass="Sym")
If you're too lazy to do the algebra:
Wolfram Alpha says in the most general case (assuming none of these denominators are zero):
x=(a*c1+b*c2-c3)/(a+b-c3)
y=(b*c1-b*c2-c1*c3+c3)/(-a*c1+a-b*c2+b)
z=(a*(c1-c2)+(c2-1)*c3)/(a*(c1-1)+b*(c2-1))
Related
I am trying to solve an optimization problem.
The objective function and all constraints of this problem are linear except x-x^2<=0.
Is there any way to linearize x-x^2<=0, where x is a continuous variable?
Note that x is not in the objective function.
The usual approach is to convert the problem to an iterative, non-linear one where you solve for increments:
f(x) = x - x^2
df/dx = 1 -2x
Make an initial guess x0; take a step for dx; solve for df; calculate x1 = x0 + dx and f1 = f0 + df and iterate until convergence.
You might look into optimization with constraints. Read up on Lagrange multipliers.
All,
I've just been starting to play around with the Julia language and am enjoying it quite a bit. At the end of the 3rd tutorial there's an interesting problem: genericize the quadratic formula such that it solves for the roots of any n-order polynomial equation.
This struck me as (a) an interesting programming problem and (b) an interesting Julia problem. Has anyone out there solved this one? For reference, here is the Julia code with a couple toy examples. Again, the idea is to make this generic for any n-order polynomial.
Cheers,
Aaron
function derivative(f)
return function(x)
# pick a small value for h
h = x == 0 ? sqrt(eps(Float64)) : sqrt(eps(Float64)) * x
# floating point arithmetic gymnastics
xph = x + h
dx = xph - x
# evaluate f at x + h
f1 = f(xph)
# evaluate f at x
f0 = f(x)
# divide the difference by h
return (f1 - f0) / dx
end
end
function quadratic(f)
f1 = derivative(f)
c = f(0.0)
b = f1(0.0)
a = f(1.0) - b - c
return (-b + sqrt(b^2 - 4a*c + 0im))/2a, (-b - sqrt(b^2 - 4a*c + 0im))/2a
end
quadratic((x) -> x^2 - x - 2)
quadratic((x) -> x^2 + 2)
The package PolynomialRoots.jl provides the function roots() to find all (real and complex) roots of polynomials of any order. The only mandatory argument is the array with coefficients of the polynomial in ascending order.
For example, in order to find the roots of
6x^5 + 5x^4 + 3x^2 + 2x + 1
after loading the package (using PolynomialRoots) you can use
julia> roots([1, 2, 3, 4, 5, 6])
5-element Array{Complex{Float64},1}:
0.294195-0.668367im
-0.670332+2.77556e-17im
0.294195+0.668367im
-0.375695-0.570175im
-0.375695+0.570175im
The package is a Julia implementation of the root-finding algorithm described in this paper: http://arxiv.org/abs/1203.1034
PolynomialRoots.jl has also support for arbitrary precision calculation. This is useful for solving equation that cannot be solved in double precision. For example
julia> r = roots([94906268.375, -189812534, 94906265.625]);
julia> (r[1], r[2])
(1.0000000144879793 - 0.0im,1.0000000144879788 + 0.0im)
gives the wrong result for the polynomial, instead passing the input array in arbitrary precision forces arbitrary precision calculations that provide the right answer (see https://en.wikipedia.org/wiki/Loss_of_significance):
julia> r = roots([BigFloat(94906268.375), BigFloat(-189812534), BigFloat(94906265.625)]);
julia> (Float64(r[1]), Float64(r[2]))
(1.0000000289759583,1.0)
There are no algebraic formulae for a general polynomials of degree five and above (infact there cant be see here). So theoretically, you could proceed using the same methodology for solutions to cubics and quartics, but even that would be a lot of hard work given very unwieldy formulae for roots of quartics. You could also use a CAS like SymPy to find out those formulae.
I have a functional like this :
(LaTex formula: $v[y]=\int_0^2 (y'^2+23yy'+12y^2+3ye^{2t})dt$)
with given start and end conditions y(0)=-1, y(2)=18.
How can I find extreme values of this functional in R? I realize how it can be done for example in Excel but didn't find appropriate solution in R.
Before trying to solve such a task in a numerical setting, it might be better to lean back and think about it for a moment.
This is a problem typically treated in the mathematical discipline of "variational calculus". A necessary condition for a function y(t) to be an extremum of the functional (ie. the integral) is the so-called Euler-Lagrange equation, see
Calculus of Variations at Wolfram Mathworld.
Applying it to f(t, y, y') as the integrand in your request, I get (please check, I can easily have made a mistake)
y'' - 12*y + 3/2*exp(2*t) = 0
You can go now and find a symbolic solution for this differential equation (with the help of a textbook, or some CAS), or solve it numerically with the help of an R package such as 'deSolve'.
PS: Solving this as an optimization problem based on discretization is possible, but may lead you on a long and stony road. I remember solving the "brachistochrone problem" to a satisfactory accuracy only by applying several hundred variables (not in R).
Here is a numerical solution in R. First the functional:
f<-function(y,t=head(seq(0,2,len=length(y)),-1)){
len<-length(y)-1
dy<-diff(y)*len/2
y0<-(head(y,-1)+y[-1])/2
2*sum(dy^2+23*y0*dy+12*y0^2+3*y0*exp(2*t))/len
}
Now the function that does the actual optimization. The best results I got were using the BFGS optimization method, and parametrizing using dy rather than y:
findMinY<-function(points=100, ## number of points of evaluation
boundary=c(-1,18), ## boundary values
y0=NULL, ## optional initial value
method="Nelder-Mead", ## optimization method
dff=T) ## if TRUE, optimizes based on dy rather than y
{
t<-head(seq(0,2,len=points),-1)
if(is.null(y0) || length(y0)!=points)
y0<-seq(boundary[1],boundary[2],len=points)
if(dff)
y0<-diff(y0)
else
y0<-y0[-1]
y0<-head(y0,-1)
ff<-function(z){
if(dff)
y<-c(cumsum(c(boundary[1],z)),boundary[2])
else
y<-c(boundary[1],z,boundary[2])
f(y,t)
}
res<-optim(y0,ff,control=list(maxit=1e9),method=method)
cat("Iterations:",res$counts,"\n")
ymin<-res$par
if(dff)
c(cumsum(c(boundary[1],ymin)),boundary[2])
else
c(boundary[1],ymin,boundary[2])
}
With 500 points of evaluation, it only takes a few seconds with BFGS:
> system.time(yy<-findMinY(500,method="BFGS"))
Iterations: 90 18
user system elapsed
2.696 0.000 2.703
The resulting function looks like this:
plot(seq(0,2,len=length(yy)),yy,type='l')
And now a solution that numerically integrates the Euler equation.
As #HansWerner pointed out, this problem boils down to applying the Euler-Lagrange equation to the integrand in OP's question, and then solving that differential equation, either analytically or numerically. In this case the relevant ODE is
y'' - 12*y = 3/2*exp(2*t)
subject to:
y(0) = -1
y(2) = 18
So this is a boundary value problem, best approached using bvpcol(...) in package bvpSolve.
library(bvpSolve)
F <- function(t, y.in, pars){
dy <- y.in[2]
d2y <- 12*y.in[1] + 1.5*exp(2*t)
return(list(c(dy,d2y)))
}
init <- c(-1,NA)
end <- c(18,NA)
t <- seq(0, 2, by = 0.01)
sol <- bvpcol(yini = init, yend = end, x = t, func = F)
y = function(t){ # analytic solution...
b <- sqrt(12)
a <- 1.5/(4-b*b)
u <- exp(2*b)
C1 <- ((18*u + 1) - a*(exp(4)*u-1))/(u*u - 1)
C2 <- -1 - a - C1
return(a*exp(2*t) + C1*exp(b*t) + C2*exp(-b*t))
}
par(mfrow=c(1,2))
plot(t,y(t), type="l", xlim=c(0,2),ylim=c(-1,18), col="red", main="Analytical Solution")
plot(sol[,1],sol[,2], type="l", xlim=c(0,2),ylim=c(-1,18), xlab="t", ylab="y(t)", main="Numerical Solution")
It turns out that in this very simple example, there is an analytical solution:
y(t) = a * exp(2*t) + C1 * exp(sqrt(12)*t) + C2 * exp(-sqrt(12)*t)
where a = -3/16 and C1 and C2 are determined to satisfy the boundary conditions. As the plots show, the numerical and analytic solution agree completely, and also agree with the solution provided by #mrip
I have a linear scale that ranges form 0.1 to 10 with increments of change at 0.1:
|----------[]----------|
0.1 5.0 10
However, the output really needs to be:
|----------[]----------|
0.1 1.0 10 (logarithmic scale)
I'm trying to figure out the formula needed to convert the 5 (for example) to 1.0.
Consequently, if the dial was shifted halfway between 1.0 and 10 (real value on linear scale being 7.5), what would the resulting logarithmic value be? Been thinking about this for hours, but I have not worked with this type of math in quite a few years, so I am really lost. I understand the basic concept of log10X = 10y, but that's pretty much it.
The psuedo-value of 5.0 would become 10 (or 101) while the psuedo-value of 10 would be 1010. So how to figure the pseudo-value and resulting logarithmic value of, let's say, the 7.5?
Let me know if addition information is needed.
Thanks for any help provided; this has beaten me.
Notation
As is the convention both in mathematics and programming, the "log" function is taken to be base-e. The "exp" function is the exponential function. Remember that these functions are inverses we take the functions as:
exp : ℝ → ℝ+, and
log : ℝ+ → ℝ.
Solution
You're just solving a simple equation here:
y = a exp bx
Solve for a and b passing through the points x=0.1, y=0.1 and x=10, y=10.
Observe that the ratio y1/y2 is given by:
y1/y2 = (a exp bx1) / (a exp bx2) = exp b(x1-x2)
Which allows you to solve for b
b = log (y1/y2) / (x1-x2)
The rest is easy.
b = log (10 / 0.1) / (10 - 0.1) = 20/99 log 10 ≈ 0.46516870565536284
a = y1 / exp bx1 ≈ 0.09545484566618341
More About Notation
In your career you will find people who use the convention that the log function uses base e, base 10, and even base 2. This does not mean that anybody is right or wrong. It is simply a notational convention and everybody is free to use the notational convention that they prefer.
The convention in both mathematics and computer programming is to use base e logarithm, and using base e simplifies notation in this case, which is why I chose it. It is not the same as the convention used by calculators such as the one provided by Google and your TI-84, but then again, calculators are for engineers, and engineers use different notation than mathematicians and programmers.
The following programming languages include a base-e log function in the standard library.
C log() (and C++, by inclusion)
Java Math.log()
JavaScript Math.log()
Python math.log() (including Numpy)
Fortran log()
C#, Math.Log()
R
Maxima (strictly speaking a CAS, not a language)
Scheme's log
Lisp's log
In fact, I cannot think of a single programming language where log() is anything other than the base-e logarithm. I'm sure such a programming language exists.
I realize this answer is six years too late, but it might help someone else.
Given a linear scale whose values range from x0 to x1, and a logarithmic scale whose values range from y0 to y1, the mapping between x and y (in either direction) is given by the relationship shown in equation 1:
x - x0 log(y) - log(y0)
------- = ----------------- (1)
x1 - x0 log(y1) - log(y0)
where,
x0 < x1
{ x | x0 <= x <= x1 }
y0 < y1
{ y | y0 <= y <= y1 }
y1/y0 != 1 ; i.e., log(y1) - log(y0) != 0
y0, y1, y != 0
EXAMPLE 1
The values on the linear x-axis range from 10 to 12, and the values on the logarithmic y-axis range from 300 to 3000. Given y=1000, what is x?
Rearranging equation 1 to solve for 'x' yields,
log(y) - log(y0)
x = (x1 - x0) * ----------------- + x0
log(y1) - log(y0)
log(1000) - log(300)
= (12 - 10) * -------------------- + 10
log(3000) - log(300)
≈ 11
EXAMPLE 2
Given the values in your question, the values on the linear x-axis range from 0.1 to 10, and the values on the logarithmic y-axis range from 0.1 to 10, and the log base is 10. Given x=7.5, what is y?
Rearranging equation 1 to solve for 'y' yields,
x - x0
log(y) = ------- * (log(y1) - log(y0)) + log(y0)
x1 - x0
/ x - x0 \
y = 10^| ------- * (log(y1) - log(y0)) + log(y0) |
\ x1 - x0 /
/ 7.5 - 0.1 \
= 10^| --------- * (log(10) - log(0.1)) + log(0.1) |
\ 10 - 0.1 /
/ 7.5 - 0.1 \
= 10^| --------- * (1 - (-1)) + (-1) |
\ 10 - 0.1 /
≈ 3.13
:: EDIT (11 Oct 2020) ::
For what it's worth, the number base 'n' can be any real-valued positive number. The examples above use logarithm base 10, but the logarithm base could be 2, 13, e, pi, etc. Here's a spreadsheet I created that performs the calculations for any real-valued positive number base. The "solution" cells are colored yellow and have thick borders. In these figures, I picked at random the logarithm base n=13—i.e., z = log13(y).
Figure 1. Spreadsheet values.
Figure 2. Spreadsheet formulas.
Figure 3. Mapping of X and Y values.
I have to solve the following convolution related numerical integration problem in R or perhaps computer algebra system like Maxima.
Integral[({k(y)-l(y)}^2)dy]
where
k(.) is the pdf of a standard normal distribution
l(y)=integral[k(z)*k(z+y)dz] (standard convolution)
z and y are scalars
The domain of y is -inf to +inf.
The integral in function l(.) is an indefinite integral. Do I need to add any additional assumption on z to obtain this?
Thank you.
Here is a symbolic solution from Mathematica:
R does not do symbolic integration, just numerical integration. There is the Ryacas package which intefaces with Yacas, a symbolic math program that may help.
See the distr package for possible help with the convolution parts (it will do the convolutions, I just don't know if the result will be integrable symbolicly).
You can numerically integrate the convolutions from distr using the integrate function, but all the parameters need to be specified as numbers not variables.
For the record, here is the same problem solved with Maxima 5.26.0.
(%i2) k(u):=exp(-(1/2)*u^2)/sqrt(2*%pi) $
(%i3) integrate (k(x) * k(y + x), x, minf, inf);
(%o3) %e^-(y^2/4)/(2*sqrt(%pi))
(%i4) l(y) := ''%;
(%o4) l(y):=%e^-(y^2/4)/(2*sqrt(%pi))
(%i5) integrate ((k(y) - l(y))^2, y, minf, inf);
(%o5) ((sqrt(2)+2)*sqrt(3)-2^(5/2))/(4*sqrt(3)*sqrt(%pi))
(%i6) float (%);
(%o6) .02090706601281356
Sorry for the late reply. Leaving this here in case someone finds it by searching.
I try to do something similar in matlab, where I convolute two random (Rayleigh distributed) variables. The result of fz_fun is equal to fy_fun, I don't know why. Maybe some here knows it?
sigma1 = 0.45;
sigma2 = 0.29;
fx_fun =#(x) [0*x(x<0) , (x(x>=0)./sigma1^2).*exp(-0.5*(x(x>=0)./sigma1).^2)];
fy_fun =#(y) [0*y(y<0) , (y(y>=0)./sigma2^2).*exp(-0.5*(y(y>=0)./sigma2).^2)];
% Rayleigh distribution of random var X,Y:
step = 0.1;
x= -2:step:3;
y= -2:step:3;
%% Convolution:
z= y;
fz = zeros(size(y));
for i = 1:length(y)
fz_fun(i) = integral(#(z) fy_fun(y(i)).*fx_fun(z-y(i)),0,Inf); % probability density of random variable z= x+y
end