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.cpp
#include "Symbol.hpp"
#include "Binding.hpp"
#include "Bundling.hpp"
#include "AssociativeMap.hpp"
#include "algo.hpp"
#include "random.hpp"
#include "regex.hpp"
#include "Value.hpp"
#include <string.h>
#include <typeinfo>
namespace macrovsa {
//
// Global values and static methods
//
unsigned int Symbol::dimension = 0, Symbol::dimension_sqrt = 0;
std::unordered_map < std::string, Symbol::SymbolData > Symbol::datas;
Symbol::SymbolData& Symbol::getData(String name_, SymbolType symbolType)
{
static unsigned int ids = 0;
std::string name = name_ == "" ? aidesys::echo("#%d", ids) : name_;
if(datas.find(name) == datas.cend()) {
datas[name].name = name;
datas.at(name).id = ids++;
datas.at(name).symbolType = symbolType;
} else {
aidesys::alert(datas.at(name).symbolType != symbolType, "illegal-state", "in macrovsa::Symbol::Symbol incoherence in symbol type was '%s' and now '%s'", SymbolData::fromJSONTypeName(datas.at(name).symbolType), SymbolData::fromJSONTypeName(symbolType));
}
datas.at(name).count++;
return datas.at(name);
}
const char *Symbol::SymbolData::fromJSONTypeName(SymbolType symbolType)
{
return symbolType == bundling ? "bundling" : symbolType == binding ? "binding" : "atomic";
}
void Symbol::setDimension(unsigned int d)
{
dimension = d, dimension_sqrt = (int) ceil(sqrt(d));
aidesys::alert(dimension_sqrt * dimension_sqrt != dimension, " illegal-argument", "in macrovsa::Symbol::setDimension the given dimension %d != %d^2 is not a square of an integer, dimension set to %d", dimension, dimension_sqrt, dimension_sqrt * dimension_sqrt);
dimension = dimension_sqrt * dimension_sqrt;
// Uses a rule of thum
double g = 1024 * (d < 100 ? 1 : (6 * log(d) / log(10) - 11));
algo::sigma_0 = pow(g * d, -1), algo::sigma_04 = pow(algo::sigma_0, 0.25);
for(auto it = datas.begin(); it != datas.end(); it++) {
if(it->second.vector != NULL) {
delete[] it->second.vector;
it->second.vector = NULL;
}
}
}
bool Symbol::initDimension()
{
setDimension();
return true;
}
bool Symbol::initDimensionDone = Symbol::initDimension();
//
// Symbol instance methods
//
Symbol::Symbol(String name, double tau, double sigma, SymbolType symbolType) : data(getData(name, symbolType)), belief(tau, sigma)
{}
Symbol::~Symbol()
{
data.count--;
if(data.count == 0) {
delete[] data.vector;
data.vector = NULL;
}
delete[] vector;
vector = NULL;
}
void Symbol::setBelief(double tau, double sigma)
{
const double EPSILON = 1e-12;
sigma = fabs(sigma) < EPSILON ? 0 : sigma;
aidesys::alert(sigma < 0, "illegal-argument", "in macrovsa::Symbol::setBelief(%f, %e) we must have sigma >= 0", tau, sigma);
belief.tau = tau, belief.sigma = sigma;
}
const double *Symbol::getVector() const
{
// Creates once the data vector unless the symbol is mutable and has been changed
if(data.vector == NULL || (data.symbolType == bundling && dynamic_cast < const Bundling& > (*this).values_changed)) {
delete[] data.vector;
data.vector = new double[dimension];
const_cast < Symbol * > (this)->setVector(data.vector);
if(data.symbolType == bundling) {
const_cast < Bundling & > (dynamic_cast < const Bundling& > (*this)).values_changed = false;
}
}
// Adjusts the vector magnitude if required
// This is recomputed each time because tau is mutable
if(belief.tau != 1) {
delete[] vector;
vector = new double[dimension];
for(unsigned int i = 0; i < dimension; i++) {
vector[i] = belief.tau * data.vector[i];
}
return vector;
} else {
delete[] vector;
vector = NULL;
return data.vector;
}
}
void Symbol::setVector(double *vector) const
{
double m = 0;
for(unsigned int i = 0; i < dimension; i++) {
vector[i] = aidesys::random('n'), m += vector[i] * vector[i];
}
if(m > 0) {
m = sqrt(m);
for(unsigned int i = 0; i < dimension; i++) {
vector[i] /= m;
}
}
}
std::string Symbol::asString() const
{
aidesys::alert(data.symbolType == bundling || data.symbolType == binding, "illegal-state", "in macrovsa::Symbol::asString() '%s' stringify as a symbol while with a type %s", data.name.c_str(), SymbolData::fromJSONTypeName(data.symbolType));
return data.name + asStringTail();
}
std::string Symbol::asStringTail() const
{
return belief.tau == 1 && belief.sigma == 0 ? "" : "_<" + belief.asString() + ">";
}
bool Symbol::equals(const Symbol& symbol, char what) const
{
return data.id == symbol.data.id &&
(what == 'c' ||
(fabs(belief.tau - symbol.belief.tau) <= 2 * (algo::sigma_0 + belief.sigma + symbol.belief.sigma)));
}
Symbol Symbol::nill("", 0, 0);
// Symbols remamence management
void Symbol::Symbols::clear()
{
for(auto it = values.cbegin(); it != values.cend(); it++) {
delete *it;
}
values.clear();
}
std::string Symbol::Symbols::asString() const
{
std::string string = "[";
for(auto it = values.cbegin(); it != values.cend(); it++) {
string += (*it)->asString() + " ";
}
return string + "]";
}
Symbol *Symbol::clone(const Symbol& symbol, double tau, double sigma)
{
switch(symbol.data.symbolType) {
case binding:
return new Binding(dynamic_cast < const Binding& > (symbol));
case bundling:
return new Bundling(dynamic_cast < const Bundling& > (symbol));
case associativemap:
return new AssociativeMap(dynamic_cast < const AssociativeMap& > (symbol));
default: // atomic
return new Symbol(symbol, tau, sigma);
}
}
Symbol *Symbol::clone(const Symbol& symbol, double tau, double sigma, Symbols& symbols)
{
Symbol *result = clone(symbol, tau, sigma);
symbols.add(result);
return result;
}
Symbol& Symbol::fromJSON(JSON symbol)
{
static Symbols symbols;
if(symbol.isArray()) {
Bundling b;
for(unsigned int i = 0; i < symbol.length(); i++) {
Symbol& s = fromJSON(symbol.at(i));
b.add(s);
}
return *clone(b, symbols);
} else if(symbol.isRecord()) {
if(symbol.isMember("x") && symbol.isMember("y")) {
Binding b(fromJSON (symbol.at("y")), fromJSON (symbol.at("x")), !symbol.get("u", false));
return *clone(b, symbols);
} else if(symbol.isMember("name")) {
Symbol s(symbol.get("name", ""), symbol.get("tau", 1.0), symbol.get("sigma", 0.0));
return *clone(s, symbols);
}
}
Symbol s(symbol.asString());
return *clone(s, symbols);
}
Symbol& Symbol::fromJSON(String symbol)
{
return fromJSON(wjson::string2json(symbol));
}
Symbol& Symbol::fromJSON(const char *symbol)
{
return fromJSON(wjson::string2json(symbol));
}
std::string Symbol::toJSON(const Symbol& symbol)
{
switch(symbol.data.symbolType) {
case bundling:
{
const Bundling& s = dynamic_cast < const Bundling& > (symbol);
std::string result = "[";
for(auto it = s.get().cbegin(); it != s.get().cend(); it++) {
result += " " + toJSON(*(it->second));
}
return result + " ]";
}
case binding:
{
const Binding& s = dynamic_cast < const Binding& > (symbol);
return (std::string) "{" + (s.b() ? "b" : "u") + " y: " + toJSON(s.y()) + " x: " + toJSON(s.y()) + "}";
}
default: // atomic
return aidesys::echo("{ name: " + symbol.getName() + " tau: %g sigma: %g}", symbol.belief.tau, symbol.belief.sigma);
}
}
void Symbol::dump()
{
fprintf(stderr, "{ Symbol data:\n");
for(auto it = datas.begin(); it != datas.end(); it++) {
fprintf(stderr, " { name: '%s' id: %d count: %d type: %s with_vector: %d }\n", it->first.c_str(), it->second.id, it->second.count, SymbolData::fromJSONTypeName(it->second.symbolType), it->second.vector != NULL);
}
fprintf(stderr, "}\n");
}
}
