presage.cpp
Go to the documentation of this file.
/******************************************************
* Presage, an extensible predictive text entry system
* ---------------------------------------------------
*
* Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
**********(*)*/
#include "presage.h"
#include "core/profileManager.h"
#include "core/predictorRegistry.h"
#include "core/context_tracker/contextTracker.h"
#include "core/selector.h"
#include "core/predictorActivator.h"
Presage::Presage (PresageCallback* callback)
noexcept(false)
{
profileManager = new ProfileManager();
configuration = profileManager->get_configuration();
predictorRegistry = new PredictorRegistry(configuration);
contextTracker = new ContextTracker(configuration, predictorRegistry, callback);
predictorActivator = new PredictorActivator(configuration, predictorRegistry, contextTracker);
selector = new Selector(configuration, contextTracker);
}
Presage::Presage (PresageCallback* callback, const std::string config_filename)
noexcept(false)
{
profileManager = new ProfileManager(config_filename);
configuration = profileManager->get_configuration();
predictorRegistry = new PredictorRegistry(configuration);
contextTracker = new ContextTracker(configuration, predictorRegistry, callback);
predictorActivator = new PredictorActivator(configuration, predictorRegistry, contextTracker);
selector = new Selector(configuration, contextTracker);
}
Presage::~Presage()
{
delete selector;
delete predictorActivator;
delete contextTracker;
delete predictorRegistry;
delete profileManager;
}
std::vector<std::string> Presage::predict ()
noexcept(false)
{
std::vector<std::string> result;
unsigned int multiplier = 1;
Prediction prediction = predictorActivator->predict(multiplier++, 0);
result = selector->select(prediction);
Prediction previous_prediction = prediction;
while ((result.size() < (selector->get_suggestions()))
&& (prediction = predictorActivator->predict(multiplier++, 0)).size() > previous_prediction.size()) {
// while the number of predicted tokens is lower than desired,
// search harder (i.e. higher multiplier) for a prediction of
// sufficient size (i.e. that satisfies selector), as long as
// the result of current prediction is greater than the
// previous prediction (i.e. we are finding new tokens).
result = selector->select(prediction);
previous_prediction = prediction;
}
contextTracker->update();
return result;
}
std::multimap<double, std::string> Presage::predict (std::vector<std::string> filter)
noexcept(false)
{
std::multimap<double, std::string> result;
std::vector<std::string> selection;
const char** internal_filter = 0;
if(filter.size()>0)
{
// convert filter to internal representation - currently a null
// terminated const char**
internal_filter = new const char*[filter.size() + 1];
for (std::vector<std::string>::size_type i = 0; i < filter.size(); i++) {
internal_filter[i] = filter[i].c_str();
}
internal_filter[filter.size()] = 0;
}
unsigned int multiplier = 1;
Prediction prediction = predictorActivator->predict(multiplier++, internal_filter);
selection = selector->select(prediction);
Prediction previous_prediction = prediction;
while ((selection.size() < (selector->get_suggestions()))
&& (prediction = predictorActivator->predict(multiplier++, internal_filter)).size() > previous_prediction.size()) {
// while the number of predicted tokens is lower than desired,
// search harder (i.e. higher multiplier) for a prediction of
// sufficient size (i.e. that satisfies selector), as long as
// the selection of current prediction is greater than the
// previous prediction (i.e. we are finding new tokens).
selection = selector->select(prediction);
previous_prediction = prediction;
}
delete[] internal_filter;
for (std::vector<std::string>::const_iterator it = selection.begin();
it != selection.end();
it++) {
std::pair<const double, std::string> p(prediction.getSuggestion(*it).getProbability(),
(*it));
result.insert(p);
}
contextTracker->update();
return result;
}
void Presage::learn(const std::string text) const
noexcept(false)
{
contextTracker->learn(text); // TODO: can pass additional param to
// learn to specify offline learning
}
PresageCallback* Presage::callback (PresageCallback* callback)
noexcept(false)
{
return const_cast<PresageCallback*>(contextTracker->callback(callback));
}
std::string Presage::completion (const std::string str)
noexcept(false)
{
// There are two types of completions: normal and erasing.
// normal_completion = prefix + remainder
// erasing_completion = eraser + prefix + remainder
//
// or, given that token = prefix + remainder
// normal_completion = token
// erasing_completion = eraser + token
//
// where eraser = ^H+ (one or more backspace characters)
//
// offset to first non ^H character in completion (^H are inserted
// by abbreviation expansion predictor to erase abbreviation from
// stream)
//
std::string result;
std::string::size_type offset = str.find_first_not_of('\b');
if (offset == 0) {
// normal completion,
// ensure that current prefix is a substring of completion
// token and set result
//
if (contextTracker->isCompletionValid(str)) {
std::string prefix = contextTracker->getPrefix();
result = str.substr(prefix.size());
} else {
std::string message = "[Presage] Error: token '";
message += str;
message += "' does not match prefix: ";
message += contextTracker->getPrefix();
throw PresageException(PRESAGE_TOKEN_PREFIX_MISMATCH_ERROR, message);
}
} else {
// erasing completion,
// pass it to tracker in its entirety
//
result = str;
}
// if (append_trailing_space_is_on()) // TODO: make this configurable
result += ' ';
return result;
}
std::string Presage::context () const
noexcept(false)
{
return contextTracker->getPastStream();
}
bool Presage::context_change () const
noexcept(false)
{
return contextTracker->contextChange();
}
std::string Presage::prefix () const
noexcept(false)
{
return contextTracker->getPrefix();
}
std::string Presage::config (const std::string variable) const
noexcept(false)
{
return configuration->find (variable)->get_value ();
}
void Presage::config (const std::string variable, const std::string value) const
noexcept(false)
{
configuration->insert (variable, value);
}
void Presage::save_config () const
noexcept(false)
{
profileManager->save_profile ();
}
struct _presage {
PresageCallback* presage_callback_object;
Presage* presage_object;
};
class CPresageCallback : public PresageCallback
{
public:
CPresageCallback (_presage_callback_get_past_stream past,
void* past_arg,
_presage_callback_get_future_stream future,
void* future_arg)
: m_get_past_stream_cb (past),
m_get_past_stream_cb_arg (past_arg),
m_get_future_stream_cb (future),
m_get_future_stream_cb_arg (future_arg)
{ }
virtual ~CPresageCallback() { }
std::string get_past_stream() const {
return (*m_get_past_stream_cb) (m_get_past_stream_cb_arg);
}
std::string get_future_stream() const {
return (*m_get_future_stream_cb) (m_get_future_stream_cb_arg);
}
private:
_presage_callback_get_past_stream m_get_past_stream_cb;
void* m_get_past_stream_cb_arg;
_presage_callback_get_future_stream m_get_future_stream_cb;
void* m_get_future_stream_cb_arg;
};
#define presage_exception_handler(CODE) \
try \
{ \
CODE; \
} \
catch (PresageException& ex) \
{ \
return ex.code (); \
} \
return PRESAGE_OK;
#define presage_exception_handler_with_result(CODE) \
try \
{ \
CODE; \
} \
catch (PresageException& ex) \
{ \
(*result) = 0; \
return ex.code (); \
} \
return PRESAGE_OK;
static char* alloc_c_str (const std::string& str)
{
char* result_c_str = (char*) malloc (str.size() + 1);
if (result_c_str)
strcpy (result_c_str, str.c_str());
return result_c_str;
}
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)
{
presage_exception_handler_with_result
(
(*result) = (presage_t) malloc (sizeof (_presage));
if (*result != NULL)
{
(*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
past_stream_cb_arg,
future_stream_cb,
future_stream_cb_arg);
(*result)->presage_object = new Presage ((*result)->presage_callback_object);
}
);
}
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)
{
presage_exception_handler_with_result
(
(*result) = (presage_t) malloc (sizeof (_presage));
if (*result != NULL)
{
(*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
past_stream_cb_arg,
future_stream_cb,
future_stream_cb_arg);
(*result)->presage_object = new Presage ((*result)->presage_callback_object, config);
}
);
}
void presage_free (presage_t prsg)
{
if (prsg)
{
delete prsg->presage_object;
delete prsg->presage_callback_object;
free (prsg);
}
}
void presage_free_string (char* str)
{
free (str);
}
void presage_free_string_array (char** strs)
{
if (strs) {
for (size_t t = 0; strs[t] != 0; t++) {
free (strs[t]);
}
free (strs);
}
}
presage_error_code_t presage_predict (presage_t prsg, char*** result)
{
presage_exception_handler_with_result
(
std::vector<std::string> prediction = prsg->presage_object->predict();
size_t prediction_c_str_size = prediction.size() + 1;
char** prediction_c_str = (char**) malloc (prediction_c_str_size * sizeof(char*));
if (prediction_c_str != NULL)
{
memset (prediction_c_str, 0, prediction_c_str_size * sizeof(char*));
size_t i = 0;
while (i < prediction_c_str_size - 1) {
prediction_c_str[i] = (char*) malloc (prediction[i].size() + 1);
if (prediction_c_str[i] != NULL)
strcpy (prediction_c_str[i], prediction[i].c_str());
i++;
}
prediction_c_str[i] = 0;
}
*result = prediction_c_str;
);
}
presage_error_code_t presage_learn (presage_t prsg, const char* text)
{
presage_exception_handler
(
prsg->presage_object->learn (text);
);
}
presage_error_code_t presage_completion (presage_t prsg, const char* token, char** result)
{
presage_exception_handler_with_result
(
*result = alloc_c_str (prsg->presage_object->completion (token));
);
}
presage_error_code_t presage_context (presage_t prsg, char** result)
{
presage_exception_handler_with_result
(
*result = alloc_c_str (prsg->presage_object->context ());
);
}
presage_error_code_t presage_context_change (presage_t prsg, int* result)
{
presage_exception_handler_with_result
(
*result = prsg->presage_object->context_change ();
);
}
presage_error_code_t presage_prefix (presage_t prsg, char** result)
{
presage_exception_handler_with_result
(
*result = alloc_c_str (prsg->presage_object->prefix ());
);
}
presage_error_code_t presage_config (presage_t prsg, const char* variable, char** result)
{
presage_exception_handler_with_result
(
*result = alloc_c_str (prsg->presage_object->config (variable));
);
}
presage_error_code_t presage_config_set (presage_t prsg, const char* variable, const char* value)
{
presage_exception_handler
(
prsg->presage_object->config (variable, value)
);
}
presage_error_code_t presage_save_config (presage_t prsg)
{
presage_exception_handler
(
prsg->presage_object->save_config ()
);
}
CPresageCallback
Definition presage.cpp:244
CPresageCallback::~CPresageCallback
virtual ~CPresageCallback()
Definition presage.cpp:256
CPresageCallback::CPresageCallback
CPresageCallback(_presage_callback_get_past_stream past, void *past_arg, _presage_callback_get_future_stream future, void *future_arg)
Definition presage.cpp:246
CPresageCallback::m_get_past_stream_cb_arg
void * m_get_past_stream_cb_arg
Definition presage.cpp:268
CPresageCallback::m_get_future_stream_cb_arg
void * m_get_future_stream_cb_arg
Definition presage.cpp:270
CPresageCallback::m_get_past_stream_cb
_presage_callback_get_past_stream m_get_past_stream_cb
Definition presage.cpp:267
CPresageCallback::m_get_future_stream_cb
_presage_callback_get_future_stream m_get_future_stream_cb
Definition presage.cpp:269
CPresageCallback::get_past_stream
std::string get_past_stream() const
Definition presage.cpp:258
CPresageCallback::get_future_stream
std::string get_future_stream() const
Definition presage.cpp:262
ContextTracker
Tracks user interaction and context.
Definition contextTracker.h:155
Prediction
Definition prediction.h:47
Prediction::getSuggestion
Suggestion getSuggestion(int=0) const
Definition prediction.cpp:73
Prediction::size
size_t size() const
Definition prediction.cpp:68
PredictorActivator
Definition predictorActivator.h:62
PredictorRegistry
Definition predictorRegistry.h:46
PresageCallback
Definition presageCallback.h:66
PresageCallback::PresageCallback
PresageCallback()
Definition presageCallback.h:74
PresageException
Definition presageException.h:67
Presage
Presage, the intelligent predictive text entry platform.
Definition presage.h:107
Presage::callback
PresageCallback * callback(PresageCallback *callback) noexcept(false)
Callback getter/setter.
Definition presage.cpp:146
Presage::context
std::string context() const noexcept(false)
Returns the text entered so far.
Definition presage.cpp:200
Presage::configuration
Configuration * configuration
Definition presage.h:247
Presage::completion
std::string completion(std::string str) noexcept(false)
Request presage to return the completion string for the given predicted token.
Definition presage.cpp:152
Presage::prefix
std::string prefix() const noexcept(false)
Returns the current prefix.
Definition presage.cpp:212
Presage::config
std::string config(const std::string variable) const noexcept(false)
Gets the value of specified configuration variable.
Definition presage.cpp:218
Presage::predict
std::vector< std::string > predict() noexcept(false)
Obtain a prediction.
Definition presage.cpp:64
Presage::context_change
bool context_change() const noexcept(false)
Returns true if a context change occured.
Definition presage.cpp:206
Presage::selector
Selector * selector
Definition presage.h:251
Presage::contextTracker
ContextTracker * contextTracker
Definition presage.h:249
Presage::~Presage
~Presage()
Definition presage.cpp:55
Presage::predictorRegistry
PredictorRegistry * predictorRegistry
Definition presage.h:248
Presage::Presage
Presage(PresageCallback *callback) noexcept(false)
Definition presage.cpp:33
Presage::learn
void learn(const std::string text) const noexcept(false)
Learn from text offline.
Definition presage.cpp:139
Presage::save_config
void save_config() const noexcept(false)
Save current configuration to file.
Definition presage.cpp:230
Presage::profileManager
ProfileManager * profileManager
Definition presage.h:246
Presage::predictorActivator
PredictorActivator * predictorActivator
Definition presage.h:250
ProfileManager
Definition profileManager.h:51
Selector
Definition selector.h:80
Suggestion::getProbability
double getProbability() const
Definition suggestion.cpp:69
contextTracker.h
predictorActivator.h
predictorRegistry.h
_presage_callback_get_past_stream
const char *(* _presage_callback_get_past_stream)(void *)
Definition presageCallback.h:32
_presage_callback_get_future_stream
const char *(* _presage_callback_get_future_stream)(void *)
Definition presageCallback.h:33
config
std::string config
Definition presageDemo.cpp:70
presage_error_code_t
presage_error_code_t
Definition presageException.h:33
PRESAGE_TOKEN_PREFIX_MISMATCH_ERROR
@ PRESAGE_TOKEN_PREFIX_MISMATCH_ERROR
Definition presageException.h:36
presage_prefix
presage_error_code_t presage_prefix(presage_t prsg, char **result)
Definition presage.cpp:431
presage_free_string_array
void presage_free_string_array(char **strs)
Definition presage.cpp:363
presage_context
presage_error_code_t presage_context(presage_t prsg, char **result)
Definition presage.cpp:415
presage_completion
presage_error_code_t presage_completion(presage_t prsg, const char *token, char **result)
Definition presage.cpp:407
presage_new_with_config
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_predict
presage_error_code_t presage_predict(presage_t prsg, char ***result)
Definition presage.cpp:373
presage_learn
presage_error_code_t presage_learn(presage_t prsg, const char *text)
Definition presage.cpp:399
presage_new
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
presage_exception_handler
#define presage_exception_handler(CODE)
Definition presage.cpp:273
presage_config_set
presage_error_code_t presage_config_set(presage_t prsg, const char *variable, const char *value)
Definition presage.cpp:447
presage_context_change
presage_error_code_t presage_context_change(presage_t prsg, int *result)
Definition presage.cpp:423
presage_exception_handler_with_result
#define presage_exception_handler_with_result(CODE)
Definition presage.cpp:284
alloc_c_str
static char * alloc_c_str(const std::string &str)
Definition presage.cpp:296
presage_config
presage_error_code_t presage_config(presage_t prsg, const char *variable, char **result)
Definition presage.cpp:439
presage_free
void presage_free(presage_t prsg)
Definition presage.cpp:347
presage_free_string
void presage_free_string(char *str)
Definition presage.cpp:358
presage_save_config
presage_error_code_t presage_save_config(presage_t prsg)
Definition presage.cpp:455
presage.h
presage_t
struct _presage * presage_t
Definition presage.h:271
profileManager.h
selector.h
_presage
Definition presage.cpp:238
_presage::presage_callback_object
PresageCallback * presage_callback_object
Definition presage.cpp:239
_presage::presage_object
Presage * presage_object
Definition presage.cpp:240