Skip to content
Snippets Groups Projects
Commit f08fe6c5 authored by Cyril Moineau's avatar Cyril Moineau
Browse files

Merge branch 'main' into PythonOpImpl

parents 7849d468 4feec190
No related branches found
No related tags found
1 merge request!19[OperatorImpl] Python OperatorImpl
Pipeline #33095 passed
Showing
with 1529 additions and 20 deletions
......@@ -17,6 +17,66 @@ build:ubuntu_cpp:
- build_cpp/
- install_cpp/
build:ubuntu_cpp_g++10:
stage: build
needs: []
tags:
- docker
script:
- apt install -y g++-10
- mkdir -p build_cpp
- mkdir -p install_cpp
- cd build_cpp
- export CXX=/usr/bin/g++-10
- cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON ..
- make -j4 all install
build:ubuntu_cpp_g++12:
stage: build
needs: []
tags:
- docker
script:
- apt install -y g++-12
- mkdir -p build_cpp
- mkdir -p install_cpp
- cd build_cpp
- export CXX=/usr/bin/g++-12
- cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON ..
- make -j4 all install
build:ubuntu_cpp_clang12:
stage: build
needs: []
tags:
- docker
script:
- apt install -y clang-12
- mkdir -p build_cpp
- mkdir -p install_cpp
- cd build_cpp
- export CXX=/usr/bin/clang++-12
- cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON ..
- make -j4 all install
build:ubuntu_cpp_clang15:
stage: build
needs: []
tags:
- docker
script:
- apt install -y clang-15
- mkdir -p build_cpp
- mkdir -p install_cpp
- cd build_cpp
- export CXX=/usr/bin/clang++-15
- cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON ..
- make -j4 all install
build:ubuntu_python:
stage: build
needs: []
......@@ -28,8 +88,7 @@ build:ubuntu_python:
- virtualenv venv
- source venv/bin/activate
# Numpy dependancy for unit test
- python3 -m pip install numpy
- export AIDGE_INSTALL=`pwd`/install
- python3 -m pip install -r requirements.txt
- python3 -m pip install .
artifacts:
expire_in: 1 week
......@@ -65,3 +124,31 @@ build:windows_cpp:
paths:
- build_cpp/
- install_cpp/
build:windows_python:
stage: build
needs: []
tags:
- windows
image: buildtools
before_script:
# Install Chocolatey
- Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
# Install dependencies
- choco install cmake.install --installargs '"ADD_CMAKE_TO_PATH=System"' -Y
- choco install git -Y
- choco install python -Y
# Update PATH
- $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
script:
- python -m pip install virtualenv
- virtualenv venv
- venv\Scripts\Activate.ps1
# Numpy dependancy for unit test
- python -m pip install -r requirements.txt
- python -m pip install .
artifacts:
expire_in: 1 week
paths:
- venv/
......@@ -35,8 +35,10 @@
#include "aidge/operator/GenericOperator.hpp"
#include "aidge/operator/MatMul.hpp"
#include "aidge/operator/MaxPooling.hpp"
//#include "aidge/operator/MetaOperator.hpp"
#include "aidge/operator/MetaOperator.hpp"
#include "aidge/operator/MetaOperatorDefs.hpp"
#include "aidge/operator/Operator.hpp"
#include "aidge/operator/Pad.hpp"
#include "aidge/operator/Producer.hpp"
#include "aidge/operator/ReLU.hpp"
#include "aidge/operator/Softmax.hpp"
......
......@@ -477,13 +477,14 @@ class Tensor : public Data,
if (dims().empty()) { return "{}"; }
std::string res;
std::size_t dim = 0;
std::size_t *dimVals = new std::size_t[nbDims()];
for (std::size_t i = 0; i < nbDims(); ++i) {
dimVals[i] = 0;
}
std::size_t counter = 0;
res += "{\n";
if (nbDims()>=2){
if (nbDims()>=2) {
std::size_t *dimVals = new std::size_t[nbDims()];
for (std::size_t i = 0; i < nbDims(); ++i) {
dimVals[i] = 0;
}
// std::vector<std::size_t> dimVals = std::vector<std::size_t>(nbDims(), 0);
res += "{\n";
while (counter < mSize) {
std::string spaceString = std::string((dim+1)<<1,' ');
if (dim < nbDims()-2) {
......@@ -532,31 +533,35 @@ class Tensor : public Data,
}
res += "\n";
}
if (dim == 0) {
break;
}
dimVals[dim--] = 0;
dimVals[dim]++;
}
}
for(int i = static_cast<int>(dim); i>=0; --i) {
delete[] dimVals;
for(int i = static_cast<int>(dim); i > 0; --i) {
res += std::string((dim+1)<<1,' ') + "}\n";
}
}else{
} else {
res += "{";
for (DimSize_t j = 0; j < dims()[0]; ++j) {
switch (mDataType)
{
case DataType::Int32:
res += " " + std::to_string(static_cast<int *>(mImpl->rawPtr())[j]) + ((j < dims()[0]-1) ? "," : "\n");
res += " " + std::to_string(static_cast<int *>(mImpl->rawPtr())[j]) + ((j < dims()[0]-1) ? "," : "");
break;
case DataType::Float64:
res += " " + std::to_string(static_cast<double *>(mImpl->rawPtr())[j]) + ((j < dims()[0]-1) ? "," : "\n");
res += " " + std::to_string(static_cast<double *>(mImpl->rawPtr())[j]) + ((j < dims()[0]-1) ? "," : "");
break;
default:
res += " " + std::to_string(static_cast<float *>(mImpl->rawPtr())[j]) + ((j < dims()[0]-1) ? "," : "\n");
res += " " + std::to_string(static_cast<float *>(mImpl->rawPtr())[j]) + ((j < dims()[0]-1) ? "," : "");
break;
}
}
}
res += "}";
return res;
}
......
......@@ -124,7 +124,7 @@ public:
}
/**
* @brief List dataInput connections of the GraphView object's inputNodes.
* @brief List outside dataInput connections of the GraphView object's inputNodes.
* @return std::vector<std::pair<NodePtr, IOIndex_t>>
*/
std::vector<std::pair<NodePtr, IOIndex_t>> dataInputs() const;
......@@ -137,7 +137,7 @@ public:
inline auto dataInputs(const std::string name) const { return mNodeRegistry.at(name)->dataInputs(); }
/**
* @brief List input connections of the GraphView object's inputNodes.
* @brief List outside input connections of the GraphView object's inputNodes.
* @return std::vector<std::pair<NodePtr, IOIndex_t>>
*/
std::vector<std::pair<NodePtr, IOIndex_t>> inputs() const;
......
......@@ -399,6 +399,18 @@ public:
return node->clone();
}
/**
* @brief Get the set of pointers to connected node at a distance of a delta.
* @details the recution are cut
* Return a nullptr is nofing found.
* @param delta Input delta.
* @return std::shared_ptr<Node>
*/
std::set<NodePtr> getNodeDelta(int delta,std::set<Aidge::NodePtr> nodeSee);
private:
///////////////////////////////////////////////////////
// OPERATORS
......
#ifndef AIDGE_CORE_GRAPH_FSM_INTERPRETER_H_
#define AIDGE_CORE_GRAPH_FSM_INTERPRETER_H_
#include <string>
#include <memory>
#include "aidge/utilsParsing/AstNode.hpp"
#include "aidge/graphRegex/GraphRegexTypes.hpp"
#include "aidge/graphRegex/GraphParser.hpp"
#include "aidge/graphRegex/matchFsm/FsmGraph.hpp"
namespace Aidge {
class GraphFsmInterpreter
{
private:
/* data */
GraphParser mParser;
std::size_t mActGroupe;
std::map<std::string,std::shared_ptr<ConditionalInterpreter>> mNodesCondition;
public:
GraphFsmInterpreter(const std::string graphMatchExpr,std::map<std::string,std::shared_ptr<ConditionalInterpreter>> nodesCondition);
virtual ~GraphFsmInterpreter() =default;
std::shared_ptr<FsmGraph> interpret(void);
private:
std::shared_ptr<FsmGraph> visit(std::shared_ptr<AstNode<gRegexTokenTypes>> AstTree);
/**
* @defgroup graphFsmInterpreterF Functions for interpreting AST nodes
* @brief For each node type in the AST, define how build the FsmGraph
*/
/**
* @ingroup graphFsmInterpreterF
* @brief leaf of fsm make the fsm for test one transition
*/
std::shared_ptr<FsmGraph> keyF(std::shared_ptr<AstNode<gRegexTokenTypes>> AstNode);
/**
* @ingroup graphFsmInterpreterF
* @brief combine two fsm of two expression.
*/
std::shared_ptr<FsmGraph> sepF(std::shared_ptr<FsmGraph> leftFsm,std::shared_ptr<FsmGraph> rigthFsm);
/**
* @ingroup graphFsmInterpreterF
* @brief combine two to make a new that match leftFsm next rigthFsm
*/
std::shared_ptr<FsmGraph> nextF(std::shared_ptr<FsmGraph> leftFsm,std::shared_ptr<FsmGraph> rigthFsm);
/**
* @ingroup graphFsmInterpreterF
* @brief make the fsm match +
*/
std::shared_ptr<FsmGraph> qomF(std::shared_ptr<FsmGraph> fsm);
/**
* @ingroup graphFsmInterpreterF
* @brief make the fsm match *
*/
std::shared_ptr<FsmGraph> qzmF(std::shared_ptr<FsmGraph> fsm);
};
}
#endif // AIDGE_CORE_GRAPH_FSM_INTERPRETER_H_
#ifndef AIDGE_CORE_GRAPH_LEXER_H_
#define AIDGE_CORE_GRAPH_LEXER_H_
#include <string>
#include <memory>
#include <regex>
#include <stdexcept> //error
#include <sstream>
#include "aidge/utilsParsing/ParsingToken.hpp"
#include "aidge/graphRegex/GraphRegexTypes.hpp"
namespace Aidge {
class GraphLexer
{
public:
GraphLexer( const std::string gRegexExpressions );
/**
* @brief Get the next token on the gRegexExpressions
* @return ConditionalToken
*/
std::shared_ptr<ParsingToken<gRegexTokenTypes>> getNextToken(void);
/**
* @brief Restart at the start of the gRegexExpressions
*
*/
void rstPosition(void);
/**
* @brief Test if the string is completely read
* @return bool
*/
bool isEnd(void);
/**
* @brief Get the representation of the class
* @return string
*/
const std::string rep();
private:
/**
* @brief Constructs an error message to display the character not understood by the lexer
* @return error mesage
*/
std::runtime_error badTokenError(const std::string& currentChars,std::size_t position);
/**
* @brief The expression of the test to be performed on the nodes
*/
const std::string mRegularExpressions;
/**
* @brief The lexer's current position in mConditionalExpressions
*/
std::size_t mPosition;
};
}
#endif //AIDGE_CORE_GRAPH_LEXER_H_
#ifndef AIDGE_CORE_GRAPH_PARSER_H_
#define AIDGE_CORE_GRAPH_PARSER_H_
#include <memory> // for shared_ptr
#include "aidge/graphRegex/GraphLexer.hpp"
#include "aidge/utilsParsing/AstNode.hpp"
#include "aidge/graphRegex/GraphRegexTypes.hpp"
namespace Aidge{
/**
* @brief this class uses the lexer to create an AST according to a set of gramer rules
*/
class GraphParser{
public:
/**
* @brief AST graph creation function
* @param gRegexExpressions String representing the logical fuction to be performed
*/
GraphParser(const std::string gRegexExpressions);
virtual ~GraphParser() = default;
/**
* @brief AST graph creation function
* @return The AST tree
*/
std::shared_ptr<AstNode<gRegexTokenTypes>> parse(void);
private:
/**
* @brief restart at the start of the ConditionalExpressions for LEXER and restart mCurrentToken
*/
void rstParser(void);
//////////////////
/**
* @defgroup ParsingFunctions Function for creating AST
* @brief Functions for recursive construction of the AST representing grammar rules
*/
/**
* @ingroup ParsingFunctions
* @brief Token reading and verification function
*
*/
void ackToken(gRegexTokenTypes tokenType);
//TODO TODO
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for key : KEY(QOM | QZM)? | CKEY
* @return AST node
*/
std::shared_ptr<AstNode<gRegexTokenTypes>> constructAstExp(void);
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for sequence : seq :exp (NEXT seq)*
* @return AST node
*/
std::shared_ptr<AstNode<gRegexTokenTypes>> constructAstSeq(void);
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for domain : (seq NEXT domain)? | LPAREN domain RPAREN (QOM | QZM) (NEXT domain)?
* @return AST node
*/
std::shared_ptr<AstNode<gRegexTokenTypes>> constructAstDomain(void);
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for multiple exepresion : allExpr: domain (SEP allExpr)*
* @return AST node
*/
std::shared_ptr<AstNode<gRegexTokenTypes>> constructAstAllExpr(void);
/**
* @brief The actual token in the parce
*/
std::shared_ptr<ParsingToken<gRegexTokenTypes>> mCurrentToken;
/**
* @brief The lexem use
*/
GraphLexer mLexer;
};
}
#endif //AIDGE_CORE_GRAPH_PARSER_H_
#ifndef AIDGE_CORE_GREGEX_TOKEN_TYPES_H_
#define AIDGE_CORE_GREGEX_TOKEN_TYPES_H_
namespace Aidge {
/**
* @brief enum for all types of token use in the of the regex
* 7-5 type
* 4-0 id
*/
enum class gRegexTokenTypes
{
STOP,
NEXT, /**< -> */
QOM, /**< + */
QZM, /**< * */
KEY, /**< [A-Za-z_0-9]+ */
CKEY, /**< [A-Za-z_0-9]+#[0-9]* */
SEP, /**< \( */
LPAREN, /**< \( */
RPAREN, /**< \) */
};
}
#endif //AIDGE_CORE_GREGEX_TOKEN_TYPES_H_
#ifndef AIDGE_CORE_GRAPH_FSM_INTERPRETER_H_
#define AIDGE_CORE_GRAPH_FSM_INTERPRETER_H_
#include <iostream>
#include <sstream>
#include <memory>
#include <algorithm>
#include "aidge/utilsParsing/AstNode.hpp"
#include "aidge/graphRegex/GraphRegexTypes.hpp"
#include "aidge/graphRegex/GraphParser.hpp"
#include "aidge/graphRegex/matchFsm/FsmGraph.hpp"
namespace Aidge {
class GraphStrInterpreter
{
private:
/* data */
GraphParser mParser;
std::string mToTest;
public:
GraphStrInterpreter(const std::string graphMatchExpr);
virtual ~GraphStrInterpreter() =default;
std::string interpret(void);
private:
std::string visit(std::shared_ptr<AstNode<gRegexTokenTypes>> AstTree);
};
}
#endif //AIDGE_CORE_GRAPH_FSM_INTERPRETER_H_
#ifndef AIDGE_CORE_FSM_EDGE_H_
#define AIDGE_CORE_FSM_EDGE_H_
#include <memory>
#include <set>
#include <string>
#include "aidge/nodeTester/ConditionalInterpreter.hpp"
namespace Aidge{
class FsmNode;
class FsmRunTimeContext;
struct EdgeTestResult {
bool success;
std::set<NodePtr> node;
};
/**
* @brief virtual class use test the node on the node to validate
*/
class FsmEdge: public std::enable_shared_from_this<FsmEdge>
{
private:
/**
* @brief the relative position to this test relative to all the const key
* first is common id, second is the relative position
*/
std::map<size_t,int> mRelativePos;
/**
* @brief the ptr on the source node
*/
std::shared_ptr<FsmNode> mNodeSource;
/**
* @brief the ptr on the dest node
*/
std::shared_ptr<FsmNode> mNodeDest;
/**
* @brief the weak ptr
*/
std::weak_ptr<FsmEdge> weakPtr;
public:
FsmEdge(std::shared_ptr<FsmNode>& source,std::shared_ptr<FsmNode>& dest, const std::shared_ptr<ConditionalInterpreter> toTest);
virtual ~FsmEdge(){};
FsmEdge() : weakPtr(shared_from_this()) {}
/**
* @brief test is the validation of the node, it must be defined for all types of edge
* it takes as argument an FSM traversal context and returns a set of next nodes
* @return set of next node or nullptr if not next
*/
virtual const EdgeTestResult test(const std::shared_ptr<FsmRunTimeContext> stmContext) =0;
/**
* @brief test is the egde test a common node
* @return true if is a common
*/
virtual bool isCommon(void);
/**
* @brief get the Common idx of the common test in this edge (if is a common edge)
* @return idx of the common
*/
virtual size_t getCommonIdx(void);
/**
* @brief get the relative postion to the common node deffine in this edge
* @return map
*/
const std::map<size_t,int>& getRelative(void);
/**
* @brief add new relative position
*/
void updateRelative( const std::map<size_t,int>& relativePos );
/**
* @brief get source FsmNode
* @return FsmNode
*/
std::shared_ptr<FsmNode> getSourceNode(void);
/**
* @brief set a new source to the edge
* @return FsmNode
*/
void reSetSouceNode(const std::shared_ptr<FsmNode>& newSource);
/**
* @brief get dest FsmNode
* @return FsmNode
*/
std::shared_ptr<FsmNode> getDestNode(void);
/**
* @brief set a new dest to the edge
* @return FsmNode
*/
void reSetDestNode(const std::shared_ptr<FsmNode>& newDest);
/**
* @brief propagate the edge mRelativePos to the others Edge and recalcul the relative position
*/
void propagateRelativePos(void);
/**
* @brief test to make on the node to validate
* @see ConditionalInterpreter
*/
const std::shared_ptr<ConditionalInterpreter> mToTest;
/**
* @brief update week ptr for the node, TODO best
*/
void updateWeak(void);
};
/**
* @brief class spesialisation for not commun node (node that must be match one Unique) transition
*/
class FsmEdgeUnique:public FsmEdge
{
public:
FsmEdgeUnique(std::shared_ptr<FsmNode>& source,std::shared_ptr<FsmNode>& dest, const std::shared_ptr<ConditionalInterpreter> toTest);
const EdgeTestResult test(const std::shared_ptr<FsmRunTimeContext> stmContext) override;
};
/**
* @brief class spesialisation for commun node transition
* @see FsmEdge
*/
class FsmEdgeCommon:public FsmEdge
{
private:
/**
* @brief the map that defind the ralation between the commonKey find by the lexer and a unique id use to refer to the common node
*/
static std::map<std::string,int> mCommonIdxMap;
/**
* @brief the common id test in this transition
*/
int mCommonIdx;
public:
/**
* @brief constructor commun node ,
* @details during construction,
* the node key found by the lexer is converted to a unique id and the relative positions are updated.
*/
FsmEdgeCommon(std::shared_ptr<FsmNode>& source,std::shared_ptr<FsmNode>& dest, const std::shared_ptr<ConditionalInterpreter> toTest, const std::string commonKey);
// ~FsmEdgeCommon() override {}
const EdgeTestResult test(const std::shared_ptr<FsmRunTimeContext> stmContext) override;
bool isCommon(void) override;
};
/**
* @brief class spesialisation for ref transition
* @see FsmEdge
*/
class FsmEdgeRef:public FsmEdge
{
private:
/**
* @brief the id of one common node that we use as an anchor
*/
const int mRefCommonIdx;
/**
* @brief the delta in terme of child or parent refer to the anchor
*/
const int mdeltaCommonIdx;
public:
FsmEdgeRef(std::shared_ptr<FsmNode>& source,std::shared_ptr<FsmNode>& dest, const size_t refCommonIdx,const int deltaCommonIdx);
//~FsmEdgeRef() override {}
const EdgeTestResult test(const std::shared_ptr<FsmRunTimeContext> stmContext) override;
};
/**
* @brief class spesialisation for ref empty transition
* @see FsmEdge
*/
class FsmEdgeEmpty:public FsmEdge
{
public:
FsmEdgeEmpty(std::shared_ptr<FsmNode> source,std::shared_ptr<FsmNode> dest);
//~FsmEdgeEmpty() override {}
const EdgeTestResult test(const std::shared_ptr<FsmRunTimeContext> stmContext) override;
};
////////////////////////
// FACTORY
////////////////////////
enum class FsmEdgeTypes {
EMPTY = 0,
REF,
COMMON,
UNIQUE
};
class FsmEdgeFactory {
public:
/**
* @brief factory for making edge and read the info in the lexeme of the token
* @param source source node of the edge
* @param dest Dest node of the edge
* @param type type of the edge
* @param lexeme the additional information to build the edge
* @return s prt of the edge
*/
static std::shared_ptr<FsmEdge> make(std::shared_ptr<FsmNode> source, std::shared_ptr<FsmNode> dest,
FsmEdgeTypes type,std::map<std::string, std::shared_ptr<ConditionalInterpreter>> allTest,
const std::string lexeme = "");
};
}
#endif //AIDGE_CORE_FSM_EDGE_H_
#ifndef AIDGE_CORE_FSM_GRAPH_H_
#define AIDGE_CORE_FSM_GRAPH_H_
#include <set>
#include <vector>
#include <memory>
#include <stdexcept> //error
#include "aidge/graphRegex/matchFsm/FsmNode.hpp"
#include "aidge/graphRegex/matchFsm/FsmEdge.hpp"
#include "aidge/graphRegex/matchFsm/MatchResult.hpp"
namespace Aidge{
class FsmGraph
{
private:
/**
* @brief all node origine
*/
std::set<std::size_t> mAllOrigine;
std::set<std::shared_ptr<FsmEdge>> mEdges;
public:
FsmGraph(/* args */);
virtual ~FsmGraph() = default;
std::shared_ptr<MatchResult> test(std::vector<NodePtr>& StartNodes);
const std::set<std::shared_ptr<FsmEdge>>& getEdge(void);
/**
* @brief add edge in the graph, as FsmEdge know the source and dest FsmNode these nodes are also add to the graph
*/
void addEdge(std::shared_ptr<FsmEdge>& edge);
/**
* @brief get the liste of the starting states
* @details we need to use a vector because the order of the nodes is important for start node initialization \ref test()
*/
const std::vector<std::shared_ptr<FsmNode>> getStartNodes(void);
/**
* @brief get the set of the valide states
* @return set of valide state
*/
const std::set<std::shared_ptr<FsmNode>> getValidNodes(void);
/**
* @brief get the set of all the node in the graph
* @return set of all nodes
*/
const std::set<std::shared_ptr<FsmNode>> getNodes(void);
/**
* @brief set a groupe idx for all the nodes in the graph
*/
void setGroupe(std::size_t groupeIdx);
/**
* @brief make the union beteen this graph and an input graph
* @param fsmGraph graph to union
*/
void unionG(const std::shared_ptr<FsmGraph> fsmGraph);
/**
* @brief make the union beteen this graph and an input graph and merge the valide state to the start state
* @param fsmGraph graph to merge
*/
void mergeOneStartOneValid(const std::shared_ptr< FsmGraph> fsmGraph);
/**
* @brief get the number of sub FSM
* @return number of sub Fsm
*/
std::size_t getNbSubFsm(void);
/**
* @brief increment the origine of all node in the graph
* @param incr the incrémentation value
*/
void incOrigineAllNodeBy(std::size_t incr);
private:
/**
* @brief merge tow node of the graph
* @param node
*/
void _mergeNode(std::shared_ptr<FsmNode> source,std::shared_ptr<FsmNode> dest);
};
}
#endif //AIDGE_CORE_FSM_GRAPH_H_
#ifndef AIDGE_CORE_FSM_NODE_H_
#define AIDGE_CORE_FSM_NODE_H_
#include <set>
#include <vector>
#include <memory>
//#include "graphRegex/matchFsm/FsmEdge.hpp"
//#include "graphRegex/matchFsm/FsmRunTimeContext.hpp"
namespace Aidge{
// Forward declaration of the class defined in graphRegex/matchFsm/FsmEdge.hpp
class FsmEdge;
struct EdgeTestResult;
class FsmRunTimeContext;
//------------------------------------------------------------------------------
// MAY BE IN UTILE
template <typename T>
struct lex_compare {
bool operator() (const std::weak_ptr<T> &lhs, const std::weak_ptr<T> &rhs)const {
auto lptr = lhs.lock(), rptr = rhs.lock();
if (!rptr) return false; // nothing after expired pointer
if (!lptr) return true;
return lptr < rptr;
}
};
/**
* @brief is a node in the FSM graph, it's a state in the FSM
* @details a state can be and/or :
* - a valide state, the match is valide if it stop on this edge
* - a start state , the match start on this state
* The state is also define by this origine (is the unique id of it's expretion )
* and it's groupe (for inner expression TODO)
*/
class FsmNode : public std::enable_shared_from_this<FsmNode>
{
private:
/**
* @brief the edge of the node
* @details the edge have a shared ref to the node so we use weak ref
*/
std::set<std::weak_ptr<FsmEdge>,lex_compare<FsmEdge>> mEdges;
/**
* @brief the parent of the node
*/
std::set<std::weak_ptr<FsmNode>,lex_compare<FsmNode>> mParents;
std::size_t mOrigineStm = 0;
std::size_t mGroupeStm = 0;
bool mIsAValid;
bool mIsAStart;
public:
FsmNode(bool isAValid,bool isAStart );
virtual ~FsmNode() = default;
/**
* @brief use to MAG the actual context , and return all the posible new context
* @details one input context can generate a multitude of contexts because a graph node
* can have more than one child, and each traversal possibility is a new context.
* @param actContext the actual context
* @return A vector of all the new context
*/
const std::vector<std::shared_ptr<FsmRunTimeContext>> test( std::shared_ptr<FsmRunTimeContext>);
std::size_t getOrigine(void);
void incOrigine(std::size_t inc);
void rmEdge(std::shared_ptr<FsmEdge>);
void addEdge(std::shared_ptr<FsmEdge>);
//const std::set<std::shared_ptr<FsmNode>> getChildNodes(void);
const std::set<std::weak_ptr<FsmNode>,lex_compare<FsmNode>>& getParentNodes(void);
const std::set<std::weak_ptr<FsmEdge>,lex_compare<FsmEdge>>& getEdges(void);
void setGroupe(std::size_t groupeIdx);
bool isValid(void);
bool isStart(void);
void unValid(void);
void valid(void);
void unStart(void);
void start(void);
void addParent(std::shared_ptr<FsmNode>);
void rmParent(std::shared_ptr<FsmNode>);
};
}
#endif //AIDGE_CORE_FSM_NODE_H_
#ifndef AIDGE_CORE_FSM_RUN_TIME_CONTEXT_H_
#define AIDGE_CORE_FSM_RUN_TIME_CONTEXT_H_
#include <memory>
#include <vector>
#include <set>
#include <algorithm>
#include "aidge/nodeTester/ConditionalInterpreter.hpp"
#include "aidge/graph/Node.hpp"
namespace Aidge{
class FsmNode;
class FsmNode;
/**
* @brief a class used to save the execution context of state machines, that is the actual state in the FSM, the actual node in the graph
* all node that have been Validate,Rejecte or Considered common
*/
class FsmRunTimeContext
{
private:
/**
* @brief the list of node rejected for all the context
*/
static std::vector<std::set<NodePtr>> mRejectedNodes;
/**
* @brief the actual state of this Context (where it's in the FSM graph)
*/
std::shared_ptr<FsmNode> mActState;
/**
* @brief the actual node of this Context (where it's in the graph)
*/
NodePtr mActOpNode;
/**
* @brief the map of the node consider as common and the common ID
* @details we need to store what node it's consider as common because of the end
* resolution of the matching, all node consider as common need to be the same in all context
*/
std::map<NodePtr,std::size_t> mCommonNodes;
/**
* @brief the map of the node that as been valid in this context , and the test that valide the node
*/
std::map<std::shared_ptr<ConditionalInterpreter>,std::set<NodePtr>> mValidNodes;
/**
* @brief the index in the rejected node of this context
*/
std::size_t mLocalIdxRejeced;
public:
/**
* @brief constructor
* @param actState the actual state in the FSM
* @param actOpNode the actual node in the graph
* @param idxRejeced the idx in the global regected node vector init max() as sentinel value of undefind
*/
FsmRunTimeContext(std::shared_ptr<FsmNode> actState ,NodePtr actOpNode ,std::size_t idxRejeced =std::numeric_limits<std::size_t>::max() );
FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime);
FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime,std::shared_ptr<FsmNode> actState ,NodePtr actOpNode );
virtual ~FsmRunTimeContext()=default;
/**
* @defgroup FsmRunTimeContextRejected Function for managing rejected nodes
*/
/**
* @ingroup FsmRunTimeContextRejected
* @brief Add a node as rejected in this context
*/
void addRejectedNode(NodePtr node);
/**
* @ingroup FsmRunTimeContextRejected
* @brief get the rejected nodes of this context
*/
std::set<NodePtr> getRejectedNodes(void);
/**
* @defgroup FsmRunTimeContextTest Function for test the context
*/
/**
* @ingroup FsmRunTimeContextTest
* @brief test if the actual state is valide
* @return bool
*/
bool isOnValidState(void);
/**
* @ingroup FsmRunTimeContextTest
* @brief test if the node is considered as common in this context
* @param node node to test
* @return bool
*/
bool isCommonDefined(NodePtr node);
/**
* @ingroup FsmRunTimeContextTest
* @brief test if has already validated in this context
* @param node node to test
* @return bool
*/
bool isAlreadyValid(NodePtr node);
/**
* @ingroup FsmRunTimeContextTest
* @brief test if this context is compatible with an others
* @details to say that two contexts are compatible is to check :
* that the contexts do not validate the same nodes (other than the common ones)
* and that the common ones have the same idx
* @param fsmContext the others context
* @return bool
*/
bool areCompatible(std::shared_ptr<FsmRunTimeContext> fsmContext);
/**
* @ingroup FsmRunTimeContextTest
* @brief test if this context is strictly equal with an others
* @param fsmContext the others context
* @return bool
*/
bool areEqual(std::shared_ptr<FsmRunTimeContext> fsmContext);
/**
* @defgroup FsmRunTimeContextSet Function set context
*/
void setCommon(NodePtr node,std::size_t commonIdx);
void setValid(NodePtr node,std::shared_ptr<ConditionalInterpreter> tag);
/**
* @defgroup FsmRunTimeContextGet Function get context
*/
/**
* @ingroup FsmRunTimeContextGet
* @brief get the sub idx state
* @return bool
*/
std::size_t getSubStmId(void);
NodePtr getCommonNodeFromIdx(std::size_t commonIdx);
std::size_t getCommonNodeIdx(NodePtr node);
std::set<NodePtr> getCommonNodes(void);
std::map<NodePtr,std::size_t> getCommon(void);
std::set<NodePtr> getValidNodes(void);
std::set<NodePtr> getValidNodesNoCommon(void);
std::map<std::shared_ptr<ConditionalInterpreter>,std::set<NodePtr>> getValid(void);
NodePtr getActNode(void);
std::shared_ptr<FsmNode> getActState(void);
/**
* @defgroup FsmRunTimeContextMem
*/
void rst(void);
};
}
#endif //AIDGE_CORE_FSM_RUN_TIME_CONTEXT_H_
#ifndef AIDGE_CORE_MATCH_RESULT_H_
#define AIDGE_CORE_MATCH_RESULT_H_
#include <memory>
#include <vector>
#include <map>
#include "aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp"
#include "aidge/graph/Node.hpp"
namespace Aidge{
/**
* @brief class that old the result of a matching
* give acess to all node ant there tag in the expression
*/
class MatchResult
{
private:
/* data */
std::vector<std::shared_ptr<FsmRunTimeContext>> mAllValid;
/*
the Run time of eatch sub FSM , to have a valide match we need a set of one run time per FSM compatible
the id must be contigue
*/
std::vector<std::vector<std::shared_ptr<FsmRunTimeContext>>> mIdToRunTime;
std::vector<std::set<NodePtr>> mSolve;
std::size_t mNbSubStm;
public:
MatchResult(std::vector<std::shared_ptr<FsmRunTimeContext>> allValid, std::size_t nbSubStm);
virtual ~MatchResult() = default;
/**
* @brief get the set of the node match for une expression
* @return the set of node of the graph that corresponding to an expression
*/
std::set<NodePtr> getBiggerSolution(void);
private:
/**
* @brief recurent function use to inite mSolve in the constructor
*
**/
void _generateCombinationd( std::size_t idxSubStm, std::vector<std::shared_ptr<FsmRunTimeContext>>& precedence);
};
}
#endif //AIDGE_CORE_MATCH_RESULT_H_
File moved
......@@ -31,11 +31,11 @@ protected:
public:
Hook(std::shared_ptr<Operator> op) : mOperator(op) {}
virtual ~Hook();
virtual ~Hook() = default;
virtual void call() = 0;
};
}
#endif /* Hook_H_ */
\ No newline at end of file
#endif /* Hook_H_ */
#ifndef AIDGE_CORE_CONDITIONAL_DATA_H_
#define AIDGE_CORE_CONDITIONAL_DATA_H_
#include <vector>
#include <string>
#include <stdexcept> //error
#include <memory>
#include <map>
namespace Aidge{
/////////////////////////
// The data type in AST Intepretation
////////////////////////
class BaseConditionalValue {
public:
virtual ~BaseConditionalValue() {}
};
template <typename T>
class ConditionalValue : public BaseConditionalValue {
public:
ConditionalValue(const T& data) : value(data) {}
T value;
};
struct ConditionalData {
/**
* @brief generic type to propagate all the different values in the AST interpretation
*/
//void* value;
std::unique_ptr<BaseConditionalValue> value;
const std::type_info* type =nullptr;
/////////////////////////////////
//
////////////////////////////////
/**
* @brief set a value
*/
template <typename T>
void setValue(const T& newValue) {
//make sure that the old value is free
deleteValue();
value = std::make_unique<ConditionalValue<T>>(newValue);
type = &typeid(T);
}
/**
* @brief get the actual value
* @details recaste the value to the templaited type and checks that the conversion type is compatible with type
* @tparam the type of the return value
* @return the value
*/
template <typename T>
T getValue() const {
if (type && *type == typeid(T)) {
//const Value<T>* typedValue = dynamic_cast<const Value<T>*>(static_cast<const BaseValue*>(value));
const ConditionalValue<T>* typedValue = dynamic_cast<const ConditionalValue<T>*>(value.get());
if (typedValue) {
return typedValue->value;
}
}
throw std::runtime_error(std::string("DATA ERROR ") + type->name() + " != " + typeid(T).name());
}
///////////////////////////////////
//
///////////////////////////////////
std::string getType() const {
return type ? type->name() : "nullptr";
}
template <typename T>
bool isTypeEqualTo() const {
return (type && *type == typeid(T));
}
void deleteValue() {
if (type) {
value.reset();
type = nullptr;
}
}
~ConditionalData() { // TODO best can we have a list of type supported ?
deleteValue();
}
};
}
#endif //AIDGE_CORE_CONDITIONAL_DATA_H_
#ifndef AIDGE_CORE_CONDITIONAL_INTERPRETER_H_
#define AIDGE_CORE_CONDITIONAL_INTERPRETER_H_
#include "aidge/nodeTester/ConditionalParser.hpp"
#include "aidge/nodeTester/ConditionalData.hpp"
#include <memory> // for shared_ptr
#include <unordered_map>
#include <functional>
#include "aidge/graph/Node.hpp"
#include <sstream>
namespace Aidge{
//////////////////////////////
//
/////////////////////////////
/**
* @brief class used to register any lambda function without context,
* it encapsulates the source lambda in a lambda which takes as argument ConditionalData* which are any type.
* @see ConditionalData
*/
class ConditionalRegisterFunction {
//////////////////////////
//Safe recaste
//////////////////////////
/**
* @brief recast the ConditionalData* to the argument type of the lambda
* @tparam T type of the lambda argument
* @see ConditionalData
*/
template <typename T>
T safeCastInput(ConditionalData* data) {
//cnvertion and type cheking
if (data->isTypeEqualTo<T>()){
return data->getValue<T>();
}else{
throw std::invalid_argument( "incompatible input type " + data->getType() +" "+ typeid(T).name() );
}
}
/**
* @brief recaste the output of the lambda to a ConditionalData*
* @tparam T type of the lambda return
* @see ConditionalData
*/
template <typename T>
ConditionalData* safeCastOutput(T data) {
ConditionalData* out = new ConditionalData;
out->setValue<T>(data);
return out;
}
//////////////////////
// get all the type of the function
//////////////////////
/**
* @brief Retrieves information about a function's return type and argument types.
* @tparam T The function type.
*/
template <typename T>
struct function_traits;
/**
* @brief Specialization of function_traits for function pointers.
* @tparam R The return type of the function.
* @tparam Args The argument types of the function.
*/
template <typename R, typename... Args>
struct function_traits<R (*)(Args...)> {
using return_type = R;
static constexpr std::size_t arity = sizeof...(Args);
template <std::size_t N>
struct argument {
static_assert(N < arity, "Index out of range.");
using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
};
/**
* @brief Specialization of function_traits for std::function types.
* @tparam R The return type of the function.
* @tparam Args The argument types of the function.
*/
template <typename R, typename... Args>
struct function_traits<std::function<R(Args...)>> {
using return_type = R;
static constexpr std::size_t arity = sizeof...(Args);
template <std::size_t N>
struct argument {
static_assert(N < arity, "Index out of range.");
using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
};
/////////////////////
//change the function to ConditionalData*(std::vector<ConditionalData*>)
/////////////////////
/**
* @brief Converts a function to a ConditionalData*(std::vector<ConditionalData*>).
* @tparam F The type of the function to convert.
* @tparam ParamsIdx The indices of the function parameters.
* @param f The function to convert.
* @return The pointer to the converted function.
*/
template <class F, std::size_t... ParamsIdx>
auto funcPointer(F f, std::index_sequence<ParamsIdx...>) {
//wrapp the lambda in a new one that as ConditionalData as inputs and output
return [this,f](std::vector<ConditionalData*> &args) {
if (args.size() != sizeof...(ParamsIdx)){
std::ostringstream errorMessage;
errorMessage << "bad Number of argument: get " << args.size() << " need " << sizeof...(ParamsIdx) << "\n";
throw std::runtime_error(errorMessage.str());
}
//assert(args.size() == sizeof...(ParamsIdx));//the size of the vector valide
using FuncTraits = function_traits<decltype(f)>;
using outType = typename FuncTraits::return_type;
outType result = f(safeCastInput<typename FuncTraits::template argument<ParamsIdx>::type>(args[ParamsIdx])...);
//typename
return safeCastOutput<outType>(result);
};
}
/**
* @brief Converts a function pointer to a ConditionalData*(std::vector<ConditionalData*>).
* @tparam R The return type of the function.
* @tparam Params The parameter types of the function.
* @param f The function pointer to convert.
* @return The pointer to the converted function.
*/
template <class R,class... Params>
auto funcPointer(R (*f)(Params...)) {
return funcPointer(f, std::index_sequence_for<Params...>{});
}
/**
* @brief Converts a std::function to a ConditionalData*(std::vector<ConditionalData*>).
* @tparam R The return type of the function.
* @tparam Params The parameter types of the function.
* @param f The function pointer to convert.
* @return The pointer to the converted function.
*/
template <class R,class... Params>
auto funcPointer(std::function<R(Params...)> f) {
return funcPointer(f, std::index_sequence_for<Params...>{});
}
///////////////////
// interface
///////////////////
public:
/**
* @brief Default constructor
*/
ConditionalRegisterFunction(){}
/**
* @brief Inserts a function into the map with the provided key.
* @tparam T The function type.
* @param key The key to associate with the function.
* @param f The function to insert.
*/
template <class T>
void insert(const std::string key,T f){
mWlambda.insert({ key, funcPointer(f)});
}
/**
* @brief Runs the function associated with the given key, using the provided vector of input data.
* @param key The key of the function to run.
* @param datas The vector of input data.
* @return A pointer to the output ConditionalData object.
*/
ConditionalData* run(const std::string key,std::vector<ConditionalData*> & datas);
private:
/// @brief map of name and the converted function.
std::map<const std::string, std::function<ConditionalData*(std::vector<ConditionalData*> &)>> mWlambda;
};
///////////////////
//AST tree node
// ////////////////
/**
* @brief this class interprets AST to generate a test on a graph node. For each AST node,
* it generates an interpretation and registers lambda functions that can be used in the test expression.
* there are two lambda control mechanisms:
* - A cpp mechanism which allows any lambda to be inserted into the constructor that use templaite
* - A user mechanism limited to lambda bool(NodePtr)
* @see ConditionalParser use to get the AST
*/
class ConditionalInterpreter
{
private:
/**
* @brief the AST generate by the Parser
* @see ConditionalParser
*/
std::shared_ptr<AstNode<ConditionalTokenTypes>> mTree;
/**
* @brief the registery for the lambda fuction
* @see ConditionalRegisterFunction
*/
ConditionalRegisterFunction mLambdaRegiter;
std::vector<ConditionalData*> mResolution ;
void clearRes(){
for (std::size_t i = 0; i < mResolution.size(); ++i) {
delete mResolution[i];
}
mResolution.clear();
}
public:
/**
* @brief Constructor
* @param ConditionalExpressions The expression of the test to be performed on the nodes
*/
ConditionalInterpreter(const std::string ConditionalExpressions);
~ConditionalInterpreter(){clearRes();}
/**
* @brief Test a node depending of the ConditionalExpressions
* @details the AST is visit using \ref visit() whith the $ init whit the nodeOp
* @return bool the match node has the initialized expresion
* @see visit() This function uses the visit() function to perform the evaluation.
*/
bool test( const NodePtr nodeOp);
/**
* @brief Interface for inserting custom lambda bool(NodePtr) functions in AST interpretation,
* it will be available in the ConditionalExpressions expretion as : key($)
* @param key The key that will be used to call the function in the expression
* @param f The pointer to function
*/
void insertLambda(const std::string key,std::function<bool(Aidge::NodePtr)> f);
/////
private:
/**
* @brief Recursive AST traversal function, using the for interpreting AST nodes function,
* using \ref ASTnodeInterpreterF fuctions
* @param NodeOp The node currently being tested
* @param nodes The AST given by the parsing process
*/
std::vector<ConditionalData*> visit(const ASTNodeCh& nodes, const NodePtr NodeOp );
/**
* @defgroup ASTnodeInterpreterF Functions for interpreting AST nodes
* @brief For each node type in the AST, function defines the processing to be performed
* they return a std::vector<ConditionalData*> which corresponds to the value(s) obtained
*/
/**
* @ingroup ASTnodeInterpreterF
* @brief Function that does something.
*/
void fLambda(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node);
/**
* @ingroup ASTnodeInterpreterF
* @brief Converted the lexeme to a int and to ConditionalData*
*/
void fStrToInteger(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node);
/**
* @ingroup ASTnodeInterpreterF
* @brief Converted the lexeme to a float and to ConditionalData*
*/
void fStrToFloat(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node);
/**
* @ingroup ASTnodeInterpreterF
* @brief Converted the lexeme to a str and to ConditionalData*
*/
void fStrToStr(const std::shared_ptr<AstNode<ConditionalTokenTypes>>& node);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the == operation between two previously converted ConditionalData*
*/
void fEq(void);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the != operation between two previously converted ConditionalData*
*/
void fNeq(void);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the && operation between two previously converted ConditionalData* in bool
*/
void fAnd(void);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the || operation between two previously converted ConditionalData* in bool
*/
void fOr(void);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the ! operation
*/
void fNot(void);
};
}
#endif //AIDGE_CORE_CONDITIONAL_INTERPRETER_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment