From 04c097c69b10b12a4bf81a1d7a25f80062278e39 Mon Sep 17 00:00:00 2001 From: Jim McCann Date: Tue, 9 Jan 2018 19:35:35 -0500 Subject: [PATCH] linux warning fixes, add 'stress' mode to run test cases forever, check under valgrind [no problems], add some stats output. --- plan_transfers-best_collapse.cpp | 39 ++++++++++--------- plan_transfers-best_expand.cpp | 7 ++-- plan_transfers-best_shift.cpp | 14 ++++--- plan_transfers.cpp | 12 +++--- test_plan_transfers.cpp | 66 ++++++++++++++++++++++++++++++-- 5 files changed, 100 insertions(+), 38 deletions(-) diff --git a/plan_transfers-best_collapse.cpp b/plan_transfers-best_collapse.cpp index 55d1b62..e8c96f2 100644 --- a/plan_transfers-best_collapse.cpp +++ b/plan_transfers-best_collapse.cpp @@ -149,7 +149,7 @@ void best_collapse( State next_state = state; Cost next_cost = cost; if (action.type == Action::MoveLeft) { - assert(state.l >= 0 && state.l < top.size()); + assert(state.l >= 0 && state.l < int32_t(top.size())); next_cost.penalty += top[state.l].after_offset_and_roll(action.needle - top[state.l].needle, 0).penalty(constraints.min_free, constraints.max_free); @@ -159,12 +159,12 @@ void best_collapse( //if this is the first stitch, track it: if (state.r_next_roll == State::RRollInvalid) { - assert(bottom.empty() && state.r + 1 == top.size()); + assert(bottom.empty() && state.r + 1 == int32_t(top.size())); next_state.r_next_needle = action.needle; next_state.r_next_roll = State::RRoll2; } } else if (action.type == Action::MoveRight) { - assert(state.r >= 0 && state.r < top.size()); + assert(state.r >= 0 && state.r < int32_t(top.size())); next_cost.penalty += top[state.r].after_offset_and_roll(action.needle - top[state.r].needle, 0).penalty(constraints.min_free, constraints.max_free); @@ -180,7 +180,7 @@ void best_collapse( } } else if (action.type == Action::RollLeft) { - assert(state.l >= 0 && state.l < top.size()); + assert(state.l >= 0 && state.l < int32_t(top.size())); next_cost.penalty += top[state.l].after_offset_and_roll(action.needle - top[state.l].needle, -1).penalty(constraints.min_free, constraints.max_free); @@ -190,12 +190,12 @@ void best_collapse( //if this is the first stitch, track it on the other side: if (state.r_next_roll == State::RRollInvalid) { - assert(bottom.empty() && state.r + 1 == top.size()); + assert(bottom.empty() && state.r + 1 == int32_t(top.size())); next_state.r_next_needle = action.needle; next_state.r_next_roll = State::RRoll1; } } else if (action.type == Action::RollRight) { - assert(state.r >= 0 && state.r < top.size()); + assert(state.r >= 0 && state.r < int32_t(top.size())); next_cost.penalty += top[state.r].after_offset_and_roll(action.needle - top[state.r].needle, +1).penalty(constraints.min_free, constraints.max_free); @@ -210,7 +210,7 @@ void best_collapse( next_state.l_prev_roll = State::LRoll1; } } else if (action.type == Action::Roll2Left) { - assert(state.l >= 0 && state.l < top.size()); + assert(state.l >= 0 && state.l < int32_t(top.size())); assert(bottom.empty()); assert(state.l_prev_roll == State::LRoll2 || state.l_prev_roll == State::LRollInvalid); @@ -227,7 +227,7 @@ void best_collapse( } } else if (action.type == Action::Roll2Right) { - assert(state.r >= 0 && state.r < top.size()); + assert(state.r >= 0 && state.r < int32_t(top.size())); assert(bottom.empty()); assert(state.r_next_roll == State::RRoll2 || state.r_next_roll == State::RRollInvalid); @@ -254,7 +254,7 @@ void best_collapse( auto expand_state = [&](State const &state, Cost const &cost) { assert(state.l <= state.r); - assert(state.r < top.size()); + assert(state.r < int32_t(top.size())); assert(state.l_prev_roll <= State::Roll0); assert(state.r_next_roll >= State::Roll0); @@ -263,7 +263,7 @@ void best_collapse( int32_t min_ofs = -int32_t(constraints.max_racking); int32_t max_ofs = int32_t(constraints.max_racking); - if (bottom.empty() && state.l == 0 && state.r + 1 == top.size()) { + if (bottom.empty() && state.l == 0 && state.r + 1 == int32_t(top.size())) { //no bridges to worry about! assert(state.l_prev_roll == State::LRollInvalid && state.r_next_roll == State::RRollInvalid); } else { @@ -485,22 +485,22 @@ void best_collapse( Action const &action = f->second.action; if (action.type == Action::MoveLeft) { - assert(state.l >= 0 && state.l < top.size()); + assert(state.l >= 0 && state.l < int32_t(top.size())); ops.emplace_back(BedNeedle(top_bed, top[state.l].needle), BedNeedle(to_top_bed, action.needle)); } else if (action.type == Action::MoveRight) { - assert(state.r >= 0 && state.r < top.size()); + assert(state.r >= 0 && state.r < int32_t(top.size())); ops.emplace_back(BedNeedle(top_bed, top[state.r].needle), BedNeedle(to_top_bed, action.needle)); } else if (action.type == Action::RollLeft) { - assert(state.l >= 0 && state.l < top.size()); + assert(state.l >= 0 && state.l < int32_t(top.size())); ops.emplace_back(BedNeedle(top_bed, top[state.l].needle), BedNeedle(to_bottom_bed, action.needle)); } else if (action.type == Action::RollRight) { - assert(state.r >= 0 && state.r < top.size()); + assert(state.r >= 0 && state.r < int32_t(top.size())); ops.emplace_back(BedNeedle(top_bed, top[state.r].needle), BedNeedle(to_bottom_bed, action.needle)); } else if (action.type == Action::Roll2Left) { - assert(state.l >= 0 && state.l < top.size()); + assert(state.l >= 0 && state.l < int32_t(top.size())); ops.emplace_back(BedNeedle(top_bed, top[state.l].needle), BedNeedle(to_top_bed, action.needle)); } else if (action.type == Action::Roll2Right) { - assert(state.r >= 0 && state.r < top.size()); + assert(state.r >= 0 && state.r < int32_t(top.size())); ops.emplace_back(BedNeedle(top_bed, top[state.r].needle), BedNeedle(to_top_bed, action.needle)); } else { assert(0 && "Invalid action type."); @@ -520,9 +520,10 @@ void best_collapse( std::cout.flush(); //DEBUG */ +/* std::cout << "Before Collapse:\n"; //DEBUG draw_beds(top_bed, top, bottom_bed, bottom); //DEBUG - +*/ run_transfers(constraints, top_bed, top, bottom_bed, bottom, @@ -530,10 +531,10 @@ void best_collapse( to_top_bed, &to_top, to_bottom_bed, &to_bottom); - +/* std::cout << "After Collapse:\n"; //DEBUG draw_beds(to_top_bed, to_top, to_bottom_bed, to_bottom); //DEBUG - +*/ plan.insert(plan.end(), ops.begin(), ops.end()); diff --git a/plan_transfers-best_expand.cpp b/plan_transfers-best_expand.cpp index 0af0679..ebb45aa 100644 --- a/plan_transfers-best_expand.cpp +++ b/plan_transfers-best_expand.cpp @@ -509,19 +509,20 @@ void best_expand( std::cout.flush(); //DEBUG */ +/* std::cout << "Before Expand:\n"; //DEBUG draw_beds(top_bed, top, bottom_bed, bottom); //DEBUG - +*/ run_transfers(constraints, top_bed, top, bottom_bed, bottom, ops, to_top_bed, &to_top, to_bottom_bed, &to_bottom); - +/* std::cout << "After Expand:\n"; //DEBUG draw_beds(to_top_bed, to_top, to_bottom_bed, to_bottom); //DEBUG - +*/ plan.insert(plan.end(), ops.begin(), ops.end()); diff --git a/plan_transfers-best_shift.cpp b/plan_transfers-best_shift.cpp index 1624542..669c8e5 100644 --- a/plan_transfers-best_shift.cpp +++ b/plan_transfers-best_shift.cpp @@ -62,7 +62,7 @@ void best_shift( do_ofs(ofs); if (ofs != 0) do_ofs(-ofs); } - std::cout << "Best offset: " << best_ofs << std::endl; //DEBUG + //std::cout << "Best offset: " << best_ofs << std::endl; //DEBUG assert(best_penalty < std::numeric_limits< uint32_t >::max()); @@ -76,6 +76,11 @@ void best_shift( ops.emplace_back(BedNeedle(bottom_bed, nrg.needle), BedNeedle(to_bottom_bed, nrg.needle + best_ofs)); } +/* + std::cout << "Before Shift:\n"; //DEBUG + draw_beds(top_bed, top, bottom_bed, bottom); //DEBUG +*/ + run_transfers(constraints, top_bed, top, bottom_bed, bottom, @@ -84,13 +89,10 @@ void best_shift( to_bottom_bed, &to_bottom ); - std::cout << "Before Shift:\n"; //DEBUG - draw_beds(top_bed, top, bottom_bed, bottom); //DEBUG - +/* std::cout << "After Shift:\n"; //DEBUG draw_beds(to_top_bed, to_top, to_bottom_bed, to_bottom); //DEBUG - - +*/ plan.insert(plan.end(), ops.begin(), ops.end()); diff --git a/plan_transfers.cpp b/plan_transfers.cpp index c690d08..007de36 100644 --- a/plan_transfers.cpp +++ b/plan_transfers.cpp @@ -303,10 +303,10 @@ bool plan_transfers( std::vector< Transfer > best_plan; uint32_t best_penalty = std::numeric_limits< uint32_t >::max(); uint32_t starting_penalty = penalty(shrunk_constraints, best_front, best_back); - //DEBUG: + /*//DEBUG: std::cout << " ------- [penalty: " << starting_penalty << "] -------\n"; draw_beds(BedNeedle::Back, back, BedNeedle::Front, front); - std::cout << " --------------\n"; + std::cout << " --------------\n";*/ { //collapse-to-back: std::vector< Transfer > plan; std::vector< NeedleRollGoal > collapsed_top, collapsed_bottom; @@ -338,9 +338,9 @@ bool plan_transfers( ); uint32_t p = penalty(shrunk_constraints, after_front, after_back); - std::cout << "-- -- -- (penalty: " << p << ") -- -- --\n"; + /*std::cout << "-- -- -- (penalty: " << p << ") -- -- --\n"; draw_beds(BedNeedle::Back, after_back, BedNeedle::Front, after_front); - std::cout << "-- -- -- -- -- --\n"; + std::cout << "-- -- -- -- -- --\n";*/ if (p < best_penalty) { best_front = after_front; best_back = after_back; @@ -378,9 +378,9 @@ bool plan_transfers( &plan ); uint32_t p = penalty(shrunk_constraints, after_front, after_back); - std::cout << "-- -- -- (penalty: " << p << ") -- -- --\n"; + /*std::cout << "-- -- -- (penalty: " << p << ") -- -- --\n"; draw_beds(BedNeedle::Back, after_back, BedNeedle::Front, after_front); - std::cout << "-- -- -- -- -- --\n"; + std::cout << "-- -- -- -- -- --\n";*/ if (p < best_penalty) { best_front = after_front; best_back = after_back; diff --git a/test_plan_transfers.cpp b/test_plan_transfers.cpp index 4d94500..f98c2c2 100644 --- a/test_plan_transfers.cpp +++ b/test_plan_transfers.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include //simulate_transfers applies the transfers in 'transfers' to the stitches in 'from_ccw'. // it will return 'true' if the transfers succeed in moving the stitches to 'to_ccw' without @@ -228,7 +230,7 @@ bool simulate_transfers( //walk through transfers one by one and check state: for (auto const &t : transfers) { - std::cout << " checking: " << t.to_string() << std::endl; //DEBUG + //std::cout << " checking: " << t.to_string() << std::endl; //DEBUG //find all stitches that are in the 'from' location: std::vector< Stitch * > &from = stitches_on(t.from); @@ -462,9 +464,40 @@ void dump_layout(std::vector< BedNeedle > const &ccw, std::vector< Slack > *slac std::cout.flush(); }; +std::map< uint32_t, uint32_t > count_histogram; +std::map< uint32_t, uint32_t > transfers_histogram; +uint32_t cases_run = 0; +void dump_stats() { + auto draw_hist = [](std::map< uint32_t, uint32_t > const &hist) { + uint32_t max = 0; + for (auto cc : hist) { + max = std::max(max, cc.second); + } + uint32_t scale = std::min(max, 60U); + for (auto cc : hist) { + if (cc.first < 100) std::cerr << ' '; + if (cc.first < 10) std::cerr << ' '; + std::cerr << cc.first << ' '; + std::cerr << std::string(cc.second * scale / max, '='); + std::cerr << ' ' << cc.second; + std::cerr << '\n'; + } + }; + + + { //counts histogram + std::cerr << "Test Case Size:\n"; + draw_hist(count_histogram); + } + { //moves histogram + std::cerr << "Transfers Per Stitch:\n"; + draw_hist(transfers_histogram); + } +} + +std::mt19937 mt(0xdeadbeef); bool test_plan_transfers(std::string label) { - static std::mt19937 mt(0xdeadbeef); Constraints constraints; //pick max racking in range [1,20]; generally pick 4 which is a realistic value. @@ -483,8 +516,10 @@ bool test_plan_transfers(std::string label) { } else { //...and larger sizes with some sort of decaying probability: float amt = (val - mt.max()/2) / float(mt.max()/2); - count = 10 + std::floor(100.0f * (1.0f - std::pow(1.0f / 100.0f, amt))); + count = 11 + std::floor(std::pow(100.0f, 1.0f - amt)); } + uint32_t c = (count / 5) * 5; + count_histogram.insert(std::make_pair(c, 0)).first->second += 1; } @@ -774,16 +809,39 @@ bool test_plan_transfers(std::string label) { std::cerr << "ERROR: result of plan_transfers failed checks:\n" << error << std::endl; return false; } + + uint32_t t = (transfers.size() + from_ccw.size() - 1) / from_ccw.size(); + transfers_histogram.insert(std::make_pair(t, 0)).first->second += 1; } + cases_run += 1; + if (cases_run % 100 == 0) dump_stats(); + return true; } int main(int argc, char **argv) { - constexpr uint32_t iters = 100000; + if (argc == 2) { + if (argv[1] == std::string("stress")) { + std::cout << "Running random test cases forever." << std::endl; + mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count()); + uint32_t count = 0; + while (1) { + ++count; + if (!test_plan_transfers("Test run " + std::to_string(count))) return 1; + } + return 0; + } else { + std::cerr << "Unrecognized Argument" << std::endl; + return 1; + } + } + + constexpr uint32_t iters = 1000; for (uint32_t i = 0; i < iters; ++i) { if (!test_plan_transfers(std::to_string(i) + "/" + std::to_string(iters))) return 1; } + dump_stats(); std::cout << "Passed " << iters << " random test cases." << std::endl; return 0; }