/*---------------------------------------------------------*
 *
 * File : signa.h
 * Author : NTM
 * Created : 30/09/03
 *
 *
 * Copyright (C) Nicolas Thierry-Mieg, 2006.
 *
 *
 * This file is part of InterPool, written by 
 * Nicolas Thierry-Mieg (CNRS, France) Nicolas.Thierry-Mieg@imag.fr
 *
 * InterPool 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.
 *
 * InterPool 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 InterPool; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *----------------------------------------------------------*/

#ifndef _signa_h_
#define _signa_h_

#include "types.h" /* MOT */

/*!
  \file signa.h
  \brief This file holds the signature datatype, which is used 
  to represent both observations and interpretations.


  Signature Data Structure <br>
  a signature is:
  - an int, nbPools (number of pools)
  - a vector of ints of size nbPools, holding the value of each pool.

  If the sig is an interpretation, there are only 2 possible values
  for each pool:
  - SIG_NEG -> negative interpretation,
  - SIG_POS -> positive interpretation.

  If the sig is an observation, we currently allow up to 4 discrete
  observation levels (see InterPool paper, in prep): NEG and FAINT have
  negative canonical interpetations, and WEAK and POS have positive
  canonical interpretations. In addition, for each level 2 possible
  sig values may be used, indicating whether a value is conflicting or not.
  Each function manipulating observations should say whether they are
  "enriched": this means that conflicts are identified/tagged. Otherwise
  the sig shouldn't hold any SIG_xxxCONF values but conflicts may still 
  be present. In other words, values SIG_POS, SIG_WEAK, SIG_FAINT and SIG_NEG 
  do not have the "(and does not conflict)" meaning in non-enriched observations.

  Conflicts are defined as follows:
  - if each variable in a pos pool occurs in at least one negative pool, then
  this pos pool is conflicting; otherwise this pos pool is not conflicting;
  - if a neg pool contains at least one variable which appears in a conflicting pos
  pool, then that neg pool is conflicting; otherwise that neg pool is not conflicting.

  Current acceptable values are:
  - SIG_NEG -> pool is negative (and non-conflicting in enriched sigs)
  - SIG_NEGCONF -> pool is negative and conflicting
  - SIG_FAINT -> pool is faint (NEG canonical interpretation)
  - SIG_FAINTCONF -> pool is faint (negative) and conflicting
  - SIG_WEAK -> pool is weak (POS canonical interpretation)
  - SIG_WEAKCONF -> pool is weak (positive) and conflicting
  - SIG_POS -> pool is strongly positive
  - SIG_POSCONF -> pool is stringly positive and conflicting
  
  The real values used are defined in macros here.
  Always use the symbolic names, not the values!
  

  Simulated observations are built using buildObservation.
  Real observations are read from a file with readSig.
  
  A signature vector can also be copied to a fresh vector using copysig,
  which also allocates memory. In this case subsequent calls to setsigvalue
  should be used to modify the copied (observed) signature.
*/

/* define signature values */
/* CAVEAT: if SIG_NEG is changed, some code must also be changed! eg, in 
   buildObservation the signature is initialized to 00 with memset, 
   expecting SIG_NEG to be 00... Same thing in fillSigRandom from entropy.c
   If possible don't change this value, just use other non-zero values if needed */

#define SIG_NEG 0 /*!< negative (non-conflicting) pools. */
#define SIG_NEGCONF 100 /*!< negative conflicting pools.*/
#define SIG_FAINT 1 /*!< faint (non-conflicting) pools.*/
#define SIG_FAINTCONF 101 /*!< faint conflicting pools.*/
#define SIG_WEAK 10 /*!< weak (non-conflicting) pools.*/
#define SIG_WEAKCONF 110 /*!< weak conflicting pools.*/
#define SIG_POS 11 /*!< positive (non-conflicting) pools.*/
#define SIG_POSCONF 111 /*!< positive conflicting pools.*/


/*!
  \brief Datatype to store a signature.
*/
typedef struct
{
  int nbPools ; /*!< number of pools */
  int* sig ; /*!< signature vector, size nbPools */
} signature ;


/********************************************************************* 
   low-level primitives 
**********************************************************************/


/*!
  \brief Allocate memory for a new signature with nbPools pools,
  and initialize content with all pools being SIG_NEG.
*/
signature* allocSig(int nbPools) ;

/*!
  \brief Returns the value of the pool of absolute number abspoolnum
  in the signature mySig.
*/
int getsigvalue(const signature* mySig, int abspoolnum) ;

/*!
  \brief Set the signature value of pool of absolute number
  abspoolnum to value.
*/
void setsigvalue(signature* mySig, int abspoolnum, int value) ;

/*!
  \brief Return a copy of mySig in a freshly allocated memory area.
*/
signature* copysig(signature* mySig) ;

/*!
  \brief Return a new sig holding the canonical interpretation
  of myObservation, ie change SIG_WEAK to SIG_POS and SIG_FAINT
  to SIG_NEG. myObservation should be non-enriched, ie no SIG_xxCONF.
*/
signature* canonicalInterp(signature* myObservation) ;

/*!
  \brief Test if sig1 and sig2 are equal. Return TRUE if they are, FALSE if not.
*/
bool equalSigs(signature* sig1, signature* sig2) ;

/*!
  \brief Free all memory for mySig, ie: 
  - the sig vector,
  - the mySig area itself.
*/
void freeSig(signature* mySig) ;



/********************************************************************* 
   setOfSigs datatype
**********************************************************************/

/*! 
  \brief Datatype to store a set of signatures.

  A set of signatures, along with the number of sigs in the set
  and the distance between these sigs and the observed sig.<br>
  To access signature i (where i < nbOfSigs), use allSigs[i].<br>
  distance is useful because this type is typically used as
  the return type of solvexp* functions: we return all nearest
  coherent signatures (hence they are equidistant to the observed sig).

  This type can remain unchanged as long as signatures remain int*'s:<br>
  We can add or change the meaning of sig values, but if
  signa.[hc] gets completely revamped and the structure of sigs
  completely change, this will have to change too...

  To add a signature to a setOfSigs, use addSigToSet.
  When freeing a setOfSigs, use freeSetOfSigs.
*/
typedef struct
{
  int nbOfSigs; /*!< number of signatures */
  int distance; /*!< distance between the sigs and the observed sig */
  signature** allSigs; /*!< vector of pointers to sigs. 
			 allSigs[i] is a pointer to sig i, for i < nbOfSigs */
} setOfSigs;

/*! 
  \brief create and return an empty setOfSigs.
 */
setOfSigs buildEmptySetOfSigs(void) ;


/*!
  \brief Add newSig to mySigs, i.e.:
  - increment nbOfSigs,
  - realloc allSigs so that it has room for an extra signature**, and
  - set this new pointer so that it holds the new signature* 
  (ie mySigs->allSigs[mySigs->nbOfSigs-1] = newSig). <br>
  NOTE: This function doesn't touch mySigs->distance. Set it 
  by hand yourself!
  CAVEAT: content of newSig is not copied: if you call this function do
  NOT freeSig(newSig)!
*/
void addSigToSet(setOfSigs* mySigs, signature* newSig) ;


/*!
  \brief Free all the memory pointed to in mySigs (ie, free 
  each sig from allSigs, then also free the allSigs space itself).
*/
void freeSetOfSigs(setOfSigs mySigs) ;



#endif
