Cannot transfer variable values into dsolve? - matlab

I got one question in matlab:
I get a value of c from other function, then I want to put c value 1 into dsolve to solve this differential equation. but the value cannot put into dsolve, what should I do to transfer value?
eg:
c = 1;
u = dsolve('Du = 1+u^c','t') % c is c, but is not 1!

The reason for your error is that when you use 'c', c is interpreted as a char (or string) and not a variable. What you could do is use num2str to combine strings and variables, like this:
u = dsolve(['Du = 1+u^' num2str(c)],'t') % c is c, but is not 1!
u =
C16*exp(t) - 1
If you have several variables, you can do something like this:
u = dsolve(['Du = ' num2str(1/(m*n)) '*1 + u^' num2str(c)])
u =
C16*exp(t) - 1

Related

MATLAB Equation as User Input to work with

I'm trying to write a simple script that request a equation as input and I like to calculate with this function more than once without always requesting user input.
My current script defined f as function handle and executed the function 2 times, so I'm always asking for a new equation, which is not desirable.
f = #(x) input('f(x) = ');
a = f(2); % requests user input
b = f(3); % requests user input again
And it should look more like this (not working).
func = input('f(x) = ');
f = #(x) func;
a = f(2);
b = f(3);
And here without user input to get an idea what I try to achieve.
f = #(x) x^2;
a = f(2);
b = f(3);
I think I found a solution with Symbolic Math Toolbox, but I do not have this addon, so I cannot use/test it.
Is there another solution?
There's no need for the Symbolic Mathematics Toolbox here. You can still use input. Bear in mind that the default method of input is to directly take the input and assign it as a variable where the input is assumed to be syntactically correct according to MATLAB rules. That's not what you want. You'll want to take the input as a string by using the 's' option as the second parameter then use str2func to convert the string into an anonymous function:
func = input('f(x) = ', 's');
f = str2func(['#(x) ' func]);
a = f(2);
b = f(3);
Take note that I had to concatenate the #(x) anonymous function string with the inputted function you provided with input.
Example Run
Let's say I want to create a function that squares every element in the input:
>> func = input('f(x) = ', 's');
f(x) = x.^2
>> f = str2func(['#(x) ' func])
f =
#(x)x.^2
>> a = f(2)
a =
4
>> b = f(3)
b =
9
Take special note that I assumed the function will element-wise square each elements in the input. The . operator in front of the exponentiation operator (i.e. ^) is very important.

How does one pass a function with some fixed argument as an argument in MATLAB

I want to pass a function that has arguments to another function that takes the function handler (pointer) as an argument, but some of the arguments to the function handler need to be fixed. How does one do this in MATLAB?
Concretely I want to minimize a function h(eta) using fminsearch(fun,x0). One obvious issue is that if I pass all the arguments in x0 it will minimize it with respect to all the arguments but that isn't what I want to do. What I really want to do is instead:
I have tried the following and it seems to work as far as I tested it:
function [ h ] = function_returner( x )
%
t = -10000;
h = #(eta)-10*x + t + eta^2;
end
and the script to test it:
h = function_returner(0);
h(3) %-9991
[x,fval,exitflag] = fminsearch(h,[10]) %returns [0, -10000, 1]
returns the correct minimum and the correct value of x at which the minimum is obtained. The thing that I wanted to make sure is that the variables that are fixed of h indeed remain fixed after I returned the function handler. i.e. if h is passed around, how does one make sure that the variables don't change value just because they go into an environment that has the same variables names as in the function handler?
I also wrote:
x = inf;
t = inf;
eta = inf;
h = function_returner(0);
h(3) %-9991
[x,fval,exitflag] = fminsearch(h,[10]) %returns [0, -10000, 1]
and it seems to go unaffected (i.e. it works as I want it to work). But just to be on the safe side, I was hoping there was not a some weird edge condition that this doesn't work.
You are worrying unnecessarily. :-) The thing is, when you create an anonymous function, all the outer variables that are used for its definition are frozen, so you don't need to worry that the function will change behavior behind your back via modified parameters. To test this, try this script:
a = 1;
b = 2;
f = #(u,v) u*a + v*b;
x = f(1,1); %// x is 3 = 1*1 + 1*2
a = 2;
b = 3;
g = #(w) f(w,a)
y = g(1); %// y is 5 = f(1,2) = 1*1 + 2*2

Matlab Defining A Function That Has Vector As An Input

I was given a simple exercise by my professor, which is to define a cerrtain function. Here is my function
function [a,b,c] = PHUN([x,y],[z,t,w])
a = x
b = ((y+z)^2)*t
c = z/w + x
However, matlab states that I am using invalid syntax in the first line. So, I figured, perhaps there is a particular way in which vector inputs are supposed to be typed. I have attempt several searches on defining functions with vector inputs (or arguments), but have not been successful. I was wondering if someone could possibly help me.
You can pass vectors as arguments in the same way you pass variables. Then access them in the function body appropriately. Your function could be re-written as follows:
function [a,b,c] = PHUN(X,Y)
a = X(1)
b = ((X(2)+Y(1))^2)*Y(2)
c = Y(1)/Y(3) + X(1)
Or if you want to keep the original variables:
function [a,b,c] = PHUN(X,Y)
Z = num2cell([X,Y]);
[x,y,z,t,w] = Z{:};
a = x
b = ((y+z)^2)*t
c = z/w + x

How to write a `lhs()` or `rhs()` function for symbolic expressions on Matlab

I have a symbolic expression in MATLAB with a == operator that I can use in solve(). What I want is to separate out the left hand side and the right hand side of the expression into two separate symbolic expressions.
For example:
expr = sym('[1-x^2==2*y; 1+x^2==x+y]');
side1 = lhs(expr); % returns side1 = [1-x^2; 1+x^2];
of course my expressions are far more complicated, and it is always vector or matrix form.
Workaround 1
I can use the MuPAD built-in function lhs() but I wanted to know if it possible to do this using only MATLAB functions and I want to make it work for vectors of expressions and not just one value.
This is what I have so far that works as expected. Maybe the result filling can be vectorized somehow by using : but I have not manage to get it working.
function [ r ] = lhs( expr )
%LHS Returns the left hand side an expression
% LHS(sym('[1-x^2==2*y'; 1+x^2==x+y]')) = [1-x^2; 1+x^2]
cmd = #(e)['lhs(',char(e),')'];
[m,n] = size(expr);
r = sym(zeros(m,n));
for i=1:m
for j=1:n
r(i,j) = evalin(symengine, cmd(expr(i,j)));
end
end
end
Starting R2017a, use "lhs" and "rhs" as
syms x
expr = [1-x^2==2*y; 1+x^2==x+y];
lhsExpr = lhs(expr)
lhsExpr =
1 - x^2
x^2 + 1
rhsExpr = rhs(expr)
rhsExpr =
2*y
x + y
expr = sym('[1-x^2==2*y; 1+x^2==x+y]');
lr = children(expr);
lr{1}
ans =
[ 1 - x^2, 2*y]
Note that this is more robust than EitanT's string manipulation for a simple reason: Your left- and right-hand sides may contain equals-signs themselves.
I'm thinking regular expressions, so here's my shot at this.
Let's say you have a symbolic expression expr, for instance:
expr = sym('[1-x^2==2*y; 1+x^2==x+y]')
Since it cannot be assumed to be a scalar expression, the first step would be splitting it into sub-elements, and converting each one to a string, like so:
C = arrayfun(#(n)char(expr(n)), 1:numel(expr), 'Uniform', false)
(I'm not using a simple char(expr) conversion because it adds the matrix([[...]]) syntax).
Now we use a regular expression search-and-replace to extract the LHS:
C = arrayfun(#(n)char(expr(n)), 1:numel(expr), 'Uniform', false)
C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$1') %// $1 for lhs, $2 for rhs
And then concatenate the elements back into a string and convert it into a symbolic expression:
str = sprintf('%s,', C{:})
result = reshape(sym(str(1:end - 1)), size(expr))
Voila.
Here are copy-paste friendly lhs and rhs functions:
function y = lhs(x)
C = arrayfun(#(n)char(x(n)), 1:numel(x), 'Uniform', false);
C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$1');
str = sprintf('%s,', C{:});
y = reshape(sym(str(1:end - 1)), size(x));
function y = rhs(x)
C = arrayfun(#(n)char(x(n)), 1:numel(x), 'Uniform', false);
C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$2');
str = sprintf('%s,', C{:});
y = reshape(sym(str(1:end - 1)), size(x));
Note that the only difference between lhs and rhs are the replaced tokens in regexprep.
Using $1 extracts the left-hand side, and using $2 extracts the right-hand side.

manipulating mathematical functions in matlab or any other language

Say I have a function
a = b / c
and I ask the user to input two of these variables, either b and a or c and a and I want it to calculate the unknown variable without needing to write a function for every variable
In this case I would use:
pseudo-code
if input is a & b
then c = b / a
if input is a & c
then b = a * c
if input is b & c
then a = b / c
I know this is a function with only three variables so it is easy to put it in an if-statement and voilĂ  BUT I want to apply it to a system containing lots of equations (a jet engine for example). I used TkSolver before and it was really great, you throw as many equations as you want at it (a jet engine was an example!), you only need to give a number of known quantities and in a few seconds, all the unknowns are calculated (even if I had a known quantity in one side of the equation and unknown on another side mixed with known ones, it will do the maths!)
So, is there a way to do this in MatLab or perhaps python which I'm learning?
Edit to the question, thanks for directing me to use the Symbolic toolbox, it's great, I have another problem:
I couldn't think of a way to let the program know which of the variables is entered. I can do this:
syms f a b c
f = a * c - b %(I want to write a = b / c)
c = 10; a = 5;
X = eval(solve(f,b))
What I want now is a way of letting the user enter two knowns (e.g c & a) and the code will recognise them and solve to the unknown variable (e.g b).
Edit 2: I managed to get what I want, it's a bit long and there might be another way of achieving the same thing.
clear, clc
syms a b c
var = [{'a'}, {'b'}, {'c'}];
var1n = 0;
var2n = 0;
while isvarname(var1n) == 0
var1n = input('Which variable is known: ','s');
while ( any( strcmpi(var1n,var) ) )== 0
fprintf('\nThe variable entered is wrong, please enter a, b, or c')
var1n = input('\nWhich variable is known: ', 's');
end
end
fprintf('\nPlease enter the value of %s', var1n)
var1v = input(': ');
eval([var1n '=' num2str(var1v)]);
while isvarname(var2n) == 0
var2n = input('What is the second known variable: ', 's');
while ( any( strcmpi(var2n,var) ) ) == 0
fprintf('\nThe variable entered is wrong, please enter a, b, or c')
var2n = input('\nWhat is the second known variable: ', 's');
end
end
fprintf('\nPlease enter the value of %s', var2n)
var2v = input(': ');
eval([var2n '=' num2str(var2v)]);
var3n = char ( var ( find( strcmpi(var1n, var) == strcmpi(var2n, var) ) ) );
var3v = solve(a - b / c);
eval([var3n '=' char(var3v)]);
You could use this: http://www.mathworks.de/help/toolbox/symbolic/solve.html but you have to have the symbolic math toolbox (:
EDIT: On the documentation page of solve there's a sentence:
If the right side of an equation is 0, specify the left side as a
symbolic expression or a string:
That means, if you want to solve a = b/c for the value which is NOT set, simply rewrite the equation so that there is a zero on the right hand side:, i.e. a - b/c = 0, than you can use:
syms a b c
% E.g. assign values to a and c and automatically let matlab chose the 'free' variable (in this case, it's b:
a = input('Input var a: ')
a = input('Input var c: ')
solve(a - b/c)
which than gives you b (e.g. entering a = 10 and c = 40 gives you b = a * c = 400). Input function is explained here: http://www.mathworks.de/help/techdoc/ref/input.html! Hope that helps!