diff --git a/debian/changelog b/debian/changelog index fd6c9f4b2..915a9b7e3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,80 @@ +bellmansgapc (2024.08.01-0ubuntu0ppa1~noble1) xenial; urgency=medium + + * features: + + new auto generation of "tikz" algebras" to generate tikZ code to draw + candidate trees. Just add "algebra foo auto tikz" to your gap code, as + you already did for "count" or "enum". + Note: for lager search spaces, you will probably hit the limit of + recursive LaTeX environments when compiling the generated tikZ code. + + -- janssenlab Mon, 8 January 2024 11:36:00 +0200 + +bellmansgapc (2024.08.01-0ubuntu0ppa1~mantic1) xenial; urgency=medium + + * features: + + new auto generation of "tikz" algebras" to generate tikZ code to draw + candidate trees. Just add "algebra foo auto tikz" to your gap code, as + you already did for "count" or "enum". + Note: for lager search spaces, you will probably hit the limit of + recursive LaTeX environments when compiling the generated tikZ code. + + -- janssenlab Mon, 8 January 2024 11:36:00 +0200 + +bellmansgapc (2024.08.01-0ubuntu0ppa1~lunar1) xenial; urgency=medium + + * features: + + new auto generation of "tikz" algebras" to generate tikZ code to draw + candidate trees. Just add "algebra foo auto tikz" to your gap code, as + you already did for "count" or "enum". + Note: for lager search spaces, you will probably hit the limit of + recursive LaTeX environments when compiling the generated tikZ code. + + -- janssenlab Mon, 8 January 2024 11:36:00 +0200 + +bellmansgapc (2024.08.01-0ubuntu0ppa1~jammy1) xenial; urgency=medium + + * features: + + new auto generation of "tikz" algebras" to generate tikZ code to draw + candidate trees. Just add "algebra foo auto tikz" to your gap code, as + you already did for "count" or "enum". + Note: for lager search spaces, you will probably hit the limit of + recursive LaTeX environments when compiling the generated tikZ code. + + -- janssenlab Mon, 8 January 2024 11:36:00 +0200 + +bellmansgapc (2024.08.01-0ubuntu0ppa1~focal1) xenial; urgency=medium + + * features: + + new auto generation of "tikz" algebras" to generate tikZ code to draw + candidate trees. Just add "algebra foo auto tikz" to your gap code, as + you already did for "count" or "enum". + Note: for lager search spaces, you will probably hit the limit of + recursive LaTeX environments when compiling the generated tikZ code. + + -- janssenlab Mon, 8 January 2024 11:36:00 +0200 + +bellmansgapc (2024.08.01-0ubuntu0ppa1~bionic1) xenial; urgency=medium + + * features: + + new auto generation of "tikz" algebras" to generate tikZ code to draw + candidate trees. Just add "algebra foo auto tikz" to your gap code, as + you already did for "count" or "enum". + Note: for lager search spaces, you will probably hit the limit of + recursive LaTeX environments when compiling the generated tikZ code. + + -- janssenlab Mon, 8 January 2024 11:36:00 +0200 + +bellmansgapc (2024.08.01-0ubuntu0ppa1~xenial1) xenial; urgency=medium + + * features: + + new auto generation of "tikz" algebras" to generate tikZ code to draw + candidate trees. Just add "algebra foo auto tikz" to your gap code, as + you already did for "count" or "enum". + Note: for lager search spaces, you will probably hit the limit of + recursive LaTeX environments when compiling the generated tikZ code. + + -- janssenlab Mon, 8 January 2024 11:36:00 +0200 + bellmansgapc (2023.07.05-0ubuntu0ppa1~xenial1) xenial; urgency=medium * features: diff --git a/rtlib/generic_main.cc b/rtlib/generic_main.cc index 9a55d6482..b33b52f2f 100644 --- a/rtlib/generic_main.cc +++ b/rtlib/generic_main.cc @@ -71,6 +71,8 @@ int main(int argc, char **argv) { std::cout << std::setprecision(FLOAT_ACC) << std::fixed; #endif + // print statements prior to result list, e.g. for TikZ document generation + obj.print_document_header(std::cout); #ifdef WINDOW_MODE unsigned n = obj.t_0_seq.size(); for (unsigned int i = 0; ; i+=opts.window_increment) { @@ -94,7 +96,9 @@ int main(int argc, char **argv) { gapc::add_event("end_computation"); #ifndef OUTSIDE +#ifndef TIKZ std::cout << "Answer: \n"; +#endif obj.print_result(std::cout, res); #else obj.report_insideoutside(std::cout); @@ -112,6 +116,8 @@ int main(int argc, char **argv) { gapc::add_event("end"); #endif + // print statements after result list, e.g. for TikZ document generation + obj.print_document_footer(std::cout); #ifdef STATS obj.print_stats(std::cerr); #endif diff --git a/rtlib/rna.hh b/rtlib/rna.hh index 44303c41f..f57243340 100644 --- a/rtlib/rna.hh +++ b/rtlib/rna.hh @@ -183,6 +183,10 @@ inline void char_to_rna(Basic_Sequence &seq) { using std::exp; +/* When users choose 'rna' as input type, characters get translated into a + * specific alphabet to save bits (see rnalib.h base_t). If one needs to put + * such a substring back to normal ASCII characters, we can use this function + */ template inline void append_deep_rna( rope::Ref &str, const Basic_Subsequence &sub) { @@ -191,6 +195,23 @@ inline void append_deep_rna( str.append(static_cast(base_to_char(*i))); } +/* same as append_deep_rna, but LOC will leave a instead of an empty + * string, where X is the "position" of LOC, i.e. the border between + * characters. + */ +template +inline void append_deep_rna_loc( + rope::Ref &str, const Basic_Subsequence &sub) { + for (typename Basic_Subsequence::const_iterator + i = sub.begin(); i != sub.end(); ++i) + str.append(static_cast(base_to_char(*i))); + if ((sub.size() == 0) && (sub.i == sub.j)) { + str.append('<'); + str.append(static_cast(sub.i)); + str.append('>'); + } +} + // ======== energy wrapper function ======== /* diff --git a/rtlib/rope.hh b/rtlib/rope.hh index 1e13ff4c7..932a57447 100644 --- a/rtlib/rope.hh +++ b/rtlib/rope.hh @@ -32,7 +32,9 @@ #include #include +#include #include +#include #include "../rtlib/cstr.h" #include "bitops.hh" @@ -754,6 +756,49 @@ inline void append(rope::Ref &str, const T &x) { str.append(x); } +/* accepts a string and escapes all containing characters to be compatible + * to LaTeX math mode. Used for tikZ generations. + */ +inline std::string latex(const std::string in) { + std::string out = std::string(in); + + /* https://www.cespedes.org/blog/85/how-to-escape-latex-special-characters + * note that we are in math mode, which might use different rules than + * LaTeX's "normal" text mode. */ + boost::replace_all(out, "\\", "\\backslash"); + boost::replace_all(out, "#", "\\#"); + boost::replace_all(out, "$", "\\$"); + boost::replace_all(out, "%", "\\%"); + boost::replace_all(out, "&", "\\&"); + boost::replace_all(out, "_", "\\_"); + boost::replace_all(out, "{", "\\{"); + boost::replace_all(out, "}", "\\}"); + boost::replace_all(out, "^", "\\hat{\\ }"); + boost::replace_all(out, "~", "\\tilde{\\ }"); + + return out; +} +template +inline void append_latex(rope::Ref &str, char &c) { + std::string in(1, c); + std::string out = latex(in); + str.append(out.c_str(), out.size()); +} +template +inline void append_latex(rope::Ref &str, const Subsequence &s) { + for (typename Subsequence::const_iterator i = s.begin(); i != s.end(); ++i) { + char ichar = (*i); + append_latex(str, ichar); + } +} +template +inline void append_latex(rope::Ref &str, const char *s, int slen) { + for (int i = 0; i < slen; ++i) { + char ichar = (s[i]); + append_latex(str, ichar); + } +} + template inline void append(rope::Ref &str, char c, T i) { assert(i >= 0); diff --git a/src/algebra.hh b/src/algebra.hh index a6533b018..e127f141c 100644 --- a/src/algebra.hh +++ b/src/algebra.hh @@ -51,9 +51,15 @@ class Filter; class Algebra : public Signature_Base { + public: + // if algebra is auto generated, it is one of three types: enum, count, tikz + // otherwise, it is a user defined one, i.e. not auto generated: NONE + enum AutoRole { NONE, ENUM, COUNT, TIKZ }; + private: std::string *default_choice_fn_mode; void init_choice_fns(); + AutoRole role = AutoRole::NONE; public: hashtable fns; @@ -77,9 +83,9 @@ class Algebra : public Signature_Base { signature(NULL), signature_name(NULL) { } - explicit Algebra(std::string *n) + explicit Algebra(std::string *n, AutoRole role) : Signature_Base(n), default_choice_fn_mode(0), - signature(NULL), signature_name(NULL) { + role(role), signature(NULL), signature_name(NULL) { } @@ -139,6 +145,13 @@ class Algebra : public Signature_Base { void add_choice_specialisations(Product::Two &product); Algebra *copy() const; + + /* return role of automatically generated algebra. None if algebra is user + * defined. + */ + AutoRole get_auto_role() { + return this->role; + } }; inline std::ostream &operator<<(std::ostream &s, const Algebra &a) { diff --git a/src/ast.cc b/src/ast.cc index e06354f38..1753200fd 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -61,6 +61,7 @@ AST::AST() signature(NULL), first_instance(NULL), instance_(0), backtrack_product(0), + fwd_product(0), backtrack_filter(0), original_product(0), char_type(0), @@ -739,6 +740,7 @@ Instance *AST::split_instance_for_backtrack(std::string &n) { original_product = two; backtrack_product = two->right(); + fwd_product = two->left(); backtrack_filter = two->filter(); Instance *score = new Instance(i->name(), two->left(), grammar()); return score; diff --git a/src/ast.hh b/src/ast.hh index b10bb49e8..6e886dc54 100644 --- a/src/ast.hh +++ b/src/ast.hh @@ -58,6 +58,7 @@ #include "product.hh" #include "checkpoint.hh" +#include "instance.hh" class Signature; @@ -257,6 +258,10 @@ class AST { private: // FIXME Product::Base *backtrack_product; + + // when instance is split for backtracing, fwd_product is the part computed + // in the forward pass + Product::Base *fwd_product; Filter *backtrack_filter; Product::Two *original_product; @@ -299,9 +304,12 @@ class AST { std::list > sf_filter_code; - Product::Base * get_backtrack_product() { + Product::Base * get_backtrack_product() const { return backtrack_product; } + Product::Base * get_fwd_product() const { + return fwd_product; + } Printer::Checkpoint *checkpoint; @@ -317,6 +325,12 @@ class AST { std::vector *get_outside_nt_list() const { return this->outside_nt_list; } + + bool uses_tikz() const { + return instance_->product->uses_tikz() || + (backtrack_product && backtrack_product->uses_tikz()) || + (fwd_product && fwd_product->uses_tikz()); + } }; #endif // SRC_AST_HH_ diff --git a/src/backtrack_base.cc b/src/backtrack_base.cc index ac8ea0d9e..c60822dee 100644 --- a/src/backtrack_base.cc +++ b/src/backtrack_base.cc @@ -102,6 +102,6 @@ void Backtrack_Base::gen_nt_decls(const std::list &nts) { void Backtrack_Base::gen_algebra(Signature &signature, Type::Base *alph) { Algebra *a = signature.generate_backtrace - (new std::string("bt_algebra"), value_type, pos_type, alph); + (new std::string("bt_algebra"), value_type, pos_type, alph, Algebra::NONE); algebra = a; } diff --git a/src/cpp.cc b/src/cpp.cc index f8ecc60ab..d08c61cfe 100644 --- a/src/cpp.cc +++ b/src/cpp.cc @@ -1946,6 +1946,9 @@ void Printer::Cpp::header(const AST &ast) { if (ast.outside_generation()) { stream << "#define OUTSIDE\n"; } + if (ast.uses_tikz()) { + stream << "#define TIKZ\n"; + } stream << "#define GAPC_CALL_STRING \"" << gapc_call_string << "\"" << endl; @@ -2304,12 +2307,26 @@ void Printer::Cpp::print_kbacktrack_pp(const AST &ast) { stream << indent() << "if (l) {" << endl; inc_indent(); + stream << indent() << "int rank = 1;" << endl; stream << indent() << "for (Backtrace_List<" << *bt_value << ", unsigned int>::iterator i = l->begin();" << " i != l->end(); ++i) {" << endl; inc_indent(); - stream << indent() << "(*i)->print(out);" << endl; + if (ast.uses_tikz()) { + stream << indent() << "boost::intrusive_ptr > subcandidates = (*i)->eval();" << endl; + stream << indent() << "for (Eval_List<" << *bt_value + << ">::iterator part_bt = subcandidates->begin(); part_bt != " + << "subcandidates->end(); ++part_bt) {" << endl; + inc_indent(); + print_tikz_candidate(ast, "(*part_bt)", "value"); + stream << indent() << "rank++;" << endl; + dec_indent(); + stream << indent() << "}" << endl; + } else { + stream << indent() << "(*i)->print(out);" << endl; + } dec_indent(); stream << indent() << "}" << endl; @@ -2359,11 +2376,22 @@ void Printer::Cpp::print_backtrack_pp(const AST &ast) { dec_indent(); stream << indent() << "intrusive_ptrvalue_type() - << "> > elist = bt->eval();" - << endl - << indent() << "elist->print(out, value);" << endl - << indent() << "erase(elist);" << endl - << indent() << "erase(bt);" << endl; + << "> > elist = bt->eval();" << endl; + if (ast.uses_tikz()) { + stream << indent() << "int rank = 1;" << endl; + stream << indent() << "for (Eval_List<" << *bt_type->value_type() + << ">::iterator part_bt = elist->begin(); part_bt != " + << "elist->end(); ++part_bt) {" << endl; + inc_indent(); + print_tikz_candidate(ast, "(*part_bt)", "value"); + stream << indent() << "rank++;" << endl; + dec_indent(); + stream << indent() << "}" << endl; + } else { + stream << indent() << "elist->print(out, value);" << endl; + } + stream << indent() << "erase(elist);" << endl; + stream << indent() << "erase(bt);" << endl; } dec_indent(); @@ -2434,36 +2462,51 @@ void Printer::Cpp::print_subopt_fn(const AST &ast) { print_marker_init(ast); - stream << " " << *score_type << " global_score = " << *f->name << "("; - + stream << indent() << *score_type << " global_score = " << *f->name << "("; print_axiom_args(ast); - stream << ");" << endl; if (!ast.code_mode().marker()) { - stream << " " << *f->return_type << " l = "; + stream << indent() << *f->return_type << " l = "; } - stream << f->target_name() << "("; - bool b = print_axiom_args(ast); - if (b) { stream << ", "; } - stream << "global_score, delta);" << endl; if (!ast.code_mode().marker()) { - stream << " for (" << *f->return_type->deref() - << "::iterator i " << endl - << " = l.ref().begin(); i != l.ref().end(); ++i) {" << endl; - stream << " " << *bt_type << " bt = (*i).second;" << endl - << " " << *score_type << " v = (*i).first;" << endl; - stream << " intrusive_ptr > elist = bt->eval();" << endl - << " elist->print(out, v);" << endl; - stream << " }" << endl; + if (ast.uses_tikz()) { + stream << indent() << "int rank = 1;" << endl; + } + stream << indent() << "for (" << *f->return_type->deref() + << "::iterator i = l.ref().begin(); " + << "i != l.ref().end(); ++i) {" << endl; + inc_indent(); + + stream << indent() << *bt_type << " bt = (*i).second;" << endl; + + stream << indent() << *score_type << " v = (*i).first;" << endl; + + stream << indent() << "intrusive_ptr > elist = bt->eval();" << endl; + + if (ast.uses_tikz()) { + stream << indent() << "for (Eval_List<" << *pp_type + << ">::iterator part_bt = elist->begin(); part_bt != " + << "elist->end(); ++part_bt) {" << endl; + inc_indent(); + print_tikz_candidate(ast, "(*part_bt)", "v"); + stream << indent() << "rank++;" << endl; + dec_indent(); + stream << indent() << "}" << endl; + } else { + stream << indent() << "elist->print(out, v);" << endl; + } + + dec_indent(); + stream << indent() << "}" << endl; } print_marker_clear(ast); @@ -2489,8 +2532,139 @@ void Printer::Cpp::backtrack_footer(const AST &ast) { print_backtrack_fn(ast); print_backtrack_pp(ast); print_subopt_fn(ast); + print_document_header(ast); + print_document_footer(ast); +} + +void Printer::Cpp::print_document_header(const AST & ast) { + stream << endl << indent() + << "void print_document_header(std::ostream &out) {" << endl; + inc_indent(); + + if (ast.uses_tikz()) { + // header for latex document + stream << indent() << "out << \"\\\\documentclass{article}\\n\";" << endl; + stream << indent() << "out << \"\\\\usepackage{tikz}\\n\";" << endl; + stream << indent() << "out << \"\\\\usepackage{amsmath}\\n\";" << endl; + stream << indent() << "out << \"\\\\usepackage{verbatim}\\n\";" << endl; + stream << indent() << "out << \"\\\\usetikzlibrary{external}\\n\";" << endl; + stream << indent() << "out << \"\\\\tikzexternalize[mode=list and make]" + << "\\n\";" << endl; + + stream << indent() << "out << \"\\\\tikzset{\\n\";" << endl; + stream << indent() << "out << \" png export/.style={\\n\";" << endl; + stream << indent() << "out << \" % First we call ImageMagick; change " + << "settings to requirements\\n\";" << endl; + stream << indent() << "out << \" external/system call/.add={}{; convert" + << " -density 300 -transparent white \\\"\\\\image.pdf\\\" \\\"\\" + << "\\image.png\\\"},\\n\";" << endl; + stream << indent() << "out << \" % Now we force the PNG figure to be " + << "used instead of the PDF\\n\";" << endl; + stream << indent() << "out << \" /pgf/images/external info,\\n\";" + << endl; + stream << indent() << "out << \" /pgf/images/include external/" + << ".code={\\n\";" << endl; + stream << indent() << "out << \" \\\\includegraphics[width=\\\\pgfe" + << "xternalwidth,height=\\\\pgfexternalheight]{##1.png}\\n\";" + << endl; + stream << indent() << "out << \" },\\n\";" << endl; + stream << indent() << "out << \" }\\n\";" << endl; + stream << indent() << "out << \"}\\n\";" << endl; + + stream << indent() << "out << \"\\\\begin{document}\\n\";" << endl; + stream << indent() << "out << \"\\\\tikzset{png export}\\n\";" << endl; + } + + dec_indent(); + stream << indent() << "}" << endl; +} + +void Printer::Cpp::print_document_footer(const AST & ast) { + stream << endl << indent() + << "void print_document_footer(std::ostream &out) {" << endl; + inc_indent(); + + if (ast.uses_tikz()) { + // footer for latex document + stream << indent() << "out << \"\\\\end{document}\\n\";" << endl; + stream << indent() << "out << \"\\n% You computed an instance containing " + << "the automatically generated tikZ algebra.\\n% To 'draw' these " + << "candidate trees, redirect standard output into a file and " + << "execute pdflatex on it OR\\n% directly pipe standard output " + << "to pdflatex by appending ' | pdflatex' to your previous " + << "command.\\n\";" << endl; + } + + dec_indent(); + stream << indent() << "}" << endl; +} + +void Printer::Cpp::print_tikz_singleAlgebraValue(Product::Base *product, + std::string candidate) { + Product::Base *wrk_product = product; + if (product->is(Product::OVERLAY)) { + /* return type of overlay product, as used for e.g. stochastic backtracing, + * does only hold components for the ->l part. For tikZ reporting, the + * ->r part must be omitted. */ + wrk_product = product->left(); + } + for (Product::iterator a = Product::begin(wrk_product); + a != Product::end(); ++a) { + if (((*a)->is(Product::SINGLE)) && (!(*a)->uses_tikz())) { + stream << indent() << "out << latex(\"" + << *(*a)->algebra()->name << "\") << \" & \\\\ \" << "; + stream << candidate << *wrk_product->get_component_accessor( + *(*a)->algebra()); + stream << " << \" \\\\\\\\ \";" << endl; + } + } } +bool Printer::Cpp::print_tikz_value(Product::Base *product, + std::string candidate) { + for (Product::iterator a = Product::begin(product); + a != Product::end(); ++a) { + if (((*a)->is(Product::SINGLE)) && ((*a)->uses_tikz())) { + stream << indent() << "out << " << candidate; + stream << *product->get_component_accessor(*(*a)->algebra()); + stream << ";" << endl; + return true; + } + } + return false; +} + +void Printer::Cpp::print_tikz_candidate(const AST &ast, std::string candidate, + std::string value) { + // tikz block per candidate + stream << indent() << "out << \"\\n\\\\begin{tikzpicture}\\n \\\\\";" + << endl; + + // report other algebra results per candidate as a root node + stream << indent() << "out << \"node {$\\\\begin{aligned} Rank & \\\\ \" " + << "<< std::to_string(rank) << \" \\\\\\\\ \";" << endl; + if (ast.get_backtrack_product()) { + print_tikz_singleAlgebraValue(ast.get_fwd_product(), value); + print_tikz_singleAlgebraValue(ast.get_backtrack_product(), candidate); + } else { + print_tikz_singleAlgebraValue(ast.instance_->product, candidate); + } + stream << indent() << "out << \"\\\\end{aligned}$} child {\";" << endl; + + // print TikZ string + if (ast.get_backtrack_product()) { + bool printed = print_tikz_value(ast.get_fwd_product(), value); + if (!printed) { + print_tikz_value(ast.get_backtrack_product(), candidate); + } + } else { + print_tikz_value(ast.instance_->product, candidate); + } + stream << indent() << "out << \"}\";" << endl; + + // close tikz block per candidate + stream << indent() << "out << \";\\n\\\\end{tikzpicture}\\n\\n\";" << endl; +} void Printer::Cpp::print_value_pp(const AST &ast) { stream << indent() << "template "; @@ -2508,16 +2682,37 @@ void Printer::Cpp::print_value_pp(const AST &ast) { stream << indent() << "std::lock_guard lock(print_mutex);" << endl; } - stream << indent() << "if (isEmpty(res)) {" << endl; - inc_indent(); - stream << indent() << "out << \"[]\\n\";" << endl; - dec_indent(); - stream << indent() << "} else {" << endl; - inc_indent(); - stream << indent() << "out << res << '\\n';" << endl; - dec_indent(); - stream << indent() << '}' << endl; - + if (ast.uses_tikz()) { + stream << indent() << "if (isEmpty(res)) {" << endl; + inc_indent(); + stream << indent() << "out << \"Your result list is empty!\";" << endl; + dec_indent(); + stream << indent() << "} else {" << endl; + inc_indent(); + // record rank of candidate + stream << indent() << "int rank = 1;" << endl; + // iterate through candidates + stream << indent() << "for (" + << *ast.grammar()->axiom->code()->return_type->deref() + << "::iterator i = res.ref().begin(); i != " + << "res.ref().end(); ++i, ++rank) {" << endl; + inc_indent(); + print_tikz_candidate(ast, "(*i)", "value"); + dec_indent(); + stream << indent() << "}" << endl; + dec_indent(); + stream << indent() << "}" << endl; + } else { + stream << indent() << "if (isEmpty(res)) {" << endl; + inc_indent(); + stream << indent() << "out << \"[]\\n\";" << endl; + dec_indent(); + stream << indent() << "} else {" << endl; + inc_indent(); + stream << indent() << "out << res << '\\n';" << endl; + dec_indent(); + stream << indent() << '}' << endl; + } dec_indent(); stream << indent() << '}' << endl << endl; } diff --git a/src/cpp.hh b/src/cpp.hh index c93963bd7..60dbe3f83 100644 --- a/src/cpp.hh +++ b/src/cpp.hh @@ -37,6 +37,7 @@ #include "table.hh" #include "symbol_fwd.hh" #include "para_decl_fwd.hh" +#include "product.hh" class Grammar; class AST; @@ -80,6 +81,20 @@ class Cpp : public Base { void print_run_fn(const AST &ast); void print_stats_fn(const AST &ast); + /* generate code to print statements prior to result list, useful e.g. to + * include statements for LaTeX documents when generating TikZ candidates */ + void print_document_header(const AST &ast); + /* generate code to print one line of the root node of a tikz candidate + * tree for an algebra value, e.g. let product be "(mfe * pfunc) * tikz" + * two lines for mfe and pfunc shall be listed in the root node */ + void print_tikz_singleAlgebraValue( + Product::Base *product, std::string candidate); + /* generate code to print the LaTeX tikZ generated string that represents + * the candidate tree. Return false if product does not contain tikz auto + * generated algebra */ + bool print_tikz_value(Product::Base *product, std::string candidate); + void print_tikz_candidate(const AST &ast, std::string candidate, + std::string value); void print_value_pp(const AST &ast); void print(const std::list &types, @@ -95,6 +110,11 @@ class Cpp : public Base { void print_marker_clear(const AST &ast); public: + /* generate code to print statements after reporing the result list, + * useful e.g. to include statements for LaTeX documents when generating + * TikZ candidates */ + void print_document_footer(const AST &ast); + bool in_class; std::string class_name; Cpp() diff --git a/src/instance.cc b/src/instance.cc index 63460b00d..50dc1db72 100644 --- a/src/instance.cc +++ b/src/instance.cc @@ -192,3 +192,15 @@ void Instance::check_alphabets() { "Alphabet types of algebras in the product are not compatible "); } } + +bool Instance::uses_tikz() { + for (Product::iterator i = Product::begin(product); + i != Product::end(); ++i) { + if ((*i)->is(Product::SINGLE)) { + if ((*i)->algebra()->get_auto_role() == Algebra::TIKZ) { + return true; + } + } + } + return false; +} diff --git a/src/instance.hh b/src/instance.hh index 229dacbf7..4a0ca3e1d 100644 --- a/src/instance.hh +++ b/src/instance.hh @@ -93,6 +93,11 @@ class Instance { * Thus, we need to make sure that the user does not request outside with * instances that use a signature with multiple answer types */ bool check_multiple_answer_types(bool for_outside_generation); + + /* True, if one of the algebras in the product is the auto generated tikz + * algebra. This needs to be known, to change how output in presented. + */ + bool uses_tikz(); }; inline std::ostream &operator<<(std::ostream &s, const Instance &i) { diff --git a/src/parser.y b/src/parser.y index c0b3e8efb..b2d158cec 100644 --- a/src/parser.y +++ b/src/parser.y @@ -750,12 +750,12 @@ algebra: algebra_head '{' fn_defs '}' + " already defined "); error(driver.ast.algebras[*$2]->location, "here."); } else { - Algebra *algebra = driver.ast.signature->generate($2, $4); + Algebra *algebra = driver.ast.signature->generate($2, $4, driver.ast.input); if (algebra) driver.ast.algebras[*$2] = algebra; else error(@4, "Unknown automatic modifier " + *$4 + - ". Use something like count ..."); + ". Use 'count', 'enum' or 'tikz'."); } } ; @@ -764,7 +764,8 @@ algebra: algebra_head '{' fn_defs '}' \begin{lstlisting} automatic_specifier: @enum@ | - @count@ + @count@ | + @tikz@ ; \end{lstlisting} The {\tt automatic} keyword specifies the auto generation of the diff --git a/src/product.cc b/src/product.cc index 1b3720749..0cb111948 100644 --- a/src/product.cc +++ b/src/product.cc @@ -1074,3 +1074,25 @@ Product::Times::Times(Base *a, Base *b, const Loc &lo) : Two(TIMES, lo, a, b) { Product::Two::Two(Type t, const Two &x) : Base(t), l(x.l), r(x.r) { } + +bool Product::Single::contains_algebra(Algebra &a) { + return this->algebra_ == &a; +} +bool Product::Two::contains_algebra(Algebra &a) { + return l->contains_algebra(a) || r->contains_algebra(a); +} + +std::string *Product::Single::get_component_accessor(Algebra &a) { + return new std::string(""); +} +std::string *Product::Two::get_component_accessor(Algebra &a) { + std::string *acc; + if (l->contains_algebra(a)) { + acc = new std::string(".first" + *l->get_component_accessor(a)); + } else if (r->contains_algebra(a)) { + acc = new std::string(".second" + *r->get_component_accessor(a)); + } else { + acc = new std::string(""); + } + return acc; +} diff --git a/src/product.hh b/src/product.hh index f93f48fc6..d03a0cfc2 100644 --- a/src/product.hh +++ b/src/product.hh @@ -201,6 +201,24 @@ class Base { void set_sort_product(Base *sp) { sort_product = sp; } + + /* A product can be a tuple of tuples of ... and one specific algebra + * is then nested within this structure. To test if the singular algebra is + * either contained in the first or second component, we need to down traverse + * and check the sub-structure for presence of this algebra. + */ + virtual bool contains_algebra(Algebra &a) = 0; + /* A product can be a tuple of tuples of ... + * If we to generate code that accesses a specific singular algebra, it must + * be a concatenation of .first / .second accessors. We construct this string + * with the call of this function. + */ + virtual std::string *get_component_accessor(Algebra &a) = 0; + + /* tests if an algebra product contains somewhere the auto generated tikZ + * algebra. This needs to be known to influence candidate output presentation. + */ + virtual bool uses_tikz() = 0; }; @@ -239,6 +257,13 @@ class Single : public Base { std::list &compare_code) const; Base *replace_classified(bool &x); + + bool contains_algebra(Algebra &a); + std::string *get_component_accessor(Algebra &a); + + bool uses_tikz() { + return algebra_->get_auto_role() == Algebra::TIKZ; + } }; @@ -287,6 +312,12 @@ class Two : public Base { void init_vacc(Var_Acc::Base *src, Var_Acc::Base *dst); Base *replace_classified(bool &x); + + bool contains_algebra(Algebra &a); + std::string *get_component_accessor(Algebra &a); + bool uses_tikz() { + return l->uses_tikz() || r->uses_tikz(); + } }; diff --git a/src/signature.cc b/src/signature.cc index ccfc54b22..9442c2294 100644 --- a/src/signature.cc +++ b/src/signature.cc @@ -23,8 +23,10 @@ #include #include +#include #include "signature.hh" +#include "input.hh" #include "arg.hh" #include "fn_decl.hh" @@ -33,6 +35,7 @@ #include "statement.hh" #include "expr/new.hh" #include "type/backtrace.hh" +#include "plot_grammar.hh" Signature_Base::~Signature_Base() {} @@ -144,11 +147,13 @@ Type::Base *Signature::var_lookup(const Type::Alphabet *t) { } -Algebra *Signature::generate(std::string *n, std::string *mode) { +Algebra *Signature::generate(std::string *n, std::string *mode, Input inputs) { if (*mode == "count") return generate_count(n); if (*mode == "enum") return generate_enum(n); + if (*mode == "tikz") + return generate_tikz(n, inputs); return NULL; } @@ -161,17 +166,19 @@ struct Generate_Stmts { Algebra *Signature::generate_algebra( std::string *n, Mode::Type mode_type, Type::Base *answer_type, - const Generate_Stmts &generate_stmts) { + const Generate_Stmts &generate_stmts, Algebra::AutoRole role) { // FIXME make count/enum alphabet agnostic Type::Base *alph = new Type::Char(); - return generate_algebra(n, mode_type, answer_type, alph, generate_stmts); + return generate_algebra(n, mode_type, answer_type, alph, generate_stmts, + role); } Algebra *Signature::generate_algebra( std::string *n, Mode::Type mode_type, Type::Base *answer_type, - Type::Base *alpha, const Generate_Stmts &generate_stmts) { - Algebra *a = new Algebra(n); + Type::Base *alpha, const Generate_Stmts &generate_stmts, + Algebra::AutoRole role) { + Algebra *a = new Algebra(n, role); a->signature = this; hashtable eqs; Loc l; @@ -266,7 +273,7 @@ struct Generate_Count_Stmts : public Generate_Stmts { Algebra *Signature::generate_count(std::string *n) { return generate_algebra(n, Mode::SYNOPTIC, new Type::BigInt(), - Generate_Count_Stmts()); + Generate_Count_Stmts(), Algebra::COUNT); } @@ -409,7 +416,211 @@ struct Generate_Enum_Stmts : public Generate_Stmts { Algebra *Signature::generate_enum(std::string *n) { return generate_algebra(n, Mode::PRETTY, new Type::External("Rope"), - Generate_Enum_Stmts()); + Generate_Enum_Stmts(), Algebra::ENUM); +} + + +struct Generate_TikZ_Stmts : public Generate_Stmts { + private: + Input inputs; + + public: + explicit Generate_TikZ_Stmts(Input inputs) { + this->inputs = inputs; + } + + private: + void apply(std::list &l, Para_Decl::Simple *s, + Statement::Var_Decl *&cur, Input::Mode inp, bool isNTparam) const { + Statement::Fn_Call *f; + + Type::Usage *type = dynamic_cast(s->type()); + if (type->base->is(Type::SIGNATURE)) { + } else { + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + std::string *color = new std::string(COLOR_TERMINAL); + if (isNTparam) { + color = new std::string(COLOR_INDICES); + } + f->add_arg(new Expr::Const(std::string("\\\\color[HTML]{") + \ + color->substr(1, color->size()-1) + std::string("} "))); + f->add_arg(new Expr::Const(21)); + l.push_back(f); + } + + if (type->base->is(Type::SUBSEQ)) { + if (inp == Input::RNA) { + // for RNA programs + f = new Statement::Fn_Call("append_deep_rna_loc"); + } else { + f = new Statement::Fn_Call("append_latex"); + } + f->add_arg(*cur); + f->add_arg(s->name()); + } else { + if (type->base->is(Type::VOID)) { + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const("\\\\epsilon ")); + f->add_arg(new Expr::Const(9)); + } else if (type->base->is(Type::ALPHABET)) { + f = new Statement::Fn_Call("append_latex"); + f->add_arg(*cur); + f->add_arg(s->name()); + } else { + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(s->name()); + } + } + l.push_back(f); + } + + + void apply(std::list &l, Para_Decl::Multi *m, + Statement::Var_Decl *&cur, bool isNTparam) const { + Statement::Fn_Call *f; + + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const("child { node {$\\\\begin{aligned} ")); + f->add_arg(new Expr::Const(31)); + l.push_back(f); + + const std::list &p = m->list(); + std::vector::const_iterator inp = this->inputs.modes().begin(); + for (std::list::const_iterator j = p.begin(); + j != p.end(); ++j, ++inp) { + apply(l, *j, cur, *inp, isNTparam); + if (std::next(j) != p.end()) { + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const(" \\\\\\\\ ")); + f->add_arg(new Expr::Const(4)); + l.push_back(f); + } + } + + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const("\\\\end{aligned}$ } } ")); + f->add_arg(new Expr::Const(19)); + l.push_back(f); + } + + + void apply(std::list &l, + const std::list ¶s, + Statement::Var_Decl *&cur, bool isNTparam) const { + std::list apps; + Statement::Fn_Call *f; + + for (std::list::const_iterator i = paras.begin(); + i != paras.end(); ++i) { + // check if param is part of multitrack + Para_Decl::Multi *m = dynamic_cast(*i); + if (m) { + // param in multi track context + apply(l, m, cur, isNTparam); + } else { + // param in single track context + Para_Decl::Simple *s = dynamic_cast(*i); + Type::Usage *type = dynamic_cast(s->type()); + // param to base set + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const("child { ")); + f->add_arg(new Expr::Const(8)); + l.push_back(f); + + if (!type->base->is(Type::SIGNATURE)) { + // param to alphabet + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const("node {$")); + f->add_arg(new Expr::Const(6+1)); + l.push_back(f); + } + + if (this->inputs.modes().size() > 0) { + apply(l, s, cur, *this->inputs.modes().begin(), isNTparam); + } else { + // a user might have skiped the "input" declaration at all + // it then defaults to single track raw + apply(l, s, cur, Input::RAW, isNTparam); + } + + if (!type->base->is(Type::SIGNATURE)) { + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const("$} ")); + f->add_arg(new Expr::Const(2+1)); + l.push_back(f); + } + + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*cur); + f->add_arg(new Expr::Const("} ")); + f->add_arg(new Expr::Const(2)); + l.push_back(f); + } + } + l.insert(l.end(), apps.begin(), apps.end()); + } + + + public: + void apply(Fn_Def &fn) const { + if (fn.is_Choice_Fn()) { + Statement::Return *ret = new Statement::Return(fn.names.front()); + fn.stmts.push_back(ret); + return; + } + Type::External *str = new Type::External("Rope"); + Statement::Var_Decl *ret = new Statement::Var_Decl(str, "ret"); + fn.stmts.push_back(ret); + + Statement::Fn_Call *f = new Statement::Fn_Call( + Statement::Fn_Call::STR_APPEND); + f->add_arg(*ret); + std::string *color = new std::string(COLOR_ALGFCT); + + f->add_arg(new Expr::Const("node {\\\\color[HTML]{" + \ + color->substr(1, color->size()-1) + "} ")); + f->add_arg(new Expr::Const(27)); + fn.stmts.push_back(f); + + f = new Statement::Fn_Call("append_latex"); + f->add_arg(*ret); + f->add_arg(new Expr::Const(*fn.name)); + f->add_arg(new Expr::Const(static_cast(fn.name->size()))); + fn.stmts.push_back(f); + + f = new Statement::Fn_Call(Statement::Fn_Call::STR_APPEND); + f->add_arg(*ret); + f->add_arg(new Expr::Const("} ")); + f->add_arg(new Expr::Const(2)); + fn.stmts.push_back(f); + + Statement::Var_Decl *cur = ret; + std::list l; + apply(l, fn.paras, cur, false); + + if (fn.ntparas().size() > 0) { + apply(l, fn.ntparas(), cur, true); + } + fn.stmts.insert(fn.stmts.end(), l.begin(), l.end()); + + Statement::Return *r = new Statement::Return(*ret); + fn.stmts.push_back(r); + } +}; + + +Algebra *Signature::generate_tikz(std::string *n, Input inputs) { + return generate_algebra(n, Mode::PRETTY, new Type::External("Rope"), + Generate_TikZ_Stmts(inputs), Algebra::TIKZ); } @@ -437,10 +648,10 @@ struct Generate_Backtrace_Stmts : public Generate_Stmts { Algebra *Signature::generate_backtrace( std::string *n, Type::Base *value_type, Type::Base *pos_type, - Type::Base *alph) { + Type::Base *alph, Algebra::AutoRole role) { Generate_Backtrace_Stmts gen; gen.value_type = value_type; gen.pos_type = pos_type; return generate_algebra(n, Mode::PRETTY, - new Type::Backtrace(pos_type, value_type), alph, gen); + new Type::Backtrace(pos_type, value_type), alph, gen, role); } diff --git a/src/signature.hh b/src/signature.hh index 69b09d731..0ce357075 100644 --- a/src/signature.hh +++ b/src/signature.hh @@ -32,7 +32,7 @@ #include "hashtable.hh" #include "loc.hh" #include "type.hh" - +#include "input.hh" #include "signature_base.hh" #include "algebra.hh" @@ -92,22 +92,25 @@ class Signature : public Signature_Base { void reset_algebra() { algebra = NULL; } - Algebra *generate(std::string *n, std::string *mode); + Algebra *generate(std::string *n, std::string *mode, Input inputs); private: Algebra *generate_count(std::string *n); Algebra *generate_enum(std::string *n); + Algebra *generate_tikz(std::string *n, Input inputs); Algebra *generate_algebra( std::string *n, Mode::Type mode_type, Type::Base *answer_type, - Type::Base *alph, const Generate_Stmts &generate_stmts); + Type::Base *alph, const Generate_Stmts &generate_stmts, + Algebra::AutoRole role); Algebra *generate_algebra( std::string *n, Mode::Type mode_type, Type::Base *answer_type, - const Generate_Stmts &generate_stmts); + const Generate_Stmts &generate_stmts, + Algebra::AutoRole role); public: Algebra *generate_backtrace( std::string *n, Type::Base *value_type, Type::Base *pos_type, - Type::Base *alph); + Type::Base *alph, Algebra::AutoRole role); }; diff --git a/testdata/grammar/adpf.gap b/testdata/grammar/adpf.gap index 298e67066..3cc38d860 100644 --- a/testdata/grammar/adpf.gap +++ b/testdata/grammar/adpf.gap @@ -101,7 +101,7 @@ synoptic algebra icount implements FS(alphabet = char, comp = int) algebra count auto count ; algebra enum auto enum ; - +algebra tikz auto tikz ; algebra pretty implements FS(alphabet = char, comp = string) { @@ -708,5 +708,10 @@ instance prettyshape = fold ( pretty * shape5 ) ; instance mfepf = fold ( mfe * p_func) ; - - +instance tikzpretty = fold ( tikz * enum * pretty) ; +instance tikzbacktrace = fold ( (mfe * p_func) * (tikz * pretty)); +instance identifyTikz1 = fold ( mfe * tikz * pretty ); +instance identifyTikz2 = fold ( mfe * pretty * tikz); +instance identifyTikz3 = fold ( mfe * tikz * pretty * tikz); +instance identifyTikz4 = fold ( tikz * mfe * pretty); +instance pfsampletikzpp = fold ( ( (p_func | p_func_id ) * (tikz * pretty ) ) suchthat sample_filter ) ; diff --git a/testdata/grammar/aliglob2.gap b/testdata/grammar/aliglob2.gap index 808027e5d..02ca69e65 100644 --- a/testdata/grammar/aliglob2.gap +++ b/testdata/grammar/aliglob2.gap @@ -13,6 +13,7 @@ signature Alignment (alphabet, answer) { algebra count auto count; algebra enum auto enum; +algebra tikz auto tikz; grammar globsim uses Alignment (axiom=alignment) { tabulated{alignment} @@ -23,4 +24,7 @@ grammar globsim uses Alignment (axiom=alignment) { } -instance enum = globsim(enum); \ No newline at end of file +instance enum = globsim(enum); + +instance enumtikz = globsim ( enum * tikz ) ; +instance tikz = globsim ( tikz ) ; diff --git a/testdata/grammar/flowgram2b.gap b/testdata/grammar/flowgram2b.gap index eea8cac35..035bb59d4 100644 --- a/testdata/grammar/flowgram2b.gap +++ b/testdata/grammar/flowgram2b.gap @@ -21,7 +21,7 @@ signature Align(alphabet, answer) { algebra count auto count ; algebra enum auto enum; - +algebra tikz auto tikz; algebra pretty implements Align(alphabet = single, answer = spair ) { spair r( , spair m) { @@ -242,3 +242,4 @@ instance mismatch_seqlen = flow(mismatch_seqlen); instance count = flow(count); instance enum = flow(enum); +instance tikz = flow (tikz); \ No newline at end of file diff --git a/testdata/grammar/nussinov.gap b/testdata/grammar/nussinov.gap index 93aa9f344..9ee822524 100644 --- a/testdata/grammar/nussinov.gap +++ b/testdata/grammar/nussinov.gap @@ -120,7 +120,7 @@ algebra count implements Nuss(alphabet = char, answer = int) } - +algebra tikz auto tikz; grammar nussinov uses Nuss (axiom=start) { tabulated { start, bp } @@ -148,4 +148,4 @@ instance bpmax1pp = nussinov ( bpmax . pretty ) ; instance kbpmaxpp = nussinov ( bpmax2 * pretty ) ; - +instance testbt = nussinov ((bpmax * bpmax) * (tikz * pretty)); diff --git a/testdata/grammar/pknotsRG.gap b/testdata/grammar/pknotsRG.gap index 561224604..996d94e7b 100644 --- a/testdata/grammar/pknotsRG.gap +++ b/testdata/grammar/pknotsRG.gap @@ -58,8 +58,8 @@ signature Algebra(alphabet, comp, compKnot) { choice [comp] h([comp]); choice [compKnot] hKnot([compKnot]); } - - +algebra enum auto enum; +algebra tikz auto tikz; algebra mfe implements Algebra(alphabet = char, comp = int, compKnot = mfeanswer) { int sadd(Subsequence b, int x) { return x; @@ -1658,3 +1658,4 @@ acgucgaaauaaaugccuugucugcuauauucgacg // TODO Shape Algebren fertig bekommen /* CGGCACCCAGCCGGGGCGGAGUCCGCGAAUGGG */ +instance prettyTikzMfe = pknotsRG((enforce * mfe) * pretty * tikz); \ No newline at end of file diff --git a/testdata/grammar/rnashapesmfe.gap b/testdata/grammar/rnashapesmfe.gap index 874afd681..de97ef019 100644 --- a/testdata/grammar/rnashapesmfe.gap +++ b/testdata/grammar/rnashapesmfe.gap @@ -49,7 +49,7 @@ algebra count auto count ; algebra enum auto enum ; - +algebra tikz auto tikz ; algebra mfe implements Canonical_Algebra(alphabet = char, answer = mfeanswer) { mfeanswer sadd(Subsequence lb,mfeanswer e) { @@ -939,3 +939,4 @@ instance mfeppshape = canonicals_nonamb ( mfe * (pretty * shape5) ) ; instance mfeppen = canonicals_nonamb ( mfe * (pretty * enum) ) ; instance pretty = canonicals_nonamb ( pretty ) ; instance shape5 = canonicals_nonamb ( (shape5 * mfe) * pretty) ; +instance mfetikzshape = canonicals_nonamb ( mfe * (tikz * shape5) ) ; diff --git a/testdata/grammar_outside/hmm_sonneregen.gap b/testdata/grammar_outside/hmm_sonneregen.gap index 8821c9f8d..dd8094006 100644 --- a/testdata/grammar_outside/hmm_sonneregen.gap +++ b/testdata/grammar_outside/hmm_sonneregen.gap @@ -19,6 +19,7 @@ signature sig_weather(alphabet, answer) { algebra alg_enum auto enum; algebra alg_count auto count; +algebra alg_tikz auto tikz; algebra alg_viterbi implements sig_weather(alphabet=char, answer=float) { float transition_start_hoch(float transition, float emission, float x) { @@ -249,3 +250,5 @@ instance viterbistatesmult = gra_weather(alg_viterbi * alg_states * alg_mult); instance fwd = gra_weather(alg_fwd); instance multviterbistates = gra_weather(alg_mult * alg_viterbi * alg_states); instance count = gra_weather(alg_count); +instance tikz = gra_weather(alg_tikz); +instance tikzbtrace = gra_weather(alg_viterbi * alg_tikz); diff --git a/testdata/regresstest/config b/testdata/regresstest/config index eaeb43efe..8b2048b08 100644 --- a/testdata/regresstest/config +++ b/testdata/regresstest/config @@ -632,3 +632,52 @@ GAPC="../../../gapc --outside_grammar weak --cyk --checkpoint" check_checkpoint_eq nodangle.gap unused pfunc "GUAAAAUAGGUUUUUUACCUCGGUAUGCCUUGUGACUGGCUUGACAAGCUUUUCCUCAGCUCCGUAAACUCCUUUCAGUGGGAAAUUGUGGGGCAAAGUGGGAAUAAGGGGUGAGGCUGGCAUGUUCCGGGGAGCAACGUUAGUCAAUCUCGACAGCAAAGGGCGCUUAUCAGUGCCUACCCGUUAUCGGGAACAGCUGCUUGAGAACGCUGCCGGUCAAAUGGUUUGCACCAUUGACAUUUAUCACCCGUGCCUGCUGCUUUACCCCCUGCCUGAAUGGGAAAUUAUCGAGC" cyk_cp_outside_single 1 CPPFLAGS_EXTRA="" + +# test auto generated "tikz" algebra +GRAMMAR=../../grammar +GAPC="../../../gapc" +check_new_old_eq_twotrack aliglob2.gap unused enumtikz "IT" tikz_nw "ST" + +CPPFLAGS_EXTRA=$DEFAULT_CPPFLAGS_EXTRA +check_new_old_eq adpf.gap unused tikzpretty "CCaaaGG" tikzpretty + +GRAMMAR=../../grammar_outside +check_new_old_eq hmm_sonneregen.gap unused tikz "SSRR" tikzhmm +check_new_old_eq hmm_sonneregen.gap unused tikzbtrace "T" tikzempty +GAPC="../../../gapc --kbacktrace" +check_new_old_eq hmm_sonneregen.gap unused tikzbtrace "T" tikzemptybt + +# check if RAW and RNA inputs are differentiated +GAPC="../../../gapc" +GRAMMAR=../../grammar +check_new_old_eq_twotrack flowgram2b.gap unused tikz Hallo tikzflow "W" + +# check that backtracing does not violate assumption that left/right_running_indices must be empty +GRAMMAR=../../grammar +GAPC="../../../gapc --kbacktrace" +check_new_old_eq adpf.gap unused tikzbacktrace "CCaaaGG" tikztrace +GAPC="../../../gapc --backtrace" +check_new_old_eq adpf.gap unused tikzbacktrace "CCaaaGG" tikzbatrace + +RUN_CPP_FLAGS=" -r2 " +check_new_old_eq nussinov.gap unused testbt "CGCGCG" tikztrace + +GAPC="../../../gapc --subopt" +RUN_CPP_FLAGS=" -d1000 " +check_new_old_eq rnashapesmfe.gap unused mfetikzshape "CCAAAGG" tikzsubopt + +GAPC="../../../gapc --window" +RUN_CPP_FLAGS=" -w7 -i1 " +check_new_old_eq rnashapesmfe.gap unused mfetikzshape "cCCAAAGGg" tikzwindow + +GAPC="../../../gapc" +RUN_CPP_FLAGS="" +check_new_old_eq_twotrack aliglob2.gap unused tikz "\"#$%&\^_{}~\"" tikzEscape "X" +check_new_old_eq_twotrack flowgram2b.gap unused tikz "#$&^" tikzEscape "O" + +# test reporting of algebra function parameters like "back(...; int k)" +check_new_old_eq pknotsRG.gap unused prettyTikzMfe "cgucgaaauaaaugccuu" tikzntparam + +GAPC="../../../gapc --sample" +RUN_CPP_FLAGS=" -r 3 " +check_new_old_eq adpf.gap unused pfsampletikzpp "GUAAAAUAGGUUUUUUACCUCGGUAUGCCUUGUGACUGGCUUGAC" tikzsample diff --git a/testdata/unittest/rope.cc b/testdata/unittest/rope.cc index 446f34c5f..1a60e1c72 100644 --- a/testdata/unittest/rope.cc +++ b/testdata/unittest/rope.cc @@ -31,6 +31,7 @@ #include "macros.hh" +#include "../../rtlib/subsequence.hh" #include "../../rtlib/rope.hh" #define STATS #include "../../rtlib/hash.hh"