Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
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 = a_ptr->next(), ++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 = a_ptr->next())
113  if (a_ptr->f("pos")==1)
114  for (b_ptr = b.head(); b_ptr != 0; b_ptr = b_ptr->next())
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 = a_ptr->next())
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 = r_ptr->next())
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 = r_ptr->next())
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 = r_ptr->next(); s_ptr != 0; s_ptr = s_ptr->next())
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, pos;
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 = r_ptr->next())
460  if (r_ptr->f("pos")==1)
461  ++num_test;
462 
463  for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next())
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 = t_ptr->next())
476  if (t_ptr->f("pos")==1)
477  {
478  for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next())
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 comparision 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  // for each ref label, find closest matching test label.
499  for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next())
500  {
501  if (r_ptr->f("pos")==1)
502  {
503  pos = lowest_pos(m, j);
504  // REORG - temp comment
505 // r_ptr->set_field_names(r_ptr->fields() +ftoString(m(pos, j)));
506  ++j;
507  }
508  }
509  return m;
510 }
511 
512 void multiple_matrix_compare(EST_RelationList &rlist, EST_RelationList
513  &tlist, EST_FMatrix &m, EST_String rpos,
514  EST_String tpos, int method, float t, int v)
515 {
516  EST_Litem *pr, *pt;
517  EST_String filename;
518  EST_Relation reflab, testlab;
519  EST_StrList rposlist, tposlist, rminorlist, tminorlist;
520  float ra, rc, mra, mrc;
521 
522  StringtoStrList(rpos, rposlist);
523  StringtoStrList(tpos, tposlist);
524  StringtoStrList("m l mrb mfb lrb lfb", rminorlist);
525  StringtoStrList("m l mrb mfb lrb lfb", tminorlist);
526 
527  int tot, del, ins, ltot, ldel, lins, lmdel, mdel, lmins, mins;
528  tot = del = ins = mdel = mins = 0;
529 
530  for (pt = tlist.head(); pt; pt = pt->next())
531  {
532  pr = RelationList_ptr_extract(rlist, tlist(pt).name(), TRUE);
533  if (pr != 0)
534  {
535  reflab = rlist(pr);
536  testlab = tlist(pt);
537 
538 /* convert_to_broad(reflab, rposlist);
539  convert_to_broad(testlab, tposlist);
540  convert_to_broad(reflab, rminorlist, "minor");
541  convert_to_broad(testlab, tminorlist, "minor");
542 */
543 
544 // cout << "ref\n" << reflab;
545 // cout << "test\n" << testlab;
546 
547 // cout << "features\n";
548 // print_stream_features(reflab);
549 
550  m = matrix_compare(reflab, testlab, method, t, v);
551 
552  ltot = m.num_columns();
553  ldel = matrix_deletions(m);
554  lmdel = major_matrix_deletions(m, reflab);
555  lins = matrix_insertions(m);
556  lmins = major_matrix_insertions(m, testlab);
557 
558  print_results(reflab, testlab, m, ltot, ldel, lins, v);
559 // cout << "Major Deletions: " << lmdel << endl << endl;;
560 
561  tot += ltot;
562  del += ldel;
563  mdel += lmdel;
564  ins += lins;
565  mins += lmins;
566  }
567  }
568 
569  rc = float(tot - del)/(float)tot * 100.0;
570  ra = float(tot - del -ins)/(float)tot *100.0;
571  mrc = float(tot - mdel)/(float)tot * 100.0;
572  mra = float(tot - mdel - mins)/(float)tot *100.0;
573 
574  if (v)
575  {
576  cout << "Total " << tot << " del: " << del << " ins: " << ins << endl;
577  cout << "Total " << tot << " major del " << mdel << " major ins" << mins << endl;
578  }
579  cout << "Correct " << rc << "% Accuracy " << ra << "%" << endl;
580  cout << "Major Correct " << mrc << "% Accuracy " << mra << "%" << endl;
581 }
582 
583 void error_location(EST_Relation &e, EST_FMatrix &m, int ref)
584 {
585  int i;
586  EST_Item *s;
587 
588  // reference
589  if (ref)
590  {
591  for (i = 0, s = e.head(); s; s = s->next())
592  if ((int)s->f("pos"))
593  {
594  if (column_hit(m, i) >= 0)
595  s->set("hit", 1);
596  else
597  s->set("hit", 0);
598  ++i;
599  }
600  }
601  else
602  for (i = 0, s = e.head(); s; s = s->next())
603  if ((int)s->f("pos"))
604  {
605  if (row_hit(m, i) >= 0)
606  s->set("hit", 1);
607  else
608  s->set("hit", 0);
609  ++i;
610  }
611 }
612 
613 int insdel(EST_II_KVL &a)
614 {
615  int n = 0;
616  EST_Litem *ptr;
617 
618  for (ptr = a.list.head(); ptr != 0; ptr= ptr->next())
619  if (a.val(ptr) == -1)
620  ++n;
621  return n;
622 }
623 
624 int compare_labels(EST_Utterance &ref, EST_Utterance &test, EST_String name,
625  EST_II_KVL &uref, EST_II_KVL &utest)
626 {
627  // many-to-many mapping
628  (void)ref;
629  (void)test;
630  (void)name;
631  (void)uref;
632  (void)utest;
633 #if 0
634  relation_match(ref.stream(name), test.stream(name));
635 
636  // one-to-many mapping
637  function_match(uref, ref.stream(name), test.stream(name));
638  function_match(utest, test.stream(name), ref.stream(name));
639 
640  monotonic_match(uref, utest); // one-to-one mapping
641 
642  // temporary !!!
643  // reassign_links(ref.stream(name), uref, name);
644  // reassign_links(test.stream(name), utest, name);
645 
646  // cout << "Keyval REF\n" << uref;
647  // cout << "Keyval TEST\n" << utest;
648 #endif
649  return 0;
650 }
651 
652 void reassign_links(EST_Relation &a, EST_Relation &b, EST_II_KVL &ua, EST_II_KVL &ub)
653 {
654  (void)a;
655  (void)b;
656  (void)ua;
657  (void)ub;
658 
659 #if 0
660  EST_Item *a_ptr, *b_ptr;
661 
662  for (a_ptr = a.head(); a_ptr != 0; a_ptr = a_ptr->next())
663  {
664  a_ptr->link(b.stream_name())->clear();
665  if ((a_ptr->f("pos")==1) && (ua.val(a_ptr->addr()) != -1))
666  a_ptr->make_link(b.stream_name(), ua.val(a_ptr->addr()));
667  }
668  for (b_ptr = b.head(); b_ptr != 0; b_ptr = b_ptr->next())
669  {
670  b_ptr->link(a.stream_name())->clear();
671  if ((b_ptr->f("pos")==1) && (ub.val(b_ptr->addr()) != -1))
672  b_ptr->make_link(a.stream_name(), ub.val(b_ptr->addr()));
673  }
674 #endif
675 }
676 
677 void reassign_links(EST_Relation &a, EST_II_KVL &u, EST_String stream_type)
678 {
679  (void)a;
680  (void)u;
681  (void)stream_type;
682 #if 0
683  EST_Item *a_ptr;
684 
685  for (a_ptr = a.head(); a_ptr != 0; a_ptr = a_ptr->next())
686  {
687  a_ptr->link(stream_type)->clear();
688  if ((a_ptr->f("pos")==1) && (u.val(a_ptr->addr()) != -1))
689  a_ptr->make_link(stream_type, u.val(a_ptr->addr()));
690  }
691 #endif
692 }
693 
694 
695 int commutate(EST_Item *a_ptr, EST_II_KVL &f1, EST_II_KVL &f2,
696  EST_II_KVL &lref, EST_II_KVL &ltest)
697 
698 {
699  int b, c, d, v;
700  (void)lref; // unused parameter
701  (void)a_ptr;
702 
703 // v = a_ptr->addr();
704  v = 0;
705  b = f2.val(v);
706  c = (b == -1) ? -1: ltest.val(b);
707  d = (c == -1) ? -1: f1.val(c);
708 
709  return d;
710 
711  // c = ltest.val(f2.val(v));
712  // d = f1.val(ltest.val(f2.val(v)));
713 }
714 
715 // REF TEST
716 // f1
717 // S -----------> S
718 // ^ ^
719 // lr | | lt
720 // | f2 |
721 // E -----------> E
722 //
723 // For a given element in E(ref), "e", if
724 // lr(e) == f1(lt(f2(e)))
725 // Then ei has been recognised fully.
726 
727 void test_labels(EST_Utterance &ref, EST_Utterance &test, EST_Option &op)
728 {
729  (void)ref;
730  (void)test;
731  (void)op;
732 #if 0
733  EST_II_KVL f2, inv_f2, inv_f1, f1, lref, ltest;
734 
735  compare_labels(ref, test, "Event", f2, inv_f2);
736  compare_labels(ref, test, "Syllable", f1, inv_f1);
737 
738  if (op.present("print_syllable") && op.present("print_map"))
739  {
740  cout << "Syllable mapping from ref to test\n" << f1;
741  cout << "Syllable mapping from test to ref\n" << inv_f1;
742  }
743  if (op.present("print_event") && op.present("print_map"))
744  {
745  cout << "Event mapping from ref to test\n" << f2;
746  cout << "Event mapping from test to ref\n" << inv_f2;
747  }
748 
749  if (op.present("print_syllable") && op.present("print_ins"))
750  cout << "Syllable_insertions: " << insdel(inv_f1) << endl;
751  if (op.present("print_syllable") && op.present("print_del"))
752  cout << "Syllable_deletions: " << insdel(f1) << endl;
753 
754  if (op.present("print_event") && op.present("print_ins"))
755  cout << "Event_insertions: " << insdel(inv_f2) << endl;
756  if (op.present("print_event") && op.present("print_del"))
757  cout << "Event_deletions: " << insdel(f2) << endl;
758 
759  // cout << "Ref\n" << ref.stream("Event") << ref.stream("Syllable");
760  // cout << "Test\n" << test.stream("Event") << test.stream("Syllable");
761 
762  function_match(lref, ref.stream("Event"), ref.stream("Syllable"));
763  function_match(ltest, test.stream("Event"), test.stream("Syllable"));
764 
765  if (op.present("print_functions"))
766  {
767  cout << "Lref\n" << lref;
768  cout << "Ltest\n" << ltest;
769  cout << "f1\n" << f1;
770  cout << "f2\n" << f2;
771  }
772 
773  EST_Item *a_ptr;
774  int correct, n_ev, n_syl;
775 
776  correct = n_ev = n_syl = 0;
777  for (a_ptr = ref.stream("Event").head(); a_ptr != 0; a_ptr = a_ptr->next())
778  if (a_ptr->f("pos")==1)
779  {
780  ++n_ev;
781  if (lref.val(a_ptr->addr())
782  == commutate(a_ptr, f1, f2, lref, ltest))
783  ++correct;
784  }
785  for (a_ptr = ref.stream("Syllable").head();a_ptr != 0; a_ptr = a_ptr->next())
786  if (a_ptr->f("pos")==1)
787  ++n_syl;
788 
789  if (op.present("print_syllable") && op.present("print_total"))
790  cout << "Number_of_Syllables: " << n_syl << endl;
791  if (op.present("print_event") && op.present("print_total"))
792  cout << "Number_of_Events: " << n_ev << endl;
793 
794  if (op.present("print_link"))
795  cout << "Correct_links: " << correct <<endl;
796 
797  if (op.present("print_derivation"))
798  {
799  for (a_ptr = ref.stream("Event").head();a_ptr!= 0; a_ptr = a_ptr->next())
800  {
801  if (a_ptr->f("pos")==1)
802  {
803  cout << "Lr(ei): " << lref.val(a_ptr->addr()) << endl;
804  cout << "f2(ei): " << f2.val(a_ptr->addr()) << endl;
805  cout << "Lt(f2(ei)): " << ltest.val(f2.val(a_ptr->addr()))
806  << endl;
807  cout << "f1(Lt(f2(ei))): "
808  << f1.val(ltest.val(f2.val(a_ptr->addr()))) << endl;
809  }
810  cout << "Event " << *a_ptr;
811  if ( lref.val(a_ptr->addr())
812  == f1.val(ltest.val(f2.val(a_ptr->addr()))))
813  cout << " is correct\n";
814  else
815  cout << " is incorrect\n";
816  }
817  }
818 #endif
819 }
820 
821 void print_i_d_scores(EST_FMatrix &m)
822 {
823  cout.setf(ios::left,ios::adjustfield);
824  cout << "Total: ";
825  cout.width(10);
826  cout << m.num_columns();
827  cout << "Deletions: ";
828  cout.width(10);
829  cout << matrix_deletions(m);
830  cout << "Insertions: ";
831  cout.width(10);
832  cout<< matrix_insertions(m) << endl;
833 }
834 
835 void print_matrix_scores(EST_Relation &ref, EST_Relation &test, EST_FMatrix &a)
836 {
837  int i, j;
838  EST_Item *r_ptr, *t_ptr;
839 
840  cout << " ";
841  for (r_ptr = ref.head(); r_ptr != 0; r_ptr = r_ptr->next())
842  {
843  if (r_ptr->f("pos")==1)
844  {
845  // cout.width(5);
846  // cout.setf(ios::right);
847  cout << r_ptr->name() << " ";
848  cout.width(6);
849  cout.setf(ios::right);
850  cout<< r_ptr->F("end") << " ";
851  }
852  }
853  cout << endl;
854 
855  for (t_ptr = test.head(), i = 0; i < a.num_rows(); t_ptr = t_ptr->next())
856  {
857  if (t_ptr->f("pos")==1)
858  {
859  cout << t_ptr->name() << " ";
860  for (j = 0; j < a.num_columns(); ++j)
861  {
862  cout.width(10);
863  cout.precision(3);
864  cout.setf(ios::right);
865  cout.setf(ios::fixed, ios::floatfield);
866  cout << a(i, j) << " ";
867  }
868  cout << endl;
869  ++i;
870  }
871  }
872 }
873 
874 int row_hit(EST_FMatrix &m, int r)
875 {
876  int i;
877  for (i = 0; i < m.num_columns(); ++i)
878  if (m(r, i) > 0.0)
879  return i;
880 
881  return -1;
882 }
883 
884 // return the row index of the first positive entry in column c
885 int column_hit(EST_FMatrix &m, int c)
886 {
887  int i;
888  for (i = 0; i < m.num_rows(); ++i)
889  if (m(i, c) > 0.0)
890  return i;
891 
892  return -1;
893 }
894 
895 int num_b_insertions(EST_FMatrix &m, int last, int current)
896 {
897  int c1, c2;
898  c1 = column_hit(m, last);
899  c2 = column_hit(m, current);
900 
901  return c2 - c1 -1;
902 }
903 
904 int num_b_deletions(EST_FMatrix &m, int last, int current)
905 {
906  int c1, c2;
907  c1 = row_hit(m, last);
908  c2 = row_hit(m, current);
909 
910  return c2 - c1 -1;
911 }
912 
913 void print_s_trans(EST_Relation &a, int width)
914 {
915  (void)a;
916  (void)width;
917 // for (int i = 0; i < a.length(); ++i)
918 // {
919  // cout << (int)a.nth(i)->f("pos") << " XX " << a.nth(i)->name() << endl;
920 /* if ((a.nth(i)->f("pos")==1) || (a.nth(i)->name() == " "))
921  {
922  // cout.setf(ios::fixed, ios::floatfield);
923  cout.width(width);
924  cout << a.nth(i)->name() << " ";
925  }
926  }
927 */
928  cout << endl;
929 }
930 
931 void make_hit_and_miss(EST_Relation &a)
932 {
933  EST_Item *s;
934 
935  for (s = a.head(); s; s = s->next())
936  {
937  if (s->f("pos") == 0)
938  s->set_name(".");
939  else if (s->f("hit") == 1)
940  s->set_name("HIT");
941  else
942  s->set_name("MISS");
943  s->features().clear();
944  }
945 }
946 
947 void pos_only(EST_Relation &lab)
948 {
949  EST_Item *a, *n;
950 
951  for (a = lab.head(); a; a = n)
952  {
953  n = a->next();
954  if (!a->f_present("pos"))
955  lab.remove_item(a);
956  }
957 }
958 
959 // Warning this is bugged - slight misalignments occur.
960 void print_aligned_trans(EST_Relation &ref, EST_Relation &test, EST_FMatrix &m)
961 {
962  (void)ref;
963  (void)test;
964  (void)m;
965 /* int i, j, n;
966  EST_Relation al, refal, testal;
967  EST_Item *p;
968  EST_Item pos, blank;
969 
970  blank.set_name(" ");
971 
972  pos.f.set("pos", 1);
973  blank.f.set("pos", 0);
974 
975  pos_only(test);
976  pos_only(ref);
977 
978  // first check for empty matrices - indicates all insertions or deletions
979 
980  if ((m.num_columns() == 0) && (m.num_rows() != 0))
981  {
982  cout << "REC: ";
983  print_s_trans(test);
984  return;
985  }
986  else if ((m.num_columns() != 0) && (m.num_rows() == 0))
987  {
988  cout << "LAB: ";
989  print_s_trans(ref);
990  return;
991  }
992  else if ((m.num_columns() == 0) && (m.num_rows() == 0))
993  {
994  cout << "LAB: ";
995  print_s_trans(ref);
996  return;
997  }
998 
999  int l;
1000  l = 0;
1001 
1002  // cout << "ref: " << ref.name() << endl << ref;
1003  // cout << "test: " << test.name() << endl << test;
1004 
1005  if (m(0, 0) < 0)
1006  refal.append(blank);
1007 
1008 
1009  pos.set_name(ref.head()->name());
1010  refal.append(pos);
1011  for (i = 1, p = ref.head()->next(); p; p = p->next(), ++i)
1012  {
1013  n = num_b_insertions(m, l, i);
1014 
1015  for (j = 0; j < n; ++j)
1016  refal.append(blank);
1017 
1018  if (n > -0.5)
1019  l = i;
1020  pos.set_name(p->name());
1021 
1022  refal.append(pos);
1023  }
1024 
1025  l = 0;
1026  pos.set_name(test.head()->name());
1027  testal.append(pos);
1028  for (i = 1, p = test.head()->next(); p; p = p->next(), ++i)
1029  {
1030  n = num_b_deletions(m, l, i);
1031 
1032  // cout << *p << "last " << l << " current " << i <<
1033  // " insertions " << n << endl;
1034  for (j = 0; j < n; ++j)
1035  testal.append(blank);
1036 
1037  if (n > -0.5)
1038  l = i;
1039  pos.set_name(p->name());
1040  testal.append(pos);
1041  }
1042 
1043  cout << "LAB: ";
1044  print_s_trans(refal, 3);
1045  cout << "REC: ";
1046  print_s_trans(testal, 3);
1047 */
1048 }
1049 
1050 void print_results(EST_Relation &ref, EST_Relation &test,
1051  EST_FMatrix &m, int tot,
1052  int del, int ins, int v)
1053 {
1054  (void) tot;
1055  (void) del;
1056  (void) ins;
1057  if (v == 0)
1058  return;
1059 
1060  // v == 1 prints out total insertions etc
1061 
1062  if (v == 2)
1063  {
1064  cout << basename(ref.name(), "") << endl;
1065  print_i_d_scores(m);
1066  cout << endl;
1067  }
1068  else if (v == 3)
1069  {
1070  cout << basename(ref.name(), "") << endl;
1071  print_aligned_trans(ref, test, m);
1072  print_i_d_scores(m);
1073  cout << endl;
1074  }
1075  else if (v == 4)
1076  {
1077  cout << basename(ref.name(), "") << endl;
1078  print_matrix_scores(ref, test, m);
1079  print_i_d_scores(m);
1080  cout << endl;
1081  }
1082  else if (v == 5)
1083  {
1084  cout << basename(ref.name(), "") << endl;
1085  print_matrix_scores(ref, test, m);
1086  print_aligned_trans(ref, test, m);
1087  print_i_d_scores(m);
1088  cout << endl;
1089  }
1090  else if (v == 6)
1091  {
1092  print_matrix_scores(ref, test, m);
1093  error_location(ref, m, 1);
1094  make_hit_and_miss(ref);
1095  error_location(test, m, 0);
1096  make_hit_and_miss(test);
1097  ref.save("ref.error");
1098  test.save("test.errors");
1099  }
1100  else if (v == 7)
1101  {
1102  error_location(ref, m, 1);
1103  make_hit_and_miss(ref);
1104  error_location(test, m, 0);
1105  make_hit_and_miss(test);
1106  ref.save("ref.error");
1107  test.save("test.error");
1108  }
1109 }