-
Notifications
You must be signed in to change notification settings - Fork 36
Make State a class and add Graph::mutated()
#589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,9 +14,9 @@ | |
|
|
||
| #pragma once | ||
|
|
||
| #include <cassert> | ||
| #include <memory> | ||
| #include <vector> | ||
| #include <cassert> | ||
|
|
||
| namespace dwave::optimization { | ||
|
|
||
|
|
@@ -34,6 +34,32 @@ struct NodeStateData { | |
| bool mark = false; | ||
| }; | ||
|
|
||
| using State = typename std::vector<std::unique_ptr<NodeStateData>>; | ||
| // Foward declaration for storing the mutated decision nodes on State | ||
| class DecisionNode; | ||
|
|
||
| class State { | ||
| friend class Graph; | ||
|
|
||
| public: | ||
| State(ssize_t size = 0) : node_data_(size) {} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to make the constructors private since we're granting friendship to |
||
|
|
||
| template <typename index_type> | ||
| auto& operator[](index_type index) { | ||
| return node_data_[index]; | ||
| } | ||
|
|
||
| template <typename index_type> | ||
| auto& operator[](index_type index) const { | ||
| return node_data_[index]; | ||
| } | ||
|
|
||
| void resize(ssize_t size) { node_data_.resize(size); } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're granting friendship to |
||
|
|
||
| ssize_t size() const { return node_data_.size(); } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to include |
||
|
|
||
| private: | ||
| std::vector<std::unique_ptr<NodeStateData>> node_data_; | ||
| std::vector<const DecisionNode*> mutated_nodes_; | ||
| }; | ||
|
|
||
| } // namespace dwave::optimization | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
| #endif | ||
|
|
||
| #include "dwave-optimization/array.hpp" | ||
| #include "dwave-optimization/nodes/collections.hpp" | ||
| #include "dwave-optimization/nodes/constants.hpp" | ||
| #include "dwave-optimization/nodes/inputs.hpp" | ||
|
|
||
|
|
@@ -103,9 +104,9 @@ std::vector<const Node*> Graph::descendants(State& state, std::vector<const Node | |
| } | ||
|
|
||
| std::vector<const Node*> Graph::descendants(std::vector<const Node*> sources) const { | ||
| State state; | ||
| State state(num_nodes()); | ||
| for (ssize_t i = 0, stop = num_nodes(); i < stop; ++i) { | ||
| state.emplace_back(std::make_unique<NodeStateData>()); | ||
| state[i] = std::make_unique<NodeStateData>(); | ||
| } | ||
| return descendants(state, sources); | ||
| } | ||
|
|
@@ -156,6 +157,39 @@ void Graph::initialize_state(State& state) { | |
| static_cast<const Graph*>(this)->initialize_state(state); | ||
| } | ||
|
|
||
| std::span<const DecisionNode*> Graph::mutated(State& state) const { | ||
| // We will want to eventually replace this implementation with an approach where | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO we want to do this as part of this PR. Probably means keeping a boolean array of flags as well to determine which decisions have already been added? |
||
| // decision nodes "eagerly" add themselves to the list of mutated nodes after they | ||
| // are mutated. This will avoid the need to iterate over all decision nodes every | ||
| // time this method is called. | ||
| state.mutated_nodes_.clear(); | ||
|
|
||
| for (const DecisionNode* dec_ptr : decisions()) { | ||
| if (auto* arr_ptr = dynamic_cast<const ArrayNode*>(dec_ptr); arr_ptr) { | ||
| if (not arr_ptr->diff(state).empty()) { | ||
| state.mutated_nodes_.push_back(dec_ptr); | ||
| } | ||
| } else if ( | ||
| dynamic_cast<const DisjointListsNode*>(dec_ptr) or | ||
| dynamic_cast<const DisjointBitSetsNode*>(dec_ptr) | ||
| ) { | ||
| for (const Node* suc_ptr : dec_ptr->successors()) { | ||
| const ArrayNode* arr_ptr = dynamic_cast<const ArrayNode*>(suc_ptr); | ||
| assert(arr_ptr and "all successors should be array nodes"); | ||
| if (not arr_ptr->diff(state).empty()) { | ||
| state.mutated_nodes_.push_back(dec_ptr); | ||
| break; | ||
| } | ||
| } | ||
| } else { | ||
| assert(false and "unknown decision node type"); | ||
| unreachable(); | ||
| } | ||
| } | ||
|
|
||
| return state.mutated_nodes_; | ||
| } | ||
|
|
||
| void Graph::propagate(State& state) const { | ||
| std::ranges::for_each(nodes(), [&state](const auto& ptr) { ptr->propagate(state); }); | ||
| } | ||
|
|
@@ -284,7 +318,7 @@ ssize_t Graph::remove_unused_nodes(bool ignore_listeners) { | |
|
|
||
| for (auto& uptr : nodes_ | std::views::reverse) { | ||
| if (uptr->topological_index_ == keep) continue; // we marked these to keep | ||
| if (uptr->successors().size() > 0) continue; // this node is used by other nodes | ||
| if (uptr->successors().size() > 0) continue; // this node is used by other nodes | ||
|
|
||
| // We have a node with no successors and that we haven't marked it as important. | ||
| // So let's mark it to be dropped later. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this?