/* * Copyright (C) 1999, 2000, 2001, 2002 * Heikki Tauriainen * * This program 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 2 * of the License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef __GNUC__ #pragma implementation #endif /* __GNUC__ */ #include #include #include "DispUtil.h" #include "Exception.h" #include "SharedTestData.h" #include "StatDisplay.h" #include "StringUtil.h" #include "TestRoundInfo.h" namespace StatDisplay { using namespace ::DispUtil; using namespace ::SharedTestData; using namespace ::StringUtil; /* ========================================================================= */ void printBuchiAutomatonStats (ostream& stream, int indent, vector::size_type algorithm, int result_id) /* ---------------------------------------------------------------------------- * * Description: Displays information about a Büchi automaton, extracting the * information from a TestStatistics structure stored in the * UserInterface object. * * Arguments: stream -- A reference to the output stream to which the * information should be written. * indent -- Number of spaces to leave on the left of the * output. * algorithm -- Identifier of the algorithm used for * generating the automaton. * result_id -- Selects between the automata constructed from * a formula and its negation. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); const AutomatonStats& automaton_stats = test_results[algorithm].automaton_stats[result_id]; estream << string(indent, ' '); if (!automaton_stats.buchiAutomatonComputed()) estream << "not computed"; else { estream << "number of states:" + string(6, ' ') + toString(automaton_stats.number_of_buchi_states) + '\n' + string(indent, ' ') + "number of transitions: " + toString(automaton_stats.number_of_buchi_transitions) + '\n' + string(indent, ' ') + "acceptance sets:" + string(7, ' ') + toString(automaton_stats.number_of_acceptance_sets) + '\n' + string(indent, ' ') + "computation time:" + string(6, ' '); if (automaton_stats.buchi_generation_time != -1.0) { changeStreamFormatting(stream, 9, 2, ios::fixed | ios::left); estream << automaton_stats.buchi_generation_time; restoreStreamFormatting(stream); estream << " seconds (user time)"; } else estream << "N/A"; } estream << '\n'; estream.flush(); } /* ========================================================================= */ void printProductAutomatonStats (ostream& stream, int indent, vector::size_type algorithm, int result_id) /* ---------------------------------------------------------------------------- * * Description: Displays information about a product automaton, extracting * the information from a TestStatistics structure stored in the * UserInterface object. * * Arguments: stream -- A reference to the output stream to which the * information should be written. * indent -- Number of spaces to leave on the left of the * output. * algorithm -- Identifier of the algorithm used for * generating the product automaton. * result_id -- Selects between the automata constructed from * a formula and its negation. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); const AutomatonStats& automaton_stats = test_results[algorithm].automaton_stats[result_id]; estream << string(indent, ' '); if (!automaton_stats.productAutomatonComputed()) estream << "not computed"; else { estream << "number of states:" + string(6, ' '); changeStreamFormatting(stream, 9, 0, ios::left); estream << automaton_stats.number_of_product_states; restoreStreamFormatting(stream); estream << " ["; if (automaton_stats.number_of_product_states != 0) { changeStreamFormatting(stream, 0, 2, ios::fixed); estream << static_cast (automaton_stats.number_of_product_states) / static_cast(automaton_stats.number_of_buchi_states) / static_cast(round_info.statespace->size()) * 100.0; restoreStreamFormatting(stream); estream << "% of worst case (" << automaton_stats.number_of_buchi_states * round_info.statespace->size() << ')'; } else estream << "empty automaton"; estream << "]\n" + string(indent, ' ') + "number of transitions: " + toString(automaton_stats.number_of_product_transitions); } estream << '\n'; estream.flush(); } /* ========================================================================= */ void printAcceptanceCycleStats (ostream& stream, int indent, vector::size_type algorithm, int result_id) /* ---------------------------------------------------------------------------- * * Description: Displays information about the number of system states from * which begins an execution accepted by a Büchi automaton. The * information is extracted from a TestStatistics structure * stored in the UserInterface object. * * Arguments: stream -- A reference to the output stream to which the * information should be written. * indent -- Number of spaces to leave on the left of the * output. * algorithm -- Identifier of the algorithm used for * computing the Büchi automaton whose accepting * cycles are to be considered. * result_id -- Selects between the result computed for a * formula and its negation. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); const AutomatonStats& automaton_stats = test_results[algorithm].automaton_stats[result_id]; estream << string(indent, ' '); if (!automaton_stats.emptiness_check_performed) estream << "not computed"; else if (configuration.global_options.product_mode == Configuration::LOCAL) { estream << string("cycle "); if (automaton_stats.emptiness_check_result[0]) estream << "reachable "; else estream << "not reachable"; estream << " (from the initial state)"; } else { estream << "cycle reachable from "; changeStreamFormatting(stream, 9, 0, ios::left); estream << automaton_stats.emptiness_check_result.count(); restoreStreamFormatting(stream); estream << " states\n" + string(indent, ' ') + "not reachable from "; changeStreamFormatting(stream, 9, 0, ios::left); estream << (round_info.real_emptiness_check_size - automaton_stats.emptiness_check_result.count()); restoreStreamFormatting(stream); estream << " states"; } estream << '\n'; estream.flush(); } /* ========================================================================= */ void printConsistencyCheckStats (ostream& stream, int indent, vector::size_type algorithm) /* ---------------------------------------------------------------------------- * * Description: Displays information about the consistency check result for * a given algorithm, extracting the information from a * TestStatistics structure stored in the UserInterface object. * * Arguments: stream -- A reference to an output stream to which the * information should be written. * indent -- Number of spaces to leave on the left of the * output. * algorithm -- Identifier of the algorithm whose consistency * check result should be displayed. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); const AlgorithmTestResults& test_result = test_results[algorithm]; estream << string(indent, ' '); if (test_result.consistency_check_result == -1) estream << "not performed"; else { estream << "result:" + string(18, ' '); if (test_result.consistency_check_result == 0) { estream << "failed [" + toString(test_result.failed_consistency_check_comparisons) + " ("; changeStreamFormatting(stream, 0, 2, ios::fixed); estream << ((test_result.consistency_check_comparisons == 0) ? 0.0 : static_cast (test_result.failed_consistency_check_comparisons) / test_result.consistency_check_comparisons * 100.0); restoreStreamFormatting(stream); estream << "%) of " + toString(test_result.consistency_check_comparisons) + " test cases]"; } else estream << "passed"; } estream << '\n'; estream.flush(); } /* ========================================================================= */ void printCrossComparisonStats (ostream& stream, int indent, vector::size_type algorithm) /* ---------------------------------------------------------------------------- * * Description: Displays information about the model checking result cross- * comparison check, extracting the information from a vector of * TestStatistics structures stored in the UserInterface object. * * Arguments: stream -- A reference to an output stream to which the * information should be written. * indent -- Number of spaces to leave on the left of the * output. * algorithm -- If less than the number of algorithms, show * only the results for the algorithm with this * identifier. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); bool no_errors_to_report = true; if (algorithm < configuration.algorithms.size() && !configuration.algorithms[algorithm].enabled) { estream << string(indent, ' ') + "not performed\n\n"; estream.flush(); return; } estream << string(indent, ' ') + "result:"; const AutomatonStats* alg_1_pos_results; const AutomatonStats* alg_1_neg_results; for (vector::size_type alg_1 = 0; alg_1 < test_results.size(); alg_1++) { alg_1_pos_results = &test_results[alg_1].automaton_stats[0]; alg_1_neg_results = &test_results[alg_1].automaton_stats[1]; for (vector::size_type alg_2 = alg_1 + 1; alg_2 < test_results.size(); alg_2++) { if ((algorithm >= configuration.algorithms.size() || alg_1 == algorithm || alg_2 == algorithm) && configuration.algorithms[alg_1].enabled && configuration.algorithms[alg_2].enabled) { bool pos_test, neg_test; for (int counter = 0; counter < 2; counter++) { if (counter == 0) { pos_test = !alg_1_pos_results->crossComparisonPerformed(alg_2); neg_test = !alg_1_neg_results->crossComparisonPerformed(alg_2); } else { pos_test = (alg_1_pos_results->cross_comparison_stats[alg_2]. second > 0); neg_test = (alg_1_neg_results->cross_comparison_stats[alg_2]. second > 0); } if (pos_test || neg_test) { estream << '\n' + string(indent + 2, ' '); no_errors_to_report = false; estream << string(counter == 0 ? "N/A " : "failed") + " ("; if (pos_test) estream << string("+") + (neg_test ? "-)" : ") "); else estream << "-) "; estream << ' '; if (alg_1 == round_info.number_of_translators) estream << "lbtt"; else estream << configuration.algorithmString(alg_1); estream << ", "; if (alg_2 == round_info.number_of_translators) estream << "lbtt"; else estream << configuration.algorithmString(alg_2); } } } } } if (no_errors_to_report) estream << string(20, ' ') + "no failures detected"; estream << "\n\n"; estream.flush(); } /* ========================================================================= */ void printBuchiIntersectionCheckStats (ostream& stream, int indent, vector::size_type algorithm) /* ---------------------------------------------------------------------------- * * Description: Displays information about the Büchi automaton intersection * emptiness check results, extracting the information from a * TestStatistics structure stored in the UserInterface object. * * Arguments: stream -- A reference to an output stream to which the * information should be written. * indent -- Number of spaces to leave on the left of the * output. * algorithm -- If less than the number of algorithms, show * only the results for the algorithm with this * identifier. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); bool no_errors_to_report = true; if (algorithm < round_info.number_of_translators && !configuration.algorithms[algorithm].enabled) { estream << string(indent, ' ') + "not performed\n\n"; estream.flush(); return; } estream << string(indent, ' ') + "result:"; const AutomatonStats* alg_1_pos_results; const AutomatonStats* alg_1_neg_results; for (vector::size_type alg_1 = 0; alg_1 < round_info.number_of_translators; alg_1++) { alg_1_pos_results = &test_results[alg_1].automaton_stats[0]; alg_1_neg_results = &test_results[alg_1].automaton_stats[1]; for (vector::size_type alg_2 = alg_1; alg_2 < round_info.number_of_translators; alg_2++) { if ((algorithm >= round_info.number_of_translators || alg_1 == algorithm || alg_2 == algorithm) && configuration.algorithms[alg_1].enabled && configuration.algorithms[alg_2].enabled) { bool pos_test, neg_test; for (int counter = -1; counter < 1; counter++) { pos_test = (alg_1_pos_results->buchi_intersection_check_stats[alg_2] == counter); neg_test = (alg_1_neg_results->buchi_intersection_check_stats[alg_2] == counter); if (pos_test || neg_test) { estream << '\n' + string(indent + 2, ' '); no_errors_to_report = false; estream << string(counter == -1 ? "N/A " : "failed") + ' '; if (alg_1 != alg_2) { estream << '('; if (pos_test) estream << string("+") + (neg_test ? "-)" : ") "); else estream << "-) "; } else estream << " "; estream << ' ' + configuration.algorithmString(alg_1); if (alg_1 != alg_2) { estream << ", ("; if (pos_test) estream << string("-") + (neg_test ? "+" : ""); else estream << '+'; estream << ") " + configuration.algorithmString(alg_2); } } } } } } if (no_errors_to_report) estream << string(20, ' ') + "no failures detected"; estream << "\n\n"; estream.flush(); } /* ========================================================================= */ void printAllStats (ostream& stream, int indent, vector::size_type algorithm) /* ---------------------------------------------------------------------------- * * Description: Displays all test information (Büchi automaton and product * automaton statistics, acceptance cycle information, * consistency check result) for an algorithm. * * Arguments: stream -- A reference to an output stream to which the * information should be written. * indent -- Number of spaces to leave on the left of the * output. * algorithm -- Identifier of an algorithm. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); estream << string(indent, ' ') + configuration.algorithmString(algorithm) + '\n'; estream.flush(); for (int counter = 0; counter < 2; counter++) { estream << string(indent + 2, ' ') + (counter == 0 ? "Positive" : "Negated") + " formula:\n" + string(indent + 4, ' ') + "Büchi automaton:\n"; printBuchiAutomatonStats(stream, indent + 6, algorithm, counter); if (configuration.global_options.do_comp_test || configuration.global_options.do_cons_test) { estream << string(indent + 4, ' ') + "Product automaton:\n"; printProductAutomatonStats(stream, indent + 6, algorithm, counter); estream << string(indent + 4, ' ') + "Accepting cycles:\n"; printAcceptanceCycleStats(stream, indent + 6, algorithm, counter); } } if (configuration.global_options.do_cons_test) { estream << string(indent + 2, ' ') + "Result consistency check:\n"; printConsistencyCheckStats(stream, indent + 4, algorithm); } estream << '\n'; estream.flush(); } /* ========================================================================= */ void printCollectiveCrossComparisonStats (ostream& stream, vector::size_type algorithm_y, vector::size_type algorithm_x, int data_type) /* ---------------------------------------------------------------------------- * * Description: Called by printCollectiveStats in order to fill a single cell * of the result cross-comparison table. * * Arguments: stream -- A reference to an output * stream. * algorithm_x, algorithm_y -- Identifiers of the algorithms * whose cross-comparison results * should be displayed. * data_type -- Determines the type of data to * be displayed in the cell: * 0 -- Model checking result * cross-comparison * statistics. * 1 -- Model checking result * cross-comparison * statistics (initial * state only). * 2 -- Büchi automaton * intersection check * statistics. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); estream << ' '; if (algorithm_x == algorithm_y && data_type != 2) estream << string(21, ' '); else { unsigned long int num_comparisons, num_mismatches; const TestStatistics& stats = final_statistics[algorithm_y]; switch (data_type) { case 0 : num_comparisons = stats.cross_comparisons_performed[algorithm_x]; num_mismatches = stats.cross_comparison_mismatches[algorithm_x]; break; case 1 : num_comparisons = stats.cross_comparisons_performed[algorithm_x]; num_mismatches = stats.initial_cross_comparison_mismatches[algorithm_x]; break; default : if (configuration.global_options.statespace_generation_mode & Configuration::PATH && (algorithm_x == round_info.number_of_translators || algorithm_y == round_info.number_of_translators)) { estream << string(21, ' '); return; } num_comparisons = stats.buchi_intersection_checks_performed[algorithm_x]; num_mismatches = stats.buchi_intersection_check_failures[algorithm_x]; break; } if (num_comparisons > 0) { changeStreamFormatting(stream, 5, 0, ios::right); estream << num_mismatches; restoreStreamFormatting(stream); estream << '/'; changeStreamFormatting(stream, 5, 0, ios::left); estream << num_comparisons; restoreStreamFormatting(stream); estream << " ("; double percentage = static_cast(num_mismatches) / static_cast(num_comparisons) * 100.0; changeStreamFormatting(stream, 0, 2, ios::fixed); estream << percentage; restoreStreamFormatting(stream); estream << "%)"; if (percentage < 100.0) estream << ' '; if (percentage < 10.0) estream << ' '; } else estream << " N/A" + string(14, ' '); } } /* ========================================================================= */ void printCollectiveStats(ostream& stream, int indent) /* ---------------------------------------------------------------------------- * * Description: Displays average information about a series of tests for each * tested algorithm: * - average sizes of the Büchi and product automata * - number of failed attempts to generate a Büchi automaton * - number of failed consistency checks * - number of failed path checks * - cross-comparison mismatches * - Büchi automata intersection emptiness check failures * * Arguments: stream -- A reference to an output stream. * indent -- Number of spaces to leave on the left of the * output. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); const string ind(indent, ' '); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Display state space statistics. */ estream << '\n' + ind + "Statistics after round " + toString(round_info.current_round) + '\n' + ind + string(toString(round_info.current_round).length() + 23, '*') + "\n\n\n"; if (configuration.global_options.do_comp_test || configuration.global_options.do_cons_test) { estream << ind + " State space statistics\n" + ind + " " + string(22, '=') + "\n\n" + ind + " " + toString(round_info.num_generated_statespaces) + " state spaces generated\n" + ind + " " + toString(round_info.total_statespace_states) + " states generated"; if (round_info.num_generated_statespaces > 0) { estream << " (" + toString(static_cast (round_info.total_statespace_states) / static_cast (round_info.num_generated_statespaces), 2) + " states per state space)"; } estream << '\n' + ind + " " + toString(round_info.total_statespace_transitions) + " transitions generated"; if (round_info.num_generated_statespaces > 0) { estream << " (" + toString(static_cast (round_info.total_statespace_transitions) / static_cast (round_info.num_generated_statespaces), 2) + " transitions per state space)"; } estream << "\n\n\n"; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Display LTL formula statistics. */ estream << ind + " LTL formula statistics\n" + ind + " " + string(22, '=') + "\n\n" + ind + " " + toString(round_info.num_processed_formulae) + " LTL formulas " + (!configuration.global_options.formula_input_filename.empty() ? "process" : "generat") + "ed\n"; if (round_info.num_processed_formulae > 0 && configuration.global_options.formula_input_filename.empty()) { const map, ALLOC(unsigned long int) >& proposition_statistics = configuration.formula_options.formula_generator. propositionStatistics(); const map, ALLOC(unsigned long int) > symbol_statistics = configuration.formula_options.formula_generator.symbolStatistics(); estream << '\n' + ind + " Atomic symbol distribution:\n"; string symbol_name_string; string symbol_number_string; string symbol_distribution_string; int number_of_symbols_printed = 0; if (symbol_statistics.find(::Ltl::LTL_TRUE) != symbol_statistics.end()) { const unsigned long int num = symbol_statistics.find(::Ltl::LTL_TRUE)->second; symbol_name_string += "true "; const string number_string = toString(num); symbol_number_string += number_string + string(12 - number_string.length(), ' '); const string distribution_string = toString(static_cast(num) / static_cast(round_info.num_processed_formulae), 3); symbol_distribution_string += distribution_string + string(12 - distribution_string.length(), ' '); number_of_symbols_printed++; } if (symbol_statistics.find(::Ltl::LTL_FALSE) != symbol_statistics.end()) { const unsigned long int num = symbol_statistics.find(::Ltl::LTL_FALSE)->second; symbol_name_string += "false "; const string number_string = toString(num); symbol_number_string += number_string + string(12 - number_string.length(), ' '); const string distribution_string = toString(static_cast(num) / static_cast(round_info.num_processed_formulae), 3); symbol_distribution_string += distribution_string + string(12 - distribution_string.length(), ' '); number_of_symbols_printed++; } for (map, ALLOC(unsigned long int) > ::const_iterator proposition = proposition_statistics.begin(); proposition != proposition_statistics.end(); ++proposition) { const string name_string = "p" + toString(proposition->first); symbol_name_string += name_string; const string number_string = toString(proposition->second); symbol_number_string += number_string; const string distribution_string = toString(static_cast(proposition->second) / static_cast(round_info.num_processed_formulae), 3); symbol_distribution_string += distribution_string; number_of_symbols_printed++; if (number_of_symbols_printed % 5 == 0) { estream << ind + " symbol " + symbol_name_string + '\n' + ind + " # " + symbol_number_string + '\n' + ind + " #/formula " + symbol_distribution_string + "\n\n"; symbol_name_string = symbol_number_string = symbol_distribution_string = ""; } else { symbol_name_string += string(12 - name_string.length(), ' '); symbol_number_string += string(12 - number_string.length(), ' '); symbol_distribution_string += string(12 - distribution_string.length(), ' '); } } if (number_of_symbols_printed % 5 != 0) { estream << ind + " symbol " + symbol_name_string + '\n' + ind + " # " + symbol_number_string + '\n' + ind + " #/formula " + symbol_distribution_string + "\n\n"; } estream << ind + " Operator distribution:\n"; symbol_name_string = symbol_number_string = symbol_distribution_string = ""; number_of_symbols_printed = 0; for (map, ALLOC(unsigned long int) > ::const_iterator op = symbol_statistics.begin(); op != symbol_statistics.end(); ++op) { if (op->first == ::Ltl::LTL_ATOM || op->first == ::Ltl::LTL_TRUE || op->first == ::Ltl::LTL_FALSE) continue; const string name_string = ::Ltl::infixSymbol(op->first); symbol_name_string += name_string; const string number_string = toString(op->second); symbol_number_string += number_string; const string distribution_string = toString(static_cast(op->second) / static_cast(round_info.num_processed_formulae), 3); symbol_distribution_string += distribution_string; number_of_symbols_printed++; if (number_of_symbols_printed % 5 == 0) { if (number_of_symbols_printed > 5) estream << '\n'; estream << ind + " operator " + symbol_name_string + '\n' + ind + " # " + symbol_number_string + '\n' + ind + " #/formula " + symbol_distribution_string + '\n'; symbol_name_string = symbol_number_string = symbol_distribution_string = ""; } else { symbol_name_string += string(12 - name_string.length(), ' '); symbol_number_string += string(12 - number_string.length(), ' '); symbol_distribution_string += string(12 - distribution_string.length(), ' '); } } if (number_of_symbols_printed % 5 != 0) { estream << ind + " operator " + symbol_name_string + '\n' + ind + " # " + symbol_number_string + '\n' + ind + " #/formula " + symbol_distribution_string + '\n'; } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Display the following information for each algorithm: * 0. Automata statistics. * 1. Number of failures to compute Büchi automata. * 2. Number of model checking result consistency check failures. */ string algorithm_name; for (int i = 0; i <= 2; i++) { estream << '\n' + string(2 + indent, ' '); switch (i) { case 1 : estream << "Failures to compute Büchi automaton\n" + string(2 + indent, ' ') + string(35, '=') + '\n'; break; case 2 : if (!configuration.global_options.do_cons_test) continue; estream << "Model checking result consistency check failures\n" + string(2 + indent, ' ') + string(48, '=') + '\n'; break; default : break; } for (unsigned long int algorithm = 0; algorithm < round_info.number_of_translators; ++algorithm) { estream << '\n' + string((i > 0 ? 4 : 2) + indent, ' ') + *(configuration.algorithms[algorithm].name) + '\n'; switch (i) { /* * Display a table of automaton statistics. */ case 0 : { unsigned long int failures_to_compute_automaton; unsigned long int automaton_count; unsigned long int number_of_successful_instances; unsigned long int total_number_of_states; unsigned long int total_number_of_transitions; const TestStatistics& stats = final_statistics[algorithm]; estream << string(2 + indent, ' ') + string(configuration.algorithms[algorithm].name ->length(), '='); for (int k = 0; k < 2; k++) { if (k == 1 && !configuration.global_options.do_comp_test && !configuration.global_options.do_cons_test) continue; estream << "\n\n" + string(8 + indent, ' ') + (k == 0 ? "BÜCHI " : "PRODUCT") + string(7, ' ') + "| Number of | Number of |" " Number of |\n" + string(8 + indent, ' ') + "AUTOMATA" + string(6, ' ') + "| automata | states |" " transitions |\n" + string(7 + indent, ' ') + string(15, '-') + '+'; for (int j = 0; j < 3; j++) estream << string(17, '-') + '+'; estream << '\n'; for (int j = 0; j < 3; j++) { estream << string(8 + indent, ' '); switch (j) { case 0 : estream << "Pos. formulae"; break; case 1 : estream << "Neg. formulae"; break; default : estream << "All formulae "; break; } estream << " | "; if (j < 2) { if (k == 0) { failures_to_compute_automaton = stats.failures_to_compute_buchi_automaton[j]; automaton_count = stats.buchi_automaton_count[j]; total_number_of_states = stats.total_number_of_buchi_states[j]; total_number_of_transitions = stats.total_number_of_buchi_transitions[j]; } else { failures_to_compute_automaton = stats.failures_to_compute_product_automaton[j]; automaton_count = stats.product_automaton_count[j]; total_number_of_states = stats.total_number_of_product_states[j]; total_number_of_transitions = stats.total_number_of_product_transitions[j]; } } else { if (k == 0) { failures_to_compute_automaton = stats.failures_to_compute_buchi_automaton[0] + stats.failures_to_compute_buchi_automaton[1]; automaton_count = stats.buchi_automaton_count[0] + stats.buchi_automaton_count[1]; total_number_of_states = stats.total_number_of_buchi_states[0] + stats.total_number_of_buchi_states[1]; total_number_of_transitions = stats.total_number_of_buchi_transitions[0] + stats.total_number_of_buchi_transitions[1]; } else { failures_to_compute_automaton = stats.failures_to_compute_product_automaton[0] + stats.failures_to_compute_product_automaton[1]; automaton_count = stats.product_automaton_count[0] + stats.product_automaton_count[1]; total_number_of_states = stats.total_number_of_product_states[0] + stats.total_number_of_product_states[1]; total_number_of_transitions = stats.total_number_of_product_transitions[0] + stats.total_number_of_product_transitions[1]; } } number_of_successful_instances = automaton_count - failures_to_compute_automaton; for (int z = 0; z < 2; z++) { if (z == 0) { changeStreamFormatting(stream, 15, 2, ios::right); estream << number_of_successful_instances; restoreStreamFormatting(stream); } else estream << string(indent + 15, ' ') + "(avg.) |" + string(16, ' '); estream << " | "; if (number_of_successful_instances == 0) estream << string(15, ' '); else { changeStreamFormatting(stream, 15, 2, ios::fixed | ios::right); if (z == 0) estream << total_number_of_states; else estream << total_number_of_states / static_cast (number_of_successful_instances); restoreStreamFormatting(stream); } estream << " | "; if (number_of_successful_instances == 0) estream << string(15, ' '); else { changeStreamFormatting(stream, 15, 2, ios::fixed | ios::right); if (z == 0) estream << total_number_of_transitions; else estream << total_number_of_transitions / static_cast (number_of_successful_instances); restoreStreamFormatting(stream); } estream << " |\n"; } } if (k == 0) { unsigned long int total_number_of_acceptance_sets; double buchi_generation_time; estream << '\n' + string(22 + indent, ' ') + "| Number of | Time consumed |\n" + string(22 + indent, ' ') + "| acceptance sets | (seconds) |\n" + string(7 + indent, ' ') + string(15, '-') + '+'; for (int j = 0; j < 2; j++) estream << string(17, '-') + '+'; for (int j = 0; j < 3; j++) { estream << '\n' + string(8 + indent, ' '); switch (j) { case 0 : estream << "Pos. formulae"; break; case 1 : estream << "Neg. formulae"; break; default : estream << "All formulae "; break; } estream << " | "; if (j < 2) { failures_to_compute_automaton = stats.failures_to_compute_buchi_automaton[j]; automaton_count = stats.buchi_automaton_count[j]; buchi_generation_time = stats.total_buchi_generation_time[j]; total_number_of_acceptance_sets = stats.total_number_of_acceptance_sets[j]; } else { failures_to_compute_automaton = stats.failures_to_compute_buchi_automaton[0] + stats.failures_to_compute_buchi_automaton[1]; automaton_count = stats.buchi_automaton_count[0] + stats.buchi_automaton_count[1]; buchi_generation_time = (stats.total_buchi_generation_time[0] >= 0.0 && stats.total_buchi_generation_time[1] >= 0.0 ? stats.total_buchi_generation_time[0] + stats.total_buchi_generation_time[1] : -1.0); total_number_of_acceptance_sets = stats.total_number_of_acceptance_sets[0] + stats.total_number_of_acceptance_sets[1]; } number_of_successful_instances = automaton_count - failures_to_compute_automaton; for (int z = 0; z < 2; z++) { if (number_of_successful_instances == 0) estream << string(15, ' '); else { changeStreamFormatting(stream, 15, 2, ios::fixed | ios::right); if (z == 0) estream << total_number_of_acceptance_sets; else estream << total_number_of_acceptance_sets / static_cast (number_of_successful_instances); restoreStreamFormatting(stream); } estream << " | "; if (number_of_successful_instances == 0 || buchi_generation_time < 0.0) estream << string(15, ' '); else { changeStreamFormatting(stream, 15, 2, ios::fixed | ios::right); if (z == 0) estream << buchi_generation_time; else estream << buchi_generation_time / number_of_successful_instances; restoreStreamFormatting(stream); } estream << " |"; if (z == 0) estream << '\n' + string(indent + 15, ' ') + "(avg.) | "; } } estream << '\n'; } } if (algorithm + 1 < round_info.number_of_translators) estream << '\n'; break; } /* * Display the number of automaton computation failures. */ case 1 : { unsigned long int number_of_failures; unsigned long int total_count; const TestStatistics& stats = final_statistics[algorithm]; for (int j = 0; j < 3; j++) { estream << string(8 + indent, ' '); switch (j) { case 0 : estream << "Positive formulae: "; break; case 1 : estream << "Negative formulae: "; break; default : estream << "Total:" + string(13, ' '); break; } if (j < 2) { number_of_failures = stats.failures_to_compute_buchi_automaton[j]; total_count = stats.buchi_automaton_count[j]; } else { number_of_failures = stats.failures_to_compute_buchi_automaton[0] + stats.failures_to_compute_buchi_automaton[1]; total_count = stats.buchi_automaton_count[0] + stats.buchi_automaton_count[1]; } changeStreamFormatting(stream, 5, 0, ios::left); estream << number_of_failures; restoreStreamFormatting(stream); estream << " ["; if (total_count > 0) { changeStreamFormatting(stream, 0, 2, ios::fixed); estream << static_cast(number_of_failures) / total_count * 100.0; restoreStreamFormatting(stream); estream << "% of " << total_count; } else estream << "no"; estream << " attempts]\n"; } break; } /* * Display the number of consistency check failures. */ case 2 : { const TestStatistics& stats = final_statistics[algorithm]; estream << string(8 + indent, ' '); changeStreamFormatting(stream, 5, 0, ios::left); estream << stats.consistency_check_failures; restoreStreamFormatting(stream); estream << " ["; if (stats.consistency_checks_performed > 0) { changeStreamFormatting(stream, 0, 2, ios::fixed); estream << static_cast(stats.consistency_check_failures) / stats.consistency_checks_performed * 100.0; restoreStreamFormatting(stream); estream << "% of " << stats.consistency_checks_performed; } else estream << "no"; estream << " checks performed]\n"; break; } } } estream << '\n'; } estream << '\n'; if ((configuration.algorithms.size() > 1 && configuration.global_options.do_comp_test) || configuration.global_options.do_intr_test) { vector::size_type number_of_algorithms = configuration.algorithms.size(); int legend; estream << ind + " Result inconsistency statistics\n" + ind + " " + string(31, '=') + '\n'; vector::size_type algorithm_x, algorithm_y; for (algorithm_x = 0; algorithm_x < number_of_algorithms; algorithm_x += 2) { estream << '\n' + string(30 + indent, ' '); for (int i = 0; i < 2; ++i) { if (algorithm_x + i < number_of_algorithms) { algorithm_name = (*(configuration.algorithms[algorithm_x + i].name)).substr(0, 20); estream << "| " + algorithm_name + string(21 - algorithm_name.length(), ' '); } } estream << '|'; for (algorithm_y = 0; algorithm_y < number_of_algorithms; algorithm_y++) { estream << "\n " + ind + string(26, '-'); for (int i = 0; i < 2; ++i) { if (algorithm_x + i < number_of_algorithms) estream << '+' + string(22, '-'); } estream << '+'; algorithm_name = (*(configuration.algorithms[algorithm_y].name)).substr(0, 20); bool algorithm_name_printed = false; legend = 1; for (int data_type = 0; data_type < 3; ++data_type) { if ((data_type < 2 && configuration.global_options.do_comp_test && number_of_algorithms > 1 && (data_type == 0 || configuration.global_options.product_mode == Configuration::GLOBAL)) || (data_type == 2 && configuration.global_options.do_intr_test)) { estream << "\n " + ind + (!algorithm_name_printed ? algorithm_name + string(21 - algorithm_name.length(), ' ') : string(21, ' ')) + " [" + toString(legend) + "] "; algorithm_name_printed = true; legend++; for (int i = 0; i < 2; ++i) { if (algorithm_x + i < number_of_algorithms) { estream << '|'; printCollectiveCrossComparisonStats(stream, algorithm_y, algorithm_x + i, data_type); } } estream << '|'; } } } estream << '\n'; } legend = 1; if (number_of_algorithms > 1 && configuration.global_options.do_comp_test) { if (configuration.global_options.product_mode == Configuration::GLOBAL) { estream << '\n' + string(indent + 4, ' ') + "[1] Model checking result cross-comparison failures\n" + string(indent + 9, ' ') + "(number of failures / number of global " "cross-comparisons)\n"; legend++; } estream << '\n' + string(indent + 4, ' ') + '[' + toString(legend) + "] Model checking result cross-comparison failures " "(initial state only)\n" + string(indent + 9, ' ') + "(number of failures / number of cross-comparisons)\n"; legend++; } if (configuration.global_options.do_intr_test) estream << '\n' + string(indent + 4, ' ') + '[' + toString(legend) + "] Büchi automata intersection emptiness check " "failures\n" + string(indent + 9, ' ') + "(number of failures / number of checks performed)"; estream << "\n\n"; } estream.flush(); } }