0

Here is an example where fplot doesn't plot anything:

a=0.336;
Ta=9.476;
Te=1.208;
Tw=1.498;
eqh=[0.661;0.619;0.568];
ex=[-1.24;-1.346;-1.441];
en=-ex;
ey=[0.376;0.705;0.968];
eqx=[-0.309;-0.357;-0.392];
eh=[1.594;1.583;1.545];
eyqh=[0.642;0.78;0.897];
a0=a*Ta*Te^2;
syms bt Td Ki Kp;
a1=sym([]);a2=sym([]);a3=sym([]);a4=sym([]);exqh=sym([]);

for i=1:3
        Kp=1/bt;
        exqh(i)=en(i)*eqh(i)+eqx(i)*eh(i);
        Ki=1/(bt*Td);
        a1(i)=Ta*Tw*eqh(i)+a*Te^2*en(i)+a*Te^2*ey(i)*Kp;
        a2(i)=a*Te^2*ey(i)*Ki+Ta+Tw*exqh(i)-eyqh(i)*Kp*Tw;
        a3(i)=en(i)+ey(i)*Kp-eyqh(i)*Ki*Tw;
        a4(i)=ey(i)*Ki;
        assume(bt~=0)
        f=@(bt) a1(i)
        fplot(f,[0.01 1],'b')
        hold on
end

And here is another example, where fplot works:

syms y x;
y=@(x) 2/x+6;
z=y;
assume(x~=0)
fplot(z,[-1 1],'b')

I cannot understand the difference between these two cases. In my opinion, they are the same.

Would anyone please explain why the top example doesn't work, but the bottom one does?

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Y. zeng
  • 121
  • 7
  • This question is unclear. Is there something about the `fplot` [documentation](https://www.mathworks.com/help/matlab/ref/fplot.html) that you found unclear? – Dev-iL Jul 21 '19 at 08:06
  • @Dev-iLe ‘fplot(f,[0.01 1],'b')’ is wrong, but 'fplot(z,[-1 1],'b')' is right. – Y. zeng Jul 21 '19 at 08:10
  • 2
    That's because your `f` definition is dubious. You are on one hand mixing symbolic variables with function_handle without intended reasons and on the other hand scoping your variables in your function_handle in completely disjoint places. And I do need to point out that you can nail down the source of your problem if you follow the [how to ask](https://stackoverflow.com/help/how-to-ask) guidelines and use [minimal examples](https://stackoverflow.com/help/minimal-reproducible-example). The latter is not only good for asking SO questions. It is also good for your own efficient debugging. – Argyll Jul 21 '19 at 08:35

1 Answers1

2

fplot requires an expression that returns a numeric value. f returns a sym (symbolic expression), so it doesn't work, whereas z returns a number - so it does. That's all the difference.

Note that in the working example, you overwrote the y sym on the 2nd row, which means you provided a "proper" function handle to fplot, "by mistake". In fact, you need much less code for that example to work:

fplot( @(x)2./x+6, [-1 1], 'b');

The easiest way to get the top code working is by using matlabFunction. In other words, you can fix your code by changing this line:

f=@(bt) a1(i)

to this:

f = matlabFunction(a1(i));
Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • How to tell symbolic expression and non-symbolic expression? – Y. zeng Jul 21 '19 at 08:29
  • It's the other way around. `fplot` can't take function_handle that uses symbolic variables. – Argyll Jul 21 '19 at 08:31
  • @Y.zeng You can look at the Workspace, or run the command `whos`. @Argyll could you please elaborate? – Dev-iL Jul 21 '19 at 08:35
  • @Argyll 'z' is function_handle too. – Y. zeng Jul 21 '19 at 08:38
  • @Y. zeng: I meant that `fplot` isn't intended for such. I outlined the issues with your code and question in direct comment to your question. If you edit your question with those guidelines, I am happy to test a few things out along with you. – Argyll Jul 21 '19 at 08:40
  • @Dev-iL f=4.74622697472e-1./bt+8.769327870464 and z=2/x+6. So they all returns a sym I think. – Y. zeng Jul 21 '19 at 08:43
  • @Argyll I can not imagine how matlab works. Can you recommand me a book? – Y. zeng Jul 21 '19 at 08:44
  • @Y. zeng: and btw, in your "z" example, neither `y` nor `x` is treated as symbolic variables. You first overwrote `x` in the local scope of `y` and then redefined `y` into a function_handle. – Argyll Jul 21 '19 at 08:45
  • @Y. zeng: I see. Then your problem isn't about `fplot` -- although it can still be educational to others. Your problem is about how to plot in Matlab. Maybe ask a different question on how to plot the function you wish to plot and show your two examples as what you have tried? That way, I can answer with a more idiosyncratic way to plot in Matlab that uses its strengths. (Of which the symbolic package is not a part.) You can edit your current question too. But I won't edit it because it will substantially change from the original intent. – Argyll Jul 21 '19 at 08:47
  • I believe that @Y.zeng is not really looking for correct answer but waste SO members time. I answered his question here but he didn't give any feedback. Link here https://stackoverflow.com/questions/57104609/f-415136356873531-2251799813685248bt-703048105211593-70368744177664-fplot – Adam Jul 21 '19 at 08:47
  • @Argyll check my answer, you really don't need to be fluent English speaker to understand it. This is the third similar question he is asking. He just want to challenge `matlab` syntax. Since `a(i)` is a `syms` function, does he really need to convert it into `function handle` before using `fplot`? – Adam Jul 21 '19 at 08:54
  • @Adam Yes, this is necessary. The reason for that is noted in [the documentation](https://www.mathworks.com/help/matlab/ref/fplot.html#bu6xntj-1-f): "_Support for character vector inputs will be removed in a future release. Use function handles instead._". For the purpose of evaluating `fplot`, a symbolic function is treated like a "character vector input", which is deprecated. – Dev-iL Jul 21 '19 at 09:00
  • 1
    @Adam: Indeed no, `fplot` is meant for symbolic expressions. It seems Matlab also made it compatible to function_handles (`sub` for symbolic variables does create function_handles IIRC). Anyway, I gave your answer there an upvote. (I initially voted to close that question for lack of focus btw.) – Argyll Jul 21 '19 at 09:06
  • @Argyll I wrote 'syms x y', and why neither y nor x is treated as symbolic variables? – Y. zeng Jul 21 '19 at 09:13
  • @Y.zeng: In Matlab, as with any other common languages, if you redefine a variable, the original definition is removed. `syms x y` basically creates new instances of the class symbolic variables. But later, you redefined y into a function_handle. Within the definition of y, you used x as a local variable. The local x has nothing to do with the `syms x` from earlier. – Argyll Jul 21 '19 at 09:16
  • @Adam I saw your answer (https://stackoverflow.com/questions/57104609/f-415136356873531-2251799813685248bt-703048105211593-70368744177664-fplot). Because I do not understand your explaination, I have not answered you. I am a newer studying matlab. – Y. zeng Jul 21 '19 at 09:16
  • @Dev-iL This is the first I know how to accept an answer. Before today, many people help me a lot, but I did not click accepting it for I have not known this function. – Y. zeng Jul 21 '19 at 09:20
  • @Argyll So '@' will redefine definition. I have not known what the '@' meaned. – Y. zeng Jul 21 '19 at 09:22
  • @Y.zeng The `=` operator redefines a variable. `@` in Matlab is used in a few different ways. In `function_handle` (you need to look this up), `@(x)` your `y` definition means `x` shall be a local variable of `y` whose value will be filled in when `y` is called. From here, two things are at play. 1) A local variable takes precedence over variables from higher scopes. So within `y`, `x` is re-defined. 2) Anonymous function_handle do not inherit anything from higher scopes. Together, think of it as y::x from the perspective of your computer. – Argyll Jul 21 '19 at 09:25
  • @Y.zeng Not `@` but the assignment operator, `=`, redefines things. In strongly-typed languages this would throw an error because `y` was initially symbolic and you assigned a function handle into it. Also, if you specify that `x` is the argument of the function handle (this is the meaning of `@(x)`), than any previous definition of `x` is ignored within the context of the function handle. – Dev-iL Jul 21 '19 at 09:28
  • @Y.zeng: I am afraid not. I didn't myself learn from any book. And I am not sure if any book is better than the official mathwork documents. Also, I did edit my last comment while you asked about books. Please take a look at the edit. I added a subtle but important point that I think you will benefit from in the long run. – Argyll Jul 21 '19 at 09:31
  • @Dev-iL If I wrote @x, so 'x' must be the function handle. What is the difference between the function handle and non-function handle. – Y. zeng Jul 21 '19 at 09:32
  • @Y.zeng: Back to books, I do recommend you ask a different question on how to plot -- with the specific examples you have and following the guidelines I linked, of course. That way, answers will present you with a systematic approach. You want to ask systematic questions when you know your problem isn't debugging a particular syntax. – Argyll Jul 21 '19 at 09:34
  • @Y.zeng `@x` is a function handle to an existing function that is known as `x` (this could be an `.m` file called `x.m` or an inline function called `x`, or something you defined earlier in your code). On the other hand, `@(x)...` is a function handle to an **anonymous function** (that is, a function defined on the spot). You can have handles to named, as well to anonymous functions. – Dev-iL Jul 21 '19 at 09:34
  • @Dev-iL `character vector inputs` are different from `sym variable inputs` unless you agree that `sym` and `char` derived from **the same class** – Adam Jul 21 '19 at 10:12
  • 1
    @Adam They are different, yes, and perhaps the notice does not apply to `sym` inputs. As a matter of fact, if you open the function `matlab.graphics.function.internal.sym2fn`, which is executed in the case of a `sym` input to `fplot`, `matlabFunction` is exactly what's being called. To conclude: either you convert the symbolic expression to a function handle on your own, or MATLAB will do it implicitly for you. – Dev-iL Jul 21 '19 at 11:52
  • @Dev-iL `fplot()` **_does not convert_** `sym function` to `function handle` before plotting. Check out the two results. With **sym** there is a plot ```syms x; y = log(nchoosek(1000,x));fplot(y,[1 1000]);``` while if the same function is written using **function handle** there is no plot ```y = @(x) log(nchoosek(1000,x));fplot(y,[1 1000]); ``` Link here https://stackoverflow.com/questions/56277988/plot-logn-over-k/56279391#56279391 – Adam Jul 26 '19 at 04:10
  • @Adam your conclusion is unrelated to your observation. Take a look at the docs of `fplot` where it says - "_The function must accept a vector input argument and return a vector output argument of the same size._" - which is **not** what your example does. When the sym function **_is_ converted to a handle** an `arrayfun` (among other things) is added to it, because it doesn't support vector inputs/outputs, so the function handle that gets evaluated is a far more complex expression. This can be verified by setting breakpoints in the functions I mentioned previously. – Dev-iL Jul 26 '19 at 06:50
  • Furthermore, the closed-source graphical element, `matlab.graphics.function.FunctionLine`, which is in charge of doing the actual plotting in the case of `fplot`, appears to behave differently for `sym` and function handle inputs (and produce an empty plot in the case of the latter). This is of course not documented in any way and might as well be a MATLAB bug. – Dev-iL Jul 26 '19 at 07:03
  • @Dev-iL Agree`arrayfun` will be added. My observation is about your statement wether we should convert **sym function** to **function handle** or simply let `fplot()` do it by itself. My conclusion is: let `fplot()` do it on its own. `matlabFunction()` does't always make an exact conversion of **sym** into **function handle**. You're right my observations are undocumented, after using some functions for while I found some logic by myself. – Adam Jul 26 '19 at 07:07