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
BinTree.m
Go to the documentation of this file.
1 
2 
3 /* (Autoinserted by mtoc++)
4  * This source code has been filtered by the mtoc++ executable,
5  * which generates code that can be processed by the doxygen documentation tool.
6  *
7  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
8  * Except for the comments, the function bodies of your M-file functions are untouched.
9  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
10  * attached source files that are highly readable by humans.
11  *
12  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
13  * the correct locations in the source code browser.
14  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
15  */
16 
17 class BinTree
18  :public handle {
43  private:
44 
45  root = "[]";
46 
47 
48  public: /* ( Dependent ) */
49 
51 
53 
54 
55  public: /* ( Dependent ) */
56 
57 
58 
59 #if 0 //mtoc++: 'get.Height'
60 function h = Height() {
61  h = this.height(this.root);
62  }
63 
64 #endif
65 
66 
67 
68 #if 0 //mtoc++: 'get.Values'
69 function v = Values() {
70  v = this.getvalues(this.root);
71  }
72 
73 #endif
74 
75 
76  function clear() {
77  if ~isempty(this.root)
78  this.root.delete;
79  this.root= [];
80  end
81  }
82 
83 
84  function Insert(key,value) {
85  if nargin < 3
86  value = key;
87  end
88  if numel(key) ~= numel(value)
89  error(" If key and value arguments are given they must have the same number of elements. ");
90  end
91  if KerMor.App.Verbose > 2
92  cnt = 0; cp = 0;
93  m = numel(value);
94  fprintf(" Filling tree (%d values).. ",m);
95  for idx=1:m
96  this.root= this.insert(this.root, key(idx), value(idx));
97  p = round(idx*100/m);
98  if p >= cp
99  fprintf(" %d%% ",p);
100  cp = cp+10;
101  end
102  end
103  fprintf(" \n ");
104  else
105  for idx=1:numel(value)
106  this.root= this.insert(this.root, key(idx), value(idx));
107  end
108  end
109  }
110 
111 
112  function values = Find(keys) {
113  values = this.find(this.root, keys);
114 /* end */
115  }
126  function [l , u ] = FindClosest(keys) {
127  n = numel(keys);
128  if n == 1
129  [l, u] = this.findclosest(this.root, keys);
130  elseif n < 15
131  l = zeros(1:n);
132  u = zeros(1:n);
133  for idx=1:n
134  [l(idx), u(idx)] = this.findclosest(this.root, keys(idx));
135  end
136  else
137  [l, u] = this.findclosestmulti(repmat(this.root,1,length(keys)), keys);
138  end
139  }
140 
141 
142  function display() {
143  this.printTree(this.root,0);
144  }
145 
146 
147  private: /* ( Dependent ) */
148 
149 
150  function value = find(n,key) {
151  value = [];
152  while ~isempty(n)
153  if lt(key,n.Key)
154  n = n.left;
155  elseif gt(key,n.Key)
156  n = n.right;
157  else
158  value = n.Value;
159  return;
160  end
161  end
162  }
173  function [l , u ] = findclosest(n,key) {
174  u = []; l = [];
175 /* minu = [];
176  * maxl = [];
177  * Initialize with this node n, as it might be the smallest/largest */
178  minu = n;
179  maxl = n;
180  while ~isempty(n)
181  if lt(key,n.Key)
182  minu = n;
183  n = n.left;
184  elseif gt(key,n.Key)
185  maxl = n;
186  n = n.right;
187  else
188  l = n.Value;
189  u = l;
190  return;
191  end
192  end
193  if ~isempty(minu)
194  u = minu.Value;
195  end
196  if ~isempty(maxl)
197  l = maxl.Value;
198  end
199  }
210  function [l , u ] = findclosestmulti(n,keys) {
211  u = inf(size(keys));
212  l = -u;
213  minu = BinTreeNode.empty(0,1);
214  maxl = minu;
215  while true
216  lempt = cellfun(" isempty ",[n.left]);
217  rempt = cellfun(" isempty ",[n.right]);
218 
219  low = lt(keys,[n.Key]);
220  gre = gt(keys,[n.Key]);
221 
222  minu(low) = n(low);
223  maxl(gre) = n(gre);
224 
225  golow = low & ~lempt;
226  if any(golow)
227  n(golow) = [n(golow).left];
228  end
229  goup = gre & ~rempt;
230  if any(goup)
231  n(goup) = [n(goup).right];
232  end
233  eq = ~low & ~gre;
234  if any(eq)
235  u(eq) = [n(eq).Value];
236  l(eq) = [n(eq).Value];
237  end
238  if all(~golow & ~goup)
239  break;
240  end
241  end
242  hasu = ~isnan([minu.Key]);
243  u(hasu) = [minu(hasu).Value];
244  hasl = ~isnan([maxl.Key]);
245  l(hasl) = [maxl(hasl).Value];
246  }
257  function v = getvalues(n) {
258  v = [];
259  if ~isempty(n)
260  v = [this.getvalues(n.left) n.Value this.getvalues(n.right)];
261  end
262  }
263 
264 
265 
266  function n = insert(n,key,value) {
267  if isempty(n)
268  n = BinTreeNode(key, value);
269  elseif lt(key,n.Key)
270  n.left= this.insert(n.left, key, value);
271  if n.left.height - this.height(n.right)== 2
272  if lt(key, n.left.Key)
273  n = this.rotateWithLeftChild(n);
274  else
275  n = this.doubleWithLeftChild(n);
276  end
277  end
278  elseif gt(key, n.Key)
279  n.right= this.insert(n.right, key, value);
280  if n.right.height - this.height(n.left) == 2
281  if gt(key, n.right.Key)
282  n = this.rotateWithRightChild(n);
283  else
284  n = this.doubleWithRightChild(n);
285  end
286  end
287  else
288  error(" Duplicate entry! ");
289  end
290  n.height= max(this.height(n.left), this.height(n.right)) + 1;
291  }
292 
293 
294  function h = height(n) {
295  if isempty(n)
296  h = -1;
297  else
298  h = n.height;
299  end
300  }
301 
302 
303  function n = rotateWithLeftChild(n2) {
304  n = n2.left;
305  n2.left= n.right;
306  n.right= n2;
307  n2.height= max(this.height(n2.left), this.height(n2.right)) + 1;
308  n.height= max(this.height(n.left), n2.height) + 1;
309  }
310 
311 
312  function n = rotateWithRightChild(n2) {
313  n = n2.right;
314  n2.right= n.left;
315  n.left= n2;
316  n2.height= max(this.height(n2.left), this.height(n2.right)) + 1;
317  n.height= max(this.height(n.right), n2.height ) + 1;
318  }
319 
320 
321  function n = doubleWithLeftChild(n) {
322  n.left= this.rotateWithRightChild(n.left);
323  n = this.rotateWithLeftChild(n);
324  }
325 
326 
327  function n = doubleWithRightChild(n) {
328  n.right= this.rotateWithLeftChild(n.right);
329  n = this.rotateWithRightChild(n);
330  }
331 
332 
333  function printTree(n,ntabs) {
334  if ~isempty(n)
335  this.printTree(n.left,ntabs+1);
336  fprintf([repmat(" \t ",1,ntabs) " %f => %f\n "], n.Key, n.Value);
337  this.printTree(n.right,ntabs+1);
338  end
339  }
340 
341 
342  public: /* ( Static ) */ /* ( Dependent ) */
343 
344  static function res = test_BinTree() {
345  res = true;
346 
347  /* % Init */
348  t = BinTree;
349  n = 2^4;
350 
351  /* % Test usage as Key-Value BinaryTree */
352  k = randperm(n);
353  v = randperm(n);
354  t.Insert(k,v);
355 
356  /* Find all values for keys */
357  for idx = 1:length(k)
358  res = res && v(idx) == t.Find(k(idx));
359  end
360  /* Test nonexistent key */
361  res = res && isempty(t.Find(2*n));
362 
363  /* Test multi-find
364  * vs = t.Find([k n+1]);
365  * res = res && all(v == vs(1:end-1)) && isnan(vs(end)); */
366 
367  /* % Test usage as simple BinaryTree */
368  t.clear;
369  v = randperm(n);
370  t.Insert(v);
371 
372  /* Check for correct ordering */
373  res = res && all(sort(v) == t.Values);
374 
375  /* Find all values */
376  for value=v
377  res = res && ~isempty(t.Find(value));
378  end
379 
380  /* Height check */
381  h = t.Height;
382  hlp = n / (2^(h+1));
383  res = res && hlp <= 1;
384 
385  /* Closeness check - select some random positions and check */
386  ex = randperm(n-1)+1;
387  ex = ex(1:round(n/2));
388  ks = sort(k);
389  for i=1:length(ex)
390  ru = ks(ex(i));
391  rl = ru-1;
392  [l,u] = t.FindClosest((rl+ru)/2);
393  res = res && l == rl && u == ru;
394  end
395 
396  M = [2, 10, 100, 1000, 10000];
397  R = [100, 60, 40, 20, 10];
398  for j = 1:length(R)
399  m = M(j);
400  r = R(j);
401  k = linspace(0,n+1,m);
402  tmp = tic;
403  for idx = 1:length(k)
404  [l,u] = t.FindClosest(k(idx)); /* #ok<*NASGU> */
405 
406  end
407  ti(1,j) = toc(tmp); /* #ok<*AGROW> */
408 
409 
410  tmp = tic;
411  [l,u] = t.FindClosest(k);
412  ti(2,j) = toc(tmp);
413  ti = sum(ti,2)/r;
414  fprintf(" Speed test of multi-find-closest of %d values (averaged over %d runs): %fs loop to %fs multi (factor %f faster).\n ",m,r,ti(1),ti(2),ti(1)/ti(2));
415  end
416 
417  fprintf(" BinTree test finished with n=%d, h=%d, n/2^(h+1)=%f <! 1\n ",n,h,hlp);
418  }
419 
431 };
432 
function [ l , u ] = FindClosest(keys)
Definition: BinTree.m:126
BinTree: A weighted binary tree.
Definition: BinTree.m:17
sort
ort the handle objects in any array in ascending or descending order.
function values = Find(keys)
if numel(keys) > 1 values = this.findMulti(repmat(this.root,1,length(keys)), keys); else ...
Definition: BinTree.m:112
function Insert(key, value)
Definition: BinTree.m:84
Matlab's base handle class (documentation generation substitute)
static function res = test_BinTree()
Definition: BinTree.m:344
Speed test * all(1:3)
Values
Definition: BinTree.m:52
eq
Relational functions example. See details for more information.
function clear()
Definition: BinTree.m:76
Global configuration class for all KerMor run-time settings.
Definition: KerMor.m:17
BinTreeNode:
Definition: BinTreeNode.m:17
static function KerMor theinstance = App()
The singleton KerMor instance.
Definition: KerMor.m:910
function display()
Definition: BinTree.m:142
Height
Definition: BinTree.m:50