diff --git a/.hooks/README.md b/.hooks/README.md
index 7828bc0..b649986 100644
--- a/.hooks/README.md
+++ b/.hooks/README.md
@@ -1,3 +1,3 @@
Configure hooks locally by running:
-git config core.hooksPath .hooks
+git config --local core.hooksPath .hooks
diff --git a/.hooks/pre-commit b/.hooks/pre-commit
index a41e2d9..cd34bb6 100755
--- a/.hooks/pre-commit
+++ b/.hooks/pre-commit
@@ -7,13 +7,13 @@ def get_files():
'--name-only', 'HEAD']).split()
def apply_code_style():
- files = filter(lambda x: x.find('tests/*') == -1, get_files())
+ files = filter(lambda x: x.find(b'tests/system/gt_data') == -1, get_files())
- files = filter(lambda x: x.endswith('.c') or
- x.endswith('.h') or
- x.endswith('.cpp'), files)
+ files = filter(lambda x: x.endswith(b'.c') or
+ x.endswith(b'.h') or
+ x.endswith(b'.cpp'), files)
for f in files:
- print("Apply code style to: " + f)
+ print("Apply code style to: " + str(f))
subprocess.check_output(['clang-format-7', '-i', f])
subprocess.check_output(['git', 'add', f])
@@ -21,4 +21,4 @@ def main():
apply_code_style()
if (__name__ == '__main__'):
- main()
+ main()
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index c5a704e..1bfcee8 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -25,6 +25,55 @@
"type_traits": "cpp",
"utility": "cpp",
"iostream": "cpp",
- "thread": "cpp"
- }
+ "thread": "cpp",
+ "cctype": "cpp",
+ "clocale": "cpp",
+ "cmath": "cpp",
+ "csignal": "cpp",
+ "cstdarg": "cpp",
+ "cstddef": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cstring": "cpp",
+ "ctime": "cpp",
+ "cwchar": "cpp",
+ "cwctype": "cpp",
+ "chrono": "cpp",
+ "compare": "cpp",
+ "complex": "cpp",
+ "concepts": "cpp",
+ "condition_variable": "cpp",
+ "cstdint": "cpp",
+ "map": "cpp",
+ "set": "cpp",
+ "unordered_map": "cpp",
+ "unordered_set": "cpp",
+ "exception": "cpp",
+ "functional": "cpp",
+ "iterator": "cpp",
+ "numeric": "cpp",
+ "optional": "cpp",
+ "ratio": "cpp",
+ "source_location": "cpp",
+ "system_error": "cpp",
+ "iomanip": "cpp",
+ "iosfwd": "cpp",
+ "istream": "cpp",
+ "limits": "cpp",
+ "mutex": "cpp",
+ "new": "cpp",
+ "ranges": "cpp",
+ "stop_token": "cpp",
+ "streambuf": "cpp",
+ "cinttypes": "cpp",
+ "typeindex": "cpp",
+ "typeinfo": "cpp",
+ "variant": "cpp",
+ "cfenv": "cpp",
+ "valarray": "cpp",
+ "rope": "cpp",
+ "slist": "cpp",
+ "regex": "cpp"
+ },
+ "sonarlint.pathToCompileCommands": "${workspaceFolder}/compile_commands.json"
}
\ No newline at end of file
diff --git a/causalize/sbg_implementation/Makefile.include b/causalize/sbg_implementation/Makefile.include
index c1f5638..e9a0052 100644
--- a/causalize/sbg_implementation/Makefile.include
+++ b/causalize/sbg_implementation/Makefile.include
@@ -8,6 +8,8 @@ all: $(CAUSALIZE_SBG)
# Sources
CAUSALIZE_SBG_SRC := \
$(CAUSALIZE_SBG_DIR)/main.cpp\
+ $(CAUSALIZE_SBG_DIR)/generate_sbg_input.cpp\
+ $(UTIL_DIR)/ast_visitors/constant_expression.cpp \
$(UTIL_DIR)/ast_visitors/matching_exps.cpp \
$(UTIL_DIR)/ast_visitors/pwl_map_values.cpp \
$(UTIL_DIR)/logger.cpp
diff --git a/causalize/sbg_implementation/generate_sbg_input.cpp b/causalize/sbg_implementation/generate_sbg_input.cpp
new file mode 100644
index 0000000..caeb7c4
--- /dev/null
+++ b/causalize/sbg_implementation/generate_sbg_input.cpp
@@ -0,0 +1,377 @@
+/*****************************************************************************
+
+ This file is part of Modelica C Compiler.
+
+ Modelica C Compiler 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 3 of the License, or
+ (at your option) any later version.
+
+ Modelica C Compiler 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 Modelica C Compiler. If not, see .
+
+******************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace Modelica;
+
+namespace Causalize {
+GenerateSBGInput::GenerateSBGInput(MMO_Class& mmo_class) : _mmo_class(mmo_class) {}
+
+std::string GenerateSBGInput::fileName() { return _mmo_class.name() + "_sbg_input.sbg"; }
+
+Integer GenerateSBGInput::getValue(Expression exp) const
+{
+ VarSymbolTable symbols = _mmo_class.syms();
+ EvalExpression eval_exp(symbols);
+ return Integer(Apply(eval_exp, exp));
+}
+
+void GenerateSBGInput::addDef(int node_id, int end, int dim, int step)
+{
+ std::ostringstream def;
+ std::ostringstream dim_name;
+ if (dim >= 0) {
+ dim_name << "D" << dim;
+ }
+ def << "V" << node_id << dim_name.str() << " = "
+ << "V" << node_id - 1 << dim_name.str() << "+" << end;
+ _offsets.push_back(def.str());
+ def.str("");
+ def << "[V" << node_id - 1 << dim_name.str() << "+1:" << step << ":V" << node_id << dim_name.str() << "]";
+ _V.push_back(def.str());
+}
+
+Integer GenerateSBGInput::getSize(const Index& idx) const
+{
+ OptExp exp = idx.exp();
+ if (!exp || !is(exp.get())) {
+ ERROR("Only Range expressions supported");
+ }
+ Range range = get(exp.get());
+ /// @todo Handle step size.
+ return getValue(range.end()) - getValue(range.start()) + 1;
+}
+
+Integer GenerateSBGInput::getSize(const IndexList& dom) const
+{
+ Integer ret = 1;
+ for (const auto& idx : dom) {
+ ret *= getSize(idx);
+ }
+ return ret;
+}
+
+Integer GenerateSBGInput::getMin(const Index& idx) const
+{
+ OptExp exp = idx.exp();
+ if (!exp || !is(exp.get())) {
+ ERROR("Only Range expressions supported");
+ }
+ Range range = get(exp.get());
+ return getValue(range.start());
+}
+
+void GenerateSBGInput::addIndexRange(IndexList range, const std::string& eq_id, int node_id)
+{
+ Usage usage;
+ foreach_(Index idx, range)
+ {
+ OptExp exp = idx.exp();
+ if (!exp || !is(exp.get())) {
+ ERROR("Only Range expressions supported");
+ }
+ Range idx_range = get(exp.get());
+ Integer lower = getValue(idx_range.start());
+ Integer step = 1;
+ Integer upper = getValue(idx_range.end());
+ if (idx_range.step()) {
+ step = getValue(idx_range.step().get());
+ }
+ addDef(node_id, upper, -1, step);
+ usage[idx.name()] = lower;
+ }
+ _eq_usage[eq_id] = usage;
+}
+
+/// @todo Handle for-for equations in the same way we do in QSS Solver.
+void GenerateSBGInput::buildSet(Equation eq, const std::string& eq_id, int node_id, Indexes range)
+{
+ Usage usage;
+ if (!range.indexes().empty()) {
+ if (is(eq)) {
+ ERROR("Nested for equations not implemented.");
+ return;
+ }
+ addIndexRange(range.indexes(), eq_id, node_id);
+ } else if (is(eq)) {
+ ForEq for_eq = get(eq);
+ addIndexRange(for_eq.range().indexes(), eq_id, node_id);
+ } else {
+ addDef(node_id, 1);
+ }
+}
+
+/// @todo Add dimension padding and multiple dim support.
+void GenerateSBGInput::buildSet(const VarInfo& variable, int node_id)
+{
+ Option dims = variable.indices();
+ if (dims) {
+ foreach_(Expression d, dims.get()) { addDef(node_id, getValue(d)); }
+ } else {
+ addDef(node_id, 1);
+ }
+}
+
+void GenerateSBGInput::addOffset(int edge_id, const std::string& map, int offset, int v_id, int dim)
+{
+ std::ostringstream def;
+ std::ostringstream dim_name;
+ if (dim >= 0) {
+ dim_name << "D" << dim;
+ }
+ std::ostringstream off_def;
+ if (offset > 0) {
+ off_def << " + " << offset;
+ } else if (offset < 0) {
+ off_def << " - " << offset;
+ }
+ def << "off" << map << edge_id << dim_name.str() << " = "
+ << "r(V" << v_id - 1 << ",1) - r(E" << edge_id - 1 << ",1)" << off_def.str();
+ _offsets.push_back(def.str());
+}
+
+void GenerateSBGInput::addEdgeDef(int edge_id, int end, int dim)
+{
+ std::ostringstream def;
+ std::ostringstream dim_name;
+ if (dim >= 0) {
+ dim_name << "D" << dim;
+ }
+ def << "E" << edge_id << dim_name.str() << " = "
+ << "E" << edge_id - 1 << dim_name.str() << "+" << end;
+ _offsets.push_back(def.str());
+ def.str("");
+ def << "[E" << edge_id - 1 << dim_name.str() << "+1:1:E" << edge_id << dim_name.str() << "]";
+ _E.push_back(def.str());
+}
+
+void GenerateSBGInput::generatePWLMaps(Expression exp, const std::string& eq_id, int edge_id)
+{
+ assert(is(exp));
+ const IndexList& dom = _eq_range[eq_id];
+ Integer dom_size = getSize(dom);
+ VarSymbolTable symbols = _mmo_class.syms();
+
+ Reference occur = get(exp);
+ Ref names = occur.ref();
+ assert(names.size() > 0);
+ std::string node_name = get<0>(names[0]);
+ int node_id = _var_nodes[node_name];
+ int eq_node_id = _eq_nodes[eq_id];
+ ExpList indexes = get<1>(occur.ref().front());
+ addEdgeDef(edge_id, dom_size);
+ for (Expression idx : indexes) {
+ ConstantExpression constant_index(symbols);
+ if (Apply(constant_index, idx)) {
+ addOffset(edge_id, "M1", 0, node_id);
+ _m1_slopes.push_back(1);
+ } else {
+ PWLMapValues pwl_map_values(symbols);
+ Apply(pwl_map_values, idx);
+ assert(pwl_map_values.slope() != 0);
+ Usage usage = _eq_usage[eq_id];
+ int range_init_value = usage[pwl_map_values.variable()];
+ int map_first_value = 0;
+ map_first_value = pwl_map_values.constant() + pwl_map_values.slope() * range_init_value;
+ addOffset(edge_id, "M1", map_first_value, node_id);
+ _m1_slopes.push_back(pwl_map_values.slope());
+ }
+ }
+ if (indexes.empty()) { // Scalar variable.
+ addOffset(edge_id, "M1", 0, node_id);
+ _m1_slopes.push_back(1);
+ }
+ std::for_each(dom.begin(), dom.end(), [this, edge_id, eq_node_id](auto) { addOffset(edge_id, "M2", 0, eq_node_id); });
+ if (dom.empty()) { // Scalar variable.
+ addOffset(edge_id, "M2", 0, eq_node_id);
+ }
+}
+
+void GenerateSBGInput::setup()
+{
+ IdentList variables = _mmo_class.variables();
+ VarSymbolTable symbols = _mmo_class.syms();
+
+ _sbg_input.open(fileName());
+ _max_dim = 1;
+ _node_id = 1;
+ _edge_id = 1;
+
+ // Get max dim defined in the model.
+ for (Name var_name : variables) {
+ VarInfo variable = symbols[var_name].get();
+ if (isVariable(var_name, symbols)) {
+ Option indexes = variable.indices();
+ if (indexes && (indexes->size() > _max_dim)) {
+ _max_dim = indexes->size();
+ }
+ }
+ }
+}
+
+void GenerateSBGInput::addVariableNodes()
+{
+ IdentList variables = _mmo_class.variables();
+ VarSymbolTable symbols = _mmo_class.syms();
+
+ _offsets.emplace_back("V0 = 0");
+ _offsets.emplace_back("E0 = 0");
+ // Build unknown nodes.
+ foreach_(Name var_name, variables)
+ {
+ VarInfo variable = symbols[var_name].get();
+ if (!isVariable(var_name, symbols)) {
+ buildSet(variable, _node_id);
+ _var_nodes.insert(std::make_pair(var_name, _node_id));
+ _node_id++;
+ }
+ }
+}
+
+void GenerateSBGInput::addEquationInfo(const std::string& eq_name, Equality eq, IndexList indexes, int node_id)
+{
+ _eqs.insert(std::make_pair(eq_name, eq));
+ _eq_range.insert(std::make_pair(eq_name, indexes));
+ _eq_nodes.insert(std::make_pair(eq_name, node_id));
+}
+
+void GenerateSBGInput::addEquationNodes()
+{
+ // Build equation nodes.
+ EquationList eqs = _mmo_class.equations().equations();
+ foreach_(Equation eq, eqs)
+ {
+ if (is(eq)) {
+ ForEq for_eq = get(eq);
+ std::vector for_eqs = for_eq.elements();
+ Indexes range = for_eq.range();
+ foreach_(Equation for_el, for_eqs)
+ {
+ ERROR_UNLESS(is(for_el), "Only causalization of for and equality equations");
+ std::string eq_name = "eq_" + std::to_string(_node_id);
+ buildSet(for_el, eq_name, _node_id, range);
+ addEquationInfo(eq_name, get(for_el), range.indexes(), _node_id);
+ _node_id++;
+ }
+ } else if (is(eq)) {
+ std::string eq_name = "eq_" + std::to_string(_node_id);
+ buildSet(eq, eq_name, _node_id);
+ addEquationInfo(eq_name, get(eq), IndexList(), _node_id);
+ _node_id++;
+ } else {
+ ERROR("Only causalization of for and equality equations");
+ }
+ }
+}
+
+void GenerateSBGInput::addEdges()
+{
+ VarSymbolTable symbols = _mmo_class.syms();
+
+ foreach_(auto eq_desc, _eqs)
+ {
+ Equality eq = eq_desc.second;
+ Expression left = eq.left();
+ Expression right = eq.right();
+ foreach_(const auto& node, _var_nodes)
+ {
+ Name var_name = node.first;
+ MatchingExps matching_exps(var_name, isState(var_name, symbols));
+ Apply(matching_exps, left);
+ Apply(matching_exps, right);
+ std::set matched_exps = matching_exps.matchedExps();
+ LOG << "Matched exps for: " << var_name << " in " << eq << std::endl;
+ foreach_(Expression exp, matched_exps)
+ {
+ LOG << "Expression: " << exp << std::endl;
+ generatePWLMaps(exp, eq_desc.first, _edge_id);
+ _edge_id++;
+ }
+ }
+ }
+}
+
+void GenerateSBGInput::buildFromModel()
+{
+ setup();
+ addVariableNodes();
+ addEquationNodes();
+ addEdges();
+ generateSBGInput();
+}
+
+void GenerateSBGInput::generateEdgeMap(const std::string& map_name, const std::string& map_idx, bool fixed_slopes)
+{
+ _sbg_input << map_name << " %= <<";
+ unsigned long size = 1;
+ for (std::string def : _E) {
+ int slope = fixed_slopes ? 1 : _m1_slopes[size - 1];
+ _sbg_input << "{" << def << "} -> " << slope << "*x+off" << map_idx << size << ((size < _E.size()) ? " , " : "");
+ size++;
+ }
+ _sbg_input << ">>;" << std::endl;
+}
+
+void GenerateSBGInput::generateSBGInput()
+{
+ for (std::string def : _offsets) {
+ _sbg_input << def << std::endl;
+ }
+ _sbg_input << std::endl;
+ _sbg_input << "matchSCCTS(" << std::endl;
+ _sbg_input << "V %= {";
+ unsigned long size = 1;
+ for (std::string def : _V) {
+ _sbg_input << def << ((size < _V.size()) ? " , " : "");
+ size++;
+ }
+ _sbg_input << "};" << std::endl;
+
+ _sbg_input << "Vmap %= <<";
+ size = 1;
+ for (std::string def : _V) {
+ _sbg_input << "{" << def << "} -> 0*x+" << size << ((size < _V.size()) ? " , " : "");
+ size++;
+ }
+ _sbg_input << ">>;" << std::endl;
+ generateEdgeMap("map1", "M1");
+ const bool FIXED_SLOPES = true;
+ generateEdgeMap("map2", "M2", FIXED_SLOPES);
+ _sbg_input << "Emap %= <<";
+ size = 1;
+ for (std::string def : _E) {
+ _sbg_input << "{" << def << "} -> 0*x+" << size << ((size < _E.size()) ? " , " : "");
+ size++;
+ }
+ _sbg_input << ">>;" << std::endl;
+ _sbg_input << ", 1)" << std::endl;
+ _sbg_input.close();
+}
+
+} // namespace Causalize
diff --git a/causalize/sbg_implementation/generate_sbg_input.h b/causalize/sbg_implementation/generate_sbg_input.h
new file mode 100644
index 0000000..44a3c92
--- /dev/null
+++ b/causalize/sbg_implementation/generate_sbg_input.h
@@ -0,0 +1,75 @@
+/*****************************************************************************
+
+ This file is part of Modelica C Compiler.
+
+ Modelica C Compiler 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 3 of the License, or
+ (at your option) any later version.
+
+ Modelica C Compiler 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 Modelica C Compiler. If not, see .
+
+******************************************************************************/
+
+#include
+#include
+
+#include
+
+namespace Causalize {
+
+class GenerateSBGInput {
+ public:
+ explicit GenerateSBGInput(Modelica::MMO_Class& mmo_class);
+ virtual ~GenerateSBGInput() = default;
+ virtual void buildFromModel();
+ virtual std::string fileName();
+
+ protected:
+ void setup();
+ void addVariableNodes();
+ void addEquationInfo(const std::string& eq_name, Equality eq, IndexList indexes, int node_id);
+ void addEquationNodes();
+ void addEdges();
+ void generateSBGInput();
+ void buildSet(const VarInfo& variable, int node_id);
+ void buildSet(Equation eq, const std::string& eq_id, int offset, Indexes range = IndexList());
+ Integer getValue(Expression exp) const;
+ void addDef(int node_id, int end, int dim = -1, int step = 1);
+ void addOffset(int edge_id, const std::string& map, int constant, int slope, int dim = -1);
+ void generatePWLMaps(Expression exp, const std::string& eq_id, int edge_id);
+ void addIndexRange(IndexList range, const std::string& eq_id, int node_id);
+ Integer getMin(const Index& idx) const;
+ Integer getSize(const Index& idx) const;
+ Integer getSize(const IndexList& dom) const;
+ void addEdgeDef(int edge_id, int end, int dim = -1);
+ void generateEdgeMap(const std::string& map_name, const std::string& map_idx, bool fixed_slopes = false);
+
+ private:
+ using Usage = std::map>;
+ using EqUsage = std::map>;
+
+ Modelica::MMO_Class& _mmo_class;
+ std::list _V;
+ std::list _E;
+ std::map> _eqs;
+ std::map> _eq_range;
+ std::map> _var_nodes;
+ std::map> _eq_nodes;
+ EqUsage _eq_usage;
+ std::list _V_map;
+ std::list _offsets;
+ std::ofstream _sbg_input;
+ std::vector _m1_slopes;
+ unsigned long _max_dim;
+ int _node_id;
+ int _edge_id;
+};
+
+} // namespace Causalize
diff --git a/causalize/sbg_implementation/main.cpp b/causalize/sbg_implementation/main.cpp
index 7e4173f..fc120f2 100644
--- a/causalize/sbg_implementation/main.cpp
+++ b/causalize/sbg_implementation/main.cpp
@@ -20,13 +20,12 @@
#include
#include
+#include
#include
#include
#include
#include
#include
-#include
-#include
using namespace std;
using namespace Modelica;
@@ -52,17 +51,15 @@ void version()
cout << "There is NO WARRANTY, to the extent permitted by law." << endl;
}
-int main(int argc, char **argv)
+int main(int argc, char** argv)
{
int opt;
extern char* optarg;
string output_path = "";
while (true) {
- static struct option long_options[] = {{"version", no_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
- {"output", required_argument, 0, 'o'},
- {0, 0, 0, 0}};
+ static struct option long_options[] = {
+ {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"output", required_argument, 0, 'o'}, {0, 0, 0, 0}};
int option_index = 0;
opt = getopt_long(argc, argv, "vho:", long_options, &option_index);
if (opt == EOF) {
@@ -89,7 +86,7 @@ int main(int argc, char **argv)
StoredDef stored_def;
bool status = false;
- std::string model_file;
+ std::string model_file = "";
if (argv[optind] != nullptr) {
model_file = argv[optind];
stored_def = Parser::ParseFile(model_file, status);
@@ -97,7 +94,7 @@ int main(int argc, char **argv)
std::cout << "No input file provided." << std::endl;
usage();
exit(-1);
- }
+ }
if (!status) {
std::cout << "Error parsing file " << model_file << std::endl;
@@ -111,9 +108,16 @@ int main(int argc, char **argv)
StateVariablesFinder setup_state_var(mmo_class);
setup_state_var.findStateVariables();
+ Causalize::GenerateSBGInput gen_sbg_input(mmo_class);
+
+ gen_sbg_input.buildFromModel();
+
/// Temp hack to test the binaries, hardcoded paths should go on config files.
const std::string CAUSALIZE = "../3rd-party/sbg/sb-graph-dev/bin/sbg-eval ";
- const std::string ARGS = "-f " + model_file + " > " + model_file + "_causalized.sbg";
+ const std::string DEFAULT_CAUSALIZED_JSON = "./output.json";
+ const std::string CAUSALIZED_JSON = mmo_class.name() + "_causalized.json";
+ std::string ARGS = "-f " + gen_sbg_input.fileName() + " > " + mmo_class.name() + "_causalized.sbg; mv " + DEFAULT_CAUSALIZED_JSON +
+ " ./" + CAUSALIZED_JSON;
const std::string CAUSALIZE_CMD = CAUSALIZE + ARGS;
int res = std::system(CAUSALIZE_CMD.c_str());
diff --git a/causalize/sbg_implementation/matching_graph_builder.cpp b/causalize/sbg_implementation/matching_graph_builder.cpp
deleted file mode 100644
index 1e0ddc3..0000000
--- a/causalize/sbg_implementation/matching_graph_builder.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/*****************************************************************************
-
- This file is part of Modelica C Compiler.
-
- Modelica C Compiler 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 3 of the License, or
- (at your option) any later version.
-
- Modelica C Compiler 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 Modelica C Compiler. If not, see .
-
-******************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace Modelica;
-using namespace SBG;
-
-namespace Causalize {
-MatchingGraphBuilder::MatchingGraphBuilder(MMO_Class &mmo_class) : _mmo_class(mmo_class), _U(), _F(), _eq_usage() {}
-
-Real MatchingGraphBuilder::getValue(Expression exp)
-{
- VarSymbolTable symbols = _mmo_class.syms();
- EvalExpression eval_exp(symbols);
- return Apply(eval_exp, exp);
-}
-
-void MatchingGraphBuilder::addDims(size_t max_dim, size_t exp_dim, SBG::MultiInterval& intervals, int offset)
-{
- if (max_dim > exp_dim) {
- for (size_t i = exp_dim; i < max_dim; i++) {
- Interval interval(offset, 1, offset);
- intervals.addInter(interval);
- }
- }
-}
-
-void MatchingGraphBuilder::addDims(size_t max_dim, size_t exp_dim, ORD_REALS& constant, ORD_REALS& slope)
-{
- ORD_REALS::iterator constant_it = constant.end();
- ORD_REALS::iterator slope_it = slope.end();
- if (max_dim > exp_dim) {
- for (size_t i = exp_dim; i < max_dim; i++) {
- constant_it = constant.insert(constant_it, 0);
- slope_it = slope.insert(slope_it, 0);
- }
- }
-}
-
-SBG::Set MatchingGraphBuilder::buildSet(VarInfo variable, int offset, size_t max_dim)
-{
- Option dims = variable.indices();
- MultiInterval variable_intervals;
- if (dims) {
- foreach_(Expression d, dims.get()) {
- Real res = getValue(d) - 1;
- Interval interval(offset, 1, offset + res);
- variable_intervals.addInter(interval);
- }
- addDims(max_dim, dims->size(), variable_intervals, offset);
- } else {
- addDims(max_dim, 0, variable_intervals, offset);
- }
- return createSet(variable_intervals);
-}
-
-SBG::Set MatchingGraphBuilder::buildSet(Equation eq, std::string eq_id, int offset, size_t max_dim)
-{
- Usage usage;
- MultiInterval equation_intervals;
- if (is(eq)) {
- ForEq for_eq = get(eq);
- IndexList indexes = for_eq.range().indexes();
- foreach_(Index idx, indexes) {
- OptExp exp = idx.exp();
- if (!exp || !is(exp.get())) {
- ERROR("Only Range expressions supported");
- }
- Range range = get(exp.get());
- Real lower = getValue(range.start());
- Real step = 1;
- Real upper = getValue(range.end());
- if (range.step()) {
- step = getValue(range.step().get());
- }
- Real end = offset + upper - lower;
- Interval interval(offset, step, end);
- equation_intervals.addInter(interval);
- usage[idx.name()] = lower;
- }
- addDims(max_dim, indexes.size(), equation_intervals, offset);
- _eq_usage[eq_id] = usage;
- } else {
- addDims(max_dim, 0, equation_intervals, offset);
- }
- return createSet(equation_intervals);
-}
-
-/**
- * @brief Add the offset to a given equation domain.
- *
- * @param dom
- * @param offset
- * @return SBG::Set The new set with all the offsets applied.
- */
-SBG::Set MatchingGraphBuilder::generateMapDom(SBG::Set dom, SBG::Set unk_dom, int offset, size_t max_dim)
-{
- MultiInterval edge_set_intervals;
- SBG::UNORD_MI atom_sets = dom.asets();
- foreach_(MultiInterval dom_intervals, atom_sets) {
- foreach_(Interval inter, dom_intervals.inters()) {
- Real end = inter.card() + offset - 1;
- edge_set_intervals.addInter(Interval(offset, inter.step(), end));
- }
- addDims(max_dim, dom_intervals.inters().size(), edge_set_intervals, offset);
- }
- return createSet(edge_set_intervals);
-}
-
-SetVertexDesc MatchingGraphBuilder::addVertex(std::string vertex_name, SBG::Set set, std::string desc, SBGraph& graph)
-{
- SetVertex V(vertex_name, set, desc);
- SetVertexDesc v = boost::add_vertex(graph);
- graph[v] = V;
- return v;
-}
-
-void MatchingGraphBuilder::addEquation(Equation eq, std::string id, SBG::Set set, SBGraph& graph)
-{
- std::ostringstream desc;
- desc << eq;
-
- if (!is(eq)) {
- ERROR("Only Equality equations supported.");
- }
- _F.push_back(std::make_pair(addVertex(id, set, desc.str(), graph),get(eq)));
-}
-
-PWLMap MatchingGraphBuilder::buildPWLMap(ORD_REALS constants, ORD_REALS slopes, SBG::Set dom)
-{
- LMap lmap(slopes, constants);
-
- OrdCT doms;
- doms.insert(doms.end(), dom);
-
- OrdCT maps;
- maps.insert(maps.end(), lmap);
- PWLMap map(doms, maps);
- return map;
-}
-
-MatchingGraphBuilder::MatchingMaps MatchingGraphBuilder::generatePWLMaps(Expression exp, SBG::Set dom, SBG::Set unk_dom, int offset, std::string eq_id, size_t max_dim)
-{
- assert(is(exp));
- VarSymbolTable symbols = _mmo_class.syms();
- ORD_REALS constant_pwl_map_u;
- ORD_REALS::iterator constant_pwl_map_u_it = constant_pwl_map_u.begin();
- ORD_REALS slope_pwl_map_u;
- ORD_REALS::iterator slope_pwl_map_u_it = slope_pwl_map_u.begin();
- ORD_REALS constant_pwl_map_f;
- ORD_REALS::iterator constant_pwl_map_f_it = constant_pwl_map_f.begin();
- ORD_REALS slope_pwl_map_f;
- ORD_REALS::iterator slope_pwl_map_f_it = slope_pwl_map_f.begin();
-
- Reference occur = get(exp);
- ExpList indexes = get<1>(occur.ref().front());
- SBG::ORD_INTS init_elems = unk_dom.minElem();
- assert(init_elems.size() == indexes.size() || indexes.size() == 0);
- SBG::ORD_INTS::iterator min_elem = init_elems.begin();
- SBG::Set map_dom = generateMapDom(dom, unk_dom, offset, max_dim);
- int map_offset = offset - 1;
-
- foreach_(Expression idx, indexes)
- {
- SBG::INT set_vertex_init = *min_elem -1;
- PWLMapValues pwl_map_values(symbols);
- Apply(pwl_map_values, idx);
- Usage usage = _eq_usage[eq_id];
- int range_init_value = usage[pwl_map_values.variable()];
- int set_vertex_offset = pwl_map_values.slope() * offset;
- int map_first_value = pwl_map_values.constant() + pwl_map_values.slope() * range_init_value + set_vertex_init;
- constant_pwl_map_u_it = constant_pwl_map_u.insert(constant_pwl_map_u_it, map_first_value - set_vertex_offset);
- slope_pwl_map_u_it = slope_pwl_map_u.insert(slope_pwl_map_u_it, pwl_map_values.slope());
- min_elem++;
- }
- if (indexes.empty()) { // Scalar variable.
- SBG::INT set_vertex_init = *min_elem -1;
- constant_pwl_map_u_it = constant_pwl_map_u.insert(constant_pwl_map_u_it, - map_offset + set_vertex_init);
- slope_pwl_map_u_it = slope_pwl_map_u.insert(slope_pwl_map_u_it, 1);
- addDims(max_dim, 1, constant_pwl_map_u, slope_pwl_map_u);
- } else {
- addDims(max_dim, indexes.size(), constant_pwl_map_u, slope_pwl_map_u);
- }
- for (SBG::INT init : dom.minElem()) {
- SBG::INT set_vertex_init = init -1;
- constant_pwl_map_f_it = constant_pwl_map_f.insert(constant_pwl_map_f_it, -map_offset + set_vertex_init);
- slope_pwl_map_f_it = slope_pwl_map_f.insert(slope_pwl_map_f_it, 1);
- }
- addDims(max_dim, dom.minElem().size(), constant_pwl_map_f, slope_pwl_map_f);
- return std::make_pair(buildPWLMap(constant_pwl_map_f, slope_pwl_map_f, map_dom), buildPWLMap(constant_pwl_map_u, slope_pwl_map_u, map_dom));
-}
-
-SBGraph MatchingGraphBuilder::makeGraph()
-{
- SBGraph graph;
- VarSymbolTable symbols = _mmo_class.syms();
-
- IdentList variables = _mmo_class.variables();
- size_t max_dim = 1;
- // Get max dim defined in the model.
- foreach_(Name var_name, variables)
- {
- VarInfo variable = symbols[var_name].get();
- if (!isConstant(var_name, symbols) && !isBuiltIn(var_name, symbols) && !isDiscrete(var_name, symbols) && !isParameter(var_name, symbols)) {
- Option indexes = variable.indices();
- if (indexes && indexes->size() > max_dim) {
- max_dim = indexes->size();
- }
- }
- }
-
- int set_vertex_offset = 1;
- // Build unknown nodes.
- foreach_(Name var_name, variables)
- {
- VarInfo variable = symbols[var_name].get();
- if (!isConstant(var_name, symbols) && !isBuiltIn(var_name, symbols) && !isDiscrete(var_name, symbols) && !isParameter(var_name, symbols)) {
- SBG::Set vertex_dom = buildSet(variable, set_vertex_offset, max_dim);
- _U.push_back(addVertex(var_name, vertex_dom, "", graph));
- set_vertex_offset += vertex_dom.card();
- }
- }
-
- // Build equation nodes.
- EquationList eqs = _mmo_class.equations().equations();
- int id = 1;
- foreach_(Equation eq, eqs)
- {
- SBG::Set vertex_dom;
- if (is(eq)) {
- ForEq for_eq = get(eq);
- std::vector for_eqs = for_eq.elements();
- foreach_(Equation for_el, for_eqs)
- {
- std::string eq_name = "eq_" + std::to_string(id++);
- vertex_dom = buildSet(eq, eq_name, set_vertex_offset, max_dim);
- set_vertex_offset += vertex_dom.card();
- addEquation(for_el, eq_name, vertex_dom, graph);
- }
- } else if (is(eq)) {
- std::string eq_name = "eq_" + std::to_string(id++);
- vertex_dom = buildSet(eq, eq_name, set_vertex_offset, max_dim);
- set_vertex_offset += vertex_dom.card();
- addEquation(eq, eq_name, vertex_dom, graph);
- } else {
- ERROR("Only causalization of for and equality equations");
- }
- }
-
- // Build edges.
- int set_edge_offset = 1;
- unsigned int edge_id = 1;
- foreach_(EquationDesc eq_desc, _F)
- {
- SetVertexDesc eq_vertex_desc = eq_desc.first;
- SetVertex eq_vertex = graph[eq_vertex_desc];
- Expression left = eq_desc.second.left();
- Expression right = eq_desc.second.right();
- SBG::Set dom = eq_vertex.range();
- foreach_(SetVertexDesc unknown_vertex_desc, _U)
- {
- SetVertex unknown_vertex = graph[unknown_vertex_desc];
- SBG::Set unk_dom = unknown_vertex.range();
- MatchingExps matching_exps(unknown_vertex.id(), isState(unknown_vertex.id(), symbols));
- Apply(matching_exps, left);
- Apply(matching_exps, right);
- std::set matched_exps = matching_exps.matchedExps();
- LOG << "Matched exps for: " << unknown_vertex.id() << " in " << eq_desc.second << std::endl;
- LOG << "Equation dom: " << dom << std::endl;
- foreach_(Expression exp, matched_exps)
- {
- LOG << "Expression: " << exp << std::endl;
- MatchingMaps maps = generatePWLMaps(exp, dom, unk_dom, set_edge_offset, eq_vertex.id(), max_dim);
- set_edge_offset += dom.card();
- std::string edge_name = "E_" + std::to_string(edge_id++);
- LOG << "MapF: " << maps.first << std::endl;
- LOG << "MapU: " << maps.second << std::endl;
- SetEdge edge(edge_name, maps.first, maps.second);
- SetEdgeDesc e;
- bool b;
- boost::tie(e, b) = boost::add_edge(eq_vertex_desc, unknown_vertex_desc, graph);
- graph[e] = edge;
- }
- }
- }
- return graph;
-}
-
-} // namespace Causalize
diff --git a/causalize/sbg_implementation/matching_graph_builder.h b/causalize/sbg_implementation/matching_graph_builder.h
deleted file mode 100644
index 0b231b5..0000000
--- a/causalize/sbg_implementation/matching_graph_builder.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*****************************************************************************
-
- This file is part of Modelica C Compiler.
-
- Modelica C Compiler 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 3 of the License, or
- (at your option) any later version.
-
- Modelica C Compiler 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 Modelica C Compiler. If not, see .
-
-******************************************************************************/
-
-#include
-#include
-
-namespace Causalize {
-
-class MatchingGraphBuilder {
- public:
- MatchingGraphBuilder(Modelica::MMO_Class& mmo_class);
- ~MatchingGraphBuilder() = default;
- virtual SBG::SBGraph makeGraph();
-
- protected:
- typedef std::pair MatchingMaps;
-
- SBG::Set buildSet(VarInfo variable, int offset, size_t max_dim);
- SBG::Set buildSet(Equation eq, std::string eq_id, int offset, size_t max_dim);
- SBG::Set buildSet(SBG::MultiInterval variable);
- SBG::SetVertexDesc addVertex(std::string vertex_name, SBG::Set set, std::string desc, SBG::SBGraph& graph);
- void addEquation(Equation eq, std::string id, SBG::Set set, SBG::SBGraph& graph);
- Real getValue(Expression exp);
- SBG::PWLMap buildPWLMap(SBG::ORD_REALS constants, SBG::ORD_REALS slopes, SBG::Set dom);
- MatchingMaps generatePWLMaps(Expression exp, SBG::Set dom, SBG::Set unk_dom, int offset, std::string eq_id, size_t max_dim);
- SBG::Set generateMapDom(SBG::Set dom, SBG::Set unk_dom, int offset, size_t max_dim);
- void addDims(size_t max_dim, size_t exp_dim, SBG::MultiInterval& intervals, int offset);
- void addDims(size_t max_dim, size_t exp_dim, SBG::ORD_REALS& constant, SBG::ORD_REALS& slope);
-
- private:
- typedef std::pair EquationDesc;
- typedef std::map Usage;
- typedef std::map EqUsage;
-
- Modelica::MMO_Class& _mmo_class;
- std::list _U;
- std::list _F;
- EqUsage _eq_usage;
-};
-
-} // namespace Causalize
diff --git a/causalize/sbg_implementation/test/models_test.cpp b/causalize/sbg_implementation/test/models_test.cpp
index 6baffd3..7fb54b7 100644
--- a/causalize/sbg_implementation/test/models_test.cpp
+++ b/causalize/sbg_implementation/test/models_test.cpp
@@ -35,13 +35,13 @@ TEST_P(ITests, GenerateCode)
{
const std::string NAME = GetParam();
std::cout << "Testing model: " << NAME << std::endl;
- const std::string FLATTER = "../../../bin/causalize ";
+ const std::string CAUSALIZE = "../../../bin/causalize ";
const std::string ARGS = "-o ./test_data/ ../../../test/mccprograms/" + NAME + ".mo";
const std::string RESULT_FILE = "./test_data/" + NAME + ".passed";
const std::string TEST_CMD = "./test_results.sh " + NAME;
- const std::string FLATTER_CMD = FLATTER + ARGS;
+ const std::string CAUSALIZE_CMD = CAUSALIZE + ARGS;
- std::system(FLATTER_CMD.c_str());
+ std::system(CAUSALIZE_CMD.c_str());
std::system(TEST_CMD.c_str());
std::ifstream result(RESULT_FILE.c_str());
diff --git a/util/ast_visitors/eval_expression.h b/util/ast_visitors/eval_expression.h
index fa8d159..54d5ebe 100644
--- a/util/ast_visitors/eval_expression.h
+++ b/util/ast_visitors/eval_expression.h
@@ -19,16 +19,16 @@
#ifndef AST_VISITOR_EVALEXP
#define AST_VISITOR_EVALEXP
+
#include
#include
#include
namespace Modelica {
-using namespace Modelica::AST;
-class EvalExpression : public boost::static_visitor{
+class EvalExpression : public boost::static_visitor {
public:
- EvalExpression(const VarSymbolTable &);
+ explicit EvalExpression(const VarSymbolTable &);
EvalExpression(const VarSymbolTable &, Name, Real);
Real operator()(Integer v) const;
Real operator()(Boolean v) const;
diff --git a/util/ast_visitors/pwl_map_values.cpp b/util/ast_visitors/pwl_map_values.cpp
index 9d968a2..770b016 100644
--- a/util/ast_visitors/pwl_map_values.cpp
+++ b/util/ast_visitors/pwl_map_values.cpp
@@ -24,12 +24,12 @@
namespace Modelica {
-PWLMapValues::PWLMapValues(VarSymbolTable symbols) : _constant(0), _slope(1), _symbols(symbols), _variable() {};
+PWLMapValues::PWLMapValues(VarSymbolTable symbols) : _constant(0), _slope(1), _symbols(symbols), _variable(){};
bool PWLMapValues::operator()(Integer v) const
-{
- _constant = v;
- return false;
+{
+ _constant = v;
+ return false;
}
bool PWLMapValues::operator()(Boolean v) const { return false; }
@@ -84,14 +84,15 @@ void PWLMapValues::assign(Expression left, Expression right, bool var_left, bool
} else if (var_right) {
_constant = sign * Apply(eval_exp, left);
} else {
- _constant = sign * (Apply(eval_exp, left) + Apply(eval_exp, right));
+ _constant = sign * (Apply(eval_exp, left) + Apply(eval_exp, right));
}
}
bool PWLMapValues::operator()(BinOp v) const
{
EvalExpression eval_exp(_symbols);
- Expression l = v.left(), r = v.right();
+ Expression l = v.left();
+ Expression r = v.right();
bool var_left = ApplyThis(l);
bool var_right = ApplyThis(r);
BinOpType type = v.op();
@@ -129,10 +130,10 @@ bool PWLMapValues::operator()(UnaryOp v) const
return ret;
}
-int PWLMapValues::constant() const { return _constant; }
+int PWLMapValues::constant() const { return _constant; }
-int PWLMapValues::slope() const { return _slope; }
+int PWLMapValues::slope() const { return _slope; }
-std::string PWLMapValues::variable() const { return _variable; }
+std::string PWLMapValues::variable() const { return _variable; }
} // namespace Modelica
diff --git a/util/ast_visitors/pwl_map_values.h b/util/ast_visitors/pwl_map_values.h
index 36797a8..82084a6 100644
--- a/util/ast_visitors/pwl_map_values.h
+++ b/util/ast_visitors/pwl_map_values.h
@@ -25,10 +25,9 @@
namespace Modelica {
-using namespace Modelica::AST;
class PWLMapValues : public boost::static_visitor {
public:
- PWLMapValues(VarSymbolTable symbols);
+ explicit PWLMapValues(VarSymbolTable symbols);
bool operator()(Integer v) const;
bool operator()(Boolean v) const;
bool operator()(AddAll v) const;