Generate a symbolic interpolating polynomial in Scilab - scilab

I've made a code to calculate the result of divided differences method and lagrange method by interpolating points. I would also like to build a polynomial using symbolic variables but how can I accomplish this?
function dividedDifferences(X,Y,x)
ddMatrix = X'
ddMatrix(:,2) = Y'
for j=3:length(Y)+3
for i=1:length(Y)+2-j
ddMatrix(i,j) = (ddMatrix(i,j-1)-ddMatrix(i+1,j-1))/(ddMatrix(i,1)-ddMatrix(i+j-2,1))
end
end
disp(ddMatrix)
Px = 0
for j=2:length(Y)+1
prd = 1
for i=1:j-2
prd = prd * (x - ddMatrix(i,1))
end
Px = Px + ddMatrix(1,j)*prd
end
disp(Px)
endfunction
function lagrange(X,Y,x)
for i=1:length(Y)
l(i)=1
for j=1:length(Y)
if i~=j
l(i) = l(i)*(x-X(j))/(X(i)-X(j))
end
end
end
disp(l')
L=0
for i=1:length(Y)
L = L+Y(i)*l(i)
end
disp(L)
endfunction
//example instance
X = [0 1 5 8]
Y = [0 1 8 16.4]
x = 7
dividedDifferences(X,Y,x)
lagrange(X,Y,x)

To create a symbolic polynomial, initialize a symbolic variable with x = poly(0,"x") where x is the name of the variable to use in the polynomial. Then proceed to compute with it exactly as you did in the function lagrange. I essentially copied your function to symboliclagrange below, cutting out the numerical parameter and intermediate display:
function symboliclagrange(X,Y)
x = poly(0,"x")
for i=1:length(Y)
l(i)=1
for j=1:length(Y)
if i~=j
l(i) = l(i)*(x-X(j))/(X(i)-X(j))
end
end
end
L=0
for i=1:length(Y)
L = L+Y(i)*l(i)
end
disp(L)
endfunction
With your input X = [0 1 5 8], Y = [0 1 8 16.4] the output is 0.85x+0.15x2, which is the correct interpolating polynomial.

Related

Solve a system of N equations with N unknowns using Julia

I have :
a set of N locations which can be workplace or residence
a vector of observed workers L_i, with i in N
a vector of observed residents R_n, with n in N
a matrix of distance observed between all pair residence n and workplace i
a shape parameter epsilon
Setting N=3, epsilon=5, and
d = [1 1.5 3 ; 1.5 1 1.5 ; 3 1.5 1] #distance matrix
L_i = [13 69 18] #vector of workers in each workplace
R_n = [27; 63; 10]
I want to find the vector of wages (size N) that solve this system of N equations,
with l all the workplaces.
Do I need to implement an iterative algorithm on the vectors of workers and wages? Or is it possible to directly solve this system ?
I tried this,
w_i = [1 ; 1 ; 1]
er=1
n =1
while er>1e-3
L_i = ( (w_i ./ d).^ϵ ) ./ sum( ( (w_i ./ d).^ϵ), dims=1) * R
er = maximum(abs.(L .- L_i))
w_i = 0.7.*w_i + 0.3.*w_i.*((L .- L_i) ./ L_i)
n = n+1
end
If L and R are given (i.e., do not depend on w_i), you should set up a non-linear search to get (a vector of) wages from that gravity equation (subject to normalising one w_i, of course).
Here's a minimal example. I hope it helps.
# Call Packages
using Random, NLsolve, LinearAlgebra
# Set seeds
Random.seed!(1704)
# Variables and parameters
N = 10
R = rand(N)
L = rand(N) * 0.5
d = ones(N, N) .+ Symmetric(rand(N, N)) / 10.0
d[diagind(d)] .= 1.0
ε = -3.0
# Define objective function
function obj_fun(x, d, R, L, ε)
# Find shares
S_mat = (x ./ d).^ε
den = sum(S_mat, dims = 1)
s = S_mat ./ den
# Normalize last wage
x[end] = 1.0
# Define loss function
loss = L .- s * R
# Return
return loss
end
# Run optimization
x₀ = ones(N)
res = nlsolve(x -> obj_fun(x, d, R, L, ε), x₀, show_trace = true)
# Equilibrium vector of wages
w = res.zero

Is it possible to use the input command to enter functions in order to use numderivative?

I've been working on numerical methods to solve polynomial and non-polynomial equations. I wanted to use numderivative to calculate the defined derivative of a function entered by the user with the following simple code:
clc
clear
x0 =input('Enter the x value: ') // x0 = 4
function y = f(x)
y = input('Enter your function: ') // y = sqrt(x)
endfunction
dd = numderivative(f,x0)
printf('The definite derivative value of f(x) in x = %d is %.6f',x0,dd)
The output is the following:
Enter the x value: 4
Enter your function: sqrt(x)
Enter your function: sqrt(x)
The definite derivative value of f(x) in x = 4 is 0.250000
This code asks for the function twice. I would like to know how to solve that problem. Thank in advance.
No it is not possible to enter a function, but you can enter the instructions of the function:
x0 =input('Enter the x value: ') // x0 = 4
instr = input('Enter the expression to derivate as a function of x: ',"s")//sqrt(x)
deff("y=f(x)","y="+instr)
dd = numderivative(f,x0)
printf('The definite derivative value of f(x) in x = %d is %.6f',x0,dd)

Reassign function and avoid recursive definition in Julia

I need to operate on a sequence of functions
h_k(x) = (I + f_k( ) )^k g(x)
for each k=1,...,N.
A basic example (N=2, f_k=f) is the following:
f(x) = x^2
g(x) = x
h1(x) = g(x) + f(g(x))
h2(x) = g(x) + f(g(x)) + f(g(x) + f(g(x)))
println(h1(1)) # returns 2
println(h2(1)) # returns 6
I need to write this in a loop and it would be best to redefine g(x) at each iteration. Unfortunately, I do not know how to do this in Julia without conflicting with the syntax for a recursive definition of g(x). Indeed,
f(x) = x^2
g(x) = x
for i=1:2
global g(x) = g(x) + f(g(x))
println(g(1))
end
results in a StackOverflowError.
In Julia, what is the proper way to redefine g(x), using its previous definition?
P.S. For those who would suggest that this problem could be solved with recursion: I want to use a for loop because of how the functions f_k(x) (in the above, each f_k = f) are computed in the real problem that this derives from.
I am not sure if it is best, but a natural approach is to use anonymous functions here like this:
let
f(x) = x^2
g = x -> x
for i=1:2
l = g
g = x -> l(x) + f(l(x))
println(g(1))
end
end
or like this
f(x) = x^2
g = x -> x
for i=1:4
l = g
global g = x -> l(x) + f(l(x))
println(g(1))
end
(I prefer the former option using let as it avoids using global variables)
The issue is that l is a loop local variable that gets a fresh binding at each iteration, while g is external to the loop.
You might also check out this section of the Julia manual.

How to only use the lower bounds and upper bounds for quadratic solver qpsolve from Scilab?

I have a simple question. How do I use the command qpsolve from Scilab if I only want to use the lower bounds and upper bounds limit?
ci <= x <= cs
The command can be used as this:
[x [,iact [,iter [,f]]]] = qpsolve(Q,p,C,b,ci,cs,me)
But I want to use it like this:
x = qpsolve(Q,p,[],[],ci,cs,[])
Only ci and cs should explain the limits for vector x. Unfortunately, the command cannot take empty []. Should I take [] as a row vector of ones or zeros?
https://help.scilab.org/docs/6.0.1/en_US/qpsolve.html
In Scilab 5.5.1 , [] works for C and b but not for me. so C = [];b = [];me = 0; should work.
Why
qpsolve is an interface for qp_solve :
function [x, iact, iter, f]=qpsolve(Q,p,C,b,ci,cs,me)
rhs = argn(2);
if rhs <> 7
error(msprintf(gettext("%s: Wrong number of input argument(s): %d expected.\n"), "qpsolve", 7));
end
C(me+1:$, :) = -C(me+1:$, :);
b(me+1:$) = -b(me+1:$);
// replace boundary contraints by linear constraints
Cb = []; bb = [];
if ci <> [] then
Cb = [Cb; speye(Q)]
bb = [bb; ci]
end
if cs <> [] then
Cb = [Cb; -speye(Q)]
bb = [bb; -cs]
end
C = [C; Cb]; b = [b; bb]
[x, iact, iter, f] = qp_solve(Q, -p, C', b, me)
endfunction
It transform every bound constraints into linear constraints. To begin, it swap the sign of the inequality constraints. To do that, it must know me, ie it must be an integer. Since C and b are empty matrices, is value doesn't matter.
Bonus:
if Q is inversible, you could skip the qpsolve macro and write
x = -Q\p
x(x<ci) = ci(x<ci)
x(x>cs) = cs(x>cs)

Unclassified statement at (1) in a mathematical expression

My first Fortran lesson is to plot the probability density function of the radial Sturmian functions. In case you are interested, the radial Sturmian functions are used to graph the momentum space eigenfunctions for the hydrogen atom.
In order to produce these radial functions, one needs to first produce some polynomials called the Gegenbauer polynomials, denoted
Cba(x),
where a and b should be stacked atop each other. One needs these polynomials because the Sturmians (let's call them R_n,l) are defined like so,
R_n,l(p) = N pl⁄(p2 + k2)l+2 Cn - l - 1l + 1(p2 - k2⁄p2 + k2),
where N is a normalisation constant, p is the momentum, n is the principle quantum number, l is the angular momentum and k is a constant. The normalisation constant is there so that when I come to square this function, it will produce a probability distribution for the momentum of the electron in a hydrogen atom.
Gegenbauer polynomials are generated using the following recurrence relation:
Cnl(x) = 1⁄n[2(l + n - 1) x Cn - 1l(x) - (2l + n - 2)Cn - 2l(x)],
with C0l(x) = 1 and C1l(x) = 2lx, as you may have noticed, l is fixed but n is not. At the start of my program, I will specify both l and n and work out the Gegenbauer polynomial I need for the radial function I wish to plot.
The problems I am having with my code at the moment are all in my subroutine for working out the value of the Gegenbauer polynomial Cn-l-1l+1(p2 - k2⁄p2 + k2) for incremental values of p between 0 and 3. I keep getting the error
Unclassified statement at (1)
but I cannot see what the issue is.
program Radial_Plot
implicit none
real, parameter :: pi = 4*atan(1.0)
integer, parameter :: top = 1000, l = 50, n = 100
real, dimension(1:top) :: x, y
real increment
real :: a=0.0, b = 2.5, k = 0.3
integer :: i
real, dimension(1:top) :: C
increment = (b-a)/(real(top)-1)
x(1) = 0.0
do i = 2, top
x(i) = x(i-1) + increment
end do
Call Gegenbauer(top, n, l, k, C)
y = x*C
! y is the function that I shall be plotting between values a and b.
end program Radial_Plot
Subroutine Gegenbauer(top1, n1, l1, k1, CSub)
! This subroutine is my attempt to calculate the Gegenbauer polynomials evaluated at a certain number of values between c and d.
implicit none
integer :: top1, i, j, n1, l1
real :: k1, increment1, c, d
real, dimension(1:top1) :: x1
real, dimension(1:n1 - l1, 1:top1) :: C1
real, dimension(1:n1 - l1) :: CSub
c = 0.0
d = 3.0
k1 = 0.3
n1 = 50
l1 = 25
top1 = 1000
increment1 = (d - c)/(real(top1) - 1)
x1(1) = 0.0
do i = 2, top1
x1(i) = x1(i-1) + increment1
end do
do j = 1, top1
C1(1,j) = 1
C1(2,j) = 2(l1 + 1)(x1(i)^2 - k1^2)/(x1(i)^2 + k1^2)
! All the errors occurring here are all due to, and I quote, 'Unclassifiable statement at (1)', I can't see what the heck I have done wrong.
do i = 3, n1 - l1
C1(i,j) = 2(((l1 + 1)/n1) + 1)(x1(i)^2 - k1^2)/(x1(i)^2 + k1^2)C1(i,j-1) - ((2(l1+1)/n1) + 1)C1(i,j-2)
end do
CSub(j) = Cn(n1 - l1,j)^2
end do
return
end Subroutine Gegenbauer
As francesalus correctly pointed out, the problem is because you use ^ instead of ** for exponentiation. Additionally, you do not put * between the terms you are multiplying.
C1(1,j) = 1
C1(2,j) = 2*(l1 + 1)*(x1(i)**2 - k1**2)/(x1(i)**2 + k1**2)
do i = 3, n1 - l1
C1(i,j) = 2 * (((l1 + 1)/n1) + 1) * (x1(i)**2 - k1**2) / &
(x1(i)**2 + k1**2)*C1(i,j-1) - ((2(l1+1)/n1) + 1) * &
C1(i,j-2)
end do
CSub(j) = Cn(n1 - l1,j)**2
Since you are beginning I have some advice. Learn to put all subroutines and functions to modules (unless they are internal). There is no reason for the return statement at the and of the subroutine, similarly as a stop statement isn't necessary at the and of the program.

Resources