comparison src/DLD-FUNCTIONS/chol.cc @ 7554:40574114c514

implement Cholesky factorization updating
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 04 Mar 2008 22:25:50 -0500
parents f3c00dc0912b
children 07522d7dcdf8
comparison
equal deleted inserted replaced
7553:56be6f31dd4e 7554:40574114c514
18 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see 19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>. 20 <http://www.gnu.org/licenses/>.
21 21
22 */ 22 */
23
24 // The cholupdate function was written by Jaroslav Hajek
25 // <highegg@gmail.com>, Copyright (C) 2008 VZLU Prague, a.s., Czech
26 // Republic.
23 27
24 #ifdef HAVE_CONFIG_H 28 #ifdef HAVE_CONFIG_H
25 #include <config.h> 29 #include <config.h>
26 #endif 30 #endif
27 31
439 print_usage (); 443 print_usage ();
440 444
441 return retval; 445 return retval;
442 } 446 }
443 447
448 DEFUN_DLD (cholupdate, args, nargout,
449 "-*- texinfo -*-\n\
450 @deftypefn {Loadable Function} {[@var{R1}, @var{info}]} = cholupdate (@var{R}, @var{u}, @var{op})\n\
451 Update or downdate a Cholesky factorization. Given an upper triangular\n\
452 matrix @var{R} and a column vector @var{u}, attempt to determine another\n\
453 upper triangular matrix @var{R1} such that\n\
454 @itemize @bullet\n\
455 @item\n\
456 @var{R1}'*@var{R1} = @var{R}'*@var{R} + @var{u}*@var{u}'\n\
457 if @var{op} is \"+\"\n\
458 @item\n\
459 @var{R1}'*@var{R1} = @var{R}'*@var{R} - @var{u}*@var{u}'\n\
460 if @var{op} is \"-\"\n\
461 @end itemize\n\
462 \n\
463 If @var{op} is \"-\", @var{info} is set to\n\
464 @itemize\n\
465 @item 0 if the downdate was successful,\n\
466 @item 1 if @var{R}'*@var{R} - @var{u}*@var{u}' is not positive definite,\n\
467 @item 2 if @var{R} is singular.\n\
468 @end itemize\n\
469 \n\
470 If @var{info} is not present, an error message is printed in cases 1 and 2.\n\
471 @seealso{chol, qrupdate}\n\
472 @end deftypefn")
473 {
474 int nargin = args.length ();
475
476 octave_value_list retval;
477
478 octave_value argR,argu,argop;
479
480 if ((nargin == 3 || nargin == 2)
481 && (argR = args(0), argR.is_matrix_type ())
482 && (argu = args(1), argu.is_matrix_type ())
483 && (nargin < 3 || (argop = args(2), argop.is_string ())))
484 {
485 octave_idx_type n = argR.rows ();
486
487 std::string op = (nargin < 3) ? "+" : argop.string_value();
488
489 bool down = false;
490
491 if (nargin < 3 || (op == "+") || (down = op == "-"))
492 if (argR.columns () == n
493 && argu.rows () == n && argu.columns () == 1)
494 {
495 if (argR.is_real_matrix () && argu.is_real_matrix ())
496 {
497 // real case
498 Matrix R = argR.matrix_value ();
499 Matrix u = argu.matrix_value ();
500
501 CHOL fact;
502 fact.set (R);
503 int err = 0;
504
505 if (down)
506 err = fact.downdate (u);
507 else
508 fact.update (u);
509
510 if (nargout > 1)
511 retval(1) = err;
512 else if (err)
513 error ("cholupdate: downdate violates positiveness");
514
515 retval(0) = fact.chol_matrix ();
516 }
517 else
518 {
519 // complex case
520 ComplexMatrix R = argR.complex_matrix_value ();
521 ComplexMatrix u = argu.complex_matrix_value ();
522
523 ComplexCHOL fact;
524 fact.set (R);
525 int err = 0;
526
527 if (down)
528 err = fact.downdate (u);
529 else
530 fact.update (u);
531
532 if (nargout > 1)
533 retval(1) = err;
534 else if (err)
535 error ("cholupdate: downdate violates positiveness");
536
537 retval(0) = fact.chol_matrix ();
538 }
539 }
540 else
541 error ("cholupdate: dimension mismatch");
542 else
543 error ("cholupdate: op must be \"+\" or \"-\"");
544 }
545 else
546 print_usage ();
547
548 return retval;
549 }
550
551 /*
552 %!test
553 %! A = [ 0.436997 -0.131721 0.124120 -0.061673 ;
554 %! -0.131721 0.738529 0.019851 -0.140295 ;
555 %! 0.124120 0.019851 0.354879 -0.059472 ;
556 %! -0.061673 -0.140295 -0.059472 0.600939 ];
557 %!
558 %! u = [ 0.98950 ;
559 %! 0.39844 ;
560 %! 0.63484 ;
561 %! 0.13351 ];
562 %!
563 %! R = chol(A);
564 %!
565 %! R1 = cholupdate(R,u);
566 %!
567 %! assert(norm(triu(R1)-R1,Inf) == 0)
568 %! assert(norm(R1'*R1 - R'*R - u*u',Inf) < 1e1*eps)
569 %!
570 %! R1 = cholupdate(R1,u,"-");
571 %!
572 %! assert(norm(triu(R1)-R1,Inf) == 0)
573 %! assert(norm(R1 - R,Inf) < 1e1*eps)
574 %!
575 %!test
576 %! A = [ 0.5585528 + 0.0000000i -0.1662088 - 0.0315341i 0.0107873 + 0.0236411i -0.0276775 - 0.0186073i ;
577 %! -0.1662088 + 0.0315341i 0.6760061 + 0.0000000i 0.0011452 - 0.0475528i 0.0145967 + 0.0247641i ;
578 %! 0.0107873 - 0.0236411i 0.0011452 + 0.0475528i 0.6263149 - 0.0000000i -0.1585837 - 0.0719763i ;
579 %! -0.0276775 + 0.0186073i 0.0145967 - 0.0247641i -0.1585837 + 0.0719763i 0.6034234 - 0.0000000i ];
580 %!
581 %! u = [ 0.54267 + 0.91519i ;
582 %! 0.99647 + 0.43141i ;
583 %! 0.83760 + 0.68977i ;
584 %! 0.39160 + 0.90378i ];
585 %!
586 %! R = chol(A);
587 %!
588 %! R1 = cholupdate(R,u);
589 %!
590 %! assert(norm(triu(R1)-R1,Inf) == 0)
591 %! assert(norm(R1'*R1 - R'*R - u*u',Inf) < 1e1*eps)
592 %!
593 %! R1 = cholupdate(R1,u,"-");
594 %!
595 %! assert(norm(triu(R1)-R1,Inf) == 0)
596 %! assert(norm(R1 - R,Inf) < 1e1*eps)
597 */
598
444 /* 599 /*
445 ;;; Local Variables: *** 600 ;;; Local Variables: ***
446 ;;; mode: C++ *** 601 ;;; mode: C++ ***
447 ;;; End: *** 602 ;;; End: ***
448 */ 603 */