ENH: optimize the get_tool_order func
Use Dp to refine performance jira:[NEW] Signed-off-by: xun.zhang <xun.zhang@bambulab.com> Change-Id: I38b0c875e4deee9d9fbe926087fb5b2e274f8f90 (cherry picked from commit 9b7b66dc7a1f5e3efa318227ae7694bec5ec1216)
This commit is contained in:
parent
996703021c
commit
bc36255090
|
@ -22,9 +22,74 @@ namespace Slic3r {
|
|||
|
||||
const static bool g_wipe_into_objects = false;
|
||||
|
||||
|
||||
// Shortest hamilton path problem
|
||||
static std::vector<unsigned int> solve_extruder_order(const std::vector<std::vector<float>>& wipe_volumes, std::vector<unsigned int> all_extruders, unsigned int start_extruder_id)
|
||||
{
|
||||
auto start_iter = std::find(all_extruders.begin(), all_extruders.end(), start_extruder_id);
|
||||
bool add_start_extruder_flag = false;
|
||||
if (start_iter == all_extruders.end())
|
||||
all_extruders.insert(all_extruders.begin(), start_extruder_id), add_start_extruder_flag = true;
|
||||
else
|
||||
std::swap(*all_extruders.begin(), *start_iter);
|
||||
|
||||
unsigned int iterations = (1 << all_extruders.size());
|
||||
unsigned int final_state = iterations - 1;
|
||||
std::vector<std::vector<float>>cache(iterations, std::vector<float>(all_extruders.size(),0x7fffffff));
|
||||
std::vector<std::vector<int>>prev(iterations, std::vector<int>(all_extruders.size(), -1));
|
||||
cache[1][0] = 0.;
|
||||
for (unsigned int state = 0; state < iterations; ++state) {
|
||||
if (state & 1) {
|
||||
for (unsigned int target = 0; target < all_extruders.size(); ++target) {
|
||||
if (state >> target & 1) {
|
||||
for (unsigned int mid_point = 0; mid_point < all_extruders.size(); ++mid_point) {
|
||||
if(state>>mid_point&1){
|
||||
auto tmp = cache[state - (1 << target)][mid_point] + wipe_volumes[all_extruders[mid_point]][all_extruders[target]];
|
||||
if (cache[state][target] >tmp) {
|
||||
cache[state][target] = tmp;
|
||||
prev[state][target] = mid_point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//get res
|
||||
float cost = std::numeric_limits<float>::max();
|
||||
int final_dst =0;
|
||||
for (unsigned int dst = 0; dst < all_extruders.size(); ++dst) {
|
||||
if (all_extruders[dst] != start_extruder_id && cost > cache[final_state][dst]) {
|
||||
cost = cache[final_state][dst];
|
||||
final_dst = dst;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned int>path;
|
||||
unsigned int curr_state = final_state;
|
||||
int curr_point = final_dst;
|
||||
while (curr_point != -1) {
|
||||
path.emplace_back(all_extruders[curr_point]);
|
||||
auto mid_point = prev[curr_state][curr_point];
|
||||
curr_state -= (1 << curr_point);
|
||||
curr_point = mid_point;
|
||||
};
|
||||
|
||||
if (add_start_extruder_flag)
|
||||
path.pop_back();
|
||||
|
||||
std::reverse(path.begin(), path.end());
|
||||
return path;
|
||||
}
|
||||
|
||||
std::vector<unsigned int> get_extruders_order(const std::vector<std::vector<float>> &wipe_volumes, std::vector<unsigned int> all_extruders, unsigned int start_extruder_id)
|
||||
{
|
||||
if (all_extruders.size() > 1) {
|
||||
#define USE_DP_OPTIMIZE
|
||||
#ifdef USE_DP_OPTIMIZE
|
||||
return solve_extruder_order(wipe_volumes, all_extruders, start_extruder_id);
|
||||
#else
|
||||
if (all_extruders.size() > 1) {
|
||||
int begin_index = 0;
|
||||
auto iter = std::find(all_extruders.begin(), all_extruders.end(), start_extruder_id);
|
||||
if (iter != all_extruders.end()) {
|
||||
|
@ -53,6 +118,8 @@ std::vector<unsigned int> get_extruders_order(const std::vector<std::vector<floa
|
|||
return volumes_to_extruder_order.second;
|
||||
}
|
||||
return all_extruders;
|
||||
|
||||
#endif // OPTIMIZE
|
||||
}
|
||||
|
||||
|
||||
|
@ -755,14 +822,40 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume()
|
|||
for (unsigned int i = 0; i < number_of_extruders; ++i)
|
||||
wipe_volumes.push_back(std::vector<float>(flush_matrix.begin() + i * number_of_extruders, flush_matrix.begin() + (i + 1) * number_of_extruders));
|
||||
|
||||
auto extruders_to_hash_key = [](const std::vector<unsigned int>& extruders, unsigned int initial_extruder_id)->uint32_t {
|
||||
uint32_t hash_key = 0;
|
||||
// high 16 bit define initial extruder ,low 16 bit define extruder set
|
||||
hash_key |= (1 << (16 + initial_extruder_id));
|
||||
for (auto item : extruders)
|
||||
hash_key |= (1 << item);
|
||||
return hash_key;
|
||||
};
|
||||
|
||||
|
||||
unsigned int current_extruder_id = -1;
|
||||
for (int i = 0; i < m_layer_tools.size(); ++i) {
|
||||
LayerTools& lt = m_layer_tools[i];
|
||||
if (lt.extruders.empty())
|
||||
continue;
|
||||
// todo: The algorithm complexity is too high(o(n2)), currently only 8 colors are supported
|
||||
if (i != 0 && lt.extruders.size() <= 8) {
|
||||
lt.extruders = get_extruders_order(wipe_volumes, lt.extruders, current_extruder_id);
|
||||
// The algorithm complexity is O(n2*2^n)
|
||||
if (i != 0) {
|
||||
auto hash_key = extruders_to_hash_key(lt.extruders, current_extruder_id);
|
||||
auto iter = m_tool_order_cache.find(hash_key);
|
||||
if (iter == m_tool_order_cache.end()) {
|
||||
lt.extruders = get_extruders_order(wipe_volumes, lt.extruders, current_extruder_id);
|
||||
std::vector<uint8_t> hash_val;
|
||||
hash_val.reserve(lt.extruders.size());
|
||||
for (auto item : lt.extruders)
|
||||
hash_val.emplace_back(static_cast<uint8_t>(item));
|
||||
m_tool_order_cache[hash_key] = hash_val;
|
||||
}
|
||||
else {
|
||||
std::vector<unsigned int>extruder_order;
|
||||
extruder_order.reserve(iter->second.size());
|
||||
for (auto item : iter->second)
|
||||
extruder_order.emplace_back(static_cast<unsigned int>(item));
|
||||
lt.extruders = std::move(extruder_order);
|
||||
}
|
||||
}
|
||||
current_extruder_id = lt.extruders.back();
|
||||
}
|
||||
|
|
|
@ -156,7 +156,9 @@ public:
|
|||
// (print->config().print_sequence == PrintSequence::ByObject is false).
|
||||
ToolOrdering(const Print& print, unsigned int first_extruder, bool prime_multi_material = false);
|
||||
|
||||
void clear() { m_layer_tools.clear(); }
|
||||
void clear() {
|
||||
m_layer_tools.clear(); m_tool_order_cache.clear();
|
||||
}
|
||||
|
||||
// Only valid for non-sequential print:
|
||||
// Assign a pointer to a custom G-code to the respective ToolOrdering::LayerTools.
|
||||
|
@ -207,7 +209,7 @@ private:
|
|||
unsigned int m_last_printing_extruder = (unsigned int)-1;
|
||||
// All extruders, which extrude some material over m_layer_tools.
|
||||
std::vector<unsigned int> m_all_printing_extruders;
|
||||
|
||||
std::unordered_map<uint32_t, std::vector<uint8_t>> m_tool_order_cache;
|
||||
const PrintConfig* m_print_config_ptr = nullptr;
|
||||
const PrintObject* m_print_object_ptr = nullptr;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue