Philosophical question: How to get a vector from the output of solve? Why isn't it a vector already?

16 views (last 30 days)
I am solving an equation of several variables, and the result is a struct.
SNvec = solve(nvecEqabcd,[a1,b1,c1,d1]);
I want to write it to my latex file. So I sprintf a string that will eventually get printed to my latex file (after some processing to make it pretty):
string.steadyn=sprintf('The steady state of the nvec equation is: $rupup = %f, rdowndown = %f, rupdown = rdownup = %f, r00 = %f, rbb = %f.$',struct2array(SNvec),1-sum(struct2array(SNvec)))
But today, for some reason, struct2array doesn't work. I look that up and apparently it works for some versions of matlab but it isn't really meant to be used. So I could change my sprintf to use the struct variables, SNvec.a1, etc or I could set the output of 'solve' to four different variables, then assign them to a vector:
[Eqa1, Eqb1, Eqc1, Eqd1] = solve(nvecEqabcd,[a1,b1,c1,d1]);
Equilnvec = [Eqa1, Eqb1, Eqc1, Eqd1] ;
But in my mind, the solution to my equation is a single object, a vector, with whatever dimension it happens to have, it might be twenty dimensions next time. The fact that matlab, which was invented to deal with matrices and vectors, doesn't naturally treat this thing like a vector, suggests to me that I'm thinking about something the wrong way. Why do I have to manually turn it into a vector? Is there a smart way to turn the struct into a vector? Should I be doing something else?
Obviously, low priority here, I can get my code to run and am just curious if anybody has insight about how to think about this.

Accepted Answer

Steven Lord
Steven Lord on 20 Mar 2023
syms x y
sol = solve(x == 5, y^2 == 4)
sol = struct with fields:
x: [2×1 sym] y: [2×1 sym]
sol.x
ans = 
sol.y
ans = 
How exactly would you want those two solutions to the system of equations to be represented as one vector? I could potentially see storing the solutions as one matrix but I'd be worried about ambiguity with a vector representation.
As an example, if the solution vector was [5 5 -2 2] and just looking at that vector, does it represent the four solutions to a univariate problem, the two solutions to a system of two equations in two unknowns, or the unique solution to a system of four equations in four unknowns?
  2 Comments
Emily
Emily on 20 Mar 2023
Thanks for your answer. Yes, I see it could potentially have multiple solutions. It is interesting that Matlab orders the struct as it does, though. I would have guessed that it would make a struct sol.1 which contained a vector (x1,y1) for the first solution and a sol.2 with a vector (x2,y2) for the second solution. Because the things which belong to each other are the x and the y for a single solution. But it must be how you end up actually making use of structs that suggests doing it this way.
Steven Lord
Steven Lord on 20 Mar 2023
That is one possible way the solutions could be stored in the struct, yes. But we'd need to create names for each of those fields and there could be many potential solutions. With this approach, the names of the fields are obvious: they're the names of the variables for which you're solving.
There's also the point Walter Roberson made in a comment on John D'Errico's answer. In what order should the values for the variables be stored in those vectors? Do you know how to determine the order in which MATLAB returns the list of variables for a given equation or set of equations? It's not as simple as you might think. See the documentation page for the symvar function and this documentation page.
And yes, there have been posts here on MATLAB Answers and on the old MATLAB newsgroup where users have complained that solve had a bug because they didn't realize this order dependency when they called solve with multiple outputs (with names in the "wrong" order.)
syms x y
[yy, xx] = solve([x-5==0, y^2==4])
yy = 
xx = 
You might think that yy corresponds to y and xx to x, but it's the reverse. You don't have this problem with the one-output form:
sol = solve([x-5 == 0, y^2 == 4])
sol = struct with fields:
x: [2×1 sym] y: [2×1 sym]
sol.x
ans = 
sol.y
ans = 

Sign in to comment.

More Answers (1)

John D'Errico
John D'Errico on 20 Mar 2023
Edited: John D'Errico on 20 Mar 2023
I tried it with a vector, wondering if that might make solve work more easily. And it does work.
A = magic(3);
X = sym('X',[3,1]);
B = [1;2;3];
Xsol = solve(A*X == B)
Xsol = struct with fields:
X1: 1/20 X2: 3/10 X3: 1/20
But struct2array has no problem.
struct2array(Xsol)
ans = 
syms a b c
abc = solve(A*[a;b;c] == B)
abc = struct with fields:
a: 1/20 b: 3/10 c: 1/20
struct2array(abc)
ans = 
Which also seems to work. So as long as a unique solution is returned, it works nicely. The vector was not necessary. The problem for you was surely that solve is returning multiple solutions.
In the case where there are multiple solutions, maybe you need to use struct2cell.
syms x y
xy = solve(x^2 + y^2==2,x+y==1)
xy = struct with fields:
x: [2×1 sym] y: [2×1 sym]
xycell = struct2cell(xy)
xycell = 2×1 cell array
{2×1 sym} {2×1 sym}
And now with some more manipulations, convert those results into an array as you might desire. Perhaps like this:
horzcat(xycell{:})
ans = 
Hope this helps.
  3 Comments
John D'Errico
John D'Errico on 20 Mar 2023
Yes. You would need to be careful about extracting results into an array, as you might trip over ambiguities since the elements of an array have no names.
Emily
Emily on 20 Mar 2023
Thanks, Walter Roberson. Good point that it is safer not to assume that the order of the variables in the struct will be the order that I sent them in. I will use subs, that is a nice clean way of getting a vector.

Sign in to comment.

Products


Release

R2021b

Community Treasure Hunt

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

Start Hunting!