how can I change symbols in symbolic equations with x(1), x(2), ...

Hello all
I have a nonlinear system of equations F1(p,q) = 0, F2(p,q) = 0, with F1 and F2 represented in MATLAB as symbolic expressions. I want to solve these equations using fsolve.
Now the problem is that fsolve() wants the variables to solve for to be in a vector X = [x(1) x(2) ... x(n)],so I should transform p and q into x(1) and x(2) and this transformation is giving me the problem.
As a simple example, suppose my system to be solved is defined by:
syms p q
F = [sin(p)*sin(q); p^2+q^2-1]
how can I transform these equations to something like: F = [sin(x(1)).*sin(x(2)); x(1).^2 + x(2).^2-1]
Note: this is a small example of the problem. The real program has 81 equation in 81 unknowns . So I cannot do this transformation manually and I need something intelligent to do this.
How can I do this transformation Or maybe there's a better approach to deal with the problem (say, directly in the symbolic domain?)I tried solve for my 81 equations but it takes infinite time.
Any help will be appreciated ... thank you!

 Accepted Answer

I suggest this approach:
syms p q
F = [sin(p)*sin(q); p^2+q^2-1]
F0 = subs(F, {'p', 'q'}, {'x(1)', 'x(2)'})
F1 = vectorize(F0)
The results:
F =
sin(p)*sin(q)
p^2 + q^2 - 1
F0 =
sin(x(1))*sin(x(2))
x(1)^2 + x(2)^2 - 1
F1 =
matrix([[sin(x(1)).*sin(x(2))], [x(1).^2 + x(2).^2 - 1]])
It's likely not as neat a solution as you would like because MATLAB insists on the matrix designation in F1. Even so, I definitely suggest using vectorize.
If you want them as functions you can use matlabFunction, but it probably easier to create and edit the functions yourself from the results of vectorize, for example:
F1 = @(x) [[sin(x(1)).*sin(x(2))]; [x(1).^2 + x(2).^2 - 1]];
because matlabFunction interpets the array elements x(n) as functions, creating more problems than it solves. (NOTE that I also inserted the ‘;’ separating the submatrices.) The Symbolic Math Toobox won't do subs on a function created by matlabFunction.
This likely falls short of what you would like to do, but in my experience it is the best the Symbolic Math Toolbox is able to do.

6 Comments

Thank you for your clear answer.
However,the exact solution of these equations using 'solve' is
p=[1 -1 0 0]
q=[0 0 -1 1]
when I use
F2 = @(x) [[sin(x(1)).*sin(x(2))]; [x(1).^2 + x(2).^2 -1]];
[sol2,fval]=fsolve(F2,[1 1]) I get the results
sol2 =
0.6568 0.6568
fval =
0.3728
-0.1372
which seems to be not true. I used various values of the initial conditions and it still wrong. Why this happens? How can I fix it?
Also you used copy and paste to write
F1 = @(x) [[sin(x(1)).*sin(x(2))]; [x(1).^2 + x(2).^2 - 1]];
Is there any other way that I can do it within the program without I interfere?
Thank you again.
I initially got an error (with MATLAB 2012a) using the expression for F1 in fsolve that the Symbolic Math Toolbox provided, because fsolve considered the second element in F1 to have more than one column. I corrected this by putting parentheses inside the brackets to indicate it was one expression:
F2 = @(x) [[sin(x(1)).*sin(x(2))]; [(x(1).^2 + x(2).^2 -1)]];
When I then ran fsolve on it as you did, but with a small modification:
[sol2,fval]=fsolve(F2,[1-2*rand(2,1)])
I got these results:
sol2 =
1.0000e+000
549.5837e-012
fval =
462.4587e-012
32.5892e-009
and using a different initial guess:
sol2 =
-1.0000e+000
343.6487e-015
fval =
-289.1704e-015
3.4746e-012
that are essentially the same as the results that the Symbolic Math Toolbox produced.
You will probably have to do some editing on the equations produced by the Symbolic Math Toolbox to make them work as regular MATLAB code. If you are only going to create your set of 81 equations in 81 unknowns once, and they are reasonably easy to read, then you can use the MATLAB Editor ‘Edit’ -> ‘Find and Replace’ options. Then in the ‘Find’ line type ‘matrix’ (without the quotes) with nothing in the ‘Replace’ line, unless each such line is a separate function. In that situation, put ‘Fn = @(x)’ (where ‘n’ is an integer and without the quotes) in the ‘Replace’ line. Then go through manually and edit. I refer you to the Editor's ‘Help’ menu for details.
Alternatively, you could possibly cast the entire output of the Symbolic Math Toolbox as a string, then use strrep to eliminate all the ‘matrix’ strings, doing essentially the same as I suggested with the Editor's ‘Find and Replace’. That seems to be the more complicated solution unless you are going to be doing this several times.
It may also be necessary for you to add parentheses inside matrix brackets as was necesssary with F1 here. Your version of MATLAB apparently did not catch that error, so you may have to check those yourself to be sure MATLAB will interpret them correctly.
I wish I could have provided an easier solution to getting your Symbolic Math Toolbox output into regular MATLAB code, but having encountered this myself many times, I have not been able to find better solutions.
Thank you very much.
I have seen many questions like mine but I did not see any clear answer like yours.
using the 'strrep' does not convert F1 to a function handle suitable to be passed to 'fsolve' so I have to do some manual modification while running the program but it is much better than before.
It is my pleasure to help!
I would appreciate it if you would accept my answer. That way it will be easier for others to find, who will search for it as you did.
When I tried this with my code is got the follwing error:
Error using sym/subs (line 156)
''Character vectors and strings in the first argument can only specify a variable or number. To evaluate character vectors and strings representing symbolic expressions, use 'str2sym'.''
Then I tried a with a simpler code, still getting the same error.
When I tried using str2sym(x(1)) , it says 'unknown variable x'
Would love some help as I am trying to find some really complex equations and have to run a differnt live script obtain the expressions, paste the output in notepad, replace my variables with x(1) and x(2) and then inser the newly replaced expression in another code where it is needed. And now the expressions are getting so long the I am getting memory error and it's taking forever to even copy paste them.
Code:
syms b c
a = b+c;
F0 = subs(a, {'c', 'b'}, {'x(1)', 'x(2)'})
@SSK Try this instead —
syms b c
x = sym('x', [2 1]) % <— NEWLY ADDED
x = 
a = b+c;
F0 = subs(a, {c, b}, {x(1), x(2)})
F0 = 
There have been significant changes in MATLAB in the last 12 years.
The Symbolic Math Toolbox has not perrmitted string variables for a while. It requries them in the sym call because ‘x’ has not been defined before then, however the ‘x’ array can be defined in the syms declaration in recent releases.
.

Sign in to comment.

More Answers (1)

I believe the matlabFunction function is what you are looking for: http://www.mathworks.com/help/toolbox/symbolic/matlabfunction.html
It allows you to convert symbolic equations to MATLAB functions. In the example you gave above, the syntax would look like:
myFcn = matlabFunction(F,'vars',{[p q]})
This will create a function handle myFcn that can be passed to fsolve. Note that the variables are passed in as a vector [p q]. This results in the function that is created having a single vector input, which is what you're going to want if you're passing it to an optimization solver like fsolve.

1 Comment

Thank you very much but my version of matlab does not contain 'matlabFunction'. I guess I will get a latter version within 10 days. If it happens I will definitely try this.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!