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 {
41 }
42 
43 Presage::Presage (PresageCallback* callback, const std::string config_filename)
44 {
45  profileManager = new ProfileManager(config_filename);
51 }
52 
54 {
55  delete selector;
56  delete predictorActivator;
57  delete contextTracker;
58  delete predictorRegistry;
59  delete profileManager;
60 }
61 
62 std::vector<std::string> Presage::predict ()
63 {
64  std::vector<std::string> result;
65 
66  unsigned int multiplier = 1;
67  Prediction prediction = predictorActivator->predict(multiplier++, 0);
68  result = selector->select(prediction);
69 
70  Prediction previous_prediction = prediction;
71  while ((result.size() < (selector->get_suggestions()))
72  && (prediction = predictorActivator->predict(multiplier++, 0)).size() > previous_prediction.size()) {
73  // while the number of predicted tokens is lower than desired,
74  // search harder (i.e. higher multiplier) for a prediction of
75  // sufficient size (i.e. that satisfies selector), as long as
76  // the result of current prediction is greater than the
77  // previous prediction (i.e. we are finding new tokens).
78  result = selector->select(prediction);
79  previous_prediction = prediction;
80  }
81 
83 
84  return result;
85 }
86 
87 std::multimap<double, std::string> Presage::predict (std::vector<std::string> filter)
88 {
89  std::multimap<double, std::string> result;
90 
91  std::vector<std::string> selection;
92  const char** internal_filter = 0;
93  if(filter.size()>0)
94  {
95  // convert filter to internal representation - currently a null
96  // terminated const char**
97  internal_filter = new const char*[filter.size() + 1];
98  for (std::vector<std::string>::size_type i = 0; i < filter.size(); i++) {
99  internal_filter[i] = filter[i].c_str();
100  }
101  internal_filter[filter.size()] = 0;
102  }
103 
104  unsigned int multiplier = 1;
105  Prediction prediction = predictorActivator->predict(multiplier++, internal_filter);
106  selection = selector->select(prediction);
107 
108  Prediction previous_prediction = prediction;
109  while ((selection.size() < (selector->get_suggestions()))
110  && (prediction = predictorActivator->predict(multiplier++, internal_filter)).size() > previous_prediction.size()) {
111  // while the number of predicted tokens is lower than desired,
112  // search harder (i.e. higher multiplier) for a prediction of
113  // sufficient size (i.e. that satisfies selector), as long as
114  // the selection of current prediction is greater than the
115  // previous prediction (i.e. we are finding new tokens).
116  selection = selector->select(prediction);
117  previous_prediction = prediction;
118  }
119 
120  delete[] internal_filter;
121 
122  for (std::vector<std::string>::const_iterator it = selection.begin();
123  it != selection.end();
124  it++) {
125  std::pair<const double, std::string> p(prediction.getSuggestion(*it).getProbability(),
126  (*it));
127  result.insert(p);
128  }
129 
131 
132  return result;
133 }
134 
135 void Presage::learn(const std::string text)
136 {
137  contextTracker->learn(text); // TODO: can pass additional param to
138  // learn to specify offline learning
139 }
140 
142 {
143  return const_cast<PresageCallback*>(contextTracker->callback(callback));
144 }
145 
146 std::string Presage::completion (const std::string str)
147 {
148  // There are two types of completions: normal and erasing.
149  // normal_completion = prefix + remainder
150  // erasing_completion = eraser + prefix + remainder
151  //
152  // or, given that token = prefix + remainder
153  // normal_completion = token
154  // erasing_completion = eraser + token
155  //
156  // where eraser = ^H+ (one or more backspace characters)
157  //
158  // offset to first non ^H character in completion (^H are inserted
159  // by abbreviation expansion predictor to erase abbreviation from
160  // stream)
161  //
162  std::string result;
163 
164  std::string::size_type offset = str.find_first_not_of('\b');
165  if (offset == 0) {
166  // normal completion,
167  // ensure that current prefix is a substring of completion
168  // token and set result
169  //
170  if (contextTracker->isCompletionValid(str)) {
171  std::string prefix = contextTracker->getPrefix();
172  result = str.substr(prefix.size());
173  } else {
174  std::string message = "[Presage] Error: token '";
175  message += str;
176  message += "' does not match prefix: ";
177  message += contextTracker->getPrefix();
179  }
180  } else {
181  // erasing completion,
182  // pass it to tracker in its entirety
183  //
184  result = str;
185  }
186 
187  // if (append_trailing_space_is_on()) // TODO: make this configurable
188  result += ' ';
189 
190  return result;
191 }
192 
193 std::string Presage::context ()
194 {
195  return contextTracker->getPastStream();
196 }
197 
199 {
200  return contextTracker->contextChange();
201 }
202 
203 std::string Presage::prefix ()
204 {
205  return contextTracker->getPrefix();
206 }
207 
208 std::string Presage::config (const std::string variable)
209 {
210  return configuration->find (variable)->get_value ();
211 }
212 
213 void Presage::config (const std::string variable, const std::string value)
214 {
215  configuration->insert (variable, value);
216 }
217 
219 {
221 }
222 
223 
224 
225 struct _presage {
228 };
229 
231 {
232 public:
234  void* past_arg,
236  void* future_arg)
237  : m_get_past_stream_cb (past),
238  m_get_past_stream_cb_arg (past_arg),
239  m_get_future_stream_cb (future),
240  m_get_future_stream_cb_arg (future_arg)
241  { }
242 
243  virtual ~CPresageCallback() { }
244 
245  std::string get_past_stream() const {
247  }
248 
249  std::string get_future_stream() const {
251  }
252 
253 private:
258 };
259 
260 #define presage_exception_handler(CODE) \
261  try \
262  { \
263  CODE; \
264  } \
265  catch (PresageException& ex) \
266  { \
267  return ex.code (); \
268  } \
269  return PRESAGE_OK;
270 
271 #define presage_exception_handler_with_result(CODE) \
272  try \
273  { \
274  CODE; \
275  } \
276  catch (PresageException& ex) \
277  { \
278  (*result) = 0; \
279  return ex.code (); \
280  } \
281  return PRESAGE_OK;
282 
283 static char* alloc_c_str (const std::string& str)
284 {
285  char* result_c_str = (char*) malloc (str.size() + 1);
286  if (result_c_str)
287  strcpy (result_c_str, str.c_str());
288  return result_c_str;
289 }
290 
292  void* past_stream_cb_arg,
293  _presage_callback_get_future_stream future_stream_cb,
294  void* future_stream_cb_arg,
295  presage_t* result)
296 {
298  (
299  (*result) = (presage_t) malloc (sizeof (_presage));
300  if (*result != NULL)
301  {
302  (*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
303  past_stream_cb_arg,
304  future_stream_cb,
305  future_stream_cb_arg);
306  (*result)->presage_object = new Presage ((*result)->presage_callback_object);
307  }
308 
309  );
310 }
311 
313  void* past_stream_cb_arg,
314  _presage_callback_get_future_stream future_stream_cb,
315  void* future_stream_cb_arg,
316  const char* config,
317  presage_t* result)
318 {
320  (
321  (*result) = (presage_t) malloc (sizeof (_presage));
322  if (*result != NULL)
323  {
324 
325  (*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
326  past_stream_cb_arg,
327  future_stream_cb,
328  future_stream_cb_arg);
329  (*result)->presage_object = new Presage ((*result)->presage_callback_object, config);
330  }
331  );
332 }
333 
335 {
336  if (prsg)
337  {
338  delete prsg->presage_object;
339  delete prsg->presage_callback_object;
340 
341  free (prsg);
342  }
343 }
344 
345 void presage_free_string (char* str)
346 {
347  free (str);
348 }
349 
350 void presage_free_string_array (char** strs)
351 {
352  if (strs) {
353  for (size_t t = 0; strs[t] != 0; t++) {
354  free (strs[t]);
355  }
356  free (strs);
357  }
358 }
359 
361 {
363  (
364  std::vector<std::string> prediction = prsg->presage_object->predict();
365 
366  size_t prediction_c_str_size = prediction.size() + 1;
367  char** prediction_c_str = (char**) malloc (prediction_c_str_size * sizeof(char*));
368  if (prediction_c_str != NULL)
369  {
370  memset (prediction_c_str, 0, prediction_c_str_size * sizeof(char*));
371 
372  size_t i = 0;
373  while (i < prediction_c_str_size - 1) {
374  prediction_c_str[i] = (char*) malloc (prediction[i].size() + 1);
375  if (prediction_c_str[i] != NULL)
376  strcpy (prediction_c_str[i], prediction[i].c_str());
377  i++;
378  }
379  prediction_c_str[i] = 0;
380  }
381 
382  *result = prediction_c_str;
383  );
384 }
385 
387 {
389  (
390  prsg->presage_object->learn (text);
391  );
392 }
393 
394 presage_error_code_t presage_completion (presage_t prsg, const char* token, char** result)
395 {
397  (
398  *result = alloc_c_str (prsg->presage_object->completion (token));
399  );
400 }
401 
403 {
405  (
406  *result = alloc_c_str (prsg->presage_object->context ());
407  );
408 }
409 
411 {
413  (
414  *result = prsg->presage_object->context_change ();
415  );
416 }
417 
419 {
421  (
422  *result = alloc_c_str (prsg->presage_object->prefix ());
423  );
424 }
425 
426 presage_error_code_t presage_config (presage_t prsg, const char* variable, char** result)
427 {
429  (
430  *result = alloc_c_str (prsg->presage_object->config (variable));
431  );
432 }
433 
434 presage_error_code_t presage_config_set (presage_t prsg, const char* variable, const char* value)
435 {
437  (
438  prsg->presage_object->config (variable, value)
439  );
440 }
441 
443 {
445  (
446  prsg->presage_object->save_config ()
447  );
448 }
virtual ~CPresageCallback()
Definition: presage.cpp:243
CPresageCallback(_presage_callback_get_past_stream past, void *past_arg, _presage_callback_get_future_stream future, void *future_arg)
Definition: presage.cpp:233
void * m_get_past_stream_cb_arg
Definition: presage.cpp:255
void * m_get_future_stream_cb_arg
Definition: presage.cpp:257
_presage_callback_get_past_stream m_get_past_stream_cb
Definition: presage.cpp:254
_presage_callback_get_future_stream m_get_future_stream_cb
Definition: presage.cpp:256
std::string get_past_stream() const
Definition: presage.cpp:245
std::string get_future_stream() const
Definition: presage.cpp:249
void insert(const std::string &variable, const std::string &value)
Variable * find(const std::string &variable) const
Tracks user interaction and context.
std::string getPastStream() const
bool isCompletionValid(const std::string &) const
const PresageCallback * callback(const PresageCallback *callback)
std::string getPrefix() const
void learn(const std::string &text) const
Learn from text.
Suggestion getSuggestion(int=0) const
Definition: prediction.cpp:73
size_t size() const
Definition: prediction.cpp:68
Prediction predict(unsigned int multiplier, const char **filter)
Presage, the intelligent predictive text entry platform.
Definition: presage.h:107
bool context_change()
Returns true if a context change occured.
Definition: presage.cpp:198
Configuration * configuration
Definition: presage.h:247
std::string completion(std::string str)
Request presage to return the completion string for the given predicted token.
Definition: presage.cpp:146
std::string config(const std::string variable)
Gets the value of specified configuration variable.
Definition: presage.cpp:208
std::vector< std::string > predict()
Obtain a prediction.
Definition: presage.cpp:62
PresageCallback * callback(PresageCallback *callback)
Callback getter/setter.
Definition: presage.cpp:141
void learn(const std::string text)
Learn from text offline.
Definition: presage.cpp:135
Selector * selector
Definition: presage.h:251
ContextTracker * contextTracker
Definition: presage.h:249
~Presage()
Definition: presage.cpp:53
PredictorRegistry * predictorRegistry
Definition: presage.h:248
void save_config()
Save current configuration to file.
Definition: presage.cpp:218
Presage(PresageCallback *callback)
Definition: presage.cpp:33
std::string context()
Returns the text entered so far.
Definition: presage.cpp:193
ProfileManager * profileManager
Definition: presage.h:246
std::string prefix()
Returns the current prefix.
Definition: presage.cpp:203
PredictorActivator * predictorActivator
Definition: presage.h:250
void save_profile() const
Configuration * get_configuration()
std::vector< std::string > select(Prediction)
Definition: selector.cpp:55
size_t get_suggestions() const
Definition: selector.cpp:246
double getProbability() const
Definition: suggestion.cpp:69
std::string get_value() const
Definition: variable.cpp:62
const char *(* _presage_callback_get_past_stream)(void *)
const char *(* _presage_callback_get_future_stream)(void *)
std::string config
Definition: presageDemo.cpp:70
presage_error_code_t
@ PRESAGE_TOKEN_PREFIX_MISMATCH_ERROR
presage_error_code_t presage_prefix(presage_t prsg, char **result)
Definition: presage.cpp:418
void presage_free_string_array(char **strs)
Definition: presage.cpp:350
presage_error_code_t presage_context(presage_t prsg, char **result)
Definition: presage.cpp:402
presage_error_code_t presage_completion(presage_t prsg, const char *token, char **result)
Definition: presage.cpp:394
static char * alloc_c_str(const std::string &str)
Definition: presage.cpp:283
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:312
presage_error_code_t presage_predict(presage_t prsg, char ***result)
Definition: presage.cpp:360
presage_error_code_t presage_learn(presage_t prsg, const char *text)
Definition: presage.cpp:386
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:291
#define presage_exception_handler(CODE)
Definition: presage.cpp:260
presage_error_code_t presage_config_set(presage_t prsg, const char *variable, const char *value)
Definition: presage.cpp:434
presage_error_code_t presage_context_change(presage_t prsg, int *result)
Definition: presage.cpp:410
#define presage_exception_handler_with_result(CODE)
Definition: presage.cpp:271
presage_error_code_t presage_config(presage_t prsg, const char *variable, char **result)
Definition: presage.cpp:426
void presage_free(presage_t prsg)
Definition: presage.cpp:334
void presage_free_string(char *str)
Definition: presage.cpp:345
presage_error_code_t presage_save_config(presage_t prsg)
Definition: presage.cpp:442
PresageCallback * presage_callback_object
Definition: presage.cpp:226
Presage * presage_object
Definition: presage.cpp:227