Skip to content

Commit

Permalink
linux warning fixes, add 'stress' mode to run test cases forever, che…
Browse files Browse the repository at this point in the history
…ck under valgrind [no problems], add some stats output.
  • Loading branch information
ixchow committed Jan 10, 2018
1 parent ef06eb4 commit 04c097c
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 38 deletions.
39 changes: 20 additions & 19 deletions plan_transfers-best_collapse.cpp
Expand Up @@ -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);

Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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 {
Expand Down Expand Up @@ -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.");
Expand All @@ -520,20 +520,21 @@ 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,
ops,
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());

Expand Down
7 changes: 4 additions & 3 deletions plan_transfers-best_expand.cpp
Expand Up @@ -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());

Expand Down
14 changes: 8 additions & 6 deletions plan_transfers-best_shift.cpp
Expand Up @@ -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());

Expand All @@ -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,
Expand All @@ -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());

Expand Down
12 changes: 6 additions & 6 deletions plan_transfers.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
66 changes: 62 additions & 4 deletions test_plan_transfers.cpp
Expand Up @@ -6,6 +6,8 @@
#include <random>
#include <algorithm>
#include <iostream>
#include <chrono>
#include <map>

//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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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;
}


Expand Down Expand Up @@ -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;
}

0 comments on commit 04c097c

Please sign in to comment.