wapiti 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.simplecov +3 -0
  3. data/Gemfile +25 -2
  4. data/HISTORY.md +5 -1
  5. data/LICENSE +14 -13
  6. data/README.md +9 -16
  7. data/Rakefile +38 -8
  8. data/ext/wapiti/bcd.c +126 -124
  9. data/ext/wapiti/decoder.c +203 -124
  10. data/ext/wapiti/decoder.h +6 -4
  11. data/ext/wapiti/extconf.rb +2 -2
  12. data/ext/wapiti/gradient.c +491 -320
  13. data/ext/wapiti/gradient.h +52 -34
  14. data/ext/wapiti/lbfgs.c +74 -33
  15. data/ext/wapiti/model.c +47 -37
  16. data/ext/wapiti/model.h +22 -20
  17. data/ext/wapiti/native.c +850 -839
  18. data/ext/wapiti/native.h +1 -1
  19. data/ext/wapiti/options.c +52 -20
  20. data/ext/wapiti/options.h +37 -30
  21. data/ext/wapiti/pattern.c +35 -33
  22. data/ext/wapiti/pattern.h +12 -11
  23. data/ext/wapiti/progress.c +14 -13
  24. data/ext/wapiti/progress.h +3 -2
  25. data/ext/wapiti/quark.c +14 -16
  26. data/ext/wapiti/quark.h +6 -5
  27. data/ext/wapiti/reader.c +83 -69
  28. data/ext/wapiti/reader.h +11 -9
  29. data/ext/wapiti/rprop.c +84 -43
  30. data/ext/wapiti/sequence.h +18 -16
  31. data/ext/wapiti/sgdl1.c +45 -43
  32. data/ext/wapiti/thread.c +19 -17
  33. data/ext/wapiti/thread.h +5 -4
  34. data/ext/wapiti/tools.c +7 -7
  35. data/ext/wapiti/tools.h +3 -4
  36. data/ext/wapiti/trainers.h +1 -1
  37. data/ext/wapiti/vmath.c +40 -38
  38. data/ext/wapiti/vmath.h +12 -11
  39. data/ext/wapiti/wapiti.c +159 -37
  40. data/ext/wapiti/wapiti.h +18 -4
  41. data/lib/wapiti.rb +15 -15
  42. data/lib/wapiti/errors.rb +15 -15
  43. data/lib/wapiti/model.rb +92 -84
  44. data/lib/wapiti/options.rb +123 -124
  45. data/lib/wapiti/utility.rb +14 -14
  46. data/lib/wapiti/version.rb +2 -2
  47. data/spec/spec_helper.rb +29 -9
  48. data/spec/wapiti/model_spec.rb +230 -194
  49. data/spec/wapiti/native_spec.rb +7 -8
  50. data/spec/wapiti/options_spec.rb +184 -174
  51. data/wapiti.gemspec +22 -8
  52. metadata +38 -42
  53. data/.gitignore +0 -5
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Wapiti - A linear-chain CRF tool
3
3
  *
4
- * Copyright (c) 2009-2011 CNRS
4
+ * Copyright (c) 2009-2013 CNRS
5
5
  * All rights reserved.
6
6
  *
7
7
  * Redistribution and use in source and binary forms, with or without
@@ -32,50 +32,68 @@
32
32
  #include "model.h"
33
33
  #include "sequence.h"
34
34
 
35
- /* grd_t:
35
+ /* grd_st_t:
36
36
  * State tracker for the gradient computation. To compute the gradient we need
37
37
  * to perform several steps and communicate between them a lot of intermediate
38
- * values, all these temporary are store in this object.
38
+ * values, all these temporary are stored in this object.
39
39
  * A tracker can be used to compute sequence of length <len> at most, before
40
- * using it you must call grd_check to ensure that the tracker is big enough
40
+ * using it you must call grd_stcheck to ensure that the tracker is big enough
41
41
  * for your sequence.
42
+ * This tracker is used to perform single sample gradient computations or
43
+ * partial gradient computation in online algorithms and for decoding with
44
+ * posteriors.
42
45
  */
43
- typedef struct grd_s grd_t;
44
- struct grd_s {
45
- mdl_t *mdl;
46
- int len; // =T max length of sequence
47
- double *g; // [F] vector where to put gradient updates
48
- double lloss; // loss value for the sequence
49
- double *psi; // [T][Y][Y] the transitions scores
50
- double *psiuni; // [T][Y] | Same as psi in sparse format
51
- size_t *psiyp; // [T][Y][Y] |
52
- size_t *psiidx; // [T][Y] |
53
- size_t *psioff; // [T]
54
- double *alpha; // [T][Y] forward scores
55
- double *beta; // [T][Y] backward scores
56
- double *scale; // [T] scaling factors of forward scores
57
- double *unorm; // [T] normalization factors for unigrams
58
- double *bnorm; // [T] normalization factors for bigrams
59
- int first; // first position where gradient is needed
60
- int last; // last position where gradient is needed
46
+ typedef struct grd_st_s grd_st_t;
47
+ struct grd_st_s {
48
+ mdl_t *mdl;
49
+ uint32_t len; // =T max length of sequence
50
+ double *g; // [F] vector where to put gradient updates
51
+ double lloss; // loss value for the sequence
52
+ double *psi; // [T][Y][Y] the transitions scores
53
+ double *psiuni; // [T][Y] | Same as psi in sparse format
54
+ uint32_t *psiyp; // [T][Y][Y] |
55
+ uint32_t *psiidx; // [T][Y] |
56
+ uint32_t *psioff; // [T]
57
+ double *alpha; // [T][Y] forward scores
58
+ double *beta; // [T][Y] backward scores
59
+ double *scale; // [T] scaling factors of forward scores
60
+ double *unorm; // [T] normalization factors for unigrams
61
+ double *bnorm; // [T] normalization factors for bigrams
62
+ uint32_t first; // first position where gradient is needed
63
+ uint32_t last; // last position where gradient is needed
61
64
  };
62
65
 
63
- grd_t *grd_new(mdl_t *mdl, double *g);
64
- void grd_free(grd_t *grd);
65
- void grd_check(grd_t *grd, int len);
66
+ grd_st_t *grd_stnew(mdl_t *mdl, double *g);
67
+ void grd_stfree(grd_st_t *grd_st);
68
+ void grd_stcheck(grd_st_t *grd_st, uint32_t len);
69
+
70
+ void grd_fldopsi(grd_st_t *grd_st, const seq_t *seq);
71
+ void grd_flfwdbwd(grd_st_t *grd_st, const seq_t *seq);
72
+ void grd_flupgrad(grd_st_t *grd_st, const seq_t *seq);
73
+
74
+ void grd_spdopsi(grd_st_t *grd_st, const seq_t *seq);
75
+ void grd_spfwdbwd(grd_st_t *grd_st, const seq_t *seq);
76
+ void grd_spupgrad(grd_st_t *grd_st, const seq_t *seq);
66
77
 
67
- void grd_fldopsi(grd_t *grd, const seq_t *seq);
68
- void grd_flfwdbwd(grd_t *grd, const seq_t *seq);
69
- void grd_flupgrad(grd_t *grd, const seq_t *seq);
78
+ void grd_logloss(grd_st_t *grd_st, const seq_t *seq);
70
79
 
71
- void grd_spdopsi(grd_t *grd, const seq_t *seq);
72
- void grd_spfwdbwd(grd_t *grd, const seq_t *seq);
73
- void grd_spupgrad(grd_t *grd, const seq_t *seq);
80
+ void grd_dospl(grd_st_t *grd_st, const seq_t *seq);
74
81
 
75
- void grd_logloss(grd_t *grd, const seq_t *seq);
82
+ /* grd_t:
83
+ * Multi-threaded full dataset gradient computer. This is used to compute the
84
+ * gradient by algorithm working on the full dataset at each iterations. It
85
+ * efficiently compute it using the fact it is additive to use as many threads
86
+ * as allowed.
87
+ */
88
+ typedef struct grd_s grd_t;
89
+ struct grd_s {
90
+ mdl_t *mdl;
91
+ grd_st_t **grd_st;
92
+ };
76
93
 
77
- void grd_dospl(grd_t *grd, const seq_t *seq);
78
- double grd_gradient(mdl_t *mdl, double *g, grd_t *grds[]);
94
+ grd_t *grd_new(mdl_t *mdl, double *g);
95
+ void grd_free(grd_t *grd);
96
+ double grd_gradient(grd_t *grd);
79
97
 
80
98
  #endif
81
99
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Wapiti - A linear-chain CRF tool
3
3
  *
4
- * Copyright (c) 2009-2011 CNRS
4
+ * Copyright (c) 2009-2013 CNRS
5
5
  * All rights reserved.
6
6
  *
7
7
  * Redistribution and use in source and binary forms, with or without
@@ -24,9 +24,12 @@
24
24
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
25
  * POSSIBILITY OF SUCH DAMAGE.
26
26
  */
27
+ #include <inttypes.h>
27
28
  #include <math.h>
28
29
  #include <stdbool.h>
29
30
  #include <stddef.h>
31
+ #include <stdint.h>
32
+ #include <stdio.h>
30
33
  #include <stdlib.h>
31
34
  #include <string.h>
32
35
 
@@ -58,12 +61,11 @@
58
61
  ******************************************************************************/
59
62
 
60
63
  void trn_lbfgs(mdl_t *mdl) {
61
- const size_t F = mdl->nftr;
62
- const int K = mdl->opt->maxiter;
63
- const int C = mdl->opt->objwin;
64
- const int M = mdl->opt->lbfgs.histsz;
65
- const size_t W = mdl->opt->nthread;
66
- const bool l1 = mdl->opt->rho1 != 0.0;
64
+ const uint64_t F = mdl->nftr;
65
+ const uint32_t K = mdl->opt->maxiter;
66
+ const uint32_t C = mdl->opt->objwin;
67
+ const uint32_t M = mdl->opt->lbfgs.histsz;
68
+ const bool l1 = mdl->opt->rho1 != 0.0;
67
69
  double *x, *xp; // Current and previous value of the variables
68
70
  double *g, *gp; // Current and previous value of the gradient
69
71
  double *pg; // The pseudo-gradient (only for owl-qn)
@@ -72,7 +74,6 @@ void trn_lbfgs(mdl_t *mdl) {
72
74
  double *y[M]; // History value y_k = Δ(g,pg)
73
75
  double p[M]; // ρ_k
74
76
  double fh[C]; // f(x) history
75
- grd_t *grds[W];
76
77
  // Initialization: Here, we have to allocate memory on the heap as we
77
78
  // cannot request so much memory on the stack as this will have a too
78
79
  // big impact on performance and will be refused by the system on non-
@@ -80,22 +81,50 @@ void trn_lbfgs(mdl_t *mdl) {
80
81
  x = mdl->theta;
81
82
  xp = xvm_new(F); g = xvm_new(F);
82
83
  gp = xvm_new(F); d = xvm_new(F);
83
- for (int m = 0; m < M; m++) {
84
+ for (uint32_t m = 0; m < M; m++) {
84
85
  s[m] = xvm_new(F);
85
86
  y[m] = xvm_new(F);
86
87
  }
87
88
  pg = l1 ? xvm_new(F) : NULL;
88
- grds[0] = grd_new(mdl, g);
89
- for (size_t w = 1; w < W; w++)
90
- grds[w] = grd_new(mdl, xvm_new(F));
89
+ grd_t *grd = grd_new(mdl, g);
90
+ // Restore a saved state if user specified one.
91
+ if (mdl->opt->rstate != NULL) {
92
+ const char *err = "invalid state file";
93
+ FILE *file = fopen(mdl->opt->rstate, "r");
94
+ if (file == NULL)
95
+ fatal("failed to open input state file");
96
+ int type, histsz;
97
+ uint64_t nftr;
98
+ if (fscanf(file, "#state#%d#%d#%"SCNu64"\n", &type, &histsz,
99
+ &nftr) != 3)
100
+ fatal("0 %s", err);
101
+ if (type != 0 || histsz != (int)M)
102
+ fatal("state is not compatible");
103
+ for (uint64_t i = 0; i < nftr; i++) {
104
+ uint64_t f;
105
+ if (fscanf(file, "%"PRIu64, &f) != 1)
106
+ fatal("1 %s", err);
107
+ if (fscanf(file, "%la %la", &xp[f], &gp[f]) != 2)
108
+ fatal("2 %s", err);
109
+ for (uint32_t m = 0; m < M; m++) {
110
+ if (fscanf(file, "%la", &s[m][f]) != 1)
111
+ fatal("3 %s", err);
112
+ if (fscanf(file, "%la", &y[m][f]) != 1)
113
+ fatal("4 %s", err);
114
+ }
115
+ }
116
+ for (uint32_t m = 0; m < M; m++)
117
+ p[m] = 1.0 / xvm_dot(y[m], s[m], F);
118
+ fclose(file);
119
+ }
91
120
  // Minimization: This is the heart of the function. (a big heart...) We
92
121
  // will perform iterations until one these conditions is reached
93
122
  // - the maximum iteration count is reached
94
123
  // - we have converged (upto numerical precision)
95
124
  // - the report function return false
96
125
  // - an error happen somewhere
97
- double fx = grd_gradient(mdl, g, grds);
98
- for (int k = 0; !uit_stop && k < K; k++) {
126
+ double fx = grd_gradient(grd);
127
+ for (uint32_t k = 0; !uit_stop && k < K; k++) {
99
128
  // We first compute the pseudo-gradient of f for owl-qn. It is
100
129
  // defined in [3, pp 335(4)]
101
130
  // | ∂_i^- f(x) if ∂_i^- f(x) > 0
@@ -106,7 +135,7 @@ void trn_lbfgs(mdl_t *mdl) {
106
135
  // | ±C if x_i = 0
107
136
  if (l1) {
108
137
  const double rho1 = mdl->opt->rho1;
109
- for (unsigned f = 0; f < F; f++) {
138
+ for (uint64_t f = 0; f < F; f++) {
110
139
  if (x[f] < 0.0)
111
140
  pg[f] = g[f] - rho1;
112
141
  else if (x[f] > 0.0)
@@ -130,13 +159,13 @@ void trn_lbfgs(mdl_t *mdl) {
130
159
  // gradient instead of the true one.
131
160
  xvm_neg(d, l1 ? pg : g, F);
132
161
  if (k != 0) {
133
- const int km = k % M;
134
- const int bnd = (k <= M) ? k : M;
162
+ const uint32_t km = k % M;
163
+ const uint32_t bnd = (k <= M) ? k : M;
135
164
  double alpha[M], beta;
136
165
  // α_i = ρ_j s_j^T q_{i+1}
137
166
  // q_i = q_{i+1} - α_i y_i
138
- for (int i = bnd; i > 0; i--) {
139
- const int j = (k - i + M + 1) % M;
167
+ for (uint32_t i = bnd; i > 0; i--) {
168
+ const uint32_t j = (M + 1 + k - i) % M;
140
169
  alpha[i - 1] = p[j] * xvm_dot(s[j], d, F);
141
170
  xvm_axpy(d, -alpha[i - 1], y[j], d, F);
142
171
  }
@@ -147,12 +176,12 @@ void trn_lbfgs(mdl_t *mdl) {
147
176
  // = I * 1 / ρ_k ||y_k||²
148
177
  const double y2 = xvm_dot(y[km], y[km], F);
149
178
  const double v = 1.0 / (p[km] * y2);
150
- for (size_t f = 0; f < F; f++)
179
+ for (uint64_t f = 0; f < F; f++)
151
180
  d[f] *= v;
152
181
  // β_j = ρ_j y_j^T r_i
153
182
  // r_{i+1} = r_i + s_j (α_i - β_i)
154
- for (int i = 0; i < bnd; i++) {
155
- const int j = (k - i + M) % M;
183
+ for (uint32_t i = 0; i < bnd; i++) {
184
+ const uint32_t j = (M + k - i) % M;
156
185
  beta = p[j] * xvm_dot(y[j], d, F);
157
186
  xvm_axpy(d, alpha[i] - beta, s[j], d, F);
158
187
  }
@@ -163,7 +192,7 @@ void trn_lbfgs(mdl_t *mdl) {
163
192
  // d^k = π(d^k ; v^k)
164
193
  // = π(d^k ; -◇f(x^k))
165
194
  if (l1)
166
- for (size_t f = 0; f < F; f++)
195
+ for (uint64_t f = 0; f < F; f++)
167
196
  if (d[f] * pg[f] >= 0.0)
168
197
  d[f] = 0.0;
169
198
  // 2nd step: we perform a linesearch in the computed direction,
@@ -184,7 +213,7 @@ void trn_lbfgs(mdl_t *mdl) {
184
213
  double gd = l1 ? 0.0 : xvm_dot(g, d, F); // gd = g_k^T d_k
185
214
  double fi = fx;
186
215
  bool err = false;
187
- for (int ls = 1; !uit_stop; ls++, stp *= sc) {
216
+ for (uint32_t ls = 1; !uit_stop; ls++, stp *= sc) {
188
217
  // We compute the new point using the current step and
189
218
  // search direction
190
219
  xvm_axpy(x, stp, d, xp, F);
@@ -192,7 +221,7 @@ void trn_lbfgs(mdl_t *mdl) {
192
221
  // current orthant [3, pp 35]
193
222
  // x^{k+1} = π(x^k + αp^k ; ξ)
194
223
  if (l1) {
195
- for (size_t f = 0; f < F; f++) {
224
+ for (uint64_t f = 0; f < F; f++) {
196
225
  double or = xp[f];
197
226
  if (or == 0.0)
198
227
  or = -pg[f];
@@ -202,7 +231,7 @@ void trn_lbfgs(mdl_t *mdl) {
202
231
  }
203
232
  // And we ask for the value of the objective function
204
233
  // and its gradient.
205
- fx = grd_gradient(mdl, g, grds);
234
+ fx = grd_gradient(grd);
206
235
  // Now we check if the step satisfy the conditions. For
207
236
  // l-bfgs, we check the classical decrease and curvature
208
237
  // known as the Wolfe conditions [2, pp 506]
@@ -221,7 +250,7 @@ void trn_lbfgs(mdl_t *mdl) {
221
250
  break;
222
251
  } else {
223
252
  double vp = 0.0;
224
- for (size_t f = 0; f < F; f++)
253
+ for (uint64_t f = 0; f < F; f++)
225
254
  vp += (x[f] - xp[f]) * d[f];
226
255
  if (fx < fi + vp * 1e-4)
227
256
  break;
@@ -249,7 +278,7 @@ void trn_lbfgs(mdl_t *mdl) {
249
278
  // s_k = x_{k+1} - x_k
250
279
  // y_k = g_{k+1} - g_k
251
280
  // ρ_k = 1 / y_k^T s_k
252
- const int kn = (k + 1) % M;
281
+ const uint32_t kn = (k + 1) % M;
253
282
  xvm_sub(s[kn], x, xp, F);
254
283
  xvm_sub(y[kn], g, gp, F);
255
284
  p[kn] = 1.0 / xvm_dot(y[kn], s[kn], F);
@@ -277,18 +306,30 @@ void trn_lbfgs(mdl_t *mdl) {
277
306
  break;
278
307
  }
279
308
  }
309
+ // Save the optimizer state if requested by the user
310
+ if (mdl->opt->sstate != NULL) {
311
+ FILE *file = fopen(mdl->opt->sstate, "w");
312
+ if (file == NULL)
313
+ fatal("failed to open output state file");
314
+ fprintf(file, "#state#0#%"PRIu32"#%"PRIu64"\n", M, F);
315
+ for (uint64_t f = 0; f < F; f++) {
316
+ fprintf(file, "%"PRIu64, f);
317
+ fprintf(file, " %la %la", xp[f], gp[f]);
318
+ for (uint32_t m = 0; m < M; m++)
319
+ fprintf(file, " %la %la", s[m][f], y[m][f]);
320
+ fprintf(file, "\n");
321
+ }
322
+ fclose(file);
323
+ }
280
324
  // Cleanup: We free all the vectors we have allocated.
281
325
  xvm_free(xp); xvm_free(g);
282
326
  xvm_free(gp); xvm_free(d);
283
- for (int m = 0; m < M; m++) {
327
+ for (uint32_t m = 0; m < M; m++) {
284
328
  xvm_free(s[m]);
285
329
  xvm_free(y[m]);
286
330
  }
287
331
  if (l1)
288
332
  xvm_free(pg);
289
- for (size_t w = 1; w < W; w++)
290
- xvm_free(grds[w]->g);
291
- for (size_t w = 0; w < W; w++)
292
- grd_free(grds[w]);
333
+ grd_free(grd);
293
334
  }
294
335
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Wapiti - A linear-chain CRF tool
3
3
  *
4
- * Copyright (c) 2009-2011 CNRS
4
+ * Copyright (c) 2009-2013 CNRS
5
5
  * All rights reserved.
6
6
  *
7
7
  * Redistribution and use in source and binary forms, with or without
@@ -24,8 +24,10 @@
24
24
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
25
  * POSSIBILITY OF SUCH DAMAGE.
26
26
  */
27
+ #include <inttypes.h>
27
28
  #include <stdbool.h>
28
29
  #include <stddef.h>
30
+ #include <stdint.h>
29
31
  #include <stdlib.h>
30
32
  #include <stdio.h>
31
33
  #include <string.h>
@@ -120,8 +122,8 @@ void mdl_free(mdl_t *mdl) {
120
122
  * This reduce the risk of mistakes.
121
123
  */
122
124
  void mdl_sync(mdl_t *mdl) {
123
- const size_t Y = qrk_count(mdl->reader->lbl);
124
- const size_t O = qrk_count(mdl->reader->obs);
125
+ const uint32_t Y = qrk_count(mdl->reader->lbl);
126
+ const uint64_t O = qrk_count(mdl->reader->obs);
125
127
  // If model is already synchronized, do nothing and just return
126
128
  if (mdl->nlbl == Y && mdl->nobs == O)
127
129
  return;
@@ -131,8 +133,8 @@ void mdl_sync(mdl_t *mdl) {
131
133
  // case we also display a warning as this is probably not expected by
132
134
  // the user. If only new observations was added, we will try to expand
133
135
  // the model.
134
- size_t oldF = mdl->nftr;
135
- size_t oldO = mdl->nobs;
136
+ uint64_t oldF = mdl->nftr;
137
+ uint64_t oldO = mdl->nobs;
136
138
  if (mdl->nlbl != Y && mdl->nlbl != 0) {
137
139
  warning("labels count changed, discarding the model");
138
140
  free(mdl->kind); mdl->kind = NULL;
@@ -148,16 +150,16 @@ void mdl_sync(mdl_t *mdl) {
148
150
  mdl->nobs = O;
149
151
  // Allocate the observations datastructure. If the model is empty or
150
152
  // discarded, a new one iscreated, else the old one is expanded.
151
- char *kind = wapiti_xrealloc(mdl->kind, sizeof(char ) * O);
152
- size_t *uoff = wapiti_xrealloc(mdl->uoff, sizeof(size_t) * O);
153
- size_t *boff = wapiti_xrealloc(mdl->boff, sizeof(size_t) * O);
153
+ char *kind = wapiti_xrealloc(mdl->kind, sizeof(char ) * O);
154
+ uint64_t *uoff = wapiti_xrealloc(mdl->uoff, sizeof(uint64_t) * O);
155
+ uint64_t *boff = wapiti_xrealloc(mdl->boff, sizeof(uint64_t) * O);
154
156
  mdl->kind = kind;
155
157
  mdl->uoff = uoff;
156
158
  mdl->boff = boff;
157
159
  // Now, we can setup the features. For each new observations we fill the
158
160
  // kind and offsets arrays and count total number of features as well.
159
- size_t F = oldF;
160
- for (size_t o = oldO; o < O; o++) {
161
+ uint64_t F = oldF;
162
+ for (uint64_t o = oldO; o < O; o++) {
161
163
  const char *obs = qrk_id2str(mdl->reader->obs, o);
162
164
  switch (obs[0]) {
163
165
  case 'u': kind[o] = 1; break;
@@ -176,14 +178,14 @@ void mdl_sync(mdl_t *mdl) {
176
178
  // have to allocate a new vector and copy old values ourself.
177
179
  if (oldF != 0) {
178
180
  double *new = xvm_new(F);
179
- for (size_t f = 0; f < oldF; f++)
181
+ for (uint64_t f = 0; f < oldF; f++)
180
182
  new[f] = mdl->theta[f];
181
183
  xvm_free(mdl->theta);
182
184
  mdl->theta = new;
183
185
  } else {
184
186
  mdl->theta = xvm_new(F);
185
187
  }
186
- for (size_t f = oldF; f < F; f++)
188
+ for (uint64_t f = oldF; f < F; f++)
187
189
  mdl->theta[f] = 0.0;
188
190
  // And lock the databases
189
191
  qrk_lock(mdl->reader->lbl, true);
@@ -197,7 +199,7 @@ void mdl_sync(mdl_t *mdl) {
197
199
  * and labeling.
198
200
  */
199
201
  void mdl_compact(mdl_t *mdl) {
200
- const size_t Y = mdl->nlbl;
202
+ const uint32_t Y = mdl->nlbl;
201
203
  // We first build the new observation list with only observations which
202
204
  // lead to at least one active feature. At the same time we build the
203
205
  // translation table which map the new observations index to the old
@@ -205,29 +207,29 @@ void mdl_compact(mdl_t *mdl) {
205
207
  info(" - Scan the model\n");
206
208
  qrk_t *old_obs = mdl->reader->obs;
207
209
  qrk_t *new_obs = qrk_new();
208
- size_t *trans = wapiti_xmalloc(sizeof(size_t) * mdl->nobs);
209
- for (size_t oldo = 0; oldo < mdl->nobs; oldo++) {
210
+ uint64_t *trans = wapiti_xmalloc(sizeof(uint64_t) * mdl->nobs);
211
+ for (uint64_t oldo = 0; oldo < mdl->nobs; oldo++) {
210
212
  bool active = false;
211
213
  if (mdl->kind[oldo] & 1)
212
- for (size_t y = 0; y < Y; y++)
214
+ for (uint32_t y = 0; y < Y; y++)
213
215
  if (mdl->theta[mdl->uoff[oldo] + y] != 0.0)
214
216
  active = true;
215
217
  if (mdl->kind[oldo] & 2)
216
- for (size_t d = 0; d < Y * Y; d++)
218
+ for (uint32_t d = 0; d < Y * Y; d++)
217
219
  if (mdl->theta[mdl->boff[oldo] + d] != 0.0)
218
220
  active = true;
219
221
  if (!active)
220
222
  continue;
221
- const char *str = qrk_id2str(old_obs, oldo);
222
- const size_t newo = qrk_str2id(new_obs, str);
223
+ const char *str = qrk_id2str(old_obs, oldo);
224
+ const uint64_t newo = qrk_str2id(new_obs, str);
223
225
  trans[newo] = oldo;
224
226
  }
225
227
  mdl->reader->obs = new_obs;
226
228
  // Now we save the old model features informations and build a new one
227
229
  // corresponding to the compacted model.
228
- size_t *old_uoff = mdl->uoff; mdl->uoff = NULL;
229
- size_t *old_boff = mdl->boff; mdl->boff = NULL;
230
- double *old_theta = mdl->theta; mdl->theta = NULL;
230
+ uint64_t *old_uoff = mdl->uoff; mdl->uoff = NULL;
231
+ uint64_t *old_boff = mdl->boff; mdl->boff = NULL;
232
+ double *old_theta = mdl->theta; mdl->theta = NULL;
231
233
  free(mdl->kind);
232
234
  mdl->kind = NULL;
233
235
  mdl->nlbl = mdl->nobs = mdl->nftr = 0;
@@ -235,18 +237,18 @@ void mdl_compact(mdl_t *mdl) {
235
237
  // The model is now ready, so we copy in it the features weights from
236
238
  // the old model for observations we have kept.
237
239
  info(" - Compact it\n");
238
- for (size_t newo = 0; newo < mdl->nobs; newo++) {
239
- const size_t oldo = trans[newo];
240
+ for (uint64_t newo = 0; newo < mdl->nobs; newo++) {
241
+ const uint64_t oldo = trans[newo];
240
242
  if (mdl->kind[newo] & 1) {
241
243
  double *src = old_theta + old_uoff[oldo];
242
244
  double *dst = mdl->theta + mdl->uoff[newo];
243
- for (size_t y = 0; y < Y; y++)
245
+ for (uint32_t y = 0; y < Y; y++)
244
246
  dst[y] = src[y];
245
247
  }
246
248
  if (mdl->kind[newo] & 2) {
247
249
  double *src = old_theta + old_boff[oldo];
248
250
  double *dst = mdl->theta + mdl->boff[newo];
249
- for (size_t d = 0; d < Y * Y; d++)
251
+ for (uint32_t d = 0; d < Y * Y; d++)
250
252
  dst[d] = src[d];
251
253
  }
252
254
  }
@@ -262,15 +264,15 @@ void mdl_compact(mdl_t *mdl) {
262
264
  * Save a model to be restored later in a platform independant way.
263
265
  */
264
266
  void mdl_save(mdl_t *mdl, FILE *file) {
265
- size_t nact = 0;
266
- for (size_t f = 0; f < mdl->nftr; f++)
267
+ uint64_t nact = 0;
268
+ for (uint64_t f = 0; f < mdl->nftr; f++)
267
269
  if (mdl->theta[f] != 0.0)
268
270
  nact++;
269
- fprintf(file, "#mdl#%zu\n", nact);
271
+ fprintf(file, "#mdl#%d#%"PRIu64"\n", mdl->type, nact);
270
272
  rdr_save(mdl->reader, file);
271
- for (size_t f = 0; f < mdl->nftr; f++)
273
+ for (uint64_t f = 0; f < mdl->nftr; f++)
272
274
  if (mdl->theta[f] != 0.0)
273
- fprintf(file, "%zu=%la\n", f, mdl->theta[f]);
275
+ fprintf(file, "%"PRIu64"=%la\n", f, mdl->theta[f]);
274
276
  }
275
277
 
276
278
  /* mdl_load:
@@ -280,15 +282,23 @@ void mdl_save(mdl_t *mdl, FILE *file) {
280
282
  */
281
283
  void mdl_load(mdl_t *mdl, FILE *file) {
282
284
  const char *err = "invalid model format";
283
- size_t nact = 0;
284
- if (fscanf(file, "#mdl#%zu\n", &nact) != 1)
285
- fatal(err);
285
+ uint64_t nact = 0;
286
+ int type;
287
+ if (fscanf(file, "#mdl#%d#%"SCNu64"\n", &type, &nact) == 2) {
288
+ mdl->type = type;
289
+ } else {
290
+ rewind(file);
291
+ if (fscanf(file, "#mdl#%"SCNu64"\n", &nact) == 1)
292
+ mdl->type = 0;
293
+ else
294
+ fatal(err);
295
+ }
286
296
  rdr_load(mdl->reader, file);
287
297
  mdl_sync(mdl);
288
- for (size_t i = 0; i < nact; i++) {
289
- size_t f;
298
+ for (uint64_t i = 0; i < nact; i++) {
299
+ uint64_t f;
290
300
  double v;
291
- if (fscanf(file, "%zu=%la\n", &f, &v) != 2)
301
+ if (fscanf(file, "%"SCNu64"=%la\n", &f, &v) != 2)
292
302
  fatal(err);
293
303
  mdl->theta[f] = v;
294
304
  }