Problem Details and clues
%For this problem write a script file called NC.m that implements
%the Newton-Cotes method of integration for an arbitrary function f(x). It
%should take as inputs the function and the limits of integration [a: b] and
%output the value of the definite integral. Specifically, you should use the
%Trapezoid rule as presented in Equation (11.73)
function [f]= NC(a,b,fun) %newton-cotes
%a and b are limits of intergration
%setting it up
f(a)= fun(a); %y value for lower limit
f(b)= fun(b); %y value for upper limit
%the actual function
f= (b-a)*(f(a)+f(b))/2;
end
What am i doing wrong? When I type, [f]= NC(-3,0,fun) and set fun= #(x)normpdf(x) . it keeps on returning "Array indices must be positive integers or logical values". Can someone shine some light on this?
The issue is that you try to assign to f(a) where a=0, so you mixed between a vector index and value, as well as use f for two different purposes, one as the output of the function NC, and one for the value of fun(x), that's not a good idea.
Instead you can define the output in a separate variable:
fa=fun(a);
fb=fun(n);
f=(b-a)*(fa+fb)/2;
or just write: f=(b-a)*(fun(a)+fun(b))/2;
The problem lies in the assignments to f(a) and f(b).
The syntax f(x) has three interpretations in MATLAB that are dependent on the type of f:
indexing the array f using the strictly positive integer index (or logical index) x
evaluation of the function handle f using the value of the variable x
manipulation, in some manner, of the symbolic functionf(x) using the symbolic variable x.
Due to MATLAB's dynamic typing and defaulting to double arrays, MATLAB is interpreting the assignments to f(a) and f(b) as the item (1): MATLAB is taking f to be a double array and is expecting a and b to be valid indexes into the array.
Per your intent then, a simple assignment to variable symbols without the parentheses (e.g., fa and fb) should solve your problem.
Related
I'm trying to vectorize one function in Matlab, but I have a problem with assigning values.
function [val] = clenshaw(coeffs,x)
b=zeros(1,length(coeffs)+2);
for k=length(coeffs):-1:2
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
end
val=coeffs(1)-b(3)+b(2).*x;
The purpose of this function is to use Clenshaw's algorithm to compute a value of one polynomial with coefficients "coeffs" at point x.
It work fine when x is a single value, but I'd like it to work with vector of arguments too.
When I try to pass a vector I get an error:
Unable to perform assignment because the left
and right sides have a different number of
elements.
Error in clenshaw (line 7)
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
I understand that there is a problem, because I'm trying to assign vector to a scalar variable b(k).
I tried making b a matrix instead of a vector, however I still cannot get the return output I'd like to have which would be a vector of values of this function at points from vector x.
Thank you for helping and sorry if something isn't entirely clear, because English is not my native language.
The vectorized version of your function looks like this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(x),length(coeffs)+2);
for k=length(coeffs):-1:2
b(:,k)=coeffs(k)-b(:,k+2)+2*b(:,k+1).*transpose(x);
end
val=coeffs(1)-b(:,3)+b(:,2).*transpose(x);
end
b needs to be a matrix. In your loop, you have to perform every operation per row of b. So you need to write b(:,k) instead of b(k). Since b(:,k) is a vector and not a scalar, you also have to be careful with the dimensions when using the .* operator. To get the correct results, you need to transpose x. The same goes for the calculation of val. If you don't like the transposition, just swap the rows and cols of b and you get this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(coeffs)+2, length(x));
for k=length(coeffs):-1:2
b(k,:)=coeffs(k)-b(k+2,:)+2*b(k+1,:).*x;
end
val=coeffs(1)-b(3,:)+b(2,:).*x;
end
However, the first version returns a column vector and the second a row vector. So you might need to transpose the result if the vector type is important.
I am trying to write a function in MATLAB that takes 1x3 vectors as input. My code looks something like this:
function myFunction=([x1, x2, x3], [y1, y2, y3], [z1, z2, z3])
where all inputs are numbers, and then in the body of the function I perform some calculations indexing through the numerical values in the vectors. i want the vectors to be user input, so the user will enter the vectors and their components (x1, x2, etc.) into the function argument. However, I am getting an error saying "Invalid expression. When calling a function or indexing a variable, use parentheses. Otherwise, check for mismatched delimiters." Therefore I believe I either have the syntax or something else wrong. I know MATLAB is supposed to be able to take vector input in functions, so please let me know what I am doing wrong. Thanks!
What you need to do is declare your function like this:
function myFunction(x,y,z)
% your function code here
end
Then within your function you can access the individual elements of the vectors using x(1), y(2), etc.
To call the function, including whatever number you like, you can enter on the Matlab command window (for example),
myFunction([1 2 3],[4 5 6],[7 8 9]) and the code in your function will be called with the x variable set to the vector [1,2,3], the y variable set to [4,5,6] and z to [7,8,9]. The use of commas to delineate values is optional. If your function then accesses y(2) it will get the second value of the y vector which will be 5 - it is important to note that indexing in Matlab is 1-based so the 1st element of x is obtained with x(1).
If you need to return values you can use:
function [a,b,c] = myFunction(x,y,z)
Then just assign the a, b or c in your code before the end statement.
See the offical Matlab documentation for more info.
I would add that much of the advantage of matlab is dealing with data in a vectorised form, so if you can avoid splitting out into separate elements I would do so. For example, if you need to add two vecors, you could do z = [x(1)+y(1), x(2)+y(2), x(3)+y(3)], but much better (more readable, more maintainable, faster) is z=x+y.
The situation I have is as follows:
I have a symbolic expression like:
syms X Y Z K
Ra=51.7;
P=[0 0 200];
Sa=sym('Ra^2==(Z-P(3))^2+(Y-P(2))^2')
Where Y and Z are defined as symbolic. Ra and P are vectors.
I need to get the gradient of Sa but I get an error:
G=gradient(Sa,[Y Z]);
Error using symengine (line 59)
The first argument must be of type 'Type::Arithmetical'.
Error in sym/gradient (line 39)
res = mupadmex('symobj::gradient',fsym.s,x.s);
But if I write the same expression as:
Sa(Y,Z)=((Z-P(3))^2+(Y-P(2))^2-Ra^2);
I get the expected result
G=gradient(Sa,[Y Z])
G(X, Y, Z) =
2*Y
2*Z - 400
Does anyone knows why this is so and if there's any way of using the implicit expression as this is a particular case but in general I have different implicit expressions and my code should be able to deal with them.
I've read the documentation on gradient and some sites, but if I found the answer I didn't notice.
I believe I could use the second form but still, I am curious about this subject.
Thanks for your time.
In the first one Sa is the entire equation, including the ==, while in the second one its a symbolic function depending on 2 variables.
Ultimately the way MATLAB seems to be handle this is that the first one is not derivable (also its dependent in another 2 sym variables, that doesn't know if they are related or not to the derived ones), while the second one gets identified as a function (symbolic) and can get derived.
I am trying to find the roots of a nonlinear function that depends on several symbolic variables and a symbolic function. To guarantee the existence of a solution I need to set some assumptions on the symbolic function b(x).
By using the Matlab function assume I can set simple assumptions like
syms b(x) d
assume(b(0)==0 & b(x)>=0);
Now I am looking for a way to include this assumption: (symbolic function b(x), symbolic variable d)
There is a value y such that b(x) < d*x for x < y and b(x) > d*x for x > y.
To make it easier we can fix for example d=0.1 and b(10)=1 such that y=10. However I would prefer leaving d and y symbolic.
I tried to write a function that checks the assumption but unsurprisingly Matlab does not seem to accept a symbolic function as an input variable.
Do you know a solution to this problem or have an idea?
Update 2017-01-03:
While having fixed d=0.1,b(10)=1 and y=10 I am trying to check the above assumption by using
syms b(x)
d=0.1;
assume(x, 'real');
assume(x>=0);
assume(b(0)==0 & b(x)>=0 & b(10)==1);
checkAssumption(x)= mySign(x)*(d*x-b(x));
assume(checkAssumption(x)>=0);
where
function sign=mySign(x)
if x<10
sign=-1;
else if x==10
sign=0;
else if x>10
sign=-1;
end
end
end
Then I get the error "Conversion to logical from sym is not possible." in mySign. Using double(x) as the input variable of mySign leads to the error "DOUBLE cannot convert the input expression into a double array".
Do you know a way to get mySign and checkAssumptions evaluated or have an other idea how to assume the above assumption?
Good evening everyone,
I want to create a function
f(x) = [f1(x), f2(x), ... , fn(x)]
in MatLab, with an arbitrary form and number for the fi. In my current case they are meant to be basis elements for a finite-dimensional function space, so for example a number of multi variable polynomials. I want to able to be able to set form (e.g. hermite/lagrange polynomials, ...) and number via arguments in some sort of "function creating" function, so I would like to solve this for arbitrary functions fi.
Assume for now that the fi are fi:R^d -> R, so vector input to scalar output. This means the result from f should be a n-dim vector containing the output of all n functions. The number of functions n could be fairly large, as there is permutation involved. I also need to evaluate the resulting function very often, so I hope to do it as efficiently as possible.
Currently I see two ways to do this:
Create a cell with each fi using a loop, using something like
funcell{i}=matlabFunction(createpoly(degree, x),'vars',{x})
and one of the functions from the symbolic toolbox and a symbolic x (vector). It is then possible to create the desired function with cellfun, e.g.
f=#(x) cellfun(#(v) v(x), funcell)
This is relatively short, easy and what can be found when doing searches. It even allows extension to vector output using 'UniformOutput',false and cell2mat. On the downside it is very inefficient, first during creation because of matlabFunction and then during evaluation because of cellfun.
The other idea I had is to create a string and use eval. One way to do this would be
stringcell{i}=[char(createpoly(degree, x)),';']
and then use strjoin. In theory this should yield an efficient function. There are two problems however. The first is the use of eval (mostly on principle), the second is inserting the correct arguments. The symbolic toolbox does not allow symbols of the form x(i), so the resulting string will not contain them either. The only remedy I have so far is some sort of string replacement on the xi that are allowed, but this is also far from elegant.
So I do have ways to do what I need right now, but I would appreciate any ideas for a better solution.
From my understanding of the problem, you could do the straightforward:
Initialization step:
my_fns = cell(n, 1); %where n is number of functions
my_fns{1} = #f1; % Assuming f1 is defined in f1.m etc...
my_fns{2} = #f2;
Evaluation at x:
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
For example if you put it in my_evaluate.m:
function z = my_evaluate(my_fns, x)
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
How might this possibly be sped up?
Depends on if you have special structure than can be exploited.
Are there calculations common to some subset of f1 through fn that need not be repeated with each function call? Eg. if the common calculation step is costly, you could do y = f_helper(x) and z(i) = fi(x, y).
Can the functions f1...fn be vector / matrix friendly, allowing evaluation of multiple points with each function call?
The big issue is how fast your function calls f1 through fn are, not how you collect the results from those calls in a vector.