Simulink numerical evaluation to prevent overflow - matlab

I have this function
f(a,b) = {
a*a/b if a < b,
b if a >= b
}
defined for values of a and b between 0 and 1 inclusive.
The function is continuous at all valid values of a and b in this range. (Really! try it yourself!) But I'm not sure how to evaluate it in Simulink. The problem is that I can't figure out how to restate it in a way that I could evaluate both "forks" of the function and take the min or max (e.g. min(a*a,b*b)/b) without having a divide-by-zero error at b=0, and I'd like to avoid getting into things like conditionally-executed subsystems.
Does anyone know how I might go about doing this?

You have some strange constraints. Since you insist on evaluating both forks and taking the min of the two, the only solution is to not divide by zero but by a small enough number to avoid an error (eps for instance).
or with if action blocks:

I think the simplest approach would be to use a MATLAB function block. You could code it up like this,
function retVal = myfunc(a, b)
if (a < b)
retVal = a*a/b;
else
retVal = b;
end
end
This will create a block with 2 inputs and one output. I'm not sure how you are ensuring that a,b \in [0,1], but this will work as long as that restriction is satisfied.

Related

MATLAB Initial Objective Function Evaluation Error

I am trying to create a plot in MATLAB by iterating over values of a constant (A) with respect to a system of equations. My code is pasted below:
function F=Func1(X, A)
%X(1) is c
%X(2) is h
%X(3) is lambda
%A is technology (some constant)
%a is alpha
a=1;
F(1)=1/X(1)-X(3)
F(2)=X(3)*(X(1)-A*X(2)^a)
F(3)=-1/(24-X(2))-X(3)*A*a*X(2)^(a-1)
clear, clc
init_guess=[0,0,0]
for countA=1:0.01:10
result(countA,:)=[countA,fsolve(#Func1, init_guess)]
end
display('The Loop Has Ended')
display(result)
%plot(result(:,1),result(:,2))
The first set of code, I am defining the set of equations I am attempting to solve. In the second set of lines, I am trying to write a loop which iterates through the values of A that I want, [1,10] with an increment of 0.01. Right now, I am just trying to get my loop code to work, but I keep on getting this error:
"Failure in initial objective function evaluation. FSOLVE cannot continue."
I am not sure why this is the case. From what I understand, this is the result of my initial guess matrix not being the right size, but I believe it should be of size 3, as I am solving for three variables. Additionally, I'm fairly confident there's nothing wrong with how I'm referencing my Func1 code in my Loop code.
Any advice you all could provide would be sincerely appreciated. I've only been working on MATLAB for a few days, so if this is a rather trivial fix, pardon my ignorance. Thanks.
Couple of issues with your code:
1/X(1) in function Func1 is prone to the division by zero miscalculations. I would change it to 1/(X(1)+eps).
If countA is incrementing by 0.01, it cannot be used as an index for result. Perhaps introduce an index ind to increment.
I have included your constant A within the function to clarify what optimization variables are.
Here is the updated code. I don't know if the results are reasonable or not:
init_guess=[0,0,0];
ind = 1;
for countA=1:0.01:10
result(ind,:)=[countA, fsolve(#(X) Func1(X,countA), init_guess)];
ind = ind+1;
end
display('The Loop Has Ended')
display(result)
%plot(result(:,1),result(:,2))
function F=Func1(X,A)
%X(1) is c
%X(2) is h
%X(3) is lambda
%A is technology (some constant)
%a is alpha
a=1;
F(1)=1/(X(1)+eps)-X(3);
F(2)=X(3)*(X(1)-A*X(2)^a);
F(3)=-1/(24-X(2))-X(3)*A*a*X(2)^(a-1);
end

Checking subtraction cancellation (floating point precision)

When reading about numerical methods, then subtraction cancellation is often a topic.
Simple example of cancellation:
a = 1;
b = 1e-16;
a-(a+b) = 0
hence we loss all information of b.
However, i rarely read about how to check for this problem. Could we not use a simple function to subtract number, which also warns us of problems? Example:
function c = subtract(a,b)
c = a-b;
if abs(c) < 1e-14*a
disp('Warning: Low precision on subtraction');
end
end
There are probably some deficiencies of this simple function - it was just my first idea. Anyway, would something like this work? And why is it not done? (i.e. i have never seen/heard about such checks before).

Post and previous values for an analog input inside a matlab function block in Simulink

I need a Simulink block or a group of blocks to make peak detection: compare each value of an input stream to its previous and post values. If it's larger than the previous AND larger than the next value, output this value.
I've tried to do it with a Matlab Function Block, but I cannot make the required delay. I mean it's not possible, as far as I tried, to store previous values for example.
So, what should I do?
Update: Another example
In responding to the comments, suggested solutions are helpful if I'm dealing with discrete values. So here is another example to represent my need:
A Schmidt Trigger
I need to implement a Matlab function to implement the given scenario. I can do something like
if u >= 2
y = 3;
elseif (u < 2)
y = -3;
But still this is not correct as I need to look at the previous value (hysteresis) of the input, other wise I'll end up having something like the following
PS: I know there is nothing called previous value in analog, but we all know that Simulink is dealing with analog values as a discrete in the end (much larger sampling). So I think maybe there is a way to do it.
I think your code is fine except for one minor mistake:
if u > 2
y = 3;
elseif u < -2
y = -3;
else
y = u;
The variable 'u' in elseif part should get compared with the -2 (upper threshold but with a negative sign)
Hope it helps!

MATLAB function that returns complete solution to Ax=b

I have a homework assignment that tasks me with writing a MATLAB function and I'm worried that I've missed something in my current answer. The function returns the complete solution to a linear equation of the form Ax=b, where A is a square matrix, and b is a vector of the appropriate dimension. The first line of the function is
function [Bs, Ns] = a(A, b)
where Bs is the basic solution (a vector), and Ns is the null solution - a matrix whose columns are a basis of the null space of A. There are also a few considerations in terms of the code used:
Code will be marked based on a set of test cases.
Built-in functions may be used in the code but it must be my original work.
Code that produces an error or warning, such as for a singular matrix, will be assigned a failing mark.
It can be assumed the test set will contain matrices that are all zero, non-singular, and otherwise rank deficient (complete solution exists, but MATLAB will produce an error or warning).
The code I've written is below.
function [Bs, Ns] = a(A, b)
ncols = size(A, 2);
x = pinv(A)*b;
Bs = x;
if ncols == rank(A)
Ns = zeros(ncols,1);
else
Ns = null(A);
end
end
The simplicity of my function has me worried that I've missed something (assignment is worth 4% of final grade) - either in my interpretation of the listed considerations, or that there are test cases which will cause errors/warnings. Any input would be appreciated.

What is wrong with this MATLAB code?

I am trying to do following in MATLAB,
global a b c d e f g h l;
A=[1 3;3 2];
B=[a 0;0 b];
C=[d 0;e f];
Ctranspose=transpose(C);
D=[sqrt(d) 0;0 sqrt(f)];
E=Ctranspose/D;
Etranspose=transpose(E);
K=A+E;
M=E*D*Etranspose;
for a=1:10
for b=1:10
if K==M
print(a);
print(b);
print(d);
print(e);
print(f);
end
end
end
I get following errors:
a)
Error using +
Matrix dimensions must agree.
Error in trial (line 6)
K=A+B
b)
Error using vertcat
CAT arguments dimensions are not consistent.
Error in trial (line 5)
C=[d 0;e f];
What is wrong here?
(Kindly note that I am new to MATLAB)
Thanks
Ouch! OUCH! Let me just jump right in there and interrupt you before you continue down this path!
I know you're not a programmer, but at some point in life (apparently, this is yours!), you have to face the facts and become one, however momentarily. So know that programming is not really a science, it's an art, a craftsmanship if you will, and one that is all too easy to get wrong. Know also that there have been millions upon millions of programmers before you, who paved the way for you and found out which methods work best, and which methods lead to certain disaster.
I will describe six of these "roads-to-certain-doom" that are present in your code.
First on the list, is the use of global. DON'T USE GLOBAL VARIABLES!! Sure, they are all-right for small, simple things, but the better, much more manageable, more durable, robust, much less error-prone way of passing data around is to do it manually. As a rule of thumb, create all top-level functions with as little dependencies to other functions/variables as possible. This is because global variables create a tight coupling between a program's state and a function's output, which makes reproducing any errors hard, if not impossible, and debugging (which is actually what any programmer spends most of his/her time on) a complete nightmare. Also, any function other than the one running can change them, so that
function testMe
global a;
a = 5*rand;
someFunction;
b = 4*a; % ERROR! or...will it?
function someFunction
global a;
a = a/5;
if a < 0.5
someOtherFunction; end
function someOtherFunction;
global a;
a = {'my string'};
will sometimes work, and sometimes fail. An example of something worse that can happen:
function testMe
global a, b;
a = 5; b = 6;
result = someCalculation;
result = a*b*result;
function someFunction
global a;
a = sin(pi/rand); % INTENTIONAL
% do LOTS of stuff here
for a = 1:10 % OOPS! unintentional use of variable name
% do stuff
if (some weird condition)
break; end
end
There will be no error, no warning, nothing, but your results will still be garbage. And as your functions grow larger (and they WILL, usually), this error gets harder and harder and harder to find. It's not uncommon to spend a good few days on finding this sort of mistake.
In your code, you also change the global variables a and b inside the loops. This means that any function/script that uses a and b, that gets called after this one completes, will see a=10 and b=10. Now suppose you call a function inside those loops, that changes the value of a. What will the value of a be on the next iteration of the a-loop? Suppose also you get erroneous results. How would you go about finding that error?
Code like this is usually called "spaghetti code", for obvious reasons. Perhaps it will work, and is easy to code, but in the end it will always slow you down tremendously (not to mention the one who inherits your code).
A much better approach that prevents most of this is to collect data in larger containers, and explicitly pass them around. Say we use a struct for the data a-l:
data = struct(...
'a', a,...
'b', b,...
'c', c,...
'd', d,...
'e', e,...
'f', f,...
'g', g,...
'h', h,...
'l', l);
So that you can say
result = myFunction(data);
Accessing data inside myFunction goes like this: data.a to get the value for a, or data.f for the value of f, etc. Saying data.k = 5; in myFunction will not change the result, or the original data passed to the function -- you have broken the tight coupling and prevented all the aforementioned problems.
Type help struct or help cell in the Matlab command window to learn about these sorts of generic containers.
Second on the list is using the variable name l. It's somewhat silly, and I can be short about this: don't do that :) Contrary to what most people (and even some programmers) believe, you write a line of code only once, but you read it hundreds, if not thousands of times. The best practice is to make the reading as easy as possible, not the writing. The l just looks like the 1, doesn't it? The bug k=1 vs k=l is simply harder to spot than k=m vs k=1.
Third on the list is the keyword transpose. It's kinda verbose, isn't it? In math, you would use AT, which is much easier on the eyes than writing the full definition all of the time:
B = { Aij ➝ Aji ∀ i < m ⋏ j < n
you normally just say B = AT. Same in Matlab. The transpose of a matrix can be accomplished like so:
Actrans = A' ; % conjugate transpose
Atrans = A.'; % regular transpose
which reduces your code to the much less verbose
A = [1 3;3 2];
B = [a 0;0 b];
C = [d 0;e f];
D = [sqrt(d) 0;0 sqrt(f)];
E = C.'/D;
K = A+E;
M = E*D*E.';
Fourth on the list is the equality K==M. As it stands here, K and M are matrices. The expression K==M is evaluated element-wise, for reasons that will become obvious later in your programming career :) This means that K==M will be again a matrix, the same size as K and M, containing 0 if corresponding elements in K and M are not equal, and 1 if these elements are equal. So, what will an if-statement do with such a matrix? In Matlab, it will be true whenever the first element is true (in my opinion, it should throw an error, but oh well).
This is obviously not what you want. what I think you want is that all elements in both matrices are equal. It's best you use this:
if all( abs(K(:)-M(:)) < eps )
where the (:)-notation means that the matrix K and M should be expanded to column-vectors prior to the comparison. This is because all() works down a single dimension, so all(K==M) would still be a matrix (vector, actually, but that's a different name for a special case of the same thing). Notice that I don't use equality (==), but rather check whether their difference is smaller than some tiny value (eps). This is because in floating-point arithmetic (which all computers use), operations like multiplication and square root usually suffer from things like round-off error and approximation/interpolation error. An equality is a very tough demand, too tough to evaluate to true in most cases where it mathematically speaking should. You can prevent this failure to detect the equality by comparing the difference of the two to a tiny value that's related to round-off error (eps).
Fifth on the list is the way you print things. The print statement, by itself, will send a figure to the system's default printer, you know, that moody machine that spits out paper with ink on it if it feels like cooperating today :) Now, I assume you were trying to display things on the screen. Doing it like the way you set out to display things is not the best way: you'll get a dozen times this list of unnamed, unstructured values:
1 % which would be the value of 'a'
1 % which would be the value of 'b'
3 % which would be the value of 'd'
4 % which would be the value of 'e'
5 % which would be the value of 'f'
...
Seeing only the values appear makes reading and interpreting what's going on rather tedious. Better use something more descriptive:
if all( abs(K(:)-M(:)) < eps )
% option 1
a
b
d % NOTE: not terminating with semicolon
e
f
% option 2
fprintf(...
'a: %d\n, b: %d\n, d: %d\n, e: %d\n, f: %d\n\n', a,b,d,e,f);
end
Option 1 will just show
a =
1
b =
1
etc.
which at least also shows the variable's name alongside its value. Option 2 is the nicer one:
a: 1
b: 1
d: 3
e: 4
f: 5
a: 1
b: 2
d: 3
e: 4
f: 5
etc.
(As an aside, the values a,b,d,e,f never change in the loops, so why would you want to show them in the first place?)
Sixth (and last!) on the list, is one that is specific to Matlab: for-loops. Matlab is an interpreted, matrix-based language. Its matrix nature simply means that every variable is in essence, a matrix. Interpreted means that your code will not directly be seen by the computer's processor, it will have to go through a series of interpretations and translations before anything gets calculated. This coin has two sides:
it can speed things up (like coding, or doing "trivial" things like solving linear systems, FFT, comparisons of matrices, etc.)
it can slow things down (like repeated execution of statements, like in a loop)
In light of performance, the for-loop is notorious in Matlab for bringing operations to a crawl. The way to go in Matlab is usually vectorized code, e.g., use the fact that all variables are matrices, and use matrix/tensor operations on them instead of loops. This is not a very common approach in most programming languages (and you'll see a lot of strong, heated resistance to it in programmers not accustomed to it), but in a mathematical context it makes a whole lot of sense. Always try to use matrix/tensor operations as a first line of attack (and Matlab has a lot of them, mind you!) before resorting to for-loops.
So, that's what's wrong with your code :) Oh yeah, and as Andreas Hangauer already mentioned, place the statements referring to a through l, and all that needs to be re-calculated accordinly, inside the loop, and you'll be fine.
You didn't specify what the values of a b c d e f g h l are, you specify that they are global variables.
a) First error: Given that you get an error in line 6, it is either that a or b isn't a scalar.
b) Second error: (error is in line 4 rather than line 5). Here again one of d, e or f is not a scalar. What happens here is that d and e might be scalars, but f isn't, f is instead a vector or a matrix. So the first row of the matrix has a different length than the second row, hence the error.
What is the intend of the for loops? M==K will return true only if all elements of M and K are equal, but the element in the second row and first column will never be the same. And if somehow M and K were the same matrix, then the code would just print d, e and f for all the combinations of values of a and b. (Note that a and b are redefined in the for loop.)
You have to change the order of your program.
d = 4567; % some value necessary
e = 1234; % some value necessary
f = 4567; % some value necessary
for a=1:10
for b=1:10
A=[1 3;3 2];
B=[a 0;0 b];
C=[d 0;e f];
Ctranspose=transpose(C);
D=[sqrt(d) 0;0 sqrt(f)];
E=Ctranspose/D;
Etranspose=transpose(E);
K=A+E;
M=E*D*Etranspose;
if K==M
print(a);
print(b);
print(d);
print(e);
print(f);
end
end
end
You not seem to have correctly understood the basic concept of a programming language. In a programming language (unlike mathematical notation) the statements are commands that are executed sequencially, one after another. All values that are needed in a computation have to be available when that command is executed, hence the updated execution order is necessary for intended operation.
In addition to everything mentioned here, please do format the code nicely (note: the code below is the OP's code, so it's programmatically wrong):
global a b c d e f g h l;
A = [1 3; 3 2];
B = [a 0; 0 b];
C = [d 0; e f];
Ctranspose = transpose(C);
D = [sqrt(d) 0; 0 sqrt(f)];
E = Ctranspose / D;
Etranspose = transpose(E);
K = A + E;
M = E * D * Etranspose;
for a = 1:10
for b = 1:10
if K == M
print(a);
print(b);
print(d);
print(e);
print(f);
end
end
end
This spares you time and mental resources when reading your code, which actually takes much more time than writing it.