fsolve solves a problem specified by
F(x)=0
for x. In my case, x is a 2-dimensional array of size m x n. Now suppose
that in addition to x, there is a vector y that needs to be solved for
as well. What is the best way to expand the number of variables fsolve
solves for, given that fsolve only allows for a single argument?
One solution, one that I would like to avoid, is to rewrite the problem in
terms of a single vector with entries of x and y stacked as in
x(1) ... x(m x n), y(1) ... y(m-1)
I would like to avoid this solution because the equations for the first set
of variables can be nicely defined in 2 dimensions.
Would it be possible to create a 3-dimensional array of size m x n x 2 where the first page (the 3rd dimension in Matlab terminology) is the original x-matrix and the entries of y appear on the second page? But then, what is if y is only of size m-1 so that the second page is largely empty? Would this be possible somehow?
EDIT
Here is a simplied version of the model with m=n=2.
The equations in the first set are
x(1,1)*dot(k1,y)-y(1) = 0;
x(1,2)*dot(k2,y)-y(1) = 0;
x(2,1)*dot(k1,y)-y(2) = 0;
x(2,2)*dot(k2,y)-y(2) = 0;
where k1 and k2 are two vectors of parameters.
When m=n=2, the second set of equations consists of a single equation of the form
y(1)*dot(c1,x(1,:)) + y(2)*dot(c2,x(2,:)) = 0
Where c1 and c2 are two vectors of parameters. The last entry of y, here y(2), is always a parameter.
You can combine them into a single vector but you don't need to modify F. For example suppose you have a function F(x, y) where x and y are arbitrarily sized then something like the following should work
function [x, y] = fsolve2(F, x0, y0)
% flatten x0 and y0 into a single column vector
xy0 = [x0(:); y0(:)];
% utility functions for recovering x and y from combined vector
xstart = 1;
xend = xstart + numel(x0) - 1;
xsize = size(x0);
getx = #(xy) reshape(xy(xstart:xend), xsize);
ystart = xend + 1;
yend = ystart + numel(y0) - 1;
ysize = size(y0);
gety = #(xy) reshape(xy(ystart:yend), ysize);
% define G which takes xy and calls F
G = #(xy) F(getx(xy), gety(xy));
xy = fsolve(G, xy0);
% unwrap xy into x and y
x = getx(xy);
y = gety(xy);
end
which could be called with
x, y = fsolve2(F, x0, y0);
Related
I have a function to evaluate and I want to graph it point by point. But the function only gives me a value and not the set of evaluated values.
rho = 0.999;
n = -10:1:10;
x = (rho.^(n))*(1 - rho)
y = 1 - (rho.^(n + 1))
Pb = x/y
plot(n, Pb)
x is a 1x21 double array just like y but my evaluated function Pb is a single value, not a set of evaluated values. Therefore I do not get my graph
What is the problem with the code?
I'm assuming you want to divide each element of x by its corresponding y? Fix the line
Pb = x./ y;
I'm trying to come up with an equation that relates the index of a value within a 3D array, to the index of the same array but reshaped into a column vector.
Consider the following.
A = randi([1,10],3,2,2);
A2 = reshape(A,3*2*2,1);
A and A2 have the same number of elements, but the arrangement of the elements is different for each array. If I lay out a possible example for A and A2 here it is clear geometrically how each index lines up.
A(:,:,1) = [9 10; 10 7; 2 1]
A(:,:,2) = [3 10; 6 2; 10 10]
A2 = [9; 10; 2; 10; 7; 1; 3; 6; 10; 10; 2; 10]
Let's say n=1:1:3*2*2, this is an array that is the same length as A2 and numbers each of the elements. The value of A(2,2,2)=2 and has indices [i,j,k]=[2,2,2]. I would like to have an equation relating i, j, k, and n.
I've looked into the built-in functions ind2sub and sub2ind but it seems that I inadvertently shaped my i, j, and k coordinates (which correspond with real x, y, and z points) differently than how MatLab does. This makes it difficult for me to change everything now, and is why I need an equation.
The conversion between 3D index and linear (1D) index is given by:
n=i+(j-1)*M + (k-1)*M*N
The reverse can be obtained recursively as:
k = floor((n-1)/(M*N)) +1
n = n - (k-1)*M*N
j = floor((n-1)/M) + 1
i = n - (j-1)*M
I haven't tested it, but I think it will give you what you are expeccting.
How can I for every element of a vector calculate several elements from another vector?
For example, x=[1,2] and y=[1,2,3,4] then I need to multiply and sum each element of x with all elements of y, like so;
x = [1,2]
y = [1,2,3,4]
z = [x1*y,x2*y] = [x1*y1+x1*y2+x1*y3+x1*y4,x2*y1+x2*y2+x2*y3+x2*y4]
The vectors can have unlimited elements.
x = randi(10,3,1);
y = randi(10,4,1);
tmp = bsxfun(#times,x.',y); % Pre-R2016b
% tmp = x.'*y; % Post R2016b method
out = sum(tmp(:));
One can use either bsxfun or implicit expansion to create a matrix of numel(x) * numel(y) size and then sum over the flattened array to get to a final result.
You can multiply x with sum of y
result = x * sum(y)
In Matlab, I have a 3D-curve (array with 3 coordinates) that crosses the xy-plane in a 3 dimensional coordinate system. The "curve" is just a bunch of x,y,z points and its shape is elliptical that spans across the 3D space and spirals towards the origin. It crosses the xy plane several times and I would like to interpolate the x and y coordinates when the curve intersects the xy plane (i.e. when z=0). How do I do so?
Assuming you have 3 vectors x, y, and z with coordinates,
crossidx = find(diff(sign(z)) ~= 0); % z(zcross) and z(zcross+1) have different signs
z1 = z(crossidx);
z2 = z(crossidx+1);
dz = z2 - z1;
alpha = -z1;
beta = z2;
xcross = (beta*x(crossidx) + alpha*x(crossidx+1))./dz;
ycross = (beta*y(crossidx) + alpha*y(crossidx+1))./dz;
zcross = 0;
hold on; plot3(xcross, ycross, zcross, '*');
It should work for either positive to negative or negative to positive crossing. I wrote the code assuming only 1 zero crossing, but I think it would also work for any number of crossings.
This is in C.
I have two 2D arrays, ArrayA and ArrayB, that sample the same space. B samples a different attribute than ArrayA less frequently than ArrayA, so it is smaller than A.
Just to try to define some variables:
ArrayA: SizeAX by SizeAY, indexed by indexA for a position posAX, posAY
ArrayB: SizeBX by SizeAY, indexed by indexB for a position posBX, posBY
ArrayA and ArrayB are pointers to the start of the array, where the row of X's is stored first, then Y is incremented, and the next row of X's is stored (Y=1)
So I need to set indexB from a given indexA, such that it is a nearest neighbor sample, to associate with indexA's value.
Here's where I am (correct any errors please! Note that I am starting at index 0):
If ArrayA is 9x9 and ArrayB is 3x3:
(posX,posY)
posA 0,0; indexA = 0
posB 0,0; indexB = 0
posA 8,0; indexA = 8 (end of first row)
posB 2,0; indexB = 2
posA 0,1; indexA = 9
posB 0,0; indexB = 0 (still closer to the bottom point)
posA 0,3; indexA = 27
posB 0,1; indexB = 3
posA 8,8; indexA = 80 (last point)
posB 2,2; indexB = 8
so far I have:
indexA = posAX + (posAY * SizeAX)
what I've tried (and of course failed):
indexB = (int) (indexA * (SizeBX * SizeBY / (SizeAX * SizeAY)) + 0.5) // Only appears to work for the first row and last value.. but this clearly doesn't work - but I am curious as to how exactly it maps the two together, but I'll look into that after I fix it..
I didn't have access to posAY or posAX, just indexA, but I should be able to break it down using mod and remainder, right? or is there a more efficient faster way? A
I also tried this:
indexB = (posAY * SizeBY / SizeAY) * SizeBY + (posAX * SizeBX / SizeAX)
I think the problem is that I need to round the X and Y indexes separate then use SizeBX and SizeBY afterwards?
An extra caveat is that ArrayA and ArrayB come from larger data set that both sample a larger space. Since the rectangle is arbitrary, either ArrayA or ArrayB could have the point closest to the bounds of the rectangle, leading to other issues as to which way the nearest neighbor is really grabbing. I am not sure about how to address this, either.
Those are some revolting names you've chosen, but at least they're defined.
I think you want to go through (x,y) in [0...1]x[0...1] real coordinate space; that is, the lower right of A should grab the value from the lower right of B, and likewise for mid-upper-left, etc. This means that you should think of the outside edges of points in your array as the 0-width point samples values at the edges of the [0...1]x[0...1] box; i.e. if you have a 3x3 array, there's one point at (0.5,0.5) and the rest are along an edge.
I'll assume your 2d B array has real values in it, so that it makes sense to interpolate; because the arrays are of different sizes
Here's the scheme for going from a
indexA -> (posAX,posAY) -> (x,y) -> (fracBX,fracBY) ->(by nearest neighbor interpolation) value from ArrayB
Important: (fracBX,fracBY) are real-valued coordinates in the box [0...SizeBX-1]x[0...SizeBY-1].
Let's take it one step at a time. Assuming I understood you, values are in memory in left->right, top->bottom (english reading) order, just like standard C arrays. Then:
unsigned posAX=indexA%SizeAX;
unsigned posAY=indexA/SizeAX;
Now, let's map to (x,y):
double x=posAX/(SizeAX-1.0); // we get double division when we subtract by 1.0
double y=posAY/(SizeAY-1.0);
Now, to (fracBX,fracBY), where 0<=fracBX<=SizeBX and 0<=fracBY<=SizeBY:
double fracBX=x*(SizeBX-1);
double fracBY=y*(SizeBY-1);
Now, to interpolate between the (up to 4) nearest integral points in the B array:
unsigned intBX=(unsigned)fracBX;
double aBX=fracBX-intBX;
unsigned intBY=(unsigned)fracBY;
double aBY=fracBY-intBY;
double *bv=ArrayB+(intBX*sizeBY)+intBY;
#define INTERP(alpha,v1,v2) ((1-alpha)*v1+alpha*v2)
#define INTERPI(alpha,i1,i2) (alpha>0 ? INTERP(alpha,bv[i1],bv[i2] : bv[i1])
double v0=INTERPI(aBX,0,1);
double value=fracBY>0 ? INTERP(aBY,v0,INTERPI(aBX,sizeBY,sizeBY+1)) : v0;
value is your answer. The checks for the fractional positions aBX and aBY being 0 are needed to prevent accessing values off the end of the array (which can cause a segfault even though the values are ignored by multiplying by 0). Or you can simplify things by allocating 1 more row/column than you need.
bv[0] is the ArrayB[intBX][intBY], bv[1] is one to the right, bv[sizeBY] is one down, and bv[sizeBY+1] is one down and to the right. (aBX,aBY) is another point in [0...1]x[0...1], but this time bounded by those four adjacent points in ArrayB.
What you essentially mean is that you have two grids with different spacing covering the same area and given an index of a gridpoint in one of them you want to find the closest one in the second. Like this:
int posBX = (int)floorf((float(posAX) / float(sizeAX - 1)) * float(sizeBX - 1) + 0.5f);
int posBY = (int)floorf((float(posAY) / float(sizeAY - 1)) * float(sizeBY - 1) + 0.5f);
int indexB = posBX + posBY * sizeBX;
To get posAX and posAY from indexA:
posAX = indexA % sizeAX;
posAY = indexA / sizeAX;
To do bilinear interpolation:
float bx = (float(posAX) / float(sizeAX - 1)) * float(sizeBX - 1);
float by = (float(posAY) / float(sizeAY - 1)) * float(sizeBY - 1);
int x = min(int(floorf(bx)), sizeBX - 2); //x + 1 must be <= sizeBX - 1
int y = min(int(floorf(by)), sizeBY - 2); //y + 1 must be <= sizeBY - 1
float s = bx - float(x);
float t = by - float(y);
float v[4];
v[0] = arrayB[x + y * sizeBX];
v[1] = arrayB[x + 1 + y * sizeBX];
v[2] = arrayB[x + (y + 1) * sizeBX];
v[3] = arrayB[x + 1 + (y + 1) * sizeBX];
float result = (v[0] * (1.0f - s) + v[1] * s) * (1.0f - t) +
(v[2] * (1.0f - s) + v[3] * s) * t;