/*
 *      CRFsuite library.
 *
 * Copyright (c) 2007-2010, Naoaki Okazaki
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the names of the authors nor the names of its contributors
 *       may be used to endorse or promote products derived from this
 *       software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* $Id$ */

#ifndef __CRFSUITE_H__
#define __CRFSUITE_H__

#ifdef __cplusplus
extern "C"
{
#endif /*__cplusplus*/

#include <limits.h>
#include <stdio.h>
#include <stdarg.h>

/** 
 * \addtogroup crfsuite_api CRFSuite C API
 * @{
 *
 *  The CRFSuite C API provides a low-level library for manupulating
 *  CRFSuite in C language.
 */

/** 
 * \addtogroup crfsuite_misc Miscellaneous definitions and functions
 * @{
 */

/** Version number of CRFSuite library. */
#define CRFSUITE_VERSION "0.12.2"

/** Copyright string of CRFSuite library. */
#define CRFSUITE_COPYRIGHT "Copyright (c) 2007-2013 Naoaki Okazaki"

    /** Type of a float value. */
    typedef double floatval_t;

/** Maximum value of a float value. */
#define FLOAT_MAX DBL_MAX

    /**
 * Status codes.
 */
    enum
    {
        /** Success. */
        CRFSUITE_SUCCESS = 0,
        /** Unknown error occurred. */
        CRFSUITEERR_UNKNOWN = INT_MIN,
        /** Insufficient memory. */
        CRFSUITEERR_OUTOFMEMORY,
        /** Unsupported operation. */
        CRFSUITEERR_NOTSUPPORTED,
        /** Incompatible data. */
        CRFSUITEERR_INCOMPATIBLE,
        /** Internal error. */
        CRFSUITEERR_INTERNAL_LOGIC,
        /** Overflow. */
        CRFSUITEERR_OVERFLOW,
        /** Not implemented. */
        CRFSUITEERR_NOTIMPLEMENTED,
    };

    /**@}*/

    /**
 * \addtogroup crfsuite_object Object interfaces and utilities.
 * @{
 */

    struct tag_crfsuite_model;
    /** CRFSuite model interface. */
    typedef struct tag_crfsuite_model crfsuite_model_t;

    struct tag_crfsuite_trainer;
    /** CRFSuite trainer interface. */
    typedef struct tag_crfsuite_trainer crfsuite_trainer_t;

    struct tag_crfsuite_tagger;
    /** CRFSuite tagger interface. */
    typedef struct tag_crfsuite_tagger crfsuite_tagger_t;

    struct tag_crfsuite_dictionary;
    /** CRFSuite dictionary interface. */
    typedef struct tag_crfsuite_dictionary crfsuite_dictionary_t;

    struct tag_crfsuite_params;
    /** CRFSuite parameter interface. */
    typedef struct tag_crfsuite_params crfsuite_params_t;

    /**@}*/

    /**
 * \addtogroup crfsuite_data Dataset (attribute, item, instance, dataset)
 * @{
 */

    /**
 * An attribute.
 *  An attribute consists of an attribute id with its value.
 */
    typedef struct
    {
        int aid;          /**< Attribute id. */
        floatval_t value; /**< Value of the attribute. */
    } crfsuite_attribute_t;

    /**
 * An item.
 *  An item consists of an array of attributes.
 */
    typedef struct
    {
        /** Number of contents associated with the item. */
        int num_contents;
        /** Maximum number of contents (internal use). */
        int cap_contents;
        /** Array of the attributes. */
        crfsuite_attribute_t *contents;
    } crfsuite_item_t;

    /**
 * An instance (sequence of items and labels).
 *  An instance consists of a sequence of items and labels.
 */
    typedef struct
    {
        /** Number of items/labels in the sequence. */
        int num_items;
        /** Maximum number of items/labels (internal use). */
        int cap_items;
        /** Array of the item sequence. */
        crfsuite_item_t *items;
        /** Array of the label sequence. */
        int *labels;
        /** Instance weight. */
        floatval_t weight;
        /** Group ID of the instance. */
        int group;
    } crfsuite_instance_t;

    /**
 * A data set.
 *  A data set consists of an array of instances and dictionary objects
 *  for attributes and labels.
 */
    typedef struct
    {
        /** Number of instances. */
        int num_instances;
        /** Maximum number of instances (internal use). */
        int cap_instances;
        /** Array of instances. */
        crfsuite_instance_t *instances;

        /** Dictionary object for attributes. */
        crfsuite_dictionary_t *attrs;
        /** Dictionary object for labels. */
        crfsuite_dictionary_t *labels;
    } crfsuite_data_t;

    /**@}*/

    /**
 * \addtogroup crfsuite_evaluation Evaluation utility
 * @{
 */

    /**
 * Label-wise performance values.
 */
    typedef struct
    {
        /** Number of correct predictions. */
        int num_correct;
        /** Number of occurrences of the label in the gold-standard data. */
        int num_observation;
        /** Number of predictions. */
        int num_model;
        /** Precision. */
        floatval_t precision;
        /** Recall. */
        floatval_t recall;
        /** F1 score. */
        floatval_t fmeasure;
    } crfsuite_label_evaluation_t;

    /**
 * An overall performance values.
 */
    typedef struct
    {
        /** Number of labels. */
        int num_labels;
        /** Array of label-wise evaluations. */
        crfsuite_label_evaluation_t *tbl;

        /** Number of correctly predicted items. */
        int item_total_correct;
        /** Total number of items. */
        int item_total_num;
        /** Total number of occurrences of labels in the gold-standard data. */
        int item_total_observation;
        /** Total number of predictions. */
        int item_total_model;
        /** Item-level accuracy. */
        floatval_t item_accuracy;

        /** Number of correctly predicted instances. */
        int inst_total_correct;
        /** Total number of instances. */
        int inst_total_num;
        /** Instance-level accuracy. */
        floatval_t inst_accuracy;

        /** Macro-averaged precision. */
        floatval_t macro_precision;
        /** Macro-averaged recall. */
        floatval_t macro_recall;
        /** Macro-averaged F1 score. */
        floatval_t macro_fmeasure;
    } crfsuite_evaluation_t;

    /**@}*/

    /**
 * \addtogroup crfsuite_object
 * @{
 */

    /**
 * Type of callback function for logging.
 *  @param  user        Pointer to the user-defined data.
 *  @param  format      Format string (compatible with prinf()).
 *  @param  args        Optional arguments for the format string.
 *  @return int         \c 0 to continue; non-zero to cancel the training.
 */
    typedef int (*crfsuite_logging_callback)(void *user, const char *format, va_list args);

    /**
 * CRFSuite model interface.
 */
    struct tag_crfsuite_model
    {
        /**
     * Pointer to the internal data (internal use only).
     */
        void *internal;

        /**
     * Reference counter (internal use only).
     */
        int nref;

        /**
     * Increment the reference counter.
     *  @param  model       The pointer to this model instance.
     *  @return int         The reference count after this increment.
     */
        int (*addref)(crfsuite_model_t *model);

        /**
     * Decrement the reference counter.
     *  @param  model       The pointer to this model instance.
     *  @return int         The reference count after this operation.
     */
        int (*release)(crfsuite_model_t *model);

        /**
     * Obtain the pointer to crfsuite_tagger_t interface.
     *  @param  model       The pointer to this model instance.
     *  @param  ptr_tagger  The pointer that receives a crfsuite_tagger_t
     *                      pointer.
     *  @return int         The status code.
     */
        int (*get_tagger)(crfsuite_model_t *model, crfsuite_tagger_t **ptr_tagger);

        /**
     * Obtain the pointer to crfsuite_dictionary_t interface for labels.
     *  @param  model       The pointer to this model instance.
     *  @param  ptr_labels  The pointer that receives a crfsuite_dictionary_t
     *                      pointer.
     *  @return int         The status code.
     */
        int (*get_labels)(crfsuite_model_t *model, crfsuite_dictionary_t **ptr_labels);

        /**
     * Obtain the pointer to crfsuite_dictionary_t interface for attributes.
     *  @param  model       The pointer to this model instance.
     *  @param  ptr_attrs   The pointer that receives a crfsuite_dictionary_t
     *                      pointer.
     *  @return int         The status code.
     */
        int (*get_attrs)(crfsuite_model_t *model, crfsuite_dictionary_t **ptr_attrs);

        /**
     * Print the model in human-readable format.
     *  @param  model       The pointer to this model instance.
     *  @param  fpo         The FILE* pointer.
     *  @return int         The status code.
     */
        int (*dump)(crfsuite_model_t *model, FILE *fpo);
    };

    /**
 * CRFSuite trainer interface.
 */
    struct tag_crfsuite_trainer
    {
        /**
     * Pointer to the internal data (internal use only).
     */
        void *internal;

        /**
     * Reference counter (internal use only).
     */
        int nref;

        /**
     * Increment the reference counter.
     *  @param  trainer     The pointer to this trainer instance.
     *  @return int         The reference count after this increment.
     */
        int (*addref)(crfsuite_trainer_t *trainer);

        /**
     * Decrement the reference counter.
     *  @param  trainer     The pointer to this trainer instance.
     *  @return int         The reference count after this operation.
     */
        int (*release)(crfsuite_trainer_t *trainer);

        /**
     * Obtain the pointer to crfsuite_params_t interface.
     *  @param  trainer     The pointer to this trainer instance.
     *  @return crfsuite_params_t*  The pointer to crfsuite_params_t.
     */
        crfsuite_params_t *(*params)(crfsuite_trainer_t *trainer);

        /**
     * Set the callback function and user-defined data.
     *  @param  trainer     The pointer to this trainer instance.
     *  @param  user        The pointer to the user-defined data.
     *  @param  cbm         The pointer to the callback function.
     */
        void (*set_message_callback)(crfsuite_trainer_t *trainer, void *user, crfsuite_logging_callback cbm);

        /**
     * Start a training process.
     *  @param  trainer     The pointer to this trainer instance.
     *  @param  data        The poiinter to the data set.
     *  @param  filename    The filename to which the trainer stores the model.
     *                      If an empty string is specified, this function
     *                      does not sture the model to a file.
     *  @param  holdout     The holdout group.
     *  @return int         The status code.
     */
        int (*train)(crfsuite_trainer_t *trainer, const crfsuite_data_t *data, const char *filename, int holdout);
    };

    /**
 * CRFSuite tagger interface.
 */
    struct tag_crfsuite_tagger
    {
        /**
     * Pointer to the internal data (internal use only).
     */
        void *internal;

        /**
     * Reference counter (internal use only).
     */
        int nref;

        /**
     * Increment the reference counter.
     *  @param  tagger      The pointer to this tagger instance.
     *  @return int         The reference count after this increment.
     */
        int (*addref)(crfsuite_tagger_t *tagger);

        /**
     * Decrement the reference counter.
     *  @param  tagger      The pointer to this tagger instance.
     *  @return int         The reference count after this operation.
     */
        int (*release)(crfsuite_tagger_t *tagger);

        /**
     * Set an instance to the tagger.
     *  @param  tagger      The pointer to this tagger instance.
     *  @param  inst        The item sequence to be tagged.
     *  @return int         The status code.
     */
        int (*set)(crfsuite_tagger_t *tagger, crfsuite_instance_t *inst);

        /**
     * Obtain the number of items in the current instance.
     *  @param  tagger      The pointer to this tagger instance.
     *  @return int         The number of items of the instance set by
     *                      set() function.
     *  @return int         The status code.
     */
        int (*length)(crfsuite_tagger_t *tagger);

        /**
     * Find the Viterbi label sequence.
     *  @param  tagger      The pointer to this tagger instance.
     *  @param  labels      The label array that receives the Viterbi label
     *                      sequence. The number of elements in the array must
     *                      be no smaller than the number of item.
     *  @param  ptr_score   The pointer to a float variable that receives the
     *                      score of the Viterbi label sequence.
     *  @return int         The status code.
     */
        int (*viterbi)(crfsuite_tagger_t *tagger, int *labels, floatval_t *ptr_score);

        /**
     * Compute the score of a label sequence.
     *  @param  tagger      The pointer to this tagger instance.
     *  @param  path        The label sequence.
     *  @param  ptr_score   The pointer to a float variable that receives the
     *                      score of the label sequence.
     *  @return int         The status code.
     */
        int (*score)(crfsuite_tagger_t *tagger, int *path, floatval_t *ptr_score);

        /**
     * Compute the log of the partition factor (normalization constant).
     *  @param  tagger      The pointer to this tagger instance.
     *  @param  ptr_score   The pointer to a float variable that receives the
     *                      logarithm of the partition factor.
     *  @return int         The status code.
     */
        int (*lognorm)(crfsuite_tagger_t *tagger, floatval_t *ptr_norm);

        /**
     * Compute the marginal probability of a label at a position.
     *  This function computes P(y_t = l | x), the probability when
     *  y_t is the label (l).
     *  @param  tagger      The pointer to this tagger instance.
     *  @param  l           The label.
     *  @param  t           The position.
     *  @param  ptr_prob    The pointer to a float variable that receives the
     *                      marginal probability.
     *  @return int         The status code.
     */
        int (*marginal_point)(crfsuite_tagger_t *tagger, int l, int t, floatval_t *ptr_prob);

        /**
     * Compute the marginal probability of a partial label sequence.
     *  @param  tagger      The pointer to this tagger instance.
     *  @param  path        The partial label sequence.
     *  @param  begin       The start position of the partial label sequence.
     *  @param  end         The last+1 position of the partial label sequence.
     *  @param  ptr_prob    The pointer to a float variable that receives the
     *                      marginal probability.
     *  @return int         The status code.
     */
        int (*marginal_path)(crfsuite_tagger_t *tagger, const int *path, int begin, int end, floatval_t *ptr_prob);
    };

    /**
 * CRFSuite dictionary interface.
 */
    struct tag_crfsuite_dictionary
    {
        /**
     * Pointer to the internal data (internal use only).
     */
        void *internal;

        /**
     * Reference counter (internal use only).
     */
        int nref;

        /**
     * Increment the reference counter.
     *  @param  dic         The pointer to this dictionary instance.
     *  @return int         The reference count after this increment.
     */
        int (*addref)(crfsuite_dictionary_t *dic);

        /**
     * Decrement the reference counter.
     *  @param  dic         The pointer to this dictionary instance.
     *  @return int         The reference count after this operation.
     */
        int (*release)(crfsuite_dictionary_t *dic);

        /**
     * Assign and obtain the integer ID for the string.
     *  @param  dic         The pointer to this dictionary instance.
     *  @param  str         The string.
     *  @return int         The ID associated with the string if any,
     *                      the new ID otherwise.
     */
        int (*get)(crfsuite_dictionary_t *dic, const char *str);

        /**
     * Obtain the integer ID for the string.
     *  @param  dic         The pointer to this dictionary instance.
     *  @param  str         The string.
     *  @return int         The ID associated with the string if any,
     *                      \c -1 otherwise.
     */
        int (*to_id)(crfsuite_dictionary_t *dic, const char *str);

        /**
     * Obtain the string for the ID.
     *  @param  dic         The pointer to this dictionary instance.
     *  @param  id          the string ID.
     *  @param  pstr        \c *pstr points to the string associated with
     *                      the ID if any, \c NULL otherwise.
     *  @return int         \c 0 if the string ID is associated with a string,
     *                      \c 1 otherwise.
     */
        int (*to_string)(crfsuite_dictionary_t *dic, int id, char const **pstr);

        /**
     * Obtain the number of strings in the dictionary.
     *  @param  dic         The pointer to this dictionary instance.
     *  @return int         The number of strings stored in the dictionary.
     */
        int (*num)(crfsuite_dictionary_t *dic);

        /**
     * Free the memory block allocated by to_string() function.
     *  @param  dic         The pointer to this dictionary instance.
     *  @param  str         The pointer to the string whose memory block is
     *                      freed.
     */
        void (*free)(crfsuite_dictionary_t *dic, const char *str);
    };

    /**
 * CRFSuite parameter interface.
 */
    struct tag_crfsuite_params
    {
        /**
     * Pointer to the instance data (internal use only).
     */
        void *internal;

        /**
     * Reference counter (internal use only).
     */
        int nref;

        /**
     * Increment the reference counter.
     *  @param  params      The pointer to this parameter instance.
     *  @return int         The reference count after this increment.
     */
        int (*addref)(crfsuite_params_t *params);

        /**
     * Decrement the reference counter.
     *  @param  params      The pointer to this parameter instance.
     *  @return int         The reference count after this operation.
     */
        int (*release)(crfsuite_params_t *params);

        /**
     * Obtain the number of available parameters.
     *  @param  params      The pointer to this parameter instance.
     *  @return int         The number of parameters maintained by this object.
     */
        int (*num)(crfsuite_params_t *params);

        /**
     * Obtain the name of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  i           The parameter index.
     *  @param  ptr_name    *ptr_name points to the parameter name.
     *  @return int         \c 0 always.
     */
        int (*name)(crfsuite_params_t *params, int i, char **ptr_name);

        /**
     * Set a parameter value.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  value       The parameter value in string format.
     *  @return int         \c 0 if the parameter is found, \c -1 otherwise.
     */
        int (*set)(crfsuite_params_t *params, const char *name, const char *value);

        /**
     * Get a parameter value.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  ptr_value   *ptr_value presents the parameter value in string
     *                      format.
     *  @return int         \c 0 if the parameter is found, \c -1 otherwise.
     */
        int (*get)(crfsuite_params_t *params, const char *name, char **ptr_value);

        /**
     * Set an integer value of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  value       The parameter value.
     *  @return int         \c 0 if the parameter value is set successfully,
     *                      \c -1 otherwise (unknown parameter or incompatible
     *                      type).
     */
        int (*set_int)(crfsuite_params_t *params, const char *name, int value);

        /**
     * Set a float value of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  value       The parameter value.
     *  @return int         \c 0 if the parameter value is set successfully,
     *                      \c -1 otherwise (unknown parameter or incompatible
     *                      type).
     */
        int (*set_float)(crfsuite_params_t *params, const char *name, floatval_t value);

        /**
     * Set a string value of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  value       The parameter value.
     *  @return int         \c 0 if the parameter value is set successfully,
     *                      \c -1 otherwise (unknown parameter or incompatible
     *                      type).
     */
        int (*set_string)(crfsuite_params_t *params, const char *name, const char *value);

        /**
     * Get an integer value of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  ptr_value   The pointer to a variable that receives the
     *                      integer value.
     *  @return int         \c 0 if the parameter value is obtained
     *                      successfully, \c -1 otherwise (unknown parameter
     *                      or incompatible type).
     */
        int (*get_int)(crfsuite_params_t *params, const char *name, int *ptr_value);

        /**
     * Get a float value of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  ptr_value   The pointer to a variable that receives the
     *                      float value.
     *  @return int         \c 0 if the parameter value is obtained
     *                      successfully, \c -1 otherwise (unknown parameter
     *                      or incompatible type).
     */
        int (*get_float)(crfsuite_params_t *params, const char *name, floatval_t *ptr_value);

        /**
     * Get a string value of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  ptr_value   *ptr_value presents the parameter value.
     *  @return int         \c 0 if the parameter value is obtained
     *                      successfully, \c -1 otherwise (unknown parameter
     *                      or incompatible type).
     */
        int (*get_string)(crfsuite_params_t *params, const char *name, char **ptr_value);

        /**
     * Get the help message of a parameter.
     *  @param  params      The pointer to this parameter instance.
     *  @param  name        The parameter name.
     *  @param  ptr_type    The pointer to \c char* to which this function
     *                      store the type of the parameter.
     *  @param  ptr_help    The pointer to \c char* to which this function
     *                      store the help message of the parameter.
     *  @return int         \c 0 if the parameter is found, \c -1 otherwise.
     */
        int (*help)(crfsuite_params_t *params, const char *name, char **ptr_type, char **ptr_help);

        /**
     * Free the memory block of a string allocated by this object.
     *  @param  params      The pointer to this parameter instance.
     *  @param  str         The pointer to the string.
     */
        void (*free)(crfsuite_params_t *params, const char *str);
    };

    /**@}*/

    /**
 * \addtogroup crfsuite_object
 * @{
 */

    /**
 * Create an instance of an object by an interface identifier.
 *  @param  iid         The interface identifier.
 *  @param  ptr         The pointer to \c void* that points to the
 *                      instance of the object if successful,
 *                      *ptr points to \c NULL otherwise.
 *  @return int         \c 1 if this function creates an object successfully,
 *                      \c 0 otherwise. Note that this is inconsistent with the
 *                      other CRFsuite API calls.
 */
    int crfsuite_create_instance(const char *iid, void **ptr);

    /**
 * Create an instance of a model object from a model file.
 *  @param  filename    The filename of the model.
 *  @param  ptr         The pointer to \c void* that points to the
 *                      instance of the model object if successful,
 *                      *ptr points to \c NULL otherwise.
 *  @return int         \c 0 if this function creates an object successfully,
 *                      \c 1 otherwise.
 */
    int crfsuite_create_instance_from_file(const char *filename, void **ptr);

    /**
 * Create an instance of a model object from a model in memory.
 *  @param  data        A pointer to the model data.
 *                      Must be 16-byte aligned.
 *  @param  size        A size (in bytes) of the model data.
 *  @param  ptr         The pointer to \c void* that points to the
 *                      instance of the model object if successful,
 *                      *ptr points to \c NULL otherwise.
 *  @return int         \c 0 if this function creates an object successfully,
 *                      \c 1 otherwise
 */
    int crfsuite_create_instance_from_memory(const void *data, size_t size, void **ptr);

    /**
 * Create instances of tagging object from a model file.
 *  @param  filename    The filename of the model.
 *  @param  ptr_tagger  The pointer to \c void* that points to the
 *                      instance of the tagger object if successful,
 *                      *ptr points to \c NULL otherwise.
 *  @param  ptr_attrs   The pointer to \c void* that points to the
 *                      instance of the dictionary object for attributes
 *                      if successful, *ptr points to \c NULL otherwise.
 *  @param  ptr_labels  The pointer to \c void* that points to the
 *                      instance of the dictionary object for labels
 *                      if successful, *ptr points to \c NULL otherwise.
 *  @return int         \c 0 if this function creates an object successfully,
 *                      \c 1 otherwise.
 */
    int crfsuite_create_tagger(
        const char *filename,
        crfsuite_tagger_t **ptr_tagger,
        crfsuite_dictionary_t **ptr_attrs,
        crfsuite_dictionary_t **ptr_labels);

    /**@}*/

    /**
 * \addtogroup crfsuite_data
 * @{
 */

    /**
 * Initialize an attribute structure.
 *  @param  attr        The pointer to crfsuite_attribute_t.
 */
    void crfsuite_attribute_init(crfsuite_attribute_t *attr);

    /**
 * Set an attribute and its value.
 *  @param  attr        The pointer to crfsuite_attribute_t.
 *  @param  aid         The attribute identifier.
 *  @param  value       The attribute value.
 */
    void crfsuite_attribute_set(crfsuite_attribute_t *attr, int aid, floatval_t value);

    /**
 * Copy the content of an attribute structure.
 *  @param  dst         The pointer to the destination.
 *  @param  src         The pointer to the source.
 */
    void crfsuite_attribute_copy(crfsuite_attribute_t *dst, const crfsuite_attribute_t *src);

    /**
 * Swap the contents of two attribute structures.
 *  @param  x           The pointer to an attribute structure.
 *  @param  y           The pointer to another attribute structure.
 */
    void crfsuite_attribute_swap(crfsuite_attribute_t *x, crfsuite_attribute_t *y);

    /**
 * Initialize an item structure.
 *  @param  item        The pointer to crfsuite_item_t.
 */
    void crfsuite_item_init(crfsuite_item_t *item);

    /**
 * Initialize an item structure with the number of attributes.
 *  @param  item        The pointer to crfsuite_item_t.
 *  @param  num_attributes  The number of attributes.
 */
    void crfsuite_item_init_n(crfsuite_item_t *item, int num_attributes);

    /**
 * Uninitialize an item structure.
 *  @param  item        The pointer to crfsuite_item_t.
 */
    void crfsuite_item_finish(crfsuite_item_t *item);

    /**
 * Copy the content of an item structure.
 *  @param  dst         The pointer to the destination.
 *  @param  src         The pointer to the source.
 */
    void crfsuite_item_copy(crfsuite_item_t *dst, const crfsuite_item_t *src);

    /**
 * Swap the contents of two item structures.
 *  @param  x           The pointer to an item structure.
 *  @param  y           The pointer to another item structure.
 */
    void crfsuite_item_swap(crfsuite_item_t *x, crfsuite_item_t *y);

    /**
 * Append an attribute to the item structure.
 *  @param  item        The pointer to crfsuite_item_t.
 *  @param  attr        The attribute to be added to the item.
 *  @return int         \c 0 if successful, \c -1 otherwise.
 */
    int crfsuite_item_append_attribute(crfsuite_item_t *item, const crfsuite_attribute_t *attr);

    /**
 * Check whether the item has no attribute.
 *  @param  item        The pointer to crfsuite_item_t.
 *  @return int         \c 1 if the item has no attribute, \c 0 otherwise.
 */
    int crfsuite_item_empty(crfsuite_item_t *item);

    /**
 * Initialize an instance structure.
 *  @param  seq         The pointer to crfsuite_instance_t.
 */
    void crfsuite_instance_init(crfsuite_instance_t *seq);

    /**
 * Initialize an instance structure with the number of items.
 *  @param  seq         The pointer to crfsuite_instance_t.
 *  @param  num_items   The number of items.
 */
    void crfsuite_instance_init_n(crfsuite_instance_t *seq, int num_items);

    /**
 * Uninitialize an instance structure.
 *  @param  seq         The pointer to crfsuite_instance_t.
 */
    void crfsuite_instance_finish(crfsuite_instance_t *seq);

    /**
 * Copy the content of an instance structure.
 *  @param  dst         The pointer to the destination.
 *  @param  src         The pointer to the source.
 */
    void crfsuite_instance_copy(crfsuite_instance_t *dst, const crfsuite_instance_t *src);

    /**
 * Swap the contents of two instance structures.
 *  @param  x           The pointer to an instance structure.
 *  @param  y           The pointer to another instance structure.
 */
    void crfsuite_instance_swap(crfsuite_instance_t *x, crfsuite_instance_t *y);

    /**
 * Append a pair of item and label to the instance structure.
 *  @param  seq         The pointer to crfsuite_instance_t.
 *  @param  item        The item to be added to the instance.
 *  @param  label       The label to be added to the instance.
 *  @return int         \c 0 if successful, \c -1 otherwise.
 */
    int crfsuite_instance_append(crfsuite_instance_t *seq, const crfsuite_item_t *item, int label);

    /**
 * Check whether the instance has no item.
 *  @param  seq         The pointer to crfsuite_instance_t.
 *  @return int         \c 1 if the instance has no attribute, \c 0 otherwise.
 */
    int crfsuite_instance_empty(crfsuite_instance_t *seq);

    /**
 * Initialize a dataset structure.
 *  @param  data        The pointer to crfsuite_data_t.
 */
    void crfsuite_data_init(crfsuite_data_t *data);

    /**
 * Initialize a dataset structure with the number of instances.
 *  @param  data        The pointer to crfsuite_data_t.
 *  @param  n           The number of instances.
 */
    void crfsuite_data_init_n(crfsuite_data_t *data, int n);

    /**
 * Uninitialize a dataset structure.
 *  @param  data        The pointer to crfsuite_data_t.
 */
    void crfsuite_data_finish(crfsuite_data_t *data);

    /**
 * Copy the content of a dataset structure.
 *  @param  dst         The pointer to the destination.
 *  @param  src         The pointer to the source.
 */
    void crfsuite_data_copy(crfsuite_data_t *dst, const crfsuite_data_t *src);

    /**
 * Swap the contents of two dataset structures.
 *  @param  x           The pointer to a dataset structure.
 *  @param  y           The pointer to another dataset structure.
 */
    void crfsuite_data_swap(crfsuite_data_t *x, crfsuite_data_t *y);

    /**
 * Append an instance to the dataset structure.
 *  @param  data        The pointer to crfsuite_data_t.
 *  @param  inst        The instance to be added to the dataset.
 *  @return int         \c 0 if successful, \c -1 otherwise.
 */
    int crfsuite_data_append(crfsuite_data_t *data, const crfsuite_instance_t *inst);

    /**
 * Obtain the maximum length of the instances in the dataset.
 *  @param  data        The pointer to crfsuite_data_t.
 *  @return int         The maximum number of items of the instances in the
 *                      dataset.
 */
    int crfsuite_data_maxlength(crfsuite_data_t *data);

    /**
 * Obtain the total number of items in the dataset.
 *  @param  data        The pointer to crfsuite_data_t.
 *  @return int         The total number of items in the dataset.
 */
    int crfsuite_data_totalitems(crfsuite_data_t *data);

    /**@}*/

    /**
 * \addtogroup crfsuite_evaluation
 */
    /**@{*/

    /**
 * Initialize an evaluation structure.
 *  @param  eval        The pointer to crfsuite_evaluation_t.
 *  @param  n           The number of labels in the dataset.
 */
    void crfsuite_evaluation_init(crfsuite_evaluation_t *eval, int n);

    /**
 * Uninitialize an evaluation structure.
 *  @param  eval        The pointer to crfsuite_evaluation_t.
 */
    void crfsuite_evaluation_finish(crfsuite_evaluation_t *eval);

    /**
 * Reset an evaluation structure.
 *  @param  eval        The pointer to crfsuite_evaluation_t.
 */
    void crfsuite_evaluation_clear(crfsuite_evaluation_t *eval);

    /**
 * Accmulate the correctness of the predicted label sequence.
 *  @param  eval        The pointer to crfsuite_evaluation_t.
 *  @param  reference   The reference label sequence.
 *  @param  prediction  The predicted label sequence.
 *  @param  T           The length of the label sequence.
 *  @return int         \c 0 if succeeded, \c 1 otherwise.
 */
    int crfsuite_evaluation_accmulate(crfsuite_evaluation_t *eval, const int *reference, const int *prediction, int T);

    /**
 * Finalize the evaluation result.
 *  @param  eval        The pointer to crfsuite_evaluation_t.
 */
    void crfsuite_evaluation_finalize(crfsuite_evaluation_t *eval);

    /**
 * Print the evaluation result.
 *  @param  eval        The pointer to crfsuite_evaluation_t.
 *  @param  labels      The pointer to the label dictionary.
 *  @param  cbm         The callback function to receive the evaluation result.
 *  @param  user        The pointer to the user data that is forwarded to the
 *                      callback function.
 */
    void crfsuite_evaluation_output(crfsuite_evaluation_t *eval, crfsuite_dictionary_t *labels, crfsuite_logging_callback cbm, void *user);

    /**@}*/

    /** 
 * \addtogroup crfsuite_misc Miscellaneous definitions and functions
 * @{
 */

    /**
 * Increments the value of the integer variable as an atomic operation.
 *  @param  count       The pointer to the integer variable.
 *  @return             The value after this increment.
 */
    int crfsuite_interlocked_increment(int *count);

    /**
 * Decrements the value of the integer variable as an atomic operation.
 *  @param  count       The pointer to the integer variable.
 *  @return             The value after this decrement.
 */
    int crfsuite_interlocked_decrement(int *count);

    /**@}*/

    /**@}*/

    /**
@mainpage CRFsuite: a fast implementation of Conditional Random Fields (CRFs)

@section intro Introduction

This document describes information for using
<a href="http://www.chokkan.org/software/crfsuite">CRFsuite</a> from external
programs. CRFsuite provides two APIs:
- @link crfsuite_api C API @endlink: low-level and complete interface, which
  is used by the official frontend program.
- @link crfsuite_hpp_api C++/SWIG API @endlink: high-level and easy-to-use
  interface for a number of programming languages (e.g, C++ and Python),
  which is a wrapper for the C API.

*/

#ifdef __cplusplus
}
#endif /*__cplusplus*/

#endif /*__CRFSUITE_H__*/
