From: <par...@us...> - 2010-09-12 23:03:27
|
Revision: 7704 http://octave.svn.sourceforge.net/octave/?rev=7704&view=rev Author: paramaniac Date: 2010-09-12 23:03:20 +0000 (Sun, 12 Sep 2010) Log Message: ----------- control: add new sminreal implementation and tests Modified Paths: -------------- trunk/octave-forge/main/control/inst/@lti/sminreal.m trunk/octave-forge/main/control/inst/issample.m trunk/octave-forge/main/control/inst/ltimodels.m Modified: trunk/octave-forge/main/control/inst/@lti/sminreal.m =================================================================== --- trunk/octave-forge/main/control/inst/@lti/sminreal.m 2010-09-11 20:50:58 UTC (rev 7703) +++ trunk/octave-forge/main/control/inst/@lti/sminreal.m 2010-09-12 23:03:20 UTC (rev 7704) @@ -1,4 +1,4 @@ -## Copyright (C) 2009 Lukas F. Reichlin +## Copyright (C) 2009 - 2010 Lukas F. Reichlin ## ## This file is part of LTI Syncope. ## @@ -17,44 +17,91 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {@var{sys} =} sminreal (@var{sys}) -## Perform state-space model reduction based on structure, -## i.e. retain only states which are both controllable and observable. +## @deftypefnx {Function File} {@var{sys} =} sminreal (@var{sys}, @var{tol}) +## Perform state-space model reduction based on structure. +## Remove states which have no influence on the input-output behaviour. ## The physical meaning of the states is retained. +## +## @strong{Inputs} +## @table @var +## @item sys +## State-space model. +## @item tol +## Optional tolerance for controllability and observability. +## Entries of the state-space matrices whose moduli are less or equal to @var{tol} +## are assumed to be zero. Default value is 0. +## @end table +## +## @strong{Outputs} +## @table @var +## @item sys +## Reduced state-space model. +## @end table +## +## @seealso{minreal} ## @end deftypefn -## Algorithm based on sysmin by A. Scottedward Hodel ## Author: Lukas Reichlin <luk...@gm...> ## Created: October 2009 -## Version: 0.1 +## Version: 0.2 -function sys = sminreal (sys) +function sys = sminreal (sys, tol = 0) + if (nargin > 2) # sminreal () not possible (inside @lti) + print_usage (); + endif + if (! isa (sys, "ss")) warning ("sminreal: system not in state-space form"); sys = ss (sys); endif - [cflg, Uc] = isctrb (sys); - [oflg, Uo] = isobsv (sys); + if (! (isreal (tol) && isscalar (tol) && (tol >= 0))) + error ("sminreal: second argument is not a valid tolerance"); + endif - xc = find (max (abs (Uc.')) != 0); - xo = find (max (abs (Uo.')) != 0); - st_idx = intersect (xc, xo); + [a, b, c] = ssdata (sys); + a = abs (a) > tol; + b = abs (b) > tol; + c = abs (c) > tol; + + co_idx = __controllable_states__ (a, b); + ob_idx = __controllable_states__ (a.', c.'); + + st_idx = intersect (co_idx, ob_idx); + sys = __sysprune__ (sys, ":", ":", st_idx); - warning ("sminreal: use result with caution"); - endfunction -## FIXME: algorithm returns wrong result for the example below -## -## P = ss (-2, 3, 4, 5) -## C = inv (P) -## L = P * C -## Ls = sminreal (L) -## bode (Ls) -## -## Obviously, both magnitude and phase should be straight lines at 0 dB and 0 deg -## In this case, sminreal shouldn't remove any states of L \ No newline at end of file +function c_idx = __controllable_states__ (a, b) + + n = rows (a); # number of states + a = a & ! eye (n); # set diagonal entries to zero + + c_vec = any (b, 2); # states directly controllable + c_idx = find (c_vec); # indices of directly controllable states + c_idx_new = 0; # any vector of length > 0 possible + + while (all (length (c_idx) != [0, n] && length(c_idx_new) != 0)) + + u_idx = find (! c_vec); # indices of uncontrollable states + + #{ + ## debug code + a(u_idx, :) + repmat (c_vec.', length (u_idx), 1) + a(u_idx, :) & repmat (c_vec.', length (u_idx), 1) + any (a(u_idx, :) & repmat (c_vec.', length (u_idx), 1), 2) + find (any (a(u_idx, :) & repmat (c_vec.', length (u_idx), 1), 2)) + #} + + c_idx_new = u_idx (find (any (a(u_idx, :) & repmat (c_vec.', length (u_idx), 1), 2))); + c_idx = union (c_idx, c_idx_new); + c_vec(c_idx_new) = 1; + + endwhile + +endfunction Modified: trunk/octave-forge/main/control/inst/issample.m =================================================================== --- trunk/octave-forge/main/control/inst/issample.m 2010-09-11 20:50:58 UTC (rev 7703) +++ trunk/octave-forge/main/control/inst/issample.m 2010-09-12 23:03:20 UTC (rev 7704) @@ -35,9 +35,9 @@ print_usage (); endif - if (flg == 0) # allow -1 and 0 + if (flg == 0) # refuse -1 and 0 bool = (isreal (tsam) && isscalar (tsam) && (tsam > 0)); - else # refuse -1 and 0 + else # allow -1 and 0 bool = (isreal (tsam) && isscalar (tsam) && (tsam >= 0 || tsam == -1)); endif Modified: trunk/octave-forge/main/control/inst/ltimodels.m =================================================================== --- trunk/octave-forge/main/control/inst/ltimodels.m 2010-09-11 20:50:58 UTC (rev 7703) +++ trunk/octave-forge/main/control/inst/ltimodels.m 2010-09-12 23:03:20 UTC (rev 7704) @@ -249,6 +249,36 @@ #%!assert (M, Me, 1e-4); +## ss: sminreal +%!shared B, C +%! +%! A = ss (-2, 3, 4, 5); +%! B = A / A; +%! C = sminreal (B); # no states should be removed +%! +%!assert (C.a, B.a); +%!assert (C.b, B.b); +%!assert (C.c, B.c); +%!assert (C.d, B.d); + +%!shared A, B, D, E +%! +%! A = ss (-1, 1, 1, 0); +%! B = ss (-2, 3, 4, 5); +%! C = [A, B]; +%! D = sminreal (C(:, 1)); +%! E = sminreal (C(:, 2)); +%! +%!assert (D.a, A.a); +%!assert (D.b, A.b); +%!assert (D.c, A.c); +%!assert (D.d, A.d); +%!assert (E.a, B.a); +%!assert (E.b, B.b); +%!assert (E.c, B.c); +%!assert (E.d, B.d); + + ## mtimes %!shared sysmat, sysmat_exp %! sys1 = ss ([0, 1; -3, -2], [0; 1], [-5, 1], [2]); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |