Gradient (nabla) of vector/array in Delphi - arrays

I am to implement the following formula in Delphi:
Understanding the formula:
Y_k is a floating point number which we'll call just Y.
w[i][j] is an array containing floating point numbers as well (1<=i<=43 and 1<=j<=30).
According to my source paper (p. 12) nabla(w)*Y_k is the partial derivative of (column) vector w with respect to the value Y". Is this correct?
Coding in Delphi (implementation):
So how do I implement this in Delphi?
Thanks a lot in advance!

I will assume that the problem is: "How can I compute a gradient of a scalar function in Delphi?" [I still think that the symbol given above looks more like a connection/covariant derivative as known from differential geometry/tensor calculus!]
You need to specify the input you got. The simplest case is when you got the function f whose gradient you wish to compute. Per definition, if f is a function of the k variables x1, x2, ..., xk, that is, if you'd write
f(x1, x2, ..., xk)
which is a scalar field in ℝk then the gradient is
∇f = (∂f/∂x1, ∂f/∂x2, ..., ∂f/∂xk)
that is, a vector field in ℝk (at each point in ℝk you get a k-dimensional vector).
This is rather easily implemented in Delphi. The following is an example for the case where k = 3.
type
TVector = record
x, y, z: real;
constructor Create(ax, ay, az: real);
end;
TRealValuedFunction = function(v: TVector): real;
function gradient(f: TRealValuedFunction; v: TVector): TVector;
const
h = 0.001;
begin
result.x := (f(TVector.Create(v.x + h, v.y, v.z)) - f(TVector.Create(v.x - h, v.y, v.z))) / (2*h);
result.y := (f(TVector.Create(v.x, v.y + h, v.z)) - f(TVector.Create(v.x, v.y - h, v.z))) / (2*h);
result.z := (f(TVector.Create(v.x, v.y, v.z + h)) - f(TVector.Create(v.x, v.y, v.z - h))) / (2*h);
end;
where, of course,
constructor TVector.Create(ax, ay, az: real);
begin
x := ax;
y := ay;
z := az;
end;
Sample usage:
function SampleFunction(v: TVector): real;
begin
result := 5*v.x + 7*v.y;
end;
procedure TForm4.FormCreate(Sender: TObject);
begin
with gradient(SampleFunction, TVector.Create(2, 6, 3)) do
ShowMessage(FloatToStr(x) + ', ' + FloatToStr(y) + ', ' + FloatToStr(z))
end;
The result is 5.00000000000256, 7.000000000005, 0 which is a very good approximation to the gradient of SampleFunction at v (in this case the gradient is constant in space, that is, it doesn't depend on which point v in space you select).
Of course, if you are writing anything serious, you will probably use your own vector algebra library.
Also, h = 0.001 might not be a great value in your case.

Related

Incorrect dimensions for matrix multiplication when multiplying pi*a

I've created this code and it gives me this error message:
Error using *
Incorrect dimensions for matrix multiplication.
Error in poli3 = sin(pi*a) ...
Below I show one function used in the code. I don't know if the problem comes from the value given by derivadan or what.
x = -1:0.01:1; % Intervalo en el que se evaluará el polinomio de Taylor
y = sin(pi*x); % Función
a = 0;
derivada3 = derivadan(0.01, 3, a);
derivada7 = derivadan(0.01, 7, a);
derivada3_vec = repmat(derivada3, size(x - a));
derivada7_vec = repmat(derivada7, size(x - a));
poli3 = sin(pi*a) + derivada3_vec*(x - a) + (derivada3_vec*(x - a).^2)/factorial(2) + (derivada3_vec*(x - a).^3)/factorial(3);
poli7 = sin(pi*a) + derivada7_vec*(x - a) + (derivada7_vec*(x - a).^2)/factorial(2) + (derivada7_vec*(x - a).^3)/factorial(3) + (derivada7_vec*(x - a).^4)/factorial(4) + (derivada7_vec*(x - a).^5)/factorial(5) + (derivada7_vec*(x - a).^6)/factorial(6) + (derivada7_vec*(x - a).^7)/factorial(7);
figure
plot(x, poli3, 'r', x, poli7, 'b')
legend('Taylor grau 3', 'Taylor grau 7')
title('Grafica Taylor 3 grau vs Grafica Taylor 7 grau')
function Yd = derivadan(h, grado, vecX)
Yd = zeros(size(vecX));
for i = 1:grado
Yd = (vecX(2:end) - vecX(1:end-1)) / h;
vecX = Yd;
end
end
In MATLAB one can go 2 ways when developing taylor series; the hard way and the easy way.
As asked, first the HARD way :
close all;clear all;clc
dx=.01
x = -1+dx:dx:1-dx;
y = sin(pi*x);
a =0;
[va,na]=find(x==a)
n1=3
D3y=zeros(n1,numel(x));
for k=1:1:n1
D3y(k,1:end-k)=dn(dx,k,y);
end
T3=y(na)+sum(1./factorial([1:n1])'.*D3y(:,na).*((x(1:end-n1)-a)'.^[1:n1])',1);
n2=7
D7y=zeros(n2,numel(x));
for k=1:1:n2
D7y(k,1:end-k)=dn(dx,k,y);
end
T7=y(na)+sum([1./factorial([1:n2])]'.*D7y(:,na).*((x(1:end-n2)-a)'.^[1:n2])',1);
figure(1);ax=gca
plot(ax,x(1:numel(T7)),T3(1:numel(T7)),'r')
grid on;hold on
xlabel('x')
plot(ax,x(1:numel(T7)),T7(1:numel(T7)),'b--')
plot(ax,x(1:numel(T7)),y(1:numel(T7)),'g')
axis(ax,[-1 1 -1.2 1.2])
legend('T3', 'T7','sin(pi*x)','Location','northeastoutside')
the support function being
function Yd = dn(h, n, vecX)
Yd = zeros(size(vecX));
for i = 1:n
Yd = (vecX(2:end) - vecX(1:end-1))/h;
vecX = Yd;
end
end
Explanation
1.- The custom function derivadan that I call dn shortens one sample for every unit up in grado where grado is the derivative order.
For instance, the 3rd order derivative is going to be 3 samples shorter than the input function.
This causes product mismatch and when later on attempting plot it's going to cause plot error.
2.- To avoid such mismatchs ALL vectors shortened to the size of the shortest one.
x(1:end-a)
is a samples shorter than x and y and can be used as reference vector in plot.
3.- Call function derivadan (that I call dn) correctly
dn expects as 3rd input (3rd from left) a vector, the function values to differentiate, yet you are calling derivadan with a in 3rd input field. a is scalar and you have set it null. Fixed it.
derivada3 = derivadan(0.01, 3, a);
should be called
derivada3 = derivadan(0.01, 3, y);
same for derivada7
4.- So
error using * ...
error in poly3=sin(pi*a) ...
MATLAB doesn't particularly mean that there's an error right on sin(pi*a) , that could be, but it's not the case here >
MATLAB is saying : THERE'S AN ERROR IN LINE STARTING WITH
poly3=sin(pi*a) ..
MATLAB aborts there.
Same error is found in next line starting with
poly7 ..
Since sin(pi*a)=0 because a=0 yet all other terms in sum for poly3 are repmat outcomes with different sizes all sizes being different and >1 hence attempting product of different sizes.
Operator * requires all terms have same size.
5.- Syntax Error
derivada3_vec = repmat(derivada3, size(x - a))
is built is not correct
this line repeats size(x) times the nth order derivative !
it's a really long sequence.
Now the EASY way
6.- MATLAB already has command taylor
syms x;T3=taylor(sin(pi*x),x,0)
T3 = (pi^5*x^5)/120 - (pi^3*x^3)/6 + pi*x
syms x;T3=taylor(sin(pi*x),x,0,'Order',3)
T3 = pi*x
syms x;T3=taylor(sin(pi*x),x,0,'Order',7)
T7 = (pi^5*x^5)/120 - (pi^3*x^3)/6 + pi*x
T9=taylor(sin(pi*x),x,0,'Order',9)
T9 =- (pi^7*x^7)/5040 + (pi^5*x^5)/120 - (pi^3*x^3)/6 + pi*x
It really simplfies taylor series development because it readily generates all that is needed to such endeavour :
syms f(x)
f(x) = sin(pi*x);
a=0
T_default = taylor(f, x,'ExpansionPoint',a);
T8 = taylor(f, x, 'Order', 8,'ExpansionPoint',a);
T10 = taylor(f, x, 'Order', 10,'ExpansionPoint',a);
figure(2)
fplot([T_default T8 T10 f])
axis([-2 3 -1.2 1.2])
hold on
plot(a,f(a),'r*')
grid on;xlabel('x')
title(['Taylor Series Expansion x =' num2str(a)])
a=.5
T_default = taylor(f, x,'ExpansionPoint',a);
T8 = taylor(f, x, 'Order', 8,'ExpansionPoint',a);
T10 = taylor(f, x, 'Order', 10,'ExpansionPoint',a);
figure(3)
fplot([T_default T8 T10 f])
axis([-2 3 -1.2 1.2])
hold on
plot(a,f(a),'r*')
grid on;xlabel('x')
title(['Taylor Series Expansion x =' num2str(a)])
a=1
T_default = taylor(f, x,'ExpansionPoint',a);
T8 = taylor(f, x, 'Order', 8,'ExpansionPoint',a);
T10 = taylor(f, x, 'Order', 10,'ExpansionPoint',a);
figure(4)
fplot([T_default T8 T10 f])
axis([-2 3 -1.2 1.2])
hold on
plot(a,f(a),'r*')
grid on;xlabel('x')
title(['Taylor Series Expansion x =' num2str(a)])
thanks for reading
I checked the line that you were having issues with; it seems that the error is in the derivada3_vec*(x - a) (as well as in the other terms that use derivada3_vec).
Looking at the variable itself: derivada3_vec is an empty vector. Going back further, the derivada3 variable is also an empty vector.
Your issue is in your function derivadan. You're inputting a 1x1 vector (a = [0]), but the function assumes that a is at least 1x2 (or 2x1).
I suspect there are other issues, but this is the cause of your error message.

I’m confused with how to convert RGB to YCrCb

Given that:
Y = 0.299R + 0.587G + 0.114B
What values do we put in for R,G, and B? I’m assuming 0-255. For arguments sake, if R, G, B are each 50, then does it mean Y=0.299(50) + 0.587(500) + 0.11(50)?
The next two are also confusing. How can B - Y even be possible if Y contains Blue then isn’t B - Y just taking away itself?
Cb = 0.564( B − Y )
Cr =0.713(R−Y)
It's just simple (confusing) math ...
Remark: There are few standards of YCbCr following formula applies BT.601, with "full range":
Equation (1): Y = 0.299R + 0.587G + 0.114B
The common definition of YCbCr assumes that R, G, and B are 8 bits unsigned integers in range [0, 255].
There are cases where R, G, B are floating point values in range [0, 1] (normalized values).
There are also HDR cases where range is [0, 1023] for example.
In case R=50, G=50, B=50, you just need to assign the values:
Y = 0.299*50 + 0.587*50 + 0.114*50
Result: Y = 50.
Since Y represents the Luma (line luminescence), and RGB=(50,50,50), is a gray pixel, it does make sense that Y = 50.
The following equations Cb = 0.564(B - Y), Cr = 0.713(R - Y) are incorrect.
Instead of Cb, and Cr they should be named Pb and Pr.
Equation (2): Pb = 0.564(B - Y)
Equation (3): Pr = 0.713(R - Y)
The equations mean that you can compute Y first, and then use the result for computing Pb and Pr.
Remark: don't round the value of Y when you are using it for computing Pb and Pr.
You can also assign Equation (1) in (2) and (3):
Pb = 0.564(B - Y) = 0.564(B - (0.299R + 0.587G + 0.114B)) = 0.4997*B - 0.3311*G - 0.1686*R
Pr = 0.713(R - Y) = 0.713(R - (0.299R + 0.587G + 0.114B)) = 0.4998*R - 0.4185*G - 0.0813*B
There are some small inaccuracies.
Wikipedia is more accurate (but still just a result of mathematical assignments):
Y = 0.299*R + 0.587*G + 0.114*B
Pb = -0.168736*R - 0.331264*G + 0.5*B
Pr = 0.5*R - 0.418688*G - 0.081312*B
In the above formulas the range of Pb, Pr is [-127.5, 127.5].
In the "full range" formula of YCbCr (not YPbPr), an offset of 128 is added to Pb and Pr (so result is always positive).
In case of 8 bits, the final result is limited to range [0, 255] and rounded.
What you're referencing is the conversion of RGB to YPbPr.
Conversion to YCbCr is as follows:
Y = 0.299 * R + 0.587 * G + 0.114 * B
Cb = -0.167 * R - 0.3313 * G - 0.5 * B + 128
Cr = 0.5 * R - 0.4187 * G - 0.0813 * B + 128
Yours is YPbPr (which is better for JPEG Compression, see below):
delta = 0.5
Y = 0.299 * R + 0.587 * G + 0.114 * B (same as above)
Pb: (B - Y) * 0.564 + delta
Pr: (B - Y) * 0.713 + delta
The above answer did a better job of explaining this.
I've been looking into JPEG Compression for implementation in Pytorch and found this thread (https://photo.stackexchange.com/a/8357) useful to explain why we use YPbPr for compression over YCbCr.
Pb and Pr versions are better for image compression because the luminance information (which contains the most detail) is retained in only one (Y) channel, while Pb and Pr would contain the chrominance information. Thus when you're doing down-sampling later down the line, there's less loss of valuable info.

How to get partial expression from symbolic expression containing specific variable MAPLE?

I have a symbolic expressions as below
y1 = (1/a)-(b/a^2)+x*a*b-x/b
y2 = a*b+a*x+b*sqrt(x)
now I need to get the partial expressions which have specific term. Like
xFunction(y1, x) # should return x*a*b-x/b
xFunction(y2,x) # should return a*x+b*sqrt(x)
any suggestions or idea are very healpful
Thank you
restart;
y1 := (1/a)-(b/a^2)+x*a*b-x/b:
y2 := a*b+a*x+b*sqrt(x):
K := (ee,x) -> `if`(ee::`+`,select(depends,ee,x),ee):
K( y1, x );
x
x a b - -
b
K( y2, x );
(1/2)
a x + b x
#
# Leave alone an expression which is not a sum of terms.
#
K( sin(x+4)*x^3, x );
3
sin(x + 4) x
#
# Don't select subterms in which `x` is a just dummy name.
#
K( x^3 + sin(x) + Int(sqrt(x), x=a..b), x );
3
x + sin(x)
[edited]
y1 := (1/a)-(b/a^2)+x*a*b-x/b;
1 b x
y1 := - - -- + x a b - -
a 2 b
a
op(3,y1);
x a b
depends(op(3,y1), x);
true
The select command maps its first argument over
all the operands of its second argument.
select( s->depends(s,x), y1 );
x
x a b - -
b
A more terse syntax, where select maps its first
argument depends over the operands of its second
argument, and passes its third argument as additional
options (to the selector).
select( depends, y1, x );
x
x a b - -
b
Now create a procedure to do it. Use a conditional
test, so that it returns the first argument itself
whenever that is not a sum of terms.
K1 := proc(ee, x)
if type(ee,`+`) then
select( depends, ee, x );
else
# leave it alone
ee;
end if;
end proc:
K1( y1, x);
x
x a b - -
b
Using a more terse syntax for that type-check.
K2 := proc(ee, x)
if ee::`+` then
select( depends, ee, x );
else
# leave it alone
ee;
end if;
end proc:
K2( y1, x);
x
x a b - -
b
Using a more terse syntax for that if..then..end if.
This is the so-called operator form of if. The word
if is within name-quotes, to distinguish it from the
language keyword within an if...then...end if .
K3 := proc(ee, x)
`if`( ee::`+` , select( depends, ee, x ), x );
end proc:
K3( y1, x);
x
x a b - -
b
Since the body of the procedure K3 has only a single statement then
we can make it more terse, using the so-called operator
form.
K4 := (ee, x) -> `if`( ee::`+` , select( depends, ee, x ), x ):
K4( y1, x);
x
x a b - -
b
listOfTerms = op(expression); # y1 or y2
numberOfSubExpressions=nops(expression); # for y1 or y2
requiredTerm = 0;
for i 1 to numberOfSubExpressions do
if has(listOfTerms [i], x) then # x is our required term
requiredTerm := requiredTerm +listOfTerms [i]
end if
end do
Above code does my requirement. But, if are there any bugs for special expressions please let me know. Because op function behaves differently when we have functions like(sin,cos Log ..etc)

How to obtain elements of an array close to another array in MATLAB?

There must be an easier way to do this, optimization method is also welcome. I have an array 'Y' and many parameters that has to be adjusted such that Y nears zero (= 'X') as given in the MWE. Is there a much better procedure to minimize this difference? This is just an example equation, there can be 6 coefficients to optimized.
x = zeros(10,1)
y = rand(10,1)
for a=1:0.1:4
for b=2:0.1:5
for c = 3:0.1:6
z = (a * y .^ 3 + b * y + c) - x
if -1<= range(z) <= 1
a, b, c
break
end
end
end
end
I believe
p = polyfit(y,x,2);
is what you are looking for.
where p will be an array of your [a, b, c] coefficients.

formatting data inputs for Matlab streamline function

I'm attempting to draw streamlines for a two-dimensional vector field. I have the data in a two-dimensional array with one column each containing the X coordinate, y-coordinate, horizontal velocity, and vertical velocity. I'm attempting to use the streamline function but I'm having trouble figuring out how to format the input data correctly.
I know that each input matrix should be the same size. So I have attempted to use the following to get workable inputs:
[X Y]= meshgrid(sf(1:250:end,1), sf(1:250:end, 2));
[U V]= meshgrid(sf(1:250:end,3), sf(1:250:end,4));
But my velocity matrices obviously no longer make sense compared to my locations.
I'm at a bit of a loss so any help would be awesome.
You may use griddata to re-arrange your data into a regular grid
f = min( sf(:,1:2), [], 1 ); %// XY grid starting points
t = max( sf(:,1:2), [], 1 ); %// XY endpoints
[X Y] = meshgrid( linspace( f(1), t(1), 50 ), linspace( f(2), t(2), 50 ) ); %//grid
U = griddata( sf(:,1), sf(:,2), sf(:,3), X, Y );
V = griddata( sf(:,1), sf(:,2), sf(:,4), X, Y );
startx = ; %// define streamline starting points
starty = ; %//
streamline( X, Y, U, V, startx, starty );

Resources