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"
30#include "core/selector.h"
32
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
44Presage::Presage (PresageCallback* callback, const std::string config_filename)
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
64std::vector<std::string> Presage::predict ()
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
90std::multimap<double, std::string> Presage::predict (std::vector<std::string> filter)
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
139void Presage::learn(const std::string text) const
141{
142 contextTracker->learn(text); // TODO: can pass additional param to
143 // learn to specify offline learning
144}
145
148{
149 return const_cast<PresageCallback*>(contextTracker->callback(callback));
150}
151
152std::string Presage::completion (const std::string str)
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
200std::string Presage::context () const
202{
204}
205
208{
210}
211
212std::string Presage::prefix () const
214{
215 return contextTracker->getPrefix();
216}
217
218std::string Presage::config (const std::string variable) const
220{
221 return configuration->find (variable)->get_value ();
222}
223
224void Presage::config (const std::string variable, const std::string value) const
226{
227 configuration->insert (variable, value);
228}
229
232{
234}
235
236
237
238struct _presage {
241};
242
244{
245public:
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
266private:
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
296static 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,
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,
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
358void presage_free_string (char* str)
359{
360 free (str);
361}
362
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
407presage_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
439presage_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
447presage_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 (
460 );
461}
virtual ~CPresageCallback()
Definition: presage.cpp:256
CPresageCallback(_presage_callback_get_past_stream past, void *past_arg, _presage_callback_get_future_stream future, void *future_arg)
Definition: presage.cpp:246
void * m_get_past_stream_cb_arg
Definition: presage.cpp:268
void * m_get_future_stream_cb_arg
Definition: presage.cpp:270
_presage_callback_get_past_stream m_get_past_stream_cb
Definition: presage.cpp:267
_presage_callback_get_future_stream m_get_future_stream_cb
Definition: presage.cpp:269
std::string get_past_stream() const
Definition: presage.cpp:258
std::string get_future_stream() const
Definition: presage.cpp:262
Tracks user interaction and context.
std::string getPastStream() const
std::string getPrefix() const
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:113
bool context_change() const EXCEPT(PresageException)
Returns true if a context change occured.
Definition: presage.cpp:206
std::string context() const EXCEPT(PresageException)
Returns the text entered so far.
Definition: presage.cpp:200
void save_config() const EXCEPT(PresageException)
Save current configuration to file.
Definition: presage.cpp:230
void learn(const std::string text) const EXCEPT(PresageException)
Learn from text offline.
Definition: presage.cpp:139
std::vector< std::string > predict() EXCEPT(PresageException)
Obtain a prediction.
Definition: presage.cpp:64
Presage(PresageCallback *callback) EXCEPT(PresageException)
Definition: presage.cpp:33
Selector * selector
Definition: presage.h:257
ContextTracker * contextTracker
Definition: presage.h:255
~Presage()
Definition: presage.cpp:55
std::string completion(std::string str) EXCEPT(PresageException)
Request presage to return the completion string for the given predicted token.
Definition: presage.cpp:152
PredictorRegistry * predictorRegistry
Definition: presage.h:254
PresageCallback * callback(PresageCallback *callback) EXCEPT(PresageException)
Callback getter/setter.
Definition: presage.cpp:146
std::string prefix() const EXCEPT(PresageException)
Returns the current prefix.
Definition: presage.cpp:212
ProfileManager * profileManager
Definition: presage.h:252
std::string config(const std::string variable) const EXCEPT(PresageException)
Gets the value of specified configuration variable.
Definition: presage.cpp:218
PredictorActivator * predictorActivator
Definition: presage.h:256
void save_profile() const
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
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:431
void presage_free_string_array(char **strs)
Definition: presage.cpp:363
presage_error_code_t presage_context(presage_t prsg, char **result)
Definition: presage.cpp:415
presage_error_code_t presage_completion(presage_t prsg, const char *token, char **result)
Definition: presage.cpp:407
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_predict(presage_t prsg, char ***result)
Definition: presage.cpp:373
presage_error_code_t presage_learn(presage_t prsg, const char *text)
Definition: presage.cpp:399
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
#define presage_exception_handler(CODE)
Definition: presage.cpp:273
presage_error_code_t presage_config_set(presage_t prsg, const char *variable, const char *value)
Definition: presage.cpp:447
presage_error_code_t presage_context_change(presage_t prsg, int *result)
Definition: presage.cpp:423
#define presage_exception_handler_with_result(CODE)
Definition: presage.cpp:284
static char * alloc_c_str(const std::string &str)
Definition: presage.cpp:296
presage_error_code_t presage_config(presage_t prsg, const char *variable, char **result)
Definition: presage.cpp:439
void presage_free(presage_t prsg)
Definition: presage.cpp:347
void presage_free_string(char *str)
Definition: presage.cpp:358
presage_error_code_t presage_save_config(presage_t prsg)
Definition: presage.cpp:455
#define EXCEPT(...)
Definition: presage.h:34
PresageCallback * presage_callback_object
Definition: presage.cpp:239
Presage * presage_object
Definition: presage.cpp:240