Edinburgh Speech Tools  2.1-release
wfst_train.cc
Go to the documentation of this file.
1 /*************************************************************************/
2 /* */
3 /* Language Technologies Institute */
4 /* Carnegie Mellon University */
5 /* Copyright (c) 1999-2003 */
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 /* CARNEGIE MELLON UNIVERSITY 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 CARNEGIE MELLON UNIVERSITY 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 : Alan W Black */
34 /* Date : October 1999 */
35 /*-----------------------------------------------------------------------*/
36 /* */
37 /* Training method to split states of existing WFST based on data to */
38 /* optimize entropy */
39 /* */
40 /* Confusing as this has nothing to do with the modelling */
41 /* technique known as "maximum entropy" */
42 /* */
43 /*=======================================================================*/
44 #include <iostream>
45 #include <cstdlib>
46 #include "EST_WFST.h"
47 #include "wfst_aux.h"
48 #include "EST_Token.h"
49 #include "EST_simplestats.h"
50 
51 using namespace std;
52 
57 
58 static LISP *find_state_usage(EST_WFST &wfst, LISP data);
59 static double entropy(const EST_WFST_State *s);
60 static LISP *find_state_entropies(const EST_WFST &wfst, LISP *data);
62  int split_state,
63  LISP *data);
64 static LISP find_best_split(EST_WFST &wfst,
65  int split_state_name,
66  LISP *data);
67 static double find_score_if_split(EST_WFST &wfst,
68  int fromstate,
69  EST_WFST_Transition *trans,
70  LISP *data);
71 static LISP find_split_pdfs(EST_WFST &wfst,
72  int split_state_name,
73  LISP *data,
75 static double score_pdf_combine(EST_DiscreteProbDistribution &a,
78 #if 0
79 static void split_state(EST_WFST &wfst, EST_WFST_Transition *trans);
80 #endif
81 static void split_state(EST_WFST &wfst, LISP trans_list, int ostate);
82 
83 LISP load_string_data(EST_WFST &wfst,EST_String &filename)
84 {
85  // Load in sentences into data table, assume sentence per line
86  EST_TokenStream ts;
87  LISP ss = NIL;
88  EST_String t;
89  int id;
90  int i,j;
91 
92  if (ts.open(filename) == -1)
93  EST_error("wfst_train: failed to read data from \"%s\"",
94  (const char *)filename);
95 
96  i = 0;
97  j = 0;
98  while (!ts.eof())
99  {
100  LISP s = NIL;
101  do
102  {
103  t = (EST_String)ts.get();
104  id = wfst.in_symbol(t);
105  if (id == -1)
106  {
107  cerr << "wfst_train: data contains unknown symbol \"" <<
108  t << "\"" << endl;
109  }
110  s = cons(flocons(id),s);
111  j++;
112  }
113  while (!ts.eoln() && !ts.eof());
114  i++;
115  ss = cons(reverse(s),ss);
116  }
117 
118  printf("wfst_train: loaded %d lines of %d tokens\n",
119  i,j);
120 
121  return reverse(ss);
122 }
123 
124 static LISP *find_state_usage(EST_WFST &wfst, LISP data)
125 {
126  // Builds list of states, and which data points the represent
127  LISP *state_data = new LISP[wfst.num_states()];
128  static LISP ddd = NIL;
129  int s,i,id;
130  LISP d,w;
131  EST_WFST_Transition *trans;
132 // EST_Litem *tp;
133 
134  if (ddd == NIL)
135  gc_protect(&ddd);
136 
137  ddd = NIL;
138 
139  wfst.start_cumulate(); // zero existing weights
140 
141  for (i=0; i < wfst.num_states(); i++)
142  {
143  state_data[i] = NIL;
144  ddd = cons(state_data[i],ddd);
145 // // smoothing
146 // for (tp=wfst.state(i)->transitions.head(); tp != 0; tp = tp->next())
147 // wfst.state(i)->transitions(tp)->set_weight(1);
148  }
149 
150  for (i=0,d=data; d; d=cdr(d),i++)
151  {
152  s = wfst.start_state();
153  for (w=car(d); w; w=cdr(w))
154  {
155  state_data[s] = cons(w,state_data[s]);
156  id = get_c_int(car(w));
157  trans = wfst.find_transition(s,id,id);
158  if (!trans)
159  {
160  printf("sentence %d not in language, skipping\n",i);
161  continue;
162  }
163  else
164  {
165  trans->set_weight(trans->weight()+1);
166  s = trans->state();
167  }
168  }
169  }
170 
171  wfst.stop_cumulate();
172  return state_data;
173 }
174 
175 static double entropy(const EST_WFST_State *s)
176 {
177  double sentropy,w;
178  EST_Litem *tp;
179  for (sentropy=0,tp=s->transitions.head(); tp != 0; tp = tp->next())
180  {
181  w = s->transitions(tp)->weight(); /* the probability */
182  if (w > 0)
183  sentropy += w * log(w);
184  }
185  return -1 * sentropy;
186 }
187 
188 void wfst_train(EST_WFST &wfst, LISP data)
189 {
190  LISP *state_data;
191  LISP *state_entropies;
192  LISP best_trans_list = NIL;
193  int c=0,i, max_entropy_state;
194  gc_protect(&data);
195 
196  while (1)
197  {
198  // Build table of state to points in data, and cumulate transitions
199  state_data = find_state_usage(wfst,data);
200 
201  /* find entropy for each state (sorted) */
202  state_entropies = find_state_entropies(wfst,state_data);
203 
204  max_entropy_state = -1;
205  for (i=0; i < wfst.num_states(); i++)
206  {
207 // double me = (double)get_c_float(car(state_entropies[i]));
208  max_entropy_state = get_c_int(cdr(state_entropies[i]));
209 // printf("trying %d %g\n",max_entropy_state,me);
210 
211 // best_trans = find_best_trans_split(wfst,max_entropy_state,
212 // state_data);
213  best_trans_list = find_best_split(wfst,max_entropy_state,
214  state_data);
215  if (best_trans_list != NIL)
216  break;
217 // else
218 // printf("No best trans\n");
219  }
220  delete [] state_entropies;
221 
222  if (max_entropy_state == -1)
223  {
224  printf("No new max_entropy state\n");
225  delete [] state_data;
226  break;
227  }
228  if (best_trans_list == NIL)
229  {
230  printf("No best_trans in max_entropy state\n");
231  delete [] state_data;
232  break;
233  }
234 
235  /* for each transition *entering* max_entropy_state */
236  /* find entropy if it were split */
237  /* find best split */
238 
239  /* print stats */
240  /* some sort of stop check */
241  c++;
242  printf("c is %d\n",c);
243  if (c > 5000)
244  {
245  printf("reached cycle end %d\n",c);
246  delete [] state_data;
247  break;
248  }
249  /* split on best split */
250  split_state(wfst, best_trans_list, max_entropy_state);
251 
252  if ((c % 100) == 0)
253  {
254  EST_String chkpntname = "chkpnt";
255  char bbb[7];
256  sprintf(bbb,"%03d",c);
257  wfst.save(chkpntname+bbb+".wfst");
258  }
259 
260  delete [] state_data;
261  user_gc(NIL);
262  }
263 }
264 
265 static int me_compare_function(const void *a, const void *b)
266 {
267  LISP la;
268  LISP lb;
269  la = *(LISP *)a;
270  lb = *(LISP *)b;
271 
272  float fa = get_c_float(car(la));
273  float fb = get_c_float(car(lb));
274 
275  if (fa < fb)
276  return 1;
277  else if (fa == fb)
278  return 0;
279  else
280  return -1;
281 }
282 
283 static LISP *find_state_entropies(const EST_WFST &wfst, LISP *data)
284 {
285  double all_entropy = 0;
286  int i;
287  double sentropy;
288  LISP *slist = new LISP[wfst.num_states()];
289  static LISP ddd = NIL;
290 
291  if (ddd == NIL)
292  gc_protect(&ddd);
293  ddd = NIL;
294 
295  for (i=0; i < wfst.num_states(); i++)
296  {
297  const EST_WFST_State *s = wfst.state(i);
298  sentropy = entropy(s);
299 // printf("dlength is %d %d\n",i,siod_llength(data[i]));
300  all_entropy += sentropy * siod_llength(data[i]);
301  slist[i] = cons(flocons(sentropy),flocons(i));
302  ddd = cons(slist[i],ddd);
303  }
304  printf("average entropy is %g\n",all_entropy/i);
305 
306  qsort(slist,wfst.num_states(),sizeof(LISP),me_compare_function);
307 
308  return slist;
309 }
310 
311 static LISP find_best_split(EST_WFST &wfst,
312  int split_state_name,
313  LISP *data)
314 {
315  // Find the best partition of incoming translations that
316  // minimises entropy
317  EST_DiscreteProbDistribution pdf_all(&wfst.in_symbols());
318  EST_DiscreteProbDistribution *a_pdf, *b_pdf;
319  LISP splits,s,dd,r;
320  LISP *ssplits;
321  gc_protect(&splits);
322  EST_String sname;
323  int b,best_b;
324  EST_Litem *i;
325  int num_pdfs;
326  double best_score, score, sfreq;
327 
328  for (dd = data[split_state_name]; dd; dd = cdr(dd))
329  pdf_all.cumulate(get_c_int(car(car(dd))));
330  splits = find_split_pdfs(wfst,split_state_name,data,pdf_all);
331  if (siod_llength(splits) < 2)
332  return NIL;
333  ssplits = new LISP[siod_llength(splits)];
334  for (num_pdfs=0,s=splits; s != NIL; s=cdr(s),num_pdfs++)
335  ssplits[num_pdfs] = car(s);
336 
337  qsort(ssplits,num_pdfs,sizeof(LISP),me_compare_function);
338  // Combine trans pdfs in pdfs until more combination doesn't improve
339  while (1)
340  {
341 
342  best_score = get_c_float(car(ssplits[0]));
343  best_b = -1;
344  a_pdf = pdf(car(cdr(cdr(ssplits[0]))));
345  for (b=1; b < num_pdfs; b++)
346  {
347  if (ssplits[b] == NIL)
348  continue;
349  score = score_pdf_combine(*a_pdf,*pdf(car(cdr(cdr(ssplits[b])))),
350  pdf_all);
351  if (score < best_score)
352  {
353  best_score = score;
354  best_b = b;
355  }
356  }
357 
358  // combine a and b
359  if (best_b == -1)
360  break;
361  else
362  {
363  // combine a and b
364  // Add trans to 0
365  setcar(cdr(ssplits[0]),
366  append(car(cdr(ssplits[0])),
367  car(cdr(ssplits[best_b]))));
368  setcar(ssplits[0], flocons(best_score));
369  // Update 0's pdf with values from best_b's
370  b_pdf = pdf(car(cdr(cdr(ssplits[best_b]))));
371  for (i=b_pdf->item_start(); !b_pdf->item_end(i);
372  i = b_pdf->item_next(i))
373  {
374  b_pdf->item_freq(i,sname,sfreq);
375  a_pdf->cumulate(i,sfreq);
376  }
377  ssplits[best_b] = NIL;
378  }
379 
380  }
381 
382  printf("score %g ",(double)get_c_float(car(ssplits[0])));
383  for (dd=car(cdr(ssplits[0])); dd; dd=cdr(dd))
384  printf("%s ",(const char *)wfst.in_symbol(trans(car(dd))->in_symbol()));
385  printf("\n");
386  gc_unprotect(&splits);
387  r = car(cdr(ssplits[0]));
388  delete [] ssplits;
389  return r;
390 }
391 
392 static double score_pdf_combine(EST_DiscreteProbDistribution &a,
395 {
396  // Find score of (a+b) vs (all-(a+b))
398  EST_DiscreteProbDistribution all_but_ab(all);
399  EST_Litem *i;
400  EST_String sname;
401  double sfreq, score;
402  for (i=b.item_start(); !b.item_end(i);
403  i = b.item_next(i))
404  {
405  b.item_freq(i,sname,sfreq);
406  ab.cumulate(i,sfreq);
407  }
408 
409  for (i=ab.item_start(); !ab.item_end(i);
410  i = ab.item_next(i))
411  {
412  ab.item_freq(i,sname,sfreq);
413  all_but_ab.cumulate(i,-1*sfreq);
414  }
415 
416  score = (ab.entropy() * ab.samples()) +
417  (all_but_ab.entropy() * all_but_ab.samples());
418 
419  return score;
420 
421 }
422 
423 static LISP find_split_pdfs(EST_WFST &wfst,
424  int split_state_name,
425  LISP *data,
427 {
428  // Find following pdfs for each incoming transition as if they where
429  // split to a new state
430  int i,id, in;
431  EST_Litem *tp;
432  LISP pdfs = NIL,dd,ttt,p,t;
434  double value;
435 
436  for (i=0; i < wfst.num_states(); i++)
437  {
438  const EST_WFST_State *s = wfst.state(i);
439  for (tp=s->transitions.head(); tp != 0; tp = tp->next())
440  {
441  if ((s->transitions(tp)->state() == split_state_name)
442  && (s->transitions(tp)->weight() > 0))
443  {
444  in = s->transitions(tp)->in_symbol();
447  for (dd = data[i]; dd; dd = cdr(dd))
448  {
449  id = get_c_int(car(car(dd)));
450  if (id == in)
451  { // This one would go to the new state so we count it
452  if (cdr(car(dd))) // not end of data string
453  pdf->cumulate(get_c_int(car(cdr(car(dd)))));
454  }
455  }
456  // value, list of trans, pdf
457  value = score_pdf_combine(*pdf,empty,pdf_all);
458  if ((value > 0) && // ignore transitions with no data
459  (pdf->samples() > 10))// and those with only a few data pnts
460  {
461  t = siod(s->transitions(tp));
462  p = siod(pdf);
463  ttt = cons(flocons(value),
464  cons(cons(t,NIL),
465  cons(p,NIL)));
466  pdfs = cons(ttt,pdfs);
467  }
468  else
469  delete pdf;
470  }
471  }
472  }
473  return pdfs;
474 }
475 
477  int split_state_name,
478  LISP *data)
479 {
480  EST_Litem *tp;
481  EST_WFST_Transition *best_trans = 0;
482  const EST_WFST_State *split_state = wfst.state(split_state_name);
483  double best_score,bb;
484  int i;
485 
486  best_score = entropy(split_state)*siod_llength(data[split_state_name]);
487 // printf("unsplit score %g\n",best_score);
488 
489  /* For each transition going to split_state */
490  for (i=1; i < wfst.num_states(); i++)
491  {
492  const EST_WFST_State *s = wfst.state(i);
493  for (tp=s->transitions.head(); tp != 0; tp = tp->next())
494  {
495  if ((wfst.state(s->transitions(tp)->state()) == split_state) &&
496  (s->transitions(tp)->weight() > 0))
497  {
498  bb = find_score_if_split(wfst,i,s->transitions(tp),data);
499 // cout << i << " "
500 // << wfst.in_symbol(s->transitions(tp)->in_symbol()) << " "
501 // << s->transitions(tp)->state() << " " << bb << endl;
502  if (bb == -1) /* didn't find a split */
503  continue;
504  if (bb < best_score)
505  {
506  best_score = bb;
507  best_trans = s->transitions(tp);
508  }
509  }
510  }
511  }
512 
513  if (best_trans)
514  cout << "best " << wfst.in_symbol(best_trans->in_symbol()) << " "
515  << best_trans->weight() << " "
516  << best_trans->state() << " " << best_score << endl;
517  return best_trans;
518 }
519 
520 static double find_score_if_split(EST_WFST &wfst,
521  int fromstate,
522  EST_WFST_Transition *trans,
523  LISP *data)
524 {
525  double ent_split;
526  double ent_remain;
527  double score;
528  EST_DiscreteProbDistribution pdf_split(&wfst.in_symbols());
529  EST_DiscreteProbDistribution pdf_remain(&wfst.in_symbols());
530  int in, tostate, id;
531  EST_Litem *i;
532  double sfreq;
533  EST_String sname;
534 
535  ent_split = ent_remain = 32*32*32*32;
536  LISP dd;
537 
538 // printf("considering %d %s %g %d\n",
539 // fromstate,
540 // (const char *)wfst.in_symbol(trans->in_symbol()),
541 // trans->weight(),
542 // trans->state());
543 
544  /* find entropy of possible new state */
545  /* for each data point through fromstate */
546  in = trans->in_symbol();
547  for (dd = data[fromstate]; dd; dd = cdr(dd))
548  {
549  id = get_c_int(car(car(dd)));
550  if (id == in)
551  { // This one would go to the new state so we count it
552  if (cdr(car(dd))) // not end of data string
553  pdf_split.cumulate(get_c_int(car(cdr(car(dd)))));
554  }
555  }
556  if (pdf_split.samples() > 0)
557  ent_split = pdf_split.entropy();
558  /* find entropy of old state minus trans into it */
559  tostate = trans->state();
560  // Actually only need to do this once per state
561  for (dd = data[tostate]; dd; dd = cdr(dd))
562  pdf_remain.cumulate(get_c_int(car(car(dd))));
563  // Subtract the bit thats split
564  for (i=pdf_split.item_start(); !pdf_split.item_end(i);
565  i = pdf_split.item_next(i))
566  {
567  pdf_split.item_freq(i,sname,sfreq);
568  pdf_remain.cumulate(i,-1*sfreq);
569  }
570  if (pdf_remain.samples() > 0)
571  ent_remain = pdf_remain.entropy();
572 
573  if ((pdf_remain.samples() == 0) ||
574  (pdf_split.samples() == 0))
575  return -1;
576 
577  score = (ent_remain * pdf_remain.samples()) +
578  (ent_split * pdf_split.samples());
579 // printf("tostate %d remain %g %d split %g %d score %g\n",
580 // tostate, ent_remain, (int)pdf_remain.samples(),
581 // ent_split, (int)pdf_split.samples(), score);
582 
583  return score;
584 }
585 
586 #if 0
587 static void split_state(EST_WFST &wfst, EST_WFST_Transition *trans)
588 {
589  /* Split off a new state for given trans. Add transitions */
590  /* to this new state for all transitions in (old) state trans */
591  /* goes to */
592  EST_Litem *tp;
593  int nstate = wfst.add_state(wfst_final);
594  int ostate = trans->state();
595 
596 // printf("state %d entropy %g\n",ostate,entropy(wfst.state(ostate)));
597  /* must be done before adding the new transitions to nstate */
598  trans->set_state(nstate);
599 
600  for (tp=wfst.state(ostate)->transitions.head(); tp != 0; tp = tp->next())
601  {
602  wfst.state_non_const(nstate)->
603  add_transition(0.0, /* weight will be filled in later*/
604  wfst.state(ostate)->transitions(tp)->state(),
605  wfst.state(ostate)->transitions(tp)->in_symbol(),
606  wfst.state(ostate)->transitions(tp)->out_symbol());
607 
608  }
609 // printf(" nstate %d entropy %g\n",nstate,entropy(wfst.state(nstate)));
610 // printf(" ostate %d entropy %g\n",ostate,entropy(wfst.state(ostate)));
611 
612 }
613 #endif
614 
615 static void split_state(EST_WFST &wfst, LISP trans_list, int ostate)
616 {
617  /* Split off a new state for given trans. Add transitions */
618  /* to this new state for all transitions in (old) state trans */
619  /* goes to */
620  EST_Litem *tp;
621  int nstate = wfst.add_state(wfst_final);
622  LISP t;
623 
624  /* must be done before adding the new transitions to nstate */
625  for (t=trans_list; t; t=cdr(t))
626  trans(car(t))->set_state(nstate);
627 
628  for (tp=wfst.state(ostate)->transitions.head(); tp != 0; tp = tp->next())
629  {
630  wfst.state_non_const(nstate)->
631  add_transition(0.0, /* weight will be filled in later*/
632  wfst.state(ostate)->transitions(tp)->state(),
633  wfst.state(ostate)->transitions(tp)->in_symbol(),
634  wfst.state(ostate)->transitions(tp)->out_symbol());
635 
636  }
637 }
638 
LISP siod(const class EST_Val v)
Definition: siod_est.cc:184
void set_state(int s)
Definition: EST_WFST.h:80
EST_TokenStream & get(EST_Token &t)
get next token in stream
Definition: EST_Token.cc:499
EST_WFST_Transition * find_best_trans_split(EST_WFST &wfst, int split_state, LISP *data)
Definition: wfst_train.cc:476
void qsort(EST_TList< T > &a)
EST_Litem * item_next(EST_Litem *idx) const
Used for iterating through members of the distribution.
#define SIOD_REGISTER_CLASS(NAME, CLASS)
Definition: siod_defs.h:207
int start_state() const
Definition: EST_WFST.h:206
float get_c_float(LISP x)
Definition: slib.cc:1858
int add_state(enum wfst_state_type state_type)
Add a new state, returns new name.
Definition: EST_WFST.cc:669
an internal class for EST_WFST for representing transitions in an WFST
Definition: EST_WFST.h:61
a call representing a weighted finite-state transducer
Definition: EST_WFST.h:154
double samples(void) const
Total number of example found.
void wfst_train(EST_WFST &wfst, LISP data)
Definition: wfst_train.cc:188
#define VAL_REGISTER_TYPE_NODEL(NAME, CLASS)
Definition: EST_Val_defs.h:110
long int get_c_int(LISP x)
Definition: slib.cc:1850
#define NIL
Definition: siod_defs.h:92
int siod_llength(LISP list)
Definition: siod.cc:202
LISP append(LISP l1, LISP l2)
Definition: slib_list.cc:177
void gc_unprotect(LISP *location)
Definition: slib.cc:759
int state() const
Definition: EST_WFST.h:76
LISP load_string_data(EST_WFST &wfst, EST_String &filename)
Definition: wfst_train.cc:83
#define VAL_REGISTER_CLASS(NAME, CLASS)
Definition: EST_Val_defs.h:62
EST_Litem * item_start() const
Used for iterating through members of the distribution.
int item_end(EST_Litem *idx) const
Used for iterating through members of the distribution.
float weight() const
Definition: EST_WFST.h:75
LISP user_gc(LISP args)
Definition: slib.cc:1269
int in_symbol(const EST_String &s) const
Map input symbol to input alphabet index.
Definition: EST_WFST.h:208
void start_cumulate()
Clear and start cumulation.
Definition: EST_WFST.cc:687
EST_UItem * next()
Definition: EST_UList.h:55
int open(const EST_String &filename)
open a EST_TokenStream for a file.
Definition: EST_Token.cc:213
void stop_cumulate()
Stop cumulation and calculate probabilities on transitions.
Definition: EST_WFST.cc:702
int eof()
end of file
Definition: EST_Token.h:362
void cumulate(const EST_String &s, double count=1)
Add this observation, may specify number of occurrences.
const EST_Discrete & in_symbols() const
Accessing the input alphabet.
Definition: EST_WFST.h:233
void item_freq(EST_Litem *idx, EST_String &s, double &freq) const
During iteration returns name and frequency given index.
an internal class for EST_WFST used to represent a state in a WFST
Definition: EST_WFST.h:98
double entropy(void) const
LISP cons(LISP x, LISP y)
Definition: slib_list.cc:97
const EST_WFST_State * state(int i) const
Return internal state information.
Definition: EST_WFST.h:226
EST_write_status save(const EST_String &filename, const EST_String type="ascii")
?
Definition: EST_WFST.cc:353
int in_symbol() const
Definition: EST_WFST.h:77
#define EST_error
Definition: EST_error.h:104
LISP setcar(LISP cell, LISP value)
Definition: slib_list.cc:54
void set_weight(float f)
Definition: EST_WFST.h:79
int num_states() const
Definition: EST_WFST.h:205
EST_WFST_Transition * find_transition(int state, int in, int out) const
Find (first) transition given in and out symbols.
Definition: EST_WFST.cc:271
EST_WFST_State * state_non_const(int i)
Return internal state information (non-const)
Definition: EST_WFST.h:228
LISP flocons(double x)
Definition: slib.cc:673
EST_UItem * head() const
Definition: EST_UList.h:97
void gc_protect(LISP *location)
Definition: slib.cc:791
LISP car(LISP x)
Definition: slib_list.cc:115
EST_StrList empty
EST_String
void reverse(EST_Wave &sig)
wfst_translist transitions
Definition: EST_WFST.h:104
LISP cdr(LISP x)
Definition: slib_list.cc:124
int eoln()
end of line
Definition: EST_Token.cc:832