https://gitlab.inria.fr/line/aide-group/macrovsa
Tip revision: 31a87d848f8ab28a06ccf77d0b359fc966974138 authored by vthierry on 15 December 2025, 21:31:50 UTC
sync from makefile
sync from makefile
Tip revision: 31a87d8
Symbol.hpp
#ifndef __macrovsa_Symbol__
#define __macrovsa_Symbol__
#include "Value.hpp"
#include "Belief.hpp"
#include <map>
#include <vector>
namespace macrovsa {
/**
* @class Symbol
* @description Creates a macroscopic ersatz of a VSA symbol.
* - For convenience the constructs
* - `Symbol(String name, double tau, double sigma)`
* - `Symbol(String name, const Belief& belief)`
* - Note: a symbol can not be copied, use the [clone()](Symbol.html/#.clone) method instead.
* @param {String|Symbol} [name] The symbol name.
* - If omitted, the name is set to `#id` where `id` is an automatic unique number, see getID().
* - If given as a symbol, the symbol name is used.
* @param {double} [tau=1] The symbol degree of belief.
* @param {double} [sigma=0] The symbol standard-deviation of the related level of noise.
*/
class Symbol {
// Non assignable
Symbol& operator = (const Symbol&) = delete;
protected:
//
// The VSA space dimension, default value is `d=10000`.
static unsigned int dimension, dimension_sqrt;
//
// Symbol shared data
//
// Symbol dynamic type (avoiding heavy dynamic_cast<T> tricks)
public:
enum SymbolType { atomic, binding, bundling, associativemap };
protected:
#ifndef SWIG
// The symbol's common information
struct SymbolData {
// Symbol human readable name
// - Anonymous symbol with no human readable name are named `#index`
std::string name;
// Symbol identifier, two symbols with the same ID are equal, possibly with different belief level.
unsigned int id = -1;
// Symbol type
SymbolType symbolType = atomic;
// Symbol instance count
mutable unsigned int count = 0;
// Symbol vector if any, the vector is calculated without taking the belief into account, thus for belief.tau = 1
mutable double *vector = NULL;
// Returns the symbolType as a string
static const char *fromJSONTypeName(SymbolType symbolType);
};
static std::unordered_map < std::string, SymbolData > datas;
//
// Symbol data: all symbol data but the belief
//
const SymbolData& data;
// Initializes a symbol data
static SymbolData& getData(String name, SymbolType symbolType);
#endif
//
// Mesoscopic elements
//
// Implements the vector mesoscopic calculation
// - By contract the setVector edits vector[dimension] already defined before used
// - If a symbol macroscopic value is changed or if the dimension is changed the value is cleared
virtual void setVector(double *vector) const;
mutable double *vector = NULL;
public:
Symbol(String name, double tau, double sigma, SymbolType symbolType = atomic);
Symbol(String name, const Belief& belief, SymbolType symbolType = atomic) : Symbol(name, belief.tau, belief.sigma, symbolType) {}
Symbol(String name, SymbolType symbolType = atomic) : Symbol(name, 1, 0, symbolType) {}
Symbol(double tau, double sigma, SymbolType symbolType = atomic) : Symbol("", tau, sigma, symbolType) {}
Symbol(const Belief& belief, SymbolType symbolType = atomic) : Symbol("", belief.tau, belief.sigma, symbolType) {}
Symbol(SymbolType symbolType = atomic) : Symbol("", 1, 0, symbolType) {}
Symbol(const Symbol& symbol) : Symbol(symbol.data.name, symbol.belief.tau, symbol.belief.sigma, symbol.data.symbolType) {}
Symbol(const Symbol& symbol, double tau, double sigma, SymbolType symbolType = atomic) : Symbol(symbol.data.name, symbol.belief.tau * tau, symbol.belief.sigma + sigma, symbolType) {}
Symbol(const Symbol& symbol, const Belief& belief, SymbolType symbolType = atomic) : Symbol(symbol, belief.tau, belief.sigma, symbolType) {}
virtual ~Symbol();
/**
* @function getName
* @memberof Symbol
* @instance
* @description Returns the symbol name.
* @return {String} The read-only symbol name value.
*/
String getName() const
{
return data.name;
}
/**
* @function getID
* @memberof Symbol
* @instance
* @description Returns the symbol ID.
* - This ID is a unique number for a given symbol.
* - Two atomic symbols with the same ID are equal, possibly with different belief level.
* - This does not apply to non atomic symbols: binding or bundling.
* @return {uint} The read-only symbol id value.
*/
unsigned int getID() const
{
return data.id;
}
/**
* @function getType
* @memberof Symbol
* @instance
* @description Returns the symbol type.
* @return {SymbolType} Either `Symbol::SymbolType::atomic`, `Symbol::SymbolType::binding`, or `Symbol::SymbolType::bundling`.
*/
SymbolType getType() const
{
return data.symbolType;
}
/**
* @function getVector
* @memberof Symbol
* @instance
* @description Returns a randomly drawn unary vector coresponding to this symbol.
* @return {Array} The `double[]` read-only symbol vector value.
*/
const double *getVector() const;
/**
* @function getBelief()
* @memberof Symbol
* @instance
* @return The degree of belief
* - `tau` between -1 (false), 0 (unknown) and true (1), 1 by default and
* - `sigma` the standard-deviation of the related level of noise, 0 by default.
*/
virtual const Belief& getBelief() const
{
return belief;
}
/**
* @function setBelief()
* @memberof Symbol
* @instance
* @param {Belief} belief The degree of belief, the `setBelief(tau, sigma)` is also available.
*/
void setBelief(const Belief& belief)
{
setBelief(belief.tau, belief.sigma);
}
virtual void setBelief(double tau = 1, double sigma = 0);
private:
Belief belief;
public:
/**
* @function equals
* @memberof Symbol
* @instance
* @description Tests if two symbol are indistiguishable.
* - Two symbols are ``colinear´´ if they have the same corresponds to the same vector, up to the magnitude.
* - Two symbols are ``indistiguishable´´ if colinear and with the same belief, up to some precision:
* <br>`|tau - symbol.tau| < 2 |[sigma_0](algo.html#.sigma_0) + sigma + symbol.sigma|
* - The `==` C++ operator corresponds to indistiguishable.
* @param {Symbol} symbol The symbol to compare with this one.
* @param {char} [what = 'i'] either 'c' for colinear or 'i' for indistiguishable
* @return {bool} True if equal, false otherwise.
*/
virtual bool equals(const Symbol& symbol, char what = 'i') const;
#ifndef SWIG
bool operator == (const Symbol& value) const {
return equals(value);
}
#endif
/**
* @function asString
* @memberof Symbol
* @instance
* @description Returns the value as a string.
* @return {String} A string of the form `name<tau+-sigma>`:
* - omitting the belief if `tau=1, sigma=0`,
* - adding the `_type` if it is an unexpected `_bundling` or a `_binding` symbol.
*/
virtual std::string asString() const;
// Returns the asString() tail with the belief <tau+-sigma>
std::string asStringTail() const;
// Cast mechanisms
operator std::string() const { return asString() ; }
operator const char* () const { return asString().c_str(); }
/**
* @member {Symbol} nill
* @memberof Symbol
* @static
* @description The `nill` symbol, with the empty string as name, with `tau=0`.
*/
static Symbol nill;
/**
* @function getDimension
* @memberof Symbol
* @static
* @description Returns the underlying VSA space dimension.
* @return {uint} The VSA space dimension, default value is `d=10000`.
*/
static unsigned int getDimension()
{
return dimension;
}
/**
* @function setDimension
* @memberof Symbol
* @static
* @description Changes the underlying VSA space dimension.
* - All computed values are reseted.
* @param {uint} [d=10000] The new VSA space dimension. It must be a square of an integer.
*/
static void setDimension(unsigned int d = 10000);
private:
// Mechanims to init the dimension at program start
static bool initDimension();
static bool initDimensionDone;
public:
/**
* @function clone
* @memberof Symbol
* @static
* @description Properly clone a atomic, binding or bundling symbol, possibly with a different belief.
* - The created symbol is available until program end.
* - The `clone(const Symbol& symbol, const Belief& belief)` form is also available.
* @param {Symbol} symbol The symbol to compare with this one.
* @param {double} [tau=1] The symbol degree of belief.
* @param {double} [sigma=0] The symbol standard-deviation of the related level of noise.
* @return {Symbol} A pointer to the new symbol to be deleted after use.
*/
static Symbol *clone(const Symbol& symbol, double tau = 1, double sigma = 0);
static Symbol *clone(const Symbol& symbol, const Belief& belief)
{
return clone(symbol, belief.tau, belief.sigma);
}
#ifndef SWIG
// Register symbols to clean them at program end, for internal use
class Symbols {
public:
std::vector < Symbol * > values;
void add(Symbol *symbol)
{
values.push_back(symbol);
}
void clear(); // All symbol are deleted it is the user responsability not to reuse them again.
~Symbols() {
clear();
}
std::string asString() const;
};
static Symbol *clone(const Symbol& symbol, double tau, double sigma, Symbols& symbols);
static Symbol *clone(const Symbol& symbol, double tau, Symbols& symbols)
{
return clone(symbol, tau, 0, symbols);
}
static Symbol *clone(const Symbol& symbol, Symbols& symbols)
{
return clone(symbol, 1, 0, symbols);
}
static Symbol *clone(const Symbol& symbol, const Belief& belief, Symbols& symbols)
{
return clone(symbol, belief.tau, belief.sigma, symbols);
}
#endif
/**
* @function fromJSON
* @memberof Symbol
* @static
* @description Parses a weak json string to generate a symbol.
* - In order to input expression we use the usual [JSON](https://www.json.org) syntax in a [weak form](https://line.gitlabpages.inria.fr/aide-group/wjson), namely:
* - Bundlings are represented by lists: <br/> `[symbol_1 ...]`.
* - Bindings are represented by the construct: <br/> `{b y: symbol x: symbol }`, <br/> where `b` stands for binding and is replaced by `u` for unbinding.
* - Atomic symbols are represented by the construct: <br/> `{ name: symbol-name tau: tau-value sigma: tau-value }, <br/> `tau` and `sigma` being optional, while atomic symbols with `tau=1` and `sigma=0` are also represented by strings.
* @param {JSON|string} symbol The weak json string to parse.
* @return {Symbol} A reference to the built symbol.
* - The built symbol is editable and remanent, i.e., available until program end.
*/
static Symbol& fromJSON(JSON symbol);
static Symbol& fromJSON(String symbol);
static Symbol& fromJSON(const char *symbol);
/**
* @function toJSON
* @memberof Symbol
* @static
* @description Returns a symbol using the weak JSON syntax of the [fromJSON](.#fromJSON).
* @param {Symbol} symbol The symbol to encode in JSON.
* @return {string} The weak JSON syntax output.
*/
static std::string toJSON(const Symbol& symbol);
/**
* @function dump
* @memberof Symbol
* @static
* @description Prints on stdout, for debugging and statistics purposes, global informations on symbol data.
*/
static void dump();
};
}
#ifndef SWIG
// Defines a hash function to use Symbol in unordered_map container
template < > struct std::hash < macrovsa::Symbol > {
size_t operator()(const macrovsa::Symbol & value) const {
return std::hash < std::string > {}
(value.asString());
}
};
#endif
#endif
