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
Rules.hpp
#ifndef __macrovsa_Rules__
#define __macrovsa_Rules__
#include "Rule.hpp"
#include <vector>
namespace macrovsa {
/**
* @class Rules
* @description Implements a VSA based inference mechanism.
* - Inference rules are typically defined using such macro construction:
*```
* class MyRules: public Rules {
* public:
* MyRules() : Rules() {
* // ClassInheritance
* Rule_2(rdfs9_,
* // getTau()
* return algo::conj(algo::sim(predicate_1, "rdf::type"), algo::sim(object_1, subject_2), algo::sim(predicate_2, "rdfs:subClassOf"));,
* // setOutput() : please note that *subject_1 and other triple references are pointer prefixed with '*'
* output.add(*subject_1, tau, "rdfs:type", *object_2);
* );
* ../.. // Here defining other rules in Rules() constructor.
* }
* } myRules;
* ```
* where `Rule_1`, `Rule_2` and `Rule_3` allows to specifies rules of arity 1, 2 ou 3, with as syntax of the form:
* ```
* Rule_i(ruleName, getTau_return_expression, setOutput_add_instruction);
* ```
* @param {uint} [maximalDepth=0] Maximal number of recursion,
* - i.e.,of reintroducing produced rule output as incoming input, 0 means unbounded.
* @param {String} [trace="ado"] Defines the inference trace log, using a combination of chars.
* - 'a' : Dumps applied valid rules application.
* - 'u' : Dumps unapplied invalid rules application.
* - 'd' : Dumps the depth value when starting the inference.
* - 'i' : Dumps incoming triples before each recursion step.
* - 'o' : Dumps output triples produces a each recursion step.
* @param {String} [traceOutput="stdout"] defines the trace target:
* - "stdout": The stdout during the inference mechanism.
* - filename : A `filename.log` file saves at the end of the inference mechanism.
*/
class Rules {
// Non assignable
Rules(Rule const& rules) = delete;
Rules& operator = (const Rules&) = delete;
//
std::vector < Rule * > rules;
unsigned int maximalDepth = 0;
std::string trace, traceOutput, traceBuffer;
public:
Rules(unsigned int maximalDepth = 0, String trace = "ado", String traceOutput = "stdout");
virtual ~Rules();
/**
* @function add
* @memberof Rules
* @instance
* @description Adds a new rule to the mechanism.
* - A typical manual construction of a rule is of the form:
* ```
* class MyRule: public Rule {
* public:
* // Defines the rule name and arity
* MyRule() : Rule("name", arity) {}
* // Implements the proper tau calculation mechanism.
* virtual Belief getTau(const Symbol& subject_1, const Symbol& predicate_1, const Symbol& object_1, const Symbol& subject_2, const Symbol& predicate_2, const Symbol& object_2) {
* return ../..
* }
* // Implements the proper triple generation mechanism.
* void setOutput(RelationalMap& output) {
* output.add( ../..
* }
* };
* static MyRule myRule;
* rules.add(myRule);
* ```
* @param {Rule} rule The rule to add.
* - Since a pointer to the rule is stored, the rule must never be deleted, e.g. a static variable.
*/
void add(Rule& rule);
/**
* @function isDifferent
* @memberof Rules
* @instance
* @description Checks if two triples are distinguishable.
* - This method is to be overloaded to implement a specific difference criterion.
* - The default implementations calculates the conjunction:
* <p> `(subject_1 . subject_2) ^ (predicate_1 . predicate_2) ^ (object_1 . object_2)`</p>
* and considers the triples as different if `tau < sigma` for the obtained belief.
* - Then, it considers the system as incremental and if not different,
* checks if the 1st triplet brings more information,
* i.e. if `tau_1 > tau_2 + 2 sigma`, `tau_i` being the product of the triple elements tau values..
* @param {Symbol} subject_1 The 1st triple subject.
* @param {Symbol} predicate_1 The 1st triple predicate.
* @param {Symbol} object_1 The 1st triple object.
* @param {Symbol} subject_2 The 2nd triple subject.
* @param {Symbol} predicate_2 The 2nd triple predicate.
* @param {Symbol} object_2 The 2nd triple object.
* @return {bool} Returns true if the two triples are distinguishable, or if the 1st triplet brings more information.
*/
virtual bool isDifferent(const Symbol& subject_1, const Symbol& predicate_1, const Symbol& object_1, const Symbol& subject_2, const Symbol& predicate_2, const Symbol& object_2);
/**
* @function apply
* @memberof Rules
* @instance
* @description Applies recursively the rules on a set of incoming triples given a set of reference triples.
* - The relational map reference is enriched by the incoming triples and all their infered consequences.
* @param {RelationalMap} triples A relational map reference with triples for rule application with the given triple.
* @param {RelationalMap} incoming A relational map reference with triples incoming the inference mechanism.
*/
void apply(RelationalMap& triples, const RelationalMap& incoming, unsigned int depth = 0);
private:
friend class Rule;
// Applies once the rules on an incoming set of triples given reference triples set and sets the output.
// Detects if a triple is not already in a triple store.
bool isDifferent(const Symbol& subject_1, const Symbol& predicate_1, const Symbol& object_1, const RelationalMap& triples);
// Applies once the rules on all incoming triples
/*
* @param {RelationalMap} output A relation map reference where to output the infered triples if the rule is valid.
* @param {RelationalMap} input A relation map reference with triples for rule application with the given triple.
* @param {RelationalMap} incoming A relation map reference with incoming triples.
*/
void applyOnce(RelationalMap& output, const RelationalMap& input, const RelationalMap& incoming);
// This allows to trace the mechanism
void dump(String string, char what);
private:
unsigned int const maxTraceLenght = 1000000;
unsigned int traceLenght = 0;
};
}
// Macro for convinient definitions
#define Rule_1(NAME, TAU, OUTPUT) \
class NAME:public Rule { \
public: \
NAME() : Rule(#NAME, 1) {} \
virtual Belief getTau(const Symbol& subject_1, const Symbol& predicate_1, const Symbol& object_1) { TAU } \
virtual void setOutput(RelationalMap & output) { OUTPUT } \
}; { static NAME rule; add(rule); }
#define Rule_2(NAME, TAU, OUTPUT) \
class NAME:public Rule { \
public: \
NAME() : Rule(#NAME, 2) {} \
virtual Belief getTau(const Symbol& subject_1, const Symbol& predicate_1, const Symbol& object_1, const Symbol& subject_2, const Symbol& predicate_2, const Symbol& object_2) { TAU } \
virtual void setOutput(RelationalMap & output) { OUTPUT } \
}; { static NAME rule; add(rule); }
#define Rule_3(NAME, TAU, OUTPUT) \
class NAME:public Rule { \
public: \
NAME() : Rule(#NAME, 3) {} \
virtual Belief getTau(const Symbol& subject_1, const Symbol& predicate_1, const Symbol& object_1, const Symbol& subject_2, const Symbol& predicate_2, const Symbol& object_2, const Symbol& subject_3, const Symbol& predicate_3, const Symbol& object_3) { TAU } \
virtual void setOutput(RelationalMap & output) { OUTPUT } \
}; { static NAME rule; add(rule); }
#endif
