Edinburgh Speech Tools  2.4-release
EST_relation_compare.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1995,1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Paul Taylor and Simon King */
34 /* Date : June 1995 */
35 /*-----------------------------------------------------------------------*/
36 /* Stream class auxiliary routines */
37 /* */
38 /*=======================================================================*/
39 
40 #include <iostream>
41 #include <fstream>
42 #include <cmath>
43 #include "EST_types.h"
44 #include "EST_FMatrix.h"
45 #include "ling_class/EST_Relation.h"
46 #include "EST_Token.h"
47 #include "EST_string_aux.h"
48 #include "ling_class/EST_relation_aux.h"
49 #include "ling_class/EST_relation_compare.h"
50 #include "EST_io_aux.h"
51 
52 
53 int close_enough(EST_Item &a, EST_Item &b)
54 {
55  return ((start(&b) < a.F("end")) && (start(&a) < b.F("end")));
56 }
57 
58 // WATCH - this uses what should be private access to Keyval class.
59 void monotonic_match(EST_II_KVL &a, EST_II_KVL &b)
60 {
61  EST_Litem *ptr;
62 
63  for (ptr = a.list.head(); ptr != 0; ptr = ptr->next())
64  {
65  if (a.val(ptr) == -1)
66  continue;
67  if (b.val(a.val(ptr)) == a.key(ptr))
68 // cout << "ok\n";
69  continue;
70  else
71  a.change_key(ptr, -1);
72  }
73  for (ptr = b.list.head(); ptr != 0; ptr = ptr->next())
74  {
75  if (b.val(ptr) == -1)
76  continue;
77  if (a.val(b.val(ptr)) == b.key(ptr))
78 // cout << "ok\n";
79  continue;
80  else
81  a.change_key(ptr, -1);
82  }
83 }
84 
85 void function_match(EST_II_KVL &u, EST_Relation &a, EST_Relation &b)
86 {
87  (void)u;
88  (void)a;
89  (void)b;
90 #if 0
91  EST_Item *a_ptr;
92  EST_Litem *i_ptr;
93  int i;
94 
95  for (i = 0, a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr), ++i)
96  {
97  if (a_ptr->f("pos")==1)
98  {
99  u.add_item(a_ptr->addr(), -1);
100  for (i_ptr = a_ptr->link(b.stream_name())->head(); i_ptr != 0;
101  i_ptr = i_ptr->next())
102  u.change_val(a_ptr->addr(), a_ptr->link(b.stream_name())->item(i_ptr));
103  }
104  }
105 #endif
106 }
107 
108 void relation_match(EST_Relation &a, EST_Relation &b)
109 {
110  EST_Item *a_ptr, *b_ptr;
111 
112  for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
113  if (a_ptr->f("pos")==1)
114  for (b_ptr = b.head(); b_ptr != 0; b_ptr = inext(b_ptr))
115  {
116  if ((b_ptr->f("pos")==1)
117  &&(close_enough(*a_ptr, *b_ptr)))
118  {
119 // cout << "linked\n";
120 #if 0
121  link(*a_ptr, *b_ptr);
122 #endif
123  }
124  }
125 
126 // if ((b.pos(b_ptr->name()))
127 // &&(close_enough(*a_ptr, *b_ptr)))
128 // link(*a_ptr, *b_ptr);
129 }
130 
131 void compare_labels(EST_Relation &reflab, EST_Relation &testlab)
132 {
133  EST_II_KVL uref, utest;
134 
135  relation_match(reflab, testlab); // many-to-many mapping
136 
137  cout << "Ref\n" << reflab;
138  cout << "Test\n" << testlab;
139 
140  function_match(uref, reflab, testlab); // one-to-many mapping
141  function_match(utest, testlab, reflab); // one-to-many mapping
142 
143  cout << "Ref\n" << reflab;
144  cout << "Test\n" << testlab;
145  cout << "Keyval REF\n" << uref;
146  cout << "Keyval TEST\n" << utest;
147 
148 // cout << "Keyval REF\n" << uref;
149 // cout << "Keyval TEST\n" << utest;
150 
151  monotonic_match(uref, utest); // one-to-one mapping
152 
153  reassign_links(reflab, uref, testlab.name());
154  reassign_links(testlab, utest, reflab.name());
155  cout << "Keyval REF\n" << uref;
156  cout << "Keyval TEST\n" << utest;
157 
158 // temporary !!!
159 
160  cout.setf(ios::left,ios::adjustfield);
161 
162  cout << "Total: ";
163  cout.width(10);
164  cout << uref.length();
165  cout << "Deletions: ";
166  cout.width(10);
167  cout << insdel(uref);
168  cout << "Insertions: ";
169  cout.width(10);
170  cout<< insdel(utest) << endl;
171 }
172 
173 EST_Item *nthpos(EST_Relation &a, int n)
174 {
175  EST_Item *a_ptr;
176  int i = 0;
177  for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
178  if (a_ptr->f("pos") == 1)
179  {
180  if (n == i)
181  return a_ptr;
182  ++i;
183  }
184  return 0;
185 }
186 
187 // measures amount of total overlap between segments
188 float label_distance1(EST_Item &ref, EST_Item &test)
189 {
190  float s, e;
191 
192  s = fabs(start(&ref) - start(&test));
193  e = fabs(ref.F("end") - test.F("end"));
194 
195  return (s + e) / duration(&ref);
196 }
197 
198 // Only penalises a test segment that extends beyond the boundaries of
199 // a ref segment
200 float label_distance2(EST_Item &ref, EST_Item &test)
201 {
202  float s, e;
203 
204  s = (start(&test) < start(&ref)) ? start(&ref) - start(&test) : 0;
205  e = (ref.F("end") < test.F("end")) ?
206  test.F("end") - ref.F("end") : 0;
207 
208  return (s + e) / duration(&ref);
209 }
210 
211 int lowest_pos(EST_FMatrix &m, int j)
212 {
213  float val = 1000.0;
214  int i, pos=0;
215 
216  for (i = 0; i < m.num_rows(); ++i)
217  if ((m(i, j) > -0.01) && (m(i, j) < val))
218  {
219  val = m(i, j);
220  pos = i;
221  }
222 
223  return pos;
224 }
225 
226 void minimise_matrix_by_column(EST_FMatrix &m)
227 {
228  float val = 1000.0;
229  int i;
230  for (int j = 0; j < m.num_columns(); ++j)
231  {
232  val = 1000.0;
233  for (i = 0; i < m.num_rows(); ++i)
234  if (m(i, j) < val)
235  val = m(i, j);
236  for (i = 0; i < m.num_rows(); ++i)
237  if (m(i, j) > val)
238  m(i, j) = -1.0;
239  }
240 }
241 
242 void minimise_matrix_by_row(EST_FMatrix &m)
243 {
244  float val;
245  int i, j;
246 
247  for (i = 0; i < m.num_rows(); ++i)
248  {
249  val = 1000.0;
250  for (j = 0; j < m.num_columns(); ++j)
251  if ((m(i, j) < val) && (m(i, j) > -0.01))
252  val = m(i, j);
253  for (j = 0; j < m.num_columns(); ++j)
254  if (m(i, j) > val)
255  m(i, j) = -1.0;
256  }
257 }
258 
259 void matrix_ceiling(EST_FMatrix &m, float max)
260 {
261  int i, j;
262 
263  for (i = 0; i < m.num_rows(); ++i)
264  for (j = 0; j < m.num_columns(); ++j)
265  if (m(i, j) > max)
266  m(i, j) = -1.0;
267 
268 }
269 
270 int matrix_insertions(EST_FMatrix &m)
271 {
272  int i, j;
273  int n = 0;
274 
275  for (i = 0; i < m.num_rows(); ++i)
276  for (j = 0; j < m.num_columns(); ++j)
277  if (m(i, j) > -1.0)
278  ++n;
279 
280  return (m.num_rows() - n);
281 }
282 
283 int major_matrix_insertions(EST_FMatrix &m, EST_Relation &ref_lab)
284 {
285  int i, j;
286  int n = 0;
287  EST_Item *s;
288 
289  for (i = 0; i < m.num_rows(); ++i)
290  {
291  s = nthpos(ref_lab, i);
292 // cout << s->name() << ": f:" << s->f("minor")<< endl;
293  if (s->f("minor") == 1)
294  ++n;
295  else
296  for (j = 0; j < m.num_columns(); ++j)
297  if (m(i, j) > -1.0)
298  ++n;
299  }
300  return (m.num_rows() - n);
301 }
302 
303 int matrix_deletions(EST_FMatrix &m)
304 {
305  int i, j;
306  int n = 0;
307 
308  for (j = 0; j < m.num_columns(); ++j)
309  for (i = 0; i < m.num_rows(); ++i)
310  if (m(i, j) > -1.0)
311  ++n;
312 
313  return (m.num_columns() - n);
314 }
315 
316 int major_matrix_deletions(EST_FMatrix &m, EST_Relation &ref_lab)
317 {
318  int i, j;
319  int n = 0;
320  EST_Item *s;
321 
322  for (j = 0; j < m.num_columns(); ++j)
323  {
324  s = nthpos(ref_lab, j);
325 // cout << s->name() << ": f:" << s->f("minor")<< endl;
326  if (s->f("minor") == 1)
327  ++n;
328  else
329  for (i = 0; i < m.num_rows(); ++i)
330  if (m(i, j) > -1.0)
331  ++n;
332  }
333 
334  return (m.num_columns() - n);
335 }
336 
337 int lowest_pos(float *m, int n)
338 {
339  float val = 1000.0;
340  int i, pos=0;
341 
342  for (i = 0; i < n; ++i)
343  if (m[i] < val)
344  {
345  val = m[i];
346  pos = i;
347  }
348 
349  return pos;
350 }
351 
352 void threshold_labels(EST_Relation &reflab, float t)
353 {
354  (void)reflab;
355  (void)t;
356 #if 0
357  EST_Item *r_ptr;
358  float score=0.0;
359  int a;
360 
361  for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
362  if (r_ptr->f("pos")==1)
363  {
364  // REORG - temp comment
365 // score = atof(r_ptr->fields());
366  cout << "score is" << score << endl;
367 
368  a = r_ptr->rlink("blank").first();
369  cout << "score is" << score << " address: " << a << endl;
370  if (score > t)
371  cout << "delete\n";
372  }
373 #endif
374 }
375 
376 /* Check through relations of each ref label, and make there aren't
377 multiple ref labels related to the same test label. If this is
378 discovered, compare scores of all the relevant labels and delete the
379 relations of all but the lowest.
380 
381 At this stage, each ref label should have one and only one relation to the
382 test labels.
383 */
384 
385 void multiple_labels(EST_Relation &reflab)
386 {
387  (void)reflab;
388 #if 0
389  EST_Item *r_ptr, *s_ptr, *t_ptr;;
390  EST_Litem *p;
391  int a, pos, i;
392  EST_TList<int> la;
393  float *score;
394  score = new float[reflab.length()];
395 
396  for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
397  if (r_ptr->f("pos")==1)
398  {
399  la.clear(); // clear list and add address of current ref label
400  la.append(r_ptr->addr());
401  a = r_ptr->rlink("test").first();
402  cout << a << endl;
403 
404  // check remainer of ref labels and add any that have same
405  // relations address as r_ptr.
406  for (s_ptr = inext(r_ptr); s_ptr != 0; s_ptr = inext(s_ptr))
407  if (s_ptr->f("pos")==1)
408  if (s_ptr->rlink("test").first() == a)
409  la.append(s_ptr->addr());
410 
411  cout << "la: " << la;
412  if (la.length() > 1) // true if the are multiple relations
413  {
414  // find scores of all relevant labels
415  for (i = 0, p = la.head(); p!= 0; p = p->next(), ++i)
416  {
417  t_ptr = reflab.item(la.item(p));
418 
419  // REORG - temp comment
420 // score[i] = atof(reflab.item(la.item(p))->fields());
421  }
422  pos = lowest_pos(score, i); // find position of lowest score
423 
424  cout << "best is " << pos << endl;
425  // delete relations of all but lowest score
426  for (i = 0, p = la.head(); p!= 0; p = p->next(), ++i)
427  if (i != pos)
428  {
429  t_ptr = reflab.item(la.item(p));
430  t_ptr->rlink("test").clear();
431  }
432  }
433  }
434 #endif
435 
436 }
437 
438 /* Compare 2 sets of labels by matrix method. This involves making a M
439 (number of test labels) x N (number of ref labels) matrix, and
440 calculating the distance from each label in the test set to each label
441 in the reference set. The lowest score for each reference is then
442 recorded. A test is carried out to make sure that no two reference
443 labels point to the same test label. Then any ref label above a
444 certain distance is classified as incorrect. The numbers of insertions
445 and deletions are then calculated. */
446 
447 EST_FMatrix matrix_compare(EST_Relation &reflab, EST_Relation &testlab, int method,
448  float t, int v)
449 {
450  int i, j;
451  int num_ref, num_test;
452  EST_Item *r_ptr, *t_ptr;
453  EST_String fns;
454  (void)v;
455 
456  num_ref = num_test = 0;
457 
458  // calculate size of matrix, based on *significant* labels
459  for (r_ptr = testlab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
460  if (r_ptr->f("pos")==1)
461  ++num_test;
462 
463  for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
464  if (r_ptr->f("pos")==1)
465  ++num_ref;
466 
467  EST_FMatrix m(num_test, num_ref);
468 
469  if ((m.num_rows() == 0) || (m.num_columns() == 0))
470  return m; // nothing to analyse, hence empty matrix
471 
472  // fill matrix values by comparing each test with each reference
473  // reference is columns, test is rows
474 
475  for (i = 0, t_ptr = testlab.head(); t_ptr != 0; t_ptr = inext(t_ptr))
476  if (t_ptr->f("pos")==1)
477  {
478  for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
479  if (r_ptr->f("pos")==1)
480  {
481  if (method == 1)
482  m(i, j) = label_distance1(*r_ptr, *t_ptr);
483  else if (method == 2)
484  m(i, j) = label_distance2(*r_ptr, *t_ptr);
485  else
486  cerr << "Unknown comparison method" << method << endl;
487  ++j;
488  }
489  ++i;
490  }
491 
492 // cout << "orig M\n";
493 // print_matrix_scores(reflab, testlab, m);
494  minimise_matrix_by_column(m);
495  minimise_matrix_by_row(m);
496  matrix_ceiling(m, t);
497 
498 #if 0
499  /* This doesn't do anything */
500  // for each ref label, find closest matching test label.
501  for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
502  {
503  if (r_ptr->f("pos")==1)
504  {
505  pos = lowest_pos(m, j);
506  // REORG - temp comment
507 // r_ptr->set_field_names(r_ptr->fields() +ftoString(m(pos, j)));
508  ++j;
509  }
510  }
511 #endif
512  return m;
513 }
514 
515 void multiple_matrix_compare(EST_RelationList &rlist, EST_RelationList
516  &tlist, EST_FMatrix &m, EST_String rpos,
517  EST_String tpos, int method, float t, int v)
518 {
519  EST_Litem *pr, *pt;
520  EST_String filename;
521  EST_Relation reflab, testlab;
522  EST_StrList rposlist, tposlist, rminorlist, tminorlist;
523  float ra, rc, mra, mrc;
524 
525  StringtoStrList(rpos, rposlist);
526  StringtoStrList(tpos, tposlist);
527  StringtoStrList("m l mrb mfb lrb lfb", rminorlist);
528  StringtoStrList("m l mrb mfb lrb lfb", tminorlist);
529 
530  int tot, del, ins, ltot, ldel, lins, lmdel, mdel, lmins, mins;
531  tot = del = ins = mdel = mins = 0;
532 
533  for (pt = tlist.head(); pt; pt = pt->next())
534  {
535  pr = RelationList_ptr_extract(rlist, tlist(pt).name(), TRUE);
536  if (pr != 0)
537  {
538  reflab = rlist(pr);
539  testlab = tlist(pt);
540 
541 /* convert_to_broad(reflab, rposlist);
542  convert_to_broad(testlab, tposlist);
543  convert_to_broad(reflab, rminorlist, "minor");
544  convert_to_broad(testlab, tminorlist, "minor");
545 */
546 
547 // cout << "ref\n" << reflab;
548 // cout << "test\n" << testlab;
549 
550 // cout << "features\n";
551 // print_stream_features(reflab);
552 
553  m = matrix_compare(reflab, testlab, method, t, v);
554 
555  ltot = m.num_columns();
556  ldel = matrix_deletions(m);
557  lmdel = major_matrix_deletions(m, reflab);
558  lins = matrix_insertions(m);
559  lmins = major_matrix_insertions(m, testlab);
560 
561  print_results(reflab, testlab, m, ltot, ldel, lins, v);
562 // cout << "Major Deletions: " << lmdel << endl << endl;;
563 
564  tot += ltot;
565  del += ldel;
566  mdel += lmdel;
567  ins += lins;
568  mins += lmins;
569  }
570  }
571 
572  rc = float(tot - del)/(float)tot * 100.0;
573  ra = float(tot - del -ins)/(float)tot *100.0;
574  mrc = float(tot - mdel)/(float)tot * 100.0;
575  mra = float(tot - mdel - mins)/(float)tot *100.0;
576 
577  if (v)
578  {
579  cout << "Total " << tot << " del: " << del << " ins: " << ins << endl;
580  cout << "Total " << tot << " major del " << mdel << " major ins" << mins << endl;
581  }
582  cout << "Correct " << rc << "% Accuracy " << ra << "%" << endl;
583  cout << "Major Correct " << mrc << "% Accuracy " << mra << "%" << endl;
584 }
585 
586 void error_location(EST_Relation &e, EST_FMatrix &m, int ref)
587 {
588  int i;
589  EST_Item *s;
590 
591  // reference
592  if (ref)
593  {
594  for (i = 0, s = e.head(); s; s = inext(s))
595  if ((int)s->f("pos"))
596  {
597  if (column_hit(m, i) >= 0)
598  s->set("hit", 1);
599  else
600  s->set("hit", 0);
601  ++i;
602  }
603  }
604  else
605  for (i = 0, s = e.head(); s; s = inext(s))
606  if ((int)s->f("pos"))
607  {
608  if (row_hit(m, i) >= 0)
609  s->set("hit", 1);
610  else
611  s->set("hit", 0);
612  ++i;
613  }
614 }
615 
616 int insdel(EST_II_KVL &a)
617 {
618  int n = 0;
619  EST_Litem *ptr;
620 
621  for (ptr = a.list.head(); ptr != 0; ptr= ptr->next())
622  if (a.val(ptr) == -1)
623  ++n;
624  return n;
625 }
626 
627 int compare_labels(EST_Utterance &ref, EST_Utterance &test, EST_String name,
628  EST_II_KVL &uref, EST_II_KVL &utest)
629 {
630  // many-to-many mapping
631  (void)ref;
632  (void)test;
633  (void)name;
634  (void)uref;
635  (void)utest;
636 #if 0
637  relation_match(ref.stream(name), test.stream(name));
638 
639  // one-to-many mapping
640  function_match(uref, ref.stream(name), test.stream(name));
641  function_match(utest, test.stream(name), ref.stream(name));
642 
643  monotonic_match(uref, utest); // one-to-one mapping
644 
645  // temporary !!!
646  // reassign_links(ref.stream(name), uref, name);
647  // reassign_links(test.stream(name), utest, name);
648 
649  // cout << "Keyval REF\n" << uref;
650  // cout << "Keyval TEST\n" << utest;
651 #endif
652  return 0;
653 }
654 
655 void reassign_links(EST_Relation &a, EST_Relation &b, EST_II_KVL &ua, EST_II_KVL &ub)
656 {
657  (void)a;
658  (void)b;
659  (void)ua;
660  (void)ub;
661 
662 #if 0
663  EST_Item *a_ptr, *b_ptr;
664 
665  for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
666  {
667  a_ptr->link(b.stream_name())->clear();
668  if ((a_ptr->f("pos")==1) && (ua.val(a_ptr->addr()) != -1))
669  a_ptr->make_link(b.stream_name(), ua.val(a_ptr->addr()));
670  }
671  for (b_ptr = b.head(); b_ptr != 0; b_ptr = inext(b_ptr))
672  {
673  b_ptr->link(a.stream_name())->clear();
674  if ((b_ptr->f("pos")==1) && (ub.val(b_ptr->addr()) != -1))
675  b_ptr->make_link(a.stream_name(), ub.val(b_ptr->addr()));
676  }
677 #endif
678 }
679 
680 void reassign_links(EST_Relation &a, EST_II_KVL &u, EST_String stream_type)
681 {
682  (void)a;
683  (void)u;
684  (void)stream_type;
685 #if 0
686  EST_Item *a_ptr;
687 
688  for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
689  {
690  a_ptr->link(stream_type)->clear();
691  if ((a_ptr->f("pos")==1) && (u.val(a_ptr->addr()) != -1))
692  a_ptr->make_link(stream_type, u.val(a_ptr->addr()));
693  }
694 #endif
695 }
696 
697 
698 int commutate(EST_Item *a_ptr, EST_II_KVL &f1, EST_II_KVL &f2,
699  EST_II_KVL &lref, EST_II_KVL &ltest)
700 
701 {
702  int b, c, d, v;
703  (void)lref; // unused parameter
704  (void)a_ptr;
705 
706 // v = a_ptr->addr();
707  v = 0;
708  b = f2.val(v);
709  c = (b == -1) ? -1: ltest.val(b);
710  d = (c == -1) ? -1: f1.val(c);
711 
712  return d;
713 
714  // c = ltest.val(f2.val(v));
715  // d = f1.val(ltest.val(f2.val(v)));
716 }
717 
718 // REF TEST
719 // f1
720 // S -----------> S
721 // ^ ^
722 // lr | | lt
723 // | f2 |
724 // E -----------> E
725 //
726 // For a given element in E(ref), "e", if
727 // lr(e) == f1(lt(f2(e)))
728 // Then ei has been recognised fully.
729 
730 void test_labels(EST_Utterance &ref, EST_Utterance &test, EST_Option &op)
731 {
732  (void)ref;
733  (void)test;
734  (void)op;
735 #if 0
736  EST_II_KVL f2, inv_f2, inv_f1, f1, lref, ltest;
737 
738  compare_labels(ref, test, "Event", f2, inv_f2);
739  compare_labels(ref, test, "Syllable", f1, inv_f1);
740 
741  if (op.present("print_syllable") && op.present("print_map"))
742  {
743  cout << "Syllable mapping from ref to test\n" << f1;
744  cout << "Syllable mapping from test to ref\n" << inv_f1;
745  }
746  if (op.present("print_event") && op.present("print_map"))
747  {
748  cout << "Event mapping from ref to test\n" << f2;
749  cout << "Event mapping from test to ref\n" << inv_f2;
750  }
751 
752  if (op.present("print_syllable") && op.present("print_ins"))
753  cout << "Syllable_insertions: " << insdel(inv_f1) << endl;
754  if (op.present("print_syllable") && op.present("print_del"))
755  cout << "Syllable_deletions: " << insdel(f1) << endl;
756 
757  if (op.present("print_event") && op.present("print_ins"))
758  cout << "Event_insertions: " << insdel(inv_f2) << endl;
759  if (op.present("print_event") && op.present("print_del"))
760  cout << "Event_deletions: " << insdel(f2) << endl;
761 
762  // cout << "Ref\n" << ref.stream("Event") << ref.stream("Syllable");
763  // cout << "Test\n" << test.stream("Event") << test.stream("Syllable");
764 
765  function_match(lref, ref.stream("Event"), ref.stream("Syllable"));
766  function_match(ltest, test.stream("Event"), test.stream("Syllable"));
767 
768  if (op.present("print_functions"))
769  {
770  cout << "Lref\n" << lref;
771  cout << "Ltest\n" << ltest;
772  cout << "f1\n" << f1;
773  cout << "f2\n" << f2;
774  }
775 
776  EST_Item *a_ptr;
777  int correct, n_ev, n_syl;
778 
779  correct = n_ev = n_syl = 0;
780  for (a_ptr = ref.stream("Event").head(); a_ptr != 0; a_ptr = inext(a_ptr))
781  if (a_ptr->f("pos")==1)
782  {
783  ++n_ev;
784  if (lref.val(a_ptr->addr())
785  == commutate(a_ptr, f1, f2, lref, ltest))
786  ++correct;
787  }
788  for (a_ptr = ref.stream("Syllable").head();a_ptr != 0; a_ptr = inext(a_ptr))
789  if (a_ptr->f("pos")==1)
790  ++n_syl;
791 
792  if (op.present("print_syllable") && op.present("print_total"))
793  cout << "Number_of_Syllables: " << n_syl << endl;
794  if (op.present("print_event") && op.present("print_total"))
795  cout << "Number_of_Events: " << n_ev << endl;
796 
797  if (op.present("print_link"))
798  cout << "Correct_links: " << correct <<endl;
799 
800  if (op.present("print_derivation"))
801  {
802  for (a_ptr = ref.stream("Event").head();a_ptr!= 0; a_ptr = inext(a_ptr))
803  {
804  if (a_ptr->f("pos")==1)
805  {
806  cout << "Lr(ei): " << lref.val(a_ptr->addr()) << endl;
807  cout << "f2(ei): " << f2.val(a_ptr->addr()) << endl;
808  cout << "Lt(f2(ei)): " << ltest.val(f2.val(a_ptr->addr()))
809  << endl;
810  cout << "f1(Lt(f2(ei))): "
811  << f1.val(ltest.val(f2.val(a_ptr->addr()))) << endl;
812  }
813  cout << "Event " << *a_ptr;
814  if ( lref.val(a_ptr->addr())
815  == f1.val(ltest.val(f2.val(a_ptr->addr()))))
816  cout << " is correct\n";
817  else
818  cout << " is incorrect\n";
819  }
820  }
821 #endif
822 }
823 
824 void print_i_d_scores(EST_FMatrix &m)
825 {
826  cout.setf(ios::left,ios::adjustfield);
827  cout << "Total: ";
828  cout.width(10);
829  cout << m.num_columns();
830  cout << "Deletions: ";
831  cout.width(10);
832  cout << matrix_deletions(m);
833  cout << "Insertions: ";
834  cout.width(10);
835  cout<< matrix_insertions(m) << endl;
836 }
837 
838 void print_matrix_scores(EST_Relation &ref, EST_Relation &test, EST_FMatrix &a)
839 {
840  int i, j;
841  EST_Item *r_ptr, *t_ptr;
842 
843  cout << " ";
844  for (r_ptr = ref.head(); r_ptr != 0; r_ptr = inext(r_ptr))
845  {
846  if (r_ptr->f("pos")==1)
847  {
848  // cout.width(5);
849  // cout.setf(ios::right);
850  cout << r_ptr->name() << " ";
851  cout.width(6);
852  cout.setf(ios::right);
853  cout<< r_ptr->F("end") << " ";
854  }
855  }
856  cout << endl;
857 
858  for (t_ptr = test.head(), i = 0; i < a.num_rows(); t_ptr = inext(t_ptr))
859  {
860  if (t_ptr->f("pos")==1)
861  {
862  cout << t_ptr->name() << " ";
863  for (j = 0; j < a.num_columns(); ++j)
864  {
865  cout.width(10);
866  cout.precision(3);
867  cout.setf(ios::right);
868  cout.setf(ios::fixed, ios::floatfield);
869  cout << a(i, j) << " ";
870  }
871  cout << endl;
872  ++i;
873  }
874  }
875 }
876 
877 int row_hit(EST_FMatrix &m, int r)
878 {
879  int i;
880  for (i = 0; i < m.num_columns(); ++i)
881  if (m(r, i) > 0.0)
882  return i;
883 
884  return -1;
885 }
886 
887 // return the row index of the first positive entry in column c
888 int column_hit(EST_FMatrix &m, int c)
889 {
890  int i;
891  for (i = 0; i < m.num_rows(); ++i)
892  if (m(i, c) > 0.0)
893  return i;
894 
895  return -1;
896 }
897 
898 int num_b_insertions(EST_FMatrix &m, int last, int current)
899 {
900  int c1, c2;
901  c1 = column_hit(m, last);
902  c2 = column_hit(m, current);
903 
904  return c2 - c1 -1;
905 }
906 
907 int num_b_deletions(EST_FMatrix &m, int last, int current)
908 {
909  int c1, c2;
910  c1 = row_hit(m, last);
911  c2 = row_hit(m, current);
912 
913  return c2 - c1 -1;
914 }
915 
916 void print_s_trans(EST_Relation &a, int width)
917 {
918  (void)a;
919  (void)width;
920 // for (int i = 0; i < a.length(); ++i)
921 // {
922  // cout << (int)a.nth(i)->f("pos") << " XX " << a.nth(i)->name() << endl;
923 /* if ((a.nth(i)->f("pos")==1) || (a.nth(i)->name() == " "))
924  {
925  // cout.setf(ios::fixed, ios::floatfield);
926  cout.width(width);
927  cout << a.nth(i)->name() << " ";
928  }
929  }
930 */
931  cout << endl;
932 }
933 
934 void make_hit_and_miss(EST_Relation &a)
935 {
936  EST_Item *s;
937 
938  for (s = a.head(); s; s = inext(s))
939  {
940  if (s->f("pos") == 0)
941  s->set_name(".");
942  else if (s->f("hit") == 1)
943  s->set_name("HIT");
944  else
945  s->set_name("MISS");
946  s->features().clear();
947  }
948 }
949 
950 void pos_only(EST_Relation &lab)
951 {
952  EST_Item *a, *n;
953 
954  for (a = lab.head(); a; a = n)
955  {
956  n = inext(a);
957  if (!a->f_present("pos"))
958  lab.remove_item(a);
959  }
960 }
961 
962 // Warning this is bugged - slight misalignments occur.
963 void print_aligned_trans(EST_Relation &ref, EST_Relation &test, EST_FMatrix &m)
964 {
965  (void)ref;
966  (void)test;
967  (void)m;
968 /* int i, j, n;
969  EST_Relation al, refal, testal;
970  EST_Item *p;
971  EST_Item pos, blank;
972 
973  blank.set_name(" ");
974 
975  pos.f.set("pos", 1);
976  blank.f.set("pos", 0);
977 
978  pos_only(test);
979  pos_only(ref);
980 
981  // first check for empty matrices - indicates all insertions or deletions
982 
983  if ((m.num_columns() == 0) && (m.num_rows() != 0))
984  {
985  cout << "REC: ";
986  print_s_trans(test);
987  return;
988  }
989  else if ((m.num_columns() != 0) && (m.num_rows() == 0))
990  {
991  cout << "LAB: ";
992  print_s_trans(ref);
993  return;
994  }
995  else if ((m.num_columns() == 0) && (m.num_rows() == 0))
996  {
997  cout << "LAB: ";
998  print_s_trans(ref);
999  return;
1000  }
1001 
1002  int l;
1003  l = 0;
1004 
1005  // cout << "ref: " << ref.name() << endl << ref;
1006  // cout << "test: " << test.name() << endl << test;
1007 
1008  if (m(0, 0) < 0)
1009  refal.append(blank);
1010 
1011 
1012  pos.set_name(ref.head()->name());
1013  refal.append(pos);
1014  for (i = 1, p = ref.head()->next(); p; p = p->next(), ++i)
1015  {
1016  n = num_b_insertions(m, l, i);
1017 
1018  for (j = 0; j < n; ++j)
1019  refal.append(blank);
1020 
1021  if (n > -0.5)
1022  l = i;
1023  pos.set_name(p->name());
1024 
1025  refal.append(pos);
1026  }
1027 
1028  l = 0;
1029  pos.set_name(test.head()->name());
1030  testal.append(pos);
1031  for (i = 1, p = test.head()->next(); p; p = p->next(), ++i)
1032  {
1033  n = num_b_deletions(m, l, i);
1034 
1035  // cout << *p << "last " << l << " current " << i <<
1036  // " insertions " << n << endl;
1037  for (j = 0; j < n; ++j)
1038  testal.append(blank);
1039 
1040  if (n > -0.5)
1041  l = i;
1042  pos.set_name(p->name());
1043  testal.append(pos);
1044  }
1045 
1046  cout << "LAB: ";
1047  print_s_trans(refal, 3);
1048  cout << "REC: ";
1049  print_s_trans(testal, 3);
1050 */
1051 }
1052 
1053 void print_results(EST_Relation &ref, EST_Relation &test,
1054  EST_FMatrix &m, int tot,
1055  int del, int ins, int v)
1056 {
1057  (void) tot;
1058  (void) del;
1059  (void) ins;
1060  if (v == 0)
1061  return;
1062 
1063  // v == 1 prints out total insertions etc
1064 
1065  if (v == 2)
1066  {
1067  cout << basename(ref.name(), "") << endl;
1068  print_i_d_scores(m);
1069  cout << endl;
1070  }
1071  else if (v == 3)
1072  {
1073  cout << basename(ref.name(), "") << endl;
1074  print_aligned_trans(ref, test, m);
1075  print_i_d_scores(m);
1076  cout << endl;
1077  }
1078  else if (v == 4)
1079  {
1080  cout << basename(ref.name(), "") << endl;
1081  print_matrix_scores(ref, test, m);
1082  print_i_d_scores(m);
1083  cout << endl;
1084  }
1085  else if (v == 5)
1086  {
1087  cout << basename(ref.name(), "") << endl;
1088  print_matrix_scores(ref, test, m);
1089  print_aligned_trans(ref, test, m);
1090  print_i_d_scores(m);
1091  cout << endl;
1092  }
1093  else if (v == 6)
1094  {
1095  print_matrix_scores(ref, test, m);
1096  error_location(ref, m, 1);
1097  make_hit_and_miss(ref);
1098  error_location(test, m, 0);
1099  make_hit_and_miss(test);
1100  ref.save("ref.error");
1101  test.save("test.errors");
1102  }
1103  else if (v == 7)
1104  {
1105  error_location(ref, m, 1);
1106  make_hit_and_miss(ref);
1107  error_location(test, m, 0);
1108  make_hit_and_miss(test);
1109  ref.save("ref.error");
1110  test.save("test.error");
1111  }
1112 }
EST_Option
Definition: EST_Option.h:50
EST_TKVL::list
EST_TList< EST_TKVI< K, V > > list
Linked list of key-val pairs. Don't use this as it will be made private in the future.
Definition: EST_TKVL.h:93
EST_Relation::name
const EST_String & name() const
Definition: EST_Relation.h:122
EST_TMatrix::num_columns
int num_columns() const
return number of columns
Definition: EST_TMatrix.h:181
EST_TList< int >
EST_Features::clear
void clear()
Definition: EST_Features.h:256
EST_Relation::save
EST_write_status save(const EST_String &filename, bool evaluate_ff=false) const
Definition: EST_Relation.cc:224
EST_TList::clear
void clear(void)
remove all items in list
Definition: EST_TList.h:239
EST_Item::f_present
int f_present(const EST_String &name) const
Definition: EST_Item.h:230
EST_TMatrix::num_rows
int num_rows() const
return number of rows
Definition: EST_TMatrix.h:179
EST_Relation::length
int length() const
Definition: EST_Relation.cc:137
EST_TList::append
void append(const T &item)
add item onto end of list
Definition: EST_TList.h:191
EST_Utterance
Definition: EST_Utterance.h:54
EST_TKVL::present
const int present(const K &rkey) const
Returns true if key is present.
Definition: EST_TKVL.cc:222
EST_Item::F
const float F(const EST_String &name) const
Definition: EST_Item.h:134
EST_TKVL::key
const K & key(EST_Litem *ptr, int m=1) const
find key, reference by ptr
Definition: EST_TKVL.cc:201
EST_TKVL::change_val
int change_val(const K &rkey, const V &rval)
Definition: EST_TKVL.cc:113
EST_UItem
Definition: EST_UList.h:51
EST_Relation
Definition: EST_Relation.h:67
EST_String
Definition: EST_String.h:70
EST_Item::set
void set(const EST_String &name, int ival)
Definition: EST_Item.h:179
EST_TKVL
Definition: EST_TKVL.h:72
EST_Relation::head
EST_Item * head() const
Definition: EST_Relation.h:125
EST_TKVL::add_item
int add_item(const K &rkey, const V &rval, int no_search=0)
add key-val pair to list
Definition: EST_TKVL.cc:248
EST_Relation::remove_item
void remove_item(EST_Item *item)
Definition: EST_Relation.cc:165
EST_FMatrix
Definition: EST_FMatrix.h:56
EST_TKVL::change_key
int change_key(EST_Litem *ptr, const K &rkey)
change name of key pair.
Definition: EST_TKVL.cc:99
EST_TKVL::val
const V & val(const K &rkey, bool m=0) const
return value according to key (const)
Definition: EST_TKVL.cc:145
EST_Item
Definition: EST_Item.h:82