presage  0.9.1
presage.cpp
Go to the documentation of this file.
1 
2 /******************************************************
3  * Presage, an extensible predictive text entry system
4  * ---------------------------------------------------
5  *
6  * Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License along
19  with this program; if not, write to the Free Software Foundation, Inc.,
20  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  **********(*)*/
23 
24 
25 #include "presage.h"
26 
27 #include "core/profileManager.h"
28 #include "core/predictorRegistry.h"
30 #include "core/selector.h"
32 
34  throw (PresageException)
35 {
36  profileManager = new ProfileManager();
37  configuration = profileManager->get_configuration();
38  predictorRegistry = new PredictorRegistry(configuration);
39  contextTracker = new ContextTracker(configuration, predictorRegistry, callback);
40  predictorActivator = new PredictorActivator(configuration, predictorRegistry, contextTracker);
41  selector = new Selector(configuration, contextTracker);
42 }
43 
44 Presage::Presage (PresageCallback* callback, const std::string config_filename)
45  throw (PresageException)
46 {
47  profileManager = new ProfileManager(config_filename);
48  configuration = profileManager->get_configuration();
49  predictorRegistry = new PredictorRegistry(configuration);
50  contextTracker = new ContextTracker(configuration, predictorRegistry, callback);
51  predictorActivator = new PredictorActivator(configuration, predictorRegistry, contextTracker);
52  selector = new Selector(configuration, contextTracker);
53 }
54 
56 {
57  delete selector;
58  delete predictorActivator;
59  delete contextTracker;
60  delete predictorRegistry;
61  delete profileManager;
62 }
63 
64 std::vector<std::string> Presage::predict ()
65  throw (PresageException)
66 {
67  std::vector<std::string> result;
68 
69  unsigned int multiplier = 1;
70  Prediction prediction = predictorActivator->predict(multiplier++, 0);
71  result = selector->select(prediction);
72 
73  Prediction previous_prediction = prediction;
74  while ((result.size() < (selector->get_suggestions()))
75  && (prediction = predictorActivator->predict(multiplier++, 0)).size() > previous_prediction.size()) {
76  // while the number of predicted tokens is lower than desired,
77  // search harder (i.e. higher multiplier) for a prediction of
78  // sufficient size (i.e. that satisfies selector), as long as
79  // the result of current prediction is greater than the
80  // previous prediction (i.e. we are finding new tokens).
81  result = selector->select(prediction);
82  previous_prediction = prediction;
83  }
84 
86 
87  return result;
88 }
89 
90 std::multimap<double, std::string> Presage::predict (std::vector<std::string> filter)
91  throw (PresageException)
92 {
93  std::multimap<double, std::string> result;
94 
95  std::vector<std::string> selection;
96  const char** internal_filter = 0;
97  if(filter.size()>0)
98  {
99  // convert filter to internal representation - currently a null
100  // terminated const char**
101  internal_filter = new const char*[filter.size() + 1];
102  for (std::vector<std::string>::size_type i = 0; i < filter.size(); i++) {
103  internal_filter[i] = filter[i].c_str();
104  }
105  internal_filter[filter.size()] = 0;
106  }
107 
108  unsigned int multiplier = 1;
109  Prediction prediction = predictorActivator->predict(multiplier++, internal_filter);
110  selection = selector->select(prediction);
111 
112  Prediction previous_prediction = prediction;
113  while ((selection.size() < (selector->get_suggestions()))
114  && (prediction = predictorActivator->predict(multiplier++, internal_filter)).size() > previous_prediction.size()) {
115  // while the number of predicted tokens is lower than desired,
116  // search harder (i.e. higher multiplier) for a prediction of
117  // sufficient size (i.e. that satisfies selector), as long as
118  // the selection of current prediction is greater than the
119  // previous prediction (i.e. we are finding new tokens).
120  selection = selector->select(prediction);
121  previous_prediction = prediction;
122  }
123 
124  delete[] internal_filter;
125 
126  for (std::vector<std::string>::const_iterator it = selection.begin();
127  it != selection.end();
128  it++) {
129  std::pair<const double, std::string> p(prediction.getSuggestion(*it).getProbability(),
130  (*it));
131  result.insert(p);
132  }
133 
134  contextTracker->update();
135 
136  return result;
137 }
138 
139 void Presage::learn(const std::string text) const
140  throw (PresageException)
141 {
142  contextTracker->learn(text); // TODO: can pass additional param to
143  // learn to specify offline learning
144 }
145 
147  throw (PresageException)
148 {
149  return const_cast<PresageCallback*>(contextTracker->callback(callback));
150 }
151 
152 std::string Presage::completion (const std::string str)
153  throw (PresageException)
154 {
155  // There are two types of completions: normal and erasing.
156  // normal_completion = prefix + remainder
157  // erasing_completion = eraser + prefix + remainder
158  //
159  // or, given that token = prefix + remainder
160  // normal_completion = token
161  // erasing_completion = eraser + token
162  //
163  // where eraser = ^H+ (one or more backspace characters)
164  //
165  // offset to first non ^H character in completion (^H are inserted
166  // by abbreviation expansion predictor to erase abbreviation from
167  // stream)
168  //
169  std::string result;
170 
171  std::string::size_type offset = str.find_first_not_of('\b');
172  if (offset == 0) {
173  // normal completion,
174  // ensure that current prefix is a substring of completion
175  // token and set result
176  //
177  if (contextTracker->isCompletionValid(str)) {
178  std::string prefix = contextTracker->getPrefix();
179  result = str.substr(prefix.size());
180  } else {
181  std::string message = "[Presage] Error: token '";
182  message += str;
183  message += "' does not match prefix: ";
184  message += contextTracker->getPrefix();
186  }
187  } else {
188  // erasing completion,
189  // pass it to tracker in its entirety
190  //
191  result = str;
192  }
193 
194  // if (append_trailing_space_is_on()) // TODO: make this configurable
195  result += ' ';
196 
197  return result;
198 }
199 
200 std::string Presage::context () const
201  throw (PresageException)
202 {
203  return contextTracker->getPastStream();
204 }
205 
207  throw (PresageException)
208 {
209  return contextTracker->contextChange();
210 }
211 
212 std::string Presage::prefix () const
213  throw (PresageException)
214 {
215  return contextTracker->getPrefix();
216 }
217 
218 std::string Presage::config (const std::string variable) const
219  throw (PresageException)
220 {
221  return configuration->find (variable)->get_value ();
222 }
223 
224 void Presage::config (const std::string variable, const std::string value) const
225  throw (PresageException)
226 {
227  configuration->insert (variable, value);
228 }
229 
230 void Presage::save_config () const
231  throw (PresageException)
232 {
234 }
235 
236 
237 
238 struct _presage {
241 };
242 
244 {
245 public:
247  void* past_arg,
249  void* future_arg)
250  : m_get_past_stream_cb (past),
251  m_get_past_stream_cb_arg (past_arg),
252  m_get_future_stream_cb (future),
253  m_get_future_stream_cb_arg (future_arg)
254  { }
255 
256  virtual ~CPresageCallback() { }
257 
258  std::string get_past_stream() const {
260  }
261 
262  std::string get_future_stream() const {
264  }
265 
266 private:
271 };
272 
273 #define presage_exception_handler(CODE) \
274  try \
275  { \
276  CODE; \
277  } \
278  catch (PresageException& ex) \
279  { \
280  return ex.code (); \
281  } \
282  return PRESAGE_OK;
283 
284 #define presage_exception_handler_with_result(CODE) \
285  try \
286  { \
287  CODE; \
288  } \
289  catch (PresageException& ex) \
290  { \
291  (*result) = 0; \
292  return ex.code (); \
293  } \
294  return PRESAGE_OK;
295 
296 static char* alloc_c_str (const std::string& str)
297 {
298  char* result_c_str = (char*) malloc (str.size() + 1);
299  if (result_c_str)
300  strcpy (result_c_str, str.c_str());
301  return result_c_str;
302 }
303 
305  void* past_stream_cb_arg,
306  _presage_callback_get_future_stream future_stream_cb,
307  void* future_stream_cb_arg,
308  presage_t* result)
309 {
311  (
312  (*result) = (presage_t) malloc (sizeof (_presage));
313  if (*result != NULL)
314  {
315  (*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
316  past_stream_cb_arg,
317  future_stream_cb,
318  future_stream_cb_arg);
319  (*result)->presage_object = new Presage ((*result)->presage_callback_object);
320  }
321 
322  );
323 }
324 
326  void* past_stream_cb_arg,
327  _presage_callback_get_future_stream future_stream_cb,
328  void* future_stream_cb_arg,
329  const char* config,
330  presage_t* result)
331 {
333  (
334  (*result) = (presage_t) malloc (sizeof (_presage));
335  if (*result != NULL)
336  {
337 
338  (*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
339  past_stream_cb_arg,
340  future_stream_cb,
341  future_stream_cb_arg);
342  (*result)->presage_object = new Presage ((*result)->presage_callback_object, config);
343  }
344  );
345 }
346 
348 {
349  if (prsg)
350  {
351  delete prsg->presage_object;
352  delete prsg->presage_callback_object;
353 
354  free (prsg);
355  }
356 }
357 
358 void presage_free_string (char* str)
359 {
360  free (str);
361 }
362 
363 void presage_free_string_array (char** strs)
364 {
365  if (strs) {
366  for (size_t t = 0; strs[t] != 0; t++) {
367  free (strs[t]);
368  }
369  free (strs);
370  }
371 }
372 
374 {
376  (
377  std::vector<std::string> prediction = prsg->presage_object->predict();
378 
379  size_t prediction_c_str_size = prediction.size() + 1;
380  char** prediction_c_str = (char**) malloc (prediction_c_str_size * sizeof(char*));
381  if (prediction_c_str != NULL)
382  {
383  memset (prediction_c_str, 0, prediction_c_str_size * sizeof(char*));
384 
385  size_t i = 0;
386  while (i < prediction_c_str_size - 1) {
387  prediction_c_str[i] = (char*) malloc (prediction[i].size() + 1);
388  if (prediction_c_str[i] != NULL)
389  strcpy (prediction_c_str[i], prediction[i].c_str());
390  i++;
391  }
392  prediction_c_str[i] = 0;
393  }
394 
395  *result = prediction_c_str;
396  );
397 }
398 
400 {
402  (
403  prsg->presage_object->learn (text);
404  );
405 }
406 
407 presage_error_code_t presage_completion (presage_t prsg, const char* token, char** result)
408 {
410  (
411  *result = alloc_c_str (prsg->presage_object->completion (token));
412  );
413 }
414 
416 {
418  (
419  *result = alloc_c_str (prsg->presage_object->context ());
420  );
421 }
422 
424 {
426  (
427  *result = prsg->presage_object->context_change ();
428  );
429 }
430 
432 {
434  (
435  *result = alloc_c_str (prsg->presage_object->prefix ());
436  );
437 }
438 
439 presage_error_code_t presage_config (presage_t prsg, const char* variable, char** result)
440 {
442  (
443  *result = alloc_c_str (prsg->presage_object->config (variable));
444  );
445 }
446 
447 presage_error_code_t presage_config_set (presage_t prsg, const char* variable, const char* value)
448 {
450  (
451  prsg->presage_object->config (variable, value)
452  );
453 }
454 
456 {
458  (
459  prsg->presage_object->save_config ()
460  );
461 }
PredictorRegistry * predictorRegistry
Definition: presage.h:248
Prediction predict(unsigned int multiplier, const char **filter)
presage_error_code_t
Selector * selector
Definition: presage.h:251
void presage_free(presage_t prsg)
Definition: presage.cpp:347
presage_error_code_t presage_save_config(presage_t prsg)
Definition: presage.cpp:455
presage_error_code_t presage_prefix(presage_t prsg, char **result)
Definition: presage.cpp:431
presage_error_code_t presage_predict(presage_t prsg, char ***result)
Definition: presage.cpp:373
std::vector< std::string > predict()
Obtain a prediction.
Definition: presage.cpp:64
bool context_change() const
Returns true if a context change occured.
Definition: presage.cpp:206
PresageCallback * callback(PresageCallback *callback)
Callback getter/setter.
Definition: presage.cpp:146
presage_error_code_t presage_learn(presage_t prsg, const char *text)
Definition: presage.cpp:399
void * m_get_future_stream_cb_arg
Definition: presage.cpp:270
presage_error_code_t presage_config(presage_t prsg, const char *variable, char **result)
Definition: presage.cpp:439
Presage(PresageCallback *callback)
Definition: presage.cpp:33
Presage * presage_object
Definition: presage.cpp:240
PresageCallback * presage_callback_object
Definition: presage.cpp:239
#define presage_exception_handler_with_result(CODE)
Definition: presage.cpp:284
void presage_free_string_array(char **strs)
Definition: presage.cpp:363
static char * alloc_c_str(const std::string &str)
Definition: presage.cpp:296
#define presage_exception_handler(CODE)
Definition: presage.cpp:273
Suggestion getSuggestion(int=0) const
Definition: prediction.cpp:73
presage_error_code_t presage_context(presage_t prsg, char **result)
Definition: presage.cpp:415
PredictorActivator * predictorActivator
Definition: presage.h:250
size_t size() const
Definition: prediction.cpp:68
presage_error_code_t presage_context_change(presage_t prsg, int *result)
Definition: presage.cpp:423
ContextTracker * contextTracker
Definition: presage.h:249
std::string config
Definition: presageDemo.cpp:70
void learn(const std::string text) const
Learn from text offline.
Definition: presage.cpp:139
std::string config(const std::string variable) const
Gets the value of specified configuration variable.
Definition: presage.cpp:218
presage_error_code_t presage_new_with_config(_presage_callback_get_past_stream past_stream_cb, void *past_stream_cb_arg, _presage_callback_get_future_stream future_stream_cb, void *future_stream_cb_arg, const char *config, presage_t *result)
Definition: presage.cpp:325
presage_error_code_t presage_config_set(presage_t prsg, const char *variable, const char *value)
Definition: presage.cpp:447
void * m_get_past_stream_cb_arg
Definition: presage.cpp:268
~Presage()
Definition: presage.cpp:55
std::string get_future_stream() const
Definition: presage.cpp:262
void save_config() const
Save current configuration to file.
Definition: presage.cpp:230
presage_error_code_t presage_new(_presage_callback_get_past_stream past_stream_cb, void *past_stream_cb_arg, _presage_callback_get_future_stream future_stream_cb, void *future_stream_cb_arg, presage_t *result)
Definition: presage.cpp:304
std::string prefix() const
Returns the current prefix.
Definition: presage.cpp:212
_presage_callback_get_past_stream m_get_past_stream_cb
Definition: presage.cpp:267
ProfileManager * profileManager
Definition: presage.h:246
const char *(* _presage_callback_get_future_stream)(void *)
Presage, the intelligent predictive text entry platform.
Definition: presage.h:107
CPresageCallback(_presage_callback_get_past_stream past, void *past_arg, _presage_callback_get_future_stream future, void *future_arg)
Definition: presage.cpp:246
std::string getPrefix() const
size_t get_suggestions() const
Definition: selector.cpp:246
std::string context() const
Returns the text entered so far.
Definition: presage.cpp:200
double getProbability() const
Definition: suggestion.cpp:69
void save_profile() const
std::vector< std::string > select(Prediction)
Definition: selector.cpp:55
presage_error_code_t presage_completion(presage_t prsg, const char *token, char **result)
Definition: presage.cpp:407
Tracks user interaction and context.
void presage_free_string(char *str)
Definition: presage.cpp:358
std::string get_past_stream() const
Definition: presage.cpp:258
const char *(* _presage_callback_get_past_stream)(void *)
_presage_callback_get_future_stream m_get_future_stream_cb
Definition: presage.cpp:269
std::string getPastStream() const
std::string completion(std::string str)
Request presage to return the completion string for the given predicted token.
Definition: presage.cpp:152
virtual ~CPresageCallback()
Definition: presage.cpp:256