KerMor  0.9
Model order reduction for nonlinear dynamical systems and nonlinear approximation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
KernelExpansion.m
Go to the documentation of this file.
1 namespace kernels{
2 
3 
4 /* (Autoinserted by mtoc++)
5  * This source code has been filtered by the mtoc++ executable,
6  * which generates code that can be processed by the doxygen documentation tool.
7  *
8  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
9  * Except for the comments, the function bodies of your M-file functions are untouched.
10  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
11  * attached source files that are highly readable by humans.
12  *
13  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
14  * the correct locations in the source code browser.
15  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
16  */
17 
19  :public KerMorObject,
20  public general.AProjectable,
66  public: /* ( Dependent, setObservable ) */
67 
87  public: /* ( Dependent ) */
88 
168  public: /* ( setObservable ) */
169 
170  struct Centers = struct("'xi',[]");
232  protected:
233 
247  public:
248 
250 
251  /* Set custom projection to true as the project method is
252  * overridden */
253  this = this@KerMorObject;
254 
255  this.fSK= kernels.GaussKernel;
256 
257  /* DONT CHANGE THIS LINE unless you know what you are doing or
258  * you are me :-)
259  * this.updateRotInv; */
260 
261  this.registerProps(" Kernel "," Centers "," Base ");
262  }
271  function fx = evaluate(matrix x,varargin) {
272  fx = this.Ma * (this.Base \ this.getKernelVector(x)^t);
273  }
286  function phi = getKernelVector(matrix x,varargin) {
287  phi = this.fSK.evaluate(x, this.Centers.xi);
288  }
302  if nargin < 3
303  x = this.Centers.xi;
304  end
305  row = this.fSK.evaluate(x, x(:,idx));
306  }
321  function J = getStateJacobian(x,varargin) {
322  J = this.Ma * (this.Base \ this.fSK.getNabla(x, this.Centers.xi)^t);
323  }
341  function K = getKernelMatrix() {
342  K = [];
343  if ~isempty(this.Centers)
344  K = this.fSK.evaluate(this.Centers.xi,[]);
345 /* cent = this.Centers.xi;
346  * if isa(cent,'data.FileMatrix')
347  * cent = cent.toMemoryMatrix;
348  * end
349  * K = this.fSK.evaluate(cent,[]); */
350  end
351  }
367  function v = scalarProductWith(f) {
368  if ~isa(f," kernels.KernelExpansion ")
369  error(" f argument must be another KernelExpansion ");
370  end
371  if size(this.Centers.xi,1) ~= size(f.Centers.xi,1)
372  error(" Function input dimension mismatch ");
373  end
374  if size(this.Ma,1) ~= size(f.Ma,1)
375  error(" Function output dimension mismatch ");
376  end
377  v = sum(sum(this.Ma .* f.evaluate(this.Centers.xi),2));
378  }
379 
380 
381  function normalize() {
382  this.Ma= this.Ma / this.NativeNorm;
383  }
384 
385 
387  this.Centers.xi= atd.xi(:,idx);
388  }
402  function kernels.KernelExpansionkexp = toTranslateBase() {
403  kexp = this.clone;
404  if kexp.HasCustomBase
405  kexp.Ma= kexp.Ma/kexp.Base;
406  kexp.Base= 1;
407  end
408  }
429  function subexp = getSubExpansion(arg) {
430  subexp = this.clone;
431  if isscalar(arg)
432  sel = 1:arg;
433  else
434  sel = arg;
435  end
436  subexp.Ma= subexp.Ma(:,sel);
437  subexp.Centers.xi= subexp.Centers.xi(:,sel);
438  if isfield(this.Centers," ti ") && ~isempty(this.Centers.ti)
439  subexp.Centers.ti= this.Centers.ti(sel);
440  end
441  if isfield(this.Centers," mui ") && ~isempty(this.Centers.mui)
442  subexp.Centers.mui= this.Centers.mui(:,sel);
443  end
444  if subexp.HasCustomBase
445  subexp.Base= subexp.Base(sel,sel);
446  end
447  }
448 
449 
450  function c = getGlobalLipschitz(double t,colvec<double> mu) {
451  c = sum(this.Ma_norms) * this.Kernel.getGlobalLipschitz;
452  }
453 
454 
455  function target = project(V,W) {
456  target = this.clone;
457  k = target.Kernel;
458  /* For rotation invariant kernel expansions the snapshots can be
459  * transferred into the subspace without loss. */
460  if k.IsRBF
461  target.Centers.xi= W^t * this.Centers.xi;
462  PG = V^t*(k.G*V);
463  if all(all(abs(PG - eye(size(PG,1))) < 100*eps))
464  PG = 1;
465  end
466  target.Kernel.G= PG;
467  elseif k.IsScProd
468  target.Centers.xi= V^t * (k.G * this.Centers.xi);
469  target.Kernel.G= 1;
470  end
471  target.Ma= W^t*this.Ma;
472  }
473 
474 
475  function copy = clone(copy) {
476  if nargin == 1
477  copy = kernels.KernelExpansion;
478  end
479  /* Copy local variables */
480  copy.Centers= this.Centers;
481  copy.Ma= this.Ma;
482  copy.Base= this.Base;
483  copy.fSK= this.fSK.clone;
484  }
485 
486 
487  function clear() {
488  this.Ma= [];
489  this.Centers.xi= [];
490  }
498  function sum = plus(B) {
499  sum = compose(A, B, 1);
500  }
510  function diff = minus(B) {
511  diff = compose(A, B, -1);
512  }
522  function neg = uminus() {
523  neg = this.clone;
524  neg.Ma= -this.Ma;
525  }
526 
527 
528  function exportToDirectory(dir) {
529  if nargin < 2
530  dir = pwd;
531  end
532  Utils.ensureDir(dir);
533  k = this.Kernel;
534  if isa(k," kernels.GaussKernel ")
535  kdata = [1 k.Gamma];
536  elseif isa(k," kernels.Wendland ")
537  kdata = [2 k.Gamma k.d k.k];
538  else
539  error(" Cannot export a kernel of type %s yet. ",class(this.Kernel));
540  end
541  Util.saveRealVector(kdata," kernel.bin ",dir);
542  Util.saveRealMatrix(this.Centers.xi," centers.bin ",dir);
543  Util.saveRealMatrix(this.Ma," coeffs.bin ",dir);
544  }
545 
546 
547  function json = toJSON(filename) {
548  json = " { ";
549  /* sprintf('{%s,"centers":%s}',coef,cent); */
550  json = [json " 'coeffs': " Util.matrixToJSON(this.Ma)];
551  json = [json " , 'centers': " Util.matrixToJSON(this.Centers.xi)];
552  if this.HasCustomBase
553  json = [json " , 'base': " Util.matrixToJSON(this.Base)];
554  end
555  json = [json " } "];
556  if nargin > 1
557  fh = fopen(filename," w+ ");
558  fprintf(fh," %s ",json);
559  fclose(fh);
560  end
561  }
562 
563 
564  function res = test_getStateJacobianInstance() {
565  n = 5;
566  xdim = size(this.Centers.xi,1);
567  meanx = mean(this.Centers.xi,2);
568  rs = RandStream(" mt19937ar "," Seed ",round(rand*1000));
569  allX = bsxfun(@plus,meanx,rs.rand(xdim,n));
570  allX = [this.Centers.xi(:,1) allX];
571  res = true;
572  for k = 1:n
573  x = allX(:,k);
574  dx = ones(xdim,1)*sqrt(eps(class(x))).*max(abs(x),1);
575  X = repmat(x,1,xdim);
576  Jc = (this.evaluate(X+diag(dx))-this.evaluate(X))*diag(1./dx);
577  J = this.getStateJacobian(x);
578  maxrel = max(max(abs((J-Jc)./Jc)));
579  if maxrel > 1e-2
580  fprintf(" %s: Max relative error: %g\n ",class(this.Kernel),maxrel);
581  res = false;
582  end
583  end
584  }
585 
586 
587  /* % Getter & Setter */
588  public:
589 
590 
591 #if 0 //mtoc++: 'set.Centers'
592 function Centers(value) {
593  C = [" xi "," ti "," mui "];
594  if isempty(value) || any(isfield(value, C))
595  this.Centers= value;
596 /* if ~isfield(value,'xi')
597  * warning('REQUIRED_FIELD:Empty','xi is a required field, which is left empty');
598  * end */
599  else
600  error(" Value passed is not a valid struct. Only the field names xi, ti, mui are allowed ");
601  end
602  }
603 
604 #endif
605 
606 
607 
608 #if 0 //mtoc++: 'get.Kernel'
609 function k = Kernel() {
610  k = this.fSK;
611  }
612 
613 #endif
614 
615 
616 
617 #if 0 //mtoc++: 'get.Size'
618 function value = Size() {
619  value = 0;
620  if ~isempty(this.Centers)
621  value = size(this.Centers.xi,2);
622  end
623  }
624 
625 #endif
626 
627 
628 
629 #if 0 //mtoc++: 'set.Kernel'
630 function Kernel(value) {
631  if isa(value," kernels.BaseKernel ")
632  this.fSK= value;
633 /* this.updateRotInv; */
634  else
635  error(" Kernel must be a subclass of kernels.BaseKernel. ");
636  end
637  }
638 
639 #endif
640 
641 
642 
643 #if 0 //mtoc++: 'get.Ma_norms'
644 function m = Ma_norms() {
645  m = sqrt(sum(this.Ma.^2,1));
646  }
647 
648 #endif
649 
650 
651 
652 #if 0 //mtoc++: 'get.ComponentNorms'
653 function n = ComponentNorms() {
654  if this.HasCustomBase
655  c = this.Ma/this.Base;
656  else
657  c = this.Ma;
658  end
659  n = sqrt(sum(c" .* (this.getKernelMatrix * c "),1))^t;
660  }
661 
662 #endif
663 
664 
665 
666 #if 0 //mtoc++: 'get.NativeNorm'
667 function n = NativeNorm() {
668 
669  /* doesnt use ComponentNorms as this way we save "sqrt(x).^2" */
670  if this.HasCustomBase
671  c = this.Ma/this.Base;
672  else
673  c = this.Ma;
674  end
675  n = sqrt(sum(sum(c" .* (this.getKernelMatrix * c "))));
676  }
677 
678 #endif
679 
686 #if 0 //mtoc++: 'get.MBnd'
687 function M = MBnd() {
688  if this.HasCustomBase
689  c = this.Ma/this.Base;
690  else
691  c = this.Ma;
692  end
693  M = max(sum(abs(c),2));
694  }
695 
696 #endif
697 
698 
699 
700 #if 0 //mtoc++: 'get.HasCustomBase'
701 function v = HasCustomBase() {
702  v = ~isempty(this.Base) && (numel(this.Base) > 1 || this.Base ~= 1);
703  }
704 
705 #endif
706 
707 
708  private:
709 
710  function c = compose(B,sgn) {
711  if ~isa(A," kernels.KernelExpansion ") || ~isa(B," kernels.KernelExpansion ")
712  error(" Both arguments must be at least kernels.KernelExpansion subclasses ");
713  end
714  if A.Kernel ~= B.Kernel
715  error(" Cannot add kernel expansions: different state space kernels ");
716  elseif ~isempty(A.Ma) && ~isempty(B.Ma) && size(A.Ma,1) ~= size(B.Ma,1)
717  error(" Cannot add kernel expansions: different output dimensions ");
718  elseif ~isempty(A.Centers.xi) && ~isempty(B.Centers.xi) && size(A.Centers.xi,1) ~= size(B.Centers.xi,1)
719  error(" Cannot add kernel expansions: different statespace center dimensions ");
720  end
721  c = A.clone;
722  c.Centers.xi= [A.Centers.xi B.Centers.xi];
723  c.Ma= [A.Ma sgn*B.Ma];
724  }
725 
726 
727  public: /* ( Static ) */
728 
729  static function res = test_getStateJacobian() {
730  rs = RandStream(" mt19937ar "," Seed ",0);
731  ke = kernels.KernelExpansion;
732  k1 = kernels.GaussKernel(1);
733  k2 = kernels.Wendland;
734 
735  s = [1 1 2 2 3 3];
736  d = [1 20 1 20 1 20];
737  gam = 4 + (1:6);
738  n = 6;
739  nc = round(rs.rand(1,6)*100);
740 
741  res = true;
742  for k = 1:n
743  ke.Centers.xi= rs.rand(d(k),nc(k));
744  ke.Ma= rs.rand(d(k)+1,nc(k));
745 
746  k1.Gamma= gam(k);
747  ke.Kernel= k1;
748  res = res & ke.test_getStateJacobianInstance;
749 
750  k2.Gamma= gam(k);
751  k2.d= d(k);
752  k2.k= s(k);
753  ke.Kernel= k2;
754  res = res & ke.test_getStateJacobianInstance;
755  end
756  }
757 
758 
759  protected: /* ( Static ) */
760 
761  static function this = loadobj(this,from) {
762  if nargin > 1
763  this.Kernel= from.Kernel;
764  this.Ma= from.Ma;
765  this.Centers= from.Centers;
766  if isfield(from," Base ")
767  this.Base= from.Base;
768  end
769  this = loadobj@KerMorObject(this, from);
770  elseif ~isa(this, " kernels.KernelExpansion ")
771  newinst = kernels.KernelExpansion;
772  newinst.Kernel= this.fSK;
773  newinst.Ma= this.Ma;
774  newinst.Centers= this.Centers;
775  if isfield(this," Base ")
776  newinst.Base= this.Base;
777  end
778  this = loadobj@KerMorObject(newinst, this);
779  end
780  }
836 };
837 }
838 
Collection of generally useful functions.
Definition: Utils.m:17
matrix< double > Ma
The coefficient data for each dimension.
data.FileMatrix xi
The state space samples , stored row-wise in a data.FileMatrix instance.
function kernels.KernelExpansion kexp = toTranslateBase()
Returns the same kernel expansion with the canonical translate base used.
function phi = getKernelVector(matrix x, varargin)
Evaluates the kernel expansion.
function c = getGlobalLipschitz(double t,colvec< double > mu)
For some error estimators, a global Lipschitz constant estimation is performed. This function has to ...
static function this = loadobj(this, from)
As the constant properties are transient, they have to be re-computed upon loading.
logical HasCustomBase
Flag that indicates if a base other than the direct translate base is used for this kernel expansion...
function subexp = getSubExpansion(arg)
Interface for all components that can be projected.
Definition: AProjectable.m:18
A double value.
function v = scalarProductWith(f)
Base class for any KerMor class.
Definition: KerMorObject.m:17
colvec< double > ComponentNorms
Returns the native space norms for each component function size(Ma,1)
function registerProps(varargin)
Call this method at any class that defines DPCM observed properties.
Definition: DPCMObject.m:125
An integer value.
virtual function c = getGlobalLipschitz()
Returns the global lipschitz constant of this kernel.
function target = project(V, W)
A boolean value.
function fx = evaluate(matrix x, varargin)
Evaluates the kernel expansion.
kernels.BaseKernel fSK
The inner (state) kernel object.
KerMorObject()
Constructs a new KerMor object.
Definition: KerMorObject.m:55
A variable number of input arguments.
function sum = plus(B)
Adds two kernel expansions and will clone the frist argument's class as result type.
rowvec Ma_norms
The norms of the coefficient matrix of the kernel expansion.
KernelExpansion()
Default constructor.
static function saveRealVector(vec, file, folder)
Stores a real double vector in little endian format.
Definition: Util.m:99
function res = test_getStateJacobianInstance()
kernels.BaseKernel Kernel
The Kernel to use for system variables.
function J = getStateJacobian(x, varargin)
Evaluates the jacobian matrix of this function at the given point.
function neg = uminus()
function K = getKernelMatrix()
Computes the kernel matrix for the currently set center data.
V
The matrix of the biorthogonal pair .
Definition: AProjectable.m:61
function setCentersFromATD(data.ApproxTrainData atd,rowvec< integer > idx)
Sets the centers according to the indices idx of the data.ApproxTrainData.
Size
The size of the kernel expansion.
MBnd
Returns the M upper bound for this KernelExpansion, which is .
function copy = clone(copy)
The interface method with returns a copy of the current class instance.
Definition: BaseKernel.m:169
#define X(i, j)
Speed test * all(1:3)
function clear()
Removes all centers and coefficients from the expansion and leaves the associated kernels untouched...
static function logical success = ensureDir(char dir)
Ensures that a directory exists.
Definition: Utils.m:700
static function char jsonobj = matrixToJSON(double value)
Takes a matrix and returns a JSON representation as JSONObject with the fields "dim" and "values"...
Definition: Util.m:140
function json = toJSON(filename)
IGLOBALLIPSCHITZ Interface for all functions that have a global lipschitz constant for the state/spat...
function exportToDirectory(dir)
function diff = minus(B)
Adds two kernel expansions and will clone the frist argument's class as result type.
static function res = test_getStateJacobian()
function copy = clone(copy)
The interface method with returns a copy of the current class instance.
A matlab row vector.
double NativeNorm
Returns the norm of in the RKHS .
ApproxTrainData: Data class for approximation training data, containing several useful bounding box p...
struct Centers
The kernel centers used in the approximation.
A MatLab struct.
Util: Utility functions for export of matrices and vectors to files.
Definition: Util.m:17
W
The matrix of the biorthogonal pair .
Definition: AProjectable.m:72
matrix< double > Base
This property lets the user store a custom base, for which the coefficients are set. The custom base tells which linear combinations of center elements belong to which base.
virtual function K = evaluate(matrix< double > x,matrix< double > y)
Evaluation method for the current kernel.
Base class for all KerMor Kernels.
Definition: BaseKernel.m:18
KernelExpansion: Base class for state-space kernel expansions.
static function saveRealMatrix(mat, file, folder)
Stores a real double matrix in little endian format.
Definition: Util.m:52
function row = getKernelMatrixColumn(integer idx,matrix x, varargin)
Evaluates the kernel expansion.