Simplify symbolic expression for optimized code generation

2 views (last 30 days)
Ehsan Tofigh
Ehsan Tofigh on 17 Apr 2017
Commented: Andrew Newell on 17 Apr 2017
I'm trying to generate optimized c code (reduce the number of operations) from symbolic MATLAB expressions. However I MATLAB doesn't seem to want to simplify even the simplest equations.
lets take the following expression as an example:
X_eq = [
q0 + (dt*q1*(gyrobx - omegax))/2 + (dt*q2*(gyroby - omegay))/2 + (dt*q3*(gyrobz - omegaz))/2;
q1 - (dt*q0*(gyrobx - omegax))/2 + (dt*q3*(gyroby - omegay))/2 - (dt*q2*(gyrobz - omegaz))/2;
q2 - (dt*q0*(gyroby - omegay))/2 - (dt*q3*(gyrobx - omegax))/2 + (dt*q1*(gyrobz - omegaz))/2;
q3 + (dt*q2*(gyrobx - omegax))/2 - (dt*q1*(gyroby - omegay))/2 - (dt*q0*(gyrobz - omegaz))/2];
What i'm looking for is (basically factor out dt and (1/2)):
X_eq = [
q0 + (((q1*(gyrobx - omegax)) + (q2*(gyroby - omegay)) + (q3*(gyrobz - omegaz)))*dt)/2;
q1 - (((q0*(gyrobx - omegax)) + (q3*(gyroby - omegay)) - (q2*(gyrobz - omegaz)))*dt)/2;
q2 - (((q0*(gyroby - omegay)) - (q3*(gyrobx - omegax)) + (q1*(gyrobz - omegaz)))*dt)/2;
q3 + (((q2*(gyrobx - omegax)) - (q1*(gyroby - omegay)) - (q0*(gyrobz - omegaz)))*dt)/2];
simplify(X_eq, 'steps', 100) returns the original expression so it's useless:
ans =
q0 + (dt*q1*(gyrobx - omegax))/2 + (dt*q2*(gyroby - omegay))/2 + (dt*q3*(gyrobz - omegaz))/2
q1 - (dt*q0*(gyrobx - omegax))/2 + (dt*q3*(gyroby - omegay))/2 - (dt*q2*(gyrobz - omegaz))/2
q2 - (dt*q0*(gyroby - omegay))/2 - (dt*q3*(gyrobx - omegax))/2 + (dt*q1*(gyrobz - omegaz))/2
q3 + (dt*q2*(gyrobx - omegax))/2 - (dt*q1*(gyroby - omegay))/2 - (dt*q0*(gyrobz - omegaz))/2
collect(X_eq, [dt]) returns the following which is a step forward but doesn't factorize (1/2):
ans =
((q1*(gyrobx - omegax))/2 + (q2*(gyroby - omegay))/2 + (q3*(gyrobz - omegaz))/2)*dt + q0
((q3*(gyroby - omegay))/2 - (q0*(gyrobx - omegax))/2 - (q2*(gyrobz - omegaz))/2)*dt + q1
((q1*(gyrobz - omegaz))/2 - (q3*(gyrobx - omegax))/2 - (q0*(gyroby - omegay))/2)*dt + q2
((q2*(gyrobx - omegax))/2 - (q1*(gyroby - omegay))/2 - (q0*(gyrobz - omegaz))/2)*dt + q3
Finally, collect(X_eq, [1/2, -1/2, dt, -dt]) does the following which comes close but is still not what I expect:
ans =
((q1*(gyrobx - omegax) + q2*(gyroby - omegay) + q3*(gyrobz - omegaz))*dt)/2 + q0
((q3*(gyroby - omegay))*dt)/2 - ((q0*(gyrobx - omegax) + q2*(gyrobz - omegaz))*dt)/2 + q1
((q1*(gyrobz - omegaz))*dt)/2 - ((q0*(gyroby - omegay) + q3*(gyrobx - omegax))*dt)/2 + q2
((q2*(gyrobx - omegax))*dt)/2 - ((q1*(gyroby - omegay) + q0*(gyrobz - omegaz))*dt)/2 + q3
I've tried subexpr() as well which has it's used by doesn't help me in this situation. The number of equations is high so finding an automated way of reducing the number of calculations is important.

Answers (1)

Andrew Newell
Andrew Newell on 17 Apr 2017
I don't know how particular you are about the exact form of the simplified expression, but this certainly produces a simpler expression:
Q = [q0; q1; q2; q3];
X_eq = Q + simplify(expand(X_eq-Q));
  5 Comments
Andrew Newell
Andrew Newell on 17 Apr 2017
Maybe because 1/2 is not a variable. How about this?
X_eq = collect(2*expand(X_eq),dt)/2;

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!