Help needed to fix a matlab code

  • MATLAB
  • Thread starter PainterGuy
  • Start date
  • #1
690
33

Main Question or Discussion Point

Hi

Could you please help me to fix the code below? I know that the code is completely wrong but I have tried to write it down so that you can get an idea what I'm trying to do. Thank you.

Code:
    %%file name fourier.m
    clear all; close all; clc;
    f = 0; %% 0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
    cos_v=[1:1:1000]; %%vector to store values
    f_w=[]; %% defining a vector

    for i1=[0:1000]; %% for loops begins, with loop index i1
    f_w = sqrt(1/(4*f));
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
    f=f+0.1;
    end
    combined_sinusoids=sum(cos_v); %% cos_v(1)+cos_v(2)+cos_v(3)+...
    x = [0:0.2:500];
    y = combined_sinusoids;
    plot(x, y)
 

Answers and Replies

  • #2
FactChecker
Science Advisor
Gold Member
5,706
2,112
I think you probably should describe what you are trying to do. Looking at the code, it looks like you end up plotting a single constant value, y = combined_sinusoids, on an XY plot.
 
  • #3
690
33
Thank you for the reply.

I'm trying to understand Fourier transform and wanted to analyze something, and that code is a result of that effort. Explaining the problem in full detail here would be little difficult because so far I haven't organized all my effort.

But let me try. F(f)=f(w)=sqrt(1/(4*f)) is cosine Fourier transform of f(x)=1/sqrt(x). I'm trying to see how well first 100 sinusoids represent f(x).

Thank you.
 
  • #4
FactChecker
Science Advisor
Gold Member
5,706
2,112
I see. I had lost track of the dimensions. What makes you think it is wrong? Is the plot all wrong? Or does it abort with an error message before that? If there are error messages or if you print intermediate steps (reduce the dimensions to see a reasonably small number of values), then you may get some hints.

PS. I do not have access to MATLAB, so I can't experiment with your code at all.
 
  • #5
690
33
Thank you.

The code doesn't compile. You don't have MATLAB installed or you are just away from your system? Anyway, let's see if someone else jumps in to help. Anyway, thanks.
 
  • #6
FactChecker
Science Advisor
Gold Member
5,706
2,112
Is that a 0 array index in cos_v(i1) on line 9? That looks wrong. When MATLAB doesn't compile, it usually tells you what line it has problems with and why. You should indicate what it said.

PS. Retired. No MATLAB at home. I'm thinking about buying it.
 
  • Like
Likes PainterGuy
  • #7
DrClaude
Mentor
7,341
3,528
Matlab:
    f = 0; %% 0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
Why not make f a vector containing the frequencies?

Matlab:
cos_v=[1:1:1000];
This statement doesn't make sense. In any case, it doesn't appear that cos_v needs to contain any initial value, so use
Code:
cos_v = zeros(1000);
Matlab:
 %%vector to store values
    f_w=[]; %% defining a vector
This statement is pointless. Again, use zeros to initialize f_w to the right size.

Matlab:
    for i1=[0:1000]; %% for loops begins, with loop index i1
Thesis not the correct syntax for a for loop. And if you define f as a vector, the loop can be replaced by vector operations, which are much more efficient.

Matlab:
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
What is x?

Matlab:
    combined_sinusoids=sum(cos_v); %% cos_v(1)+cos_v(2)+cos_v(3)+...
    x = [0:0.2:500];
    y = combined_sinusoids;
    plot(x, y)
combined_sinusoids will be a scalar, so y will be a constant. The statement for x is also incorrect, see above.
 
  • Like
Likes PainterGuy and FactChecker
  • #8
690
33
Thank you, @FactChecker, @DrClaude.

I believe MATLAB treats every variable (even a constant) as a vector. A vector is a one-dimensional array and a matrix is two-dimensional array.

Why not make f a vector containing the frequencies?
I've experience with C++ so I'd tend to stick the syntax of C++ so as I learn more about MATLAB I'll think more in MATLAB terms.

This statement is pointless. Again, use zeros to initialize f_w to the right size.
How do we define a variable in MATLAB if the require size is not known?

Thesis not the correct syntax for a for loop. And if you define f as a vector, the loop can be replaced by vector operations, which are much more efficient.
I've seen that mostly for loop is defined as, say, "for index=0:1000:. But I don't see why "for i1=[0:1000]" is wrong; yes, we can say that brackets are unnecessary.

What is x?
"x" could be a floating-point variable and it can take values from 0 to infinity. In C++ it could be written as "float x;"

combined_sinusoids will be a scalar, so y will be a constant. The statement for x is also incorrect, see above.
Yes, I want to evaluate the value of function combined_sinusoids for particular values of 'x'.

I hope it's little better now. I'm posting the code with some revisions and also the error. Thank you.

Code:
%%file name fourier.m
    clear all; close all; clc;
    f = [0]; %%defining and initializing a constant vector
           %%0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
    cos_v=zeros(1000); %%defining and initializing vector to store values
                       %%a vector with 1000 zeroes
    f_w=[0]; %% defining and initializing a vector
    double x; %%"x" is a floating point variable which can take values from 0 to
                   %%infinity, in C++ we could have written "float x" or "double x"

    for i1=[0:1000]; %% for loops begins, with loop index i1
    f_w = sqrt(1/(4*f));
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
    f=f+0.1;
    f_w=0
    end
    combined_sinusoids=sum(cos_v); %% cos_v(1)+cos_v(2)+cos_v(3)+...
    y = combined_sinusoids;
    plot(x, y)
Error:
Code:
??? Undefined function or variable 'x'.

Error in ==> fourier_new at 13
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
 
  • #9
FactChecker
Science Advisor
Gold Member
5,706
2,112
The default data type in MATLAB is double, so your "double x" statement is not doing anything for you. You should delete it. But I don't see any assignment of values to x before it is used in that line.
 
Last edited:
  • Like
Likes PainterGuy
  • #10
690
33
Thank you.

But if I don't define "x" then how am I going to use it in the expression below?
Code:
cos_v(i1)=f_w*cos(2*pi*f*x);
It's going to be undefined variable.
 
  • #11
FactChecker
Science Advisor
Gold Member
5,706
2,112
You have to initialize x to some values. It's not enough to just say what it's type is. Put your "x = [0:0.2:500];" line up before x is used in a calculation.
 
  • #12
690
33
Thank you.

You have to initialize x to some values. It's not enough to just say what it's type is. Put your "x = [0:0.2:500];" line up before x is used in a calculation.
Should I really do it? I don't think so because that's not what I'm trying to do. If x is initialized then the expression "cos_v(i1)=f_w*cos(2*pi*f*x)" will be evaluated for all elements of vector x each iteration of the loop. I experimented with it; see below. I want to evaluate the expression "combined_sinusoids" later for different values of "x".

Code:
 x = [0:0.2:1]

x =

         0    0.2000    0.4000    0.6000    0.8000    1.0000

>> cos(2*pi*0.1*x)

ans =

    1.0000    0.9921    0.9686    0.9298    0.8763    0.8090
 
  • #13
FactChecker
Science Advisor
Gold Member
5,706
2,112
If x is initialized then the expression "cos_v(i1)=f_w*cos(2*pi*f*x)" will be evaluated for all elements of vector x each iteration of the loop. I experimented with it; see below. I want to evaluate the expression "combined_sinusoids" later for different values of "x".
The equation for cos_v(i1) is evaluating a number or array of numbers. It is not defining a function of x. So x must have a value or array of values for the calculations at that point. If you set x to a single value, then that will be all you get. Since the equation for cos_v(i1) is not in a loop which changes the value of x, you will only end up with one number for it.

To develop this type of code, I like to reduce the dimensions to a small number and print intermediate results after each calculation. The dimensions can be increased once you are satisfied that the code is working as expected.
 
  • Like
Likes PainterGuy
  • #14
690
33
Thank you.

Actually I don't want to assign any value to x until later once the loops end. Please have a look here: https://www.mathworks.com/matlabcen...efine-a-variable-without-assigning-it-a-value

I'm not getting another error about dimension but it looks like that there shouldn't be any problem with the dimensions.

Code:
%%file name fourier.m
    clear all; close all; clc;
    f = [0.1]; %%defining and initializing a constant vector
           %%0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
    cos_v=zeros(1000); %%defining and initializing vector to store values
                       %%a vector with 1000 zeroes
    f_w=[0]; %% defining and initializing a vector
    x=[]; %%"x" is a floating point variable which can take values from 0 to
    %%infinity, in C++ we could have written "float x"

    for i1=[1:1000] %% for loops begins, with loop index i1
    f_w = sqrt(1/(4*f));
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
    f=f+0.1;
    f_w=0;
    end
    combined_sinusoids=sum(cos_v); %% cos_v(1)+cos_v(2)+cos_v(3)+...
    y = combined_sinusoids;
    plot(x, y)
Error:
Code:
???  In an assignment  A(I) = B, the number of elements in B and
 I must be the same.

Error in ==> fourier_new at 13
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
 
  • #15
FactChecker
Science Advisor
Gold Member
5,706
2,112
So what value would you calculate for cos(2*pi*f*x) when x has no value? This is not a programming question. It is a trigonometry question.
 
Last edited:
  • #16
DrGreg
Science Advisor
Gold Member
2,290
895
@PainterGuy, it seems you want to plot y as a function of x, and you think the way to do this is specify the formula for y in terms of x without specifying what x is, and then just say plot(x, y). MATLAB doesn't work like that. You have to specify the values of x that you want to plot (i.e. define x as a vector x = xmin:xstep:xmax), and you have to do that before you specify what y is (or any other expression involving x).
 
  • Like
Likes PainterGuy
  • #17
690
33
Thank you.

I get your point. Please note that I'm learning Matlab.

I made few changes but still it's giving an error.

Code:
%%file name fourier.m
    clear all; close all; clc;
    f = [0.1]; %%defining and initializing a constant vector
           %%0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
    cos_v=zeros(1000); %%defining and initializing vector to store values
                       %%a vector with 1000 zeroes
    f_w=[0]; %% defining and initializing a vector
    syms x; %%"x" is a floating point variable which can take values from 0 to
            %%infinity, in C++ we could have written "float x"

    for i1=[1:1000] %% for loops begins, with loop index i1
    f_w = sqrt(1/(4*f));
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
    f=f+0.1;
    f_w=0;
    end
    combined_sinusoids=sum(cos_v); %% cos_v(1)+cos_v(2)+cos_v(3)+...
    y = combined_sinusoids;
    x=linspace(0,10,2000);
    plot(x, y)
Error:
Code:
??? The following error occurred converting from sym to double:
Error using ==> mupadmex
Error in MuPAD command: DOUBLE cannot convert the input expression into a double array.

If the input expression contains a symbolic variable, use the VPA function instead.

Error in ==> fourier_new at 13
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
 
  • #18
DrGreg
Science Advisor
Gold Member
2,290
895
But you are still putting x=linspace(0,10,2000) in the wrong place. It needs to go before the loop, i.e. replace your line syms x. There are other changes you will need to make as well, but that's definitely where you need to specify the values that x takes.
 
  • Like
Likes PainterGuy
  • #19
690
33
Thank you.

The following sample code could help you to see what I'm trying to do. The code works fine. I have made few changes to the main code but as you pointed out it requires more fixes. Could you please guide me how to proceed?

Sample Code:
Code:
clc; clear;

'This program will calculate values of cosine function'

syms t; %% t (time) is a symbolic variable and can be assigned any value
syms f; %% f (frequency) is a symbolic variable and can be assigned any value

f = input('Enter value of f: ');
t = input('Enter value of t: ');
y=cos(2*pi*f*t);
fprintf('The value of cos(2*pi*f*t) is %d \n',y)
Main Code:
Code:
    %%file name fourier.m
    clear all; close all; clc;
    f = [0.1]; %%defining and initializing a constant vector
                  %%0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
    cos_v=zeros(1000); %%defining and initializing vector to store values
                                      %%a vector with 1000 zeroes
    f_w=[0]; %% defining and initializing a vector, fourier transfor,
    syms x; %%"x" is a floating point variable which can take values from 0 to
            %%infinity, in C++ we could have written "float x"

    for i1=[1:1000] %% for loops begins, with loop index i1
    f_w = sqrt(1/(4*f)); %% fourier transform
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
    f=f+0.1; %%incrementing f
    f_w=0; %%setting f_w=0 for next iteration
    end
   
    combined_sinusoids=sum(cos_v); %% cos_v(1)+cos_v(2)+cos_v(3)+...
    y = combined_sinusoids;
   
    x = input('Enter value of x: ');
   
    fprintf('The value of combined_sinusoids is %d \n',y)
Error:
Code:
??? The following error occurred converting from sym to double:
Error using ==> mupadmex
Error in MuPAD command: DOUBLE cannot convert the input expression into a double array.

If the input expression contains a symbolic variable, use the VPA function instead.

Error in ==> fourier_new at 13
    cos_v(i1)=f_w*cos(2*pi*f*x); %% i1 serves as an index for cos_v vector elements too
 
  • #20
FactChecker
Science Advisor
Gold Member
5,706
2,112
In the sample code, both f and t are given numerical values in the 'input' lines before they are used in a calculation. Likewise, you need to give the x array numerical values before you try to use it in a calculation. Set the x array to an array of specific numerical values before the cos_v(i1)=f_w*cos(2*pi*f*x) line.
 
Last edited:
  • Like
Likes PainterGuy
  • #21
wle
312
137
Should I really do it? I don't think so because that's not what I'm trying to do. If x is initialized then the expression "cos_v(i1)=f_w*cos(2*pi*f*x)" will be evaluated for all elements of vector x each iteration of the loop. I experimented with it; see below. I want to evaluate the expression "combined_sinusoids" later for different values of "x".
Then make cos_v a function that takes x as an argument, which you can later call for different values of x. For simple cases like this you can use an anonymous functions to do this:
Matlab:
F = (0:1000) / 10;
cos_v = @(X) sqrt(1./(4*F)) .* cos(2*pi*F.*X);
After this you can call cos_v(X) for any vector X with 1001 elements (the same length as the vector F) and it will return the vector of 1001 elements sqrt(1./(4*F(i))) * cos(2*pi*F(i)*X(i)) for i between 0 and 1000.


so your "double x" statement is not doing anything for you
Declaring a variable to be "double" doesn't even mean anything like it would in C++. Matlab uses dynamic typing, like Python/Ruby/Perl/Lisp and unlike Fortran/C/C++/Java which use static typing. The difference is that in statically-typed languages types are assigned to variables in the source code while in dynamically-typed languages types are assigned to the objects themselves and the language environment keeps track of this at runtime.

In Matlab it is perfectly legal to for instance assign a variable x to a number, and then later to a function handle, and then later a cell array:
Matlab:
x = 1.23;
x = @sqrt;
x = {1, 2, 3};
and you can ask what the type of the value of x currently is by calling the class function:
Matlab:
>> class(x)

ans =

cell
(This is why you can have e.g. a print function in many scripting languages for which both print(3) and print("hello") work.)
 
  • Like
Likes PainterGuy and FactChecker
  • #22
690
33
Thank you, @FactChecker, @wle.

I'm sorry if I'm going in circles. I'm sure that there wouldd be many different ways to implement the same logic but I'm trying to stick with original code to see where I'm really going wrong. Seemingly, the logic is not that wrong but there is something wrong with the implementation. As I mentioned that I'm learning Matlab in view of 'basic' C++ background. I have tried to make few changed but still it's not really working. Could you please help me? Thank you.

Matlab:
%file name fourier.m

    clear all; close all; clc;
    f = [0.1]; %defining and initializing a constant vector
               %0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
    cos_v=zeros(1000); %defining and initializing vector to store values
                       %a vector with 1000 zeroes
    f_w=[0]; % defining and initializing a vector, fourier transfor,
    x=sym('x'); %"x" is a floating point variable which can take values from 0 to
            %infinity, in C++ we could have written "float x"

    for i1=[1:1000] % for loops begins, with loop index i1
    f_w = sqrt(1/(4*f)); % fourier transform of 1/sqrt(x)
    cos_v(i1)=f_w.*vpa(cos(2*pi*f*x)); % i1 serves as an index for cos_v vector elements too
    f=f+0.1; %incrementing f
    f_w=0; %setting f_w=0 for next iteration
    end
   
    combined_sinusoids=sum(cos_v); % cos_v(1)+cos_v(2)+cos_v(3)+...
    y = combined_sinusoids;
   
    x_temp = input('Enter value of x: ');
    subs(combined_sinusoids,'x',x_temp);
   
    y_vpa=vpa(y);
   
    fprintf('The value of combined_sinusoids is %d \n',y_vpa)
   
    fprintf('The value of 1/sqrt(x) is %d \n',vpa(1/sqrt(x)))
   
    fprintf('Difference between 1/sqrt(x) and approximation by combined_sinusoids is %d \n',abs(y-(1/sqrt(x))))
Error:
Matlab:
The following error occurred converting from sym to double:
DOUBLE cannot convert the input expression into a double array.

Error in fourier_new (line 14)
    cos_v(i1)=f_w.*vpa(cos(2*pi*f*x)); % i1 serves as an index for cos_v vector elements too
 
  • #23
FactChecker
Science Advisor
Gold Member
5,706
2,112
If you insist on keeping the x value unspecified in the line defining cos_v(il), then you need to use a function definition like @wle mentions in the post above. Other than that, there is no point in asking for help that you do not intend to take or even consider seriously. I am going to bow out from this discussion.
 
  • #24
690
33
My sincerest apologies, @FactChecker. I didn't intend to disregard your suggestions. I was just looking at the problem from a particular angle. I have mended the code and have tried to incorporate what you suggested. Unfortunately, it's not working as intended. Firstly, it's outputting thousands of values; secondly, while loop isn't working as intended even when 'y' is input; thirdly, 'break' statement doesn't work. Thank you.

Matlab:
%file name fourier.m

      clear all; close all; clc;
      f = [0.1]; %defining and initializing a constant vector
               %0 Hz to 100 Hz, with 0.1 step, there would be 1000 frequencies
      cos_v=zeros(1000); %defining and initializing vector to store values
                       %a vector with 1000 zeroes
      f_w=[0]; % defining and initializing a vector, fourier transform,
      x=sym('x'); %"x" is a floating point variable which can take values from 0 to
            %infinity, in C++ we could have written "float x"
           
      user_decision = 'y';
     
while user_decision == 'y'
    x = input('Enter value of x: ');
   
    for i1=[1:1000] % for loops begins, with loop index i1
      f_w = sqrt(1/(4*f)); % fourier transform of 1/sqrt(x)
      cos_v(i1)=f_w.*(cos(2*pi*f*x)); % i1 serves as an index for cos_v vector elements too
      f=f+0.1; %incrementing f
      f_w=0; %setting f_w=0 for next iteration
    end
   
    combined_sinusoids=sum(cos_v); % cos_v(1)+cos_v(2)+cos_v(3)+...
    y = combined_sinusoids;
   
    fprintf('The value of combined_sinusoids is %d \n',y)
   
    fprintf('The value of 1/sqrt(x) is %d \n',(1/sqrt(x)))
   
    fprintf('Difference between 1/sqrt(x) and approximation by combined_sinusoids is %d \n',abs(y-(1/sqrt(x))))
   
    user_decision=input('Would you like to continue, enter Y/N: ');
   
    if user_decision=='n'
        break;
    end

end
Please have a look on this video:
 
  • #25
wle
312
137
Matlab isn't C++ and programming by guesswork (assuming things will work like in C++) is not a good idea. You should look up documentation and/or try simple commands at the interactive prompt to check that they do what you think they do.

Like I pointed out before, Matlab deals with variables differently than statically typed languages like C++ do. There is no analogue of typed variable declarations like "double x;" in Matlab. The line "x=sym('x')" in your code does nothing useful and definitely doesn't do what your comment after it says it does (it binds x to a symbolic object which you subsequently never use).

Firstly, it's outputting thousands of values
zeros(1000) creates a 1000 by 1000 matrix, not a 1000 element vector. Later when you call sum it sums the columns, so the variable y ends up being a 1000 element vector instead of a single number. When you print a vector the behaviour is to loop over the contents.

secondly, while loop isn't working as intended even when 'y' is input;
Are you typing 'y' with or without the quotes? The documentation says Matlab evaluates the input as an expression and you should pass 's' as a second argument to disable this and simply read the input as a string.

However you should consider whether you really need to read input like this in the first place. Probably a better approach would be to write a function that computes what you want (Matlab functions can return multiple values), which you can then run interactively or call from some other Matlab code. As far as I can tell this function does and returns the results of the calculations you were trying to do (whether it is actually computing a Fourier transform is a different question):
Matlab:
function [ result, ideal, delta ] = fourier(x)
    f = (1:1000) / 10;
    f_w = sqrt(1./(4*f));
    cos_v = f_w .* cos(2*pi*f*x);
    
    result = sum(cos_v);
    ideal = 1 / sqrt(x);
    delta = abs(result - ideal);
end
This returns three values (the variables result, ideal, delta) that you seemed to want to print. You can call it interactively from the prompt by doing e.g. [r, id, dt] = fourier(2).
 
  • Like
Likes PainterGuy and FactChecker

Related Threads on Help needed to fix a matlab code

  • Last Post
Replies
1
Views
3K
Replies
1
Views
2K
Replies
2
Views
4K
Replies
4
Views
3K
Replies
1
Views
1K
  • Last Post
Replies
4
Views
623
  • Last Post
Replies
3
Views
2K
  • Last Post
Replies
1
Views
2K
Top