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
53int 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.
59void 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
85void 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
108void 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
131void 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
173EST_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
188float 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
200float 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
211int 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
226void 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
242void 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
259void 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
270int 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
283int 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
303int 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
316int 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
337int 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
352void 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
377multiple ref labels related to the same test label. If this is
378discovered, compare scores of all the relevant labels and delete the
379relations of all but the lowest.
380
381At this stage, each ref label should have one and only one relation to the
382test labels.
383*/
384
385void 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;
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
440calculating the distance from each label in the test set to each label
441in the reference set. The lowest score for each reference is then
442recorded. A test is carried out to make sure that no two reference
443labels point to the same test label. Then any ref label above a
444certain distance is classified as incorrect. The numbers of insertions
445and deletions are then calculated. */
446
447EST_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
515void 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
586void 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
616int 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
627int 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
655void 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
680void 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
698int 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
730void 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
824void 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
838void 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
877int 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
888int 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
898int 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
907int 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
916void 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
934void 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
950void 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.
963void 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
1053void 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}
void set(const EST_String &name, int ival)
Definition: EST_Item.h:179
const float F(const EST_String &name) const
Definition: EST_Item.h:134
int f_present(const EST_String &name) const
Definition: EST_Item.h:230
void remove_item(EST_Item *item)
EST_Item * head() const
Definition: EST_Relation.h:125
EST_write_status save(const EST_String &filename, bool evaluate_ff=false) const
int length() const
const EST_String & name() const
Definition: EST_Relation.h:122
const int length() const
number of key value pairs in list
Definition: EST_TKVL.h:96
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_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
const V & val(const K &rkey, bool m=0) const
return value according to key (const)
Definition: EST_TKVL.cc:145
const int present(const K &rkey) const
Returns true if key is present.
Definition: EST_TKVL.cc:222
const K & key(EST_Litem *ptr, int m=1) const
find key, reference by ptr
Definition: EST_TKVL.cc:201
int change_val(const K &rkey, const V &rval)
Definition: EST_TKVL.cc:113
int change_key(EST_Litem *ptr, const K &rkey)
change name of key pair.
Definition: EST_TKVL.cc:99
void clear(void)
remove all items in list
Definition: EST_TList.h:239
void append(const T &item)
add item onto end of list
Definition: EST_TList.h:191
int num_columns() const
return number of columns
Definition: EST_TMatrix.h:181
int num_rows() const
return number of rows
Definition: EST_TMatrix.h:179