26 #ifndef DOXYGEN_SHOULD_SKIP_THIS 35 template <
typename STRUCTURAL_CONSTRAINT,
36 typename GRAPH_CHANGES_GENERATOR,
39 INLINE GraphChangesSelector4DiGraph< STRUCTURAL_CONSTRAINT,
40 GRAPH_CHANGES_GENERATOR,
42 GraphChangesSelector4DiGraph(Score< ALLOC >& score,
43 STRUCTURAL_CONSTRAINT& constraint,
44 GRAPH_CHANGES_GENERATOR& changes_generator) :
45 __score(score.clone()),
46 __constraint(&constraint), __changes_generator(&changes_generator) {
52 template <
typename STRUCTURAL_CONSTRAINT,
53 typename GRAPH_CHANGES_GENERATOR,
57 GRAPH_CHANGES_GENERATOR,
61 GRAPH_CHANGES_GENERATOR,
77 template <
typename STRUCTURAL_CONSTRAINT,
78 typename GRAPH_CHANGES_GENERATOR,
82 GRAPH_CHANGES_GENERATOR,
86 GRAPH_CHANGES_GENERATOR,
100 from.__score =
nullptr;
106 template <
typename STRUCTURAL_CONSTRAINT,
107 typename GRAPH_CHANGES_GENERATOR,
108 template <
typename >
112 STRUCTURAL_CONSTRAINT,
113 GRAPH_CHANGES_GENERATOR,
116 ALLOC< Score< ALLOC > > allocator(
__score->getAllocator());
118 allocator.deallocate(
__score, 1);
124 template <
typename STRUCTURAL_CONSTRAINT,
125 typename GRAPH_CHANGES_GENERATOR,
126 template <
typename >
129 GRAPH_CHANGES_GENERATOR,
132 GRAPH_CHANGES_GENERATOR,
135 GRAPH_CHANGES_GENERATOR,
140 ALLOC< Score< ALLOC > > allocator(
__score->getAllocator());
142 allocator.deallocate(
__score, 1);
146 if (from.__score !=
nullptr)
__score = from.__score->clone();
164 template <
typename STRUCTURAL_CONSTRAINT,
165 typename GRAPH_CHANGES_GENERATOR,
166 template <
typename >
169 GRAPH_CHANGES_GENERATOR,
172 GRAPH_CHANGES_GENERATOR,
175 GRAPH_CHANGES_GENERATOR,
179 from.__score =
nullptr;
199 template <
typename STRUCTURAL_CONSTRAINT,
200 typename GRAPH_CHANGES_GENERATOR,
201 template <
typename >
205 GRAPH_CHANGES_GENERATOR,
213 template <
typename STRUCTURAL_CONSTRAINT,
214 typename GRAPH_CHANGES_GENERATOR,
215 template <
typename >
219 GRAPH_CHANGES_GENERATOR,
227 template <
typename STRUCTURAL_CONSTRAINT,
228 typename GRAPH_CHANGES_GENERATOR,
229 template <
typename >
232 GRAPH_CHANGES_GENERATOR,
235 const DatabaseTable< ALLOC >& database =
__score->database();
236 const auto& nodeId2Columns =
__score->nodeId2Columns();
238 if (nodeId2Columns.empty()) {
241 if (!graph.existsNode(i)) { graph.addNodeWithId(i); }
244 for (
auto iter = nodeId2Columns.cbegin(); iter != nodeId2Columns.cend();
246 const NodeId id = iter.first();
247 if (!graph.existsNode(
id)) { graph.addNodeWithId(
id); }
254 if (nodeId2Columns.empty()) {
256 for (
auto node : graph) {
257 if (node >= nb_nodes) { graph.eraseNode(node); }
260 for (
auto node : graph) {
261 if (!nodeId2Columns.existsFirst(node)) { graph.eraseNode(node); }
275 if (reinterpret_cast< STRUCTURAL_CONSTRAINT* >(
286 const std::size_t nb_nodes = graph.size();
288 const std::vector< NodeId, ALLOC< NodeId > > empty_pars;
291 for (
const auto node : graph) {
292 auto& node_parents =
__parents.insert(node, empty_pars).second;
293 const NodeSet& dag_parents = graph.parents(node);
294 if (!dag_parents.empty()) {
295 node_parents.
resize(dag_parents.size());
296 std::size_t j = std::size_t(0);
297 for (
const auto par : dag_parents) {
298 node_parents[j] = par;
308 for (
const auto node : graph) {
318 __changes_generator->notifyGetCompleted();
328 std::pair< double, double >(std::numeric_limits< double >::min(),
329 std::numeric_limits< double >::min()));
333 const PriorityQueue< std::size_t, double, std::greater< double > >
335 for (
const auto node : graph) {
340 for (std::size_t i = std::size_t(0); i <
__changes.size(); ++i) {
344 const GraphChange& change =
__changes[i];
346 switch (change.type()) {
348 auto& parents =
__parents[change.node2()];
349 parents.push_back(change.node1());
350 const double delta =
__score->score(change.node2(), parents)
359 auto& parents =
__parents[change.node2()];
360 for (
auto& par : parents) {
361 if (par == change.node1()) {
362 par = *(parents.rbegin());
367 const double delta =
__score->score(change.node2(), parents)
369 parents.push_back(change.node1());
377 auto& parents2 =
__parents[change.node2()];
378 for (
auto& par : parents2) {
379 if (par == change.node1()) {
380 par = *(parents2.rbegin());
386 const double delta2 =
__score->score(change.node2(), parents2)
388 parents2.push_back(change.node1());
391 auto& parents1 =
__parents[change.node1()];
392 parents1.push_back(change.node2());
393 const double delta1 =
__score->score(change.node1(), parents1)
400 const double delta = delta1 + delta2;
408 "Method setGraph of GraphChangesSelector4DiGraph " 409 <<
"does not handle yet graph change of type " 418 for (
const auto node : graph) {
421 ? std::numeric_limits< double >::min()
430 template <
typename STRUCTURAL_CONSTRAINT,
431 typename GRAPH_CHANGES_GENERATOR,
432 template <
typename >
436 GRAPH_CHANGES_GENERATOR,
439 const GraphChange& change =
__changes[change_index];
442 PriorityQueue< std::size_t, double, std::greater< double > >& queue1 =
444 queue1.erase(change_index);
447 const double new_priority = queue1.empty()
448 ? std::numeric_limits< double >::min()
449 : queue1.topPriority();
454 PriorityQueue< std::size_t, double, std::greater< double > >& queue2 =
456 queue2.erase(change_index);
459 const double new_priority = queue2.empty()
460 ? std::numeric_limits< double >::min()
461 : queue2.topPriority();
470 template <
typename STRUCTURAL_CONSTRAINT,
471 typename GRAPH_CHANGES_GENERATOR,
472 template <
typename >
475 GRAPH_CHANGES_GENERATOR,
481 auto& queue = queue_pair.second;
495 template <
typename STRUCTURAL_CONSTRAINT,
496 typename GRAPH_CHANGES_GENERATOR,
497 template <
typename >
500 GRAPH_CHANGES_GENERATOR,
505 for (
auto& queue_pair : __change_queue_per_node) {
506 auto& queue = queue_pair.second;
514 return __change_queue_per_node[node].empty();
519 template <
typename STRUCTURAL_CONSTRAINT,
520 typename GRAPH_CHANGES_GENERATOR,
521 template <
typename >
523 INLINE
const GraphChange&
525 GRAPH_CHANGES_GENERATOR,
530 GUM_ERROR(NotFound,
"there exists no graph change applicable");
535 template <
typename STRUCTURAL_CONSTRAINT,
536 typename GRAPH_CHANGES_GENERATOR,
537 template <
typename >
539 INLINE
const GraphChange&
541 GRAPH_CHANGES_GENERATOR,
544 return __changes[__change_queue_per_node[node].top()];
546 GUM_ERROR(NotFound,
"there exists no graph change applicable");
551 template <
typename STRUCTURAL_CONSTRAINT,
552 typename GRAPH_CHANGES_GENERATOR,
553 template <
typename >
556 GRAPH_CHANGES_GENERATOR,
561 GUM_ERROR(NotFound,
"there exists no graph change applicable");
566 template <
typename STRUCTURAL_CONSTRAINT,
567 typename GRAPH_CHANGES_GENERATOR,
568 template <
typename >
572 GRAPH_CHANGES_GENERATOR,
575 return __change_queue_per_node[node].topPriority();
577 GUM_ERROR(NotFound,
"there exists no graph change applicable");
582 template <
typename STRUCTURAL_CONSTRAINT,
583 typename GRAPH_CHANGES_GENERATOR,
584 template <
typename >
587 STRUCTURAL_CONSTRAINT,
588 GRAPH_CHANGES_GENERATOR,
594 const GraphChange& change =
__changes[*iter];
596 __change_queue_per_node[change.node1()].insert(
597 *iter, std::numeric_limits< double >::min());
599 __change_queue_per_node[change.node2()].insert(
600 *iter, std::numeric_limits< double >::min());
602 changes_to_recompute.
insert(*iter);
610 template <
typename STRUCTURAL_CONSTRAINT,
611 typename GRAPH_CHANGES_GENERATOR,
612 template <
typename >
615 GRAPH_CHANGES_GENERATOR,
618 const NodeId target_node) {
619 const HashTable< std::size_t, Size >& changes =
620 __change_queue_per_node[target_node].allValues();
621 for (
auto iter = changes.cbeginSafe(); iter != changes.cendSafe(); ++iter) {
622 if (!changes_to_recompute.
exists(iter.key())) {
624 changes_to_recompute.
insert(iter.key());
634 template <
typename STRUCTURAL_CONSTRAINT,
635 typename GRAPH_CHANGES_GENERATOR,
636 template <
typename >
639 STRUCTURAL_CONSTRAINT,
640 GRAPH_CHANGES_GENERATOR,
644 for (
const auto change_index : changes_to_recompute) {
645 const GraphChange& change =
__changes[change_index];
647 switch (change.type()) {
650 auto& parents =
__parents[change.node2()];
651 parents.push_back(change.node1());
652 const double delta =
__score->score(change.node2(), parents)
660 __change_queue_per_node[change.node2()].setPriority(change_index,
663 modified_nodes.insert(change.node2());
668 auto& parents =
__parents[change.node2()];
669 for (
auto& par : parents) {
670 if (par == change.node1()) {
671 par = *(parents.rbegin());
676 const double delta =
__score->score(change.node2(), parents)
678 parents.push_back(change.node1());
684 __change_queue_per_node[change.node2()].setPriority(change_index,
687 modified_nodes.insert(change.node2());
692 auto& parents2 =
__parents[change.node2()];
693 for (
auto& par : parents2) {
694 if (par == change.node1()) {
695 par = *(parents2.rbegin());
701 const double delta2 =
__score->score(change.node2(), parents2)
703 parents2.push_back(change.node1());
706 auto& parents1 =
__parents[change.node1()];
707 parents1.push_back(change.node2());
708 const double delta1 =
__score->score(change.node1(), parents1)
717 const double delta = delta1 + delta2;
718 __change_queue_per_node[change.node1()].setPriority(change_index,
720 __change_queue_per_node[change.node2()].setPriority(change_index,
724 modified_nodes.insert(change.node1());
725 modified_nodes.insert(change.node2());
730 "Method __updateScores of GraphChangesSelector4DiGraph " 731 <<
"does not handle yet graph change of type " 738 for (
const auto node : modified_nodes) {
740 __change_queue_per_node[node].
empty()
741 ? std::numeric_limits< double >::min()
742 : __change_queue_per_node[node].topPriority());
748 template <
typename STRUCTURAL_CONSTRAINT,
749 typename GRAPH_CHANGES_GENERATOR,
750 template <
typename >
753 GRAPH_CHANGES_GENERATOR,
756 for (
const auto& change : *__changes_generator) {
765 std::pair< double, double >(std::numeric_limits< double >::min(),
766 std::numeric_limits< double >::min()));
771 __changes_generator->notifyGetCompleted();
776 template <
typename STRUCTURAL_CONSTRAINT,
777 typename GRAPH_CHANGES_GENERATOR,
778 template <
typename >
781 GRAPH_CHANGES_GENERATOR,
785 const std::size_t change_index =
__changes.pos(change);
789 switch (change.type()) {
794 __parents[change.node2()].push_back(change.node1());
797 __constraint->modifyGraph(static_cast< const ArcAddition& >(change));
798 if (reinterpret_cast< STRUCTURAL_CONSTRAINT* >(
799 &(__changes_generator->constraint()))
801 __changes_generator->constraint().modifyGraph(
802 static_cast< const ArcAddition& >(change));
807 __changes_generator->modifyGraph(
808 static_cast< const ArcAddition& >(change));
822 auto& parents =
__parents[change.node2()];
823 for (
auto& par : parents) {
824 if (par == change.node1()) {
825 par = *(parents.rbegin());
832 __constraint->modifyGraph(static_cast< const ArcDeletion& >(change));
833 if (reinterpret_cast< STRUCTURAL_CONSTRAINT* >(
834 &(__changes_generator->constraint()))
836 __changes_generator->constraint().modifyGraph(
837 static_cast< const ArcDeletion& >(change));
842 __changes_generator->modifyGraph(
843 static_cast< const ArcDeletion& >(change));
859 __parents[change.node1()].push_back(change.node2());
860 auto& parents =
__parents[change.node2()];
861 for (
auto& par : parents) {
862 if (par == change.node1()) {
863 par = *(parents.rbegin());
870 __constraint->modifyGraph(static_cast< const ArcReversal& >(change));
871 if (reinterpret_cast< STRUCTURAL_CONSTRAINT* >(
872 &(__changes_generator->constraint()))
874 __changes_generator->constraint().modifyGraph(
875 static_cast< const ArcReversal& >(change));
880 __changes_generator->modifyGraph(
881 static_cast< const ArcReversal& >(change));
894 "Method applyChange of GraphChangesSelector4DiGraph " 895 <<
"does not handle yet graph change of type " 904 template <
typename STRUCTURAL_CONSTRAINT,
905 typename GRAPH_CHANGES_GENERATOR,
906 template <
typename >
909 STRUCTURAL_CONSTRAINT,
910 GRAPH_CHANGES_GENERATOR,
913 const std::size_t change_index =
__changes.pos(change);
916 switch (change.type()) {
921 __parents[change.node2()].push_back(change.node1());
924 __constraint->modifyGraph(static_cast< const ArcAddition& >(change));
925 if (reinterpret_cast< STRUCTURAL_CONSTRAINT* >(
926 &(__changes_generator->constraint()))
928 __changes_generator->constraint().modifyGraph(
929 static_cast< const ArcAddition& >(change));
934 __changes_generator->modifyGraph(
935 static_cast< const ArcAddition& >(change));
950 auto& parents =
__parents[change.node2()];
951 for (
auto& par : parents) {
952 if (par == change.node1()) {
953 par = *(parents.rbegin());
960 __constraint->modifyGraph(static_cast< const ArcDeletion& >(change));
961 if (reinterpret_cast< STRUCTURAL_CONSTRAINT* >(
962 &(__changes_generator->constraint()))
964 __changes_generator->constraint().modifyGraph(
965 static_cast< const ArcDeletion& >(change));
970 __changes_generator->modifyGraph(
971 static_cast< const ArcDeletion& >(change));
988 __parents[change.node1()].push_back(change.node2());
989 auto& parents =
__parents[change.node2()];
990 for (
auto& par : parents) {
991 if (par == change.node1()) {
992 par = *(parents.rbegin());
999 __constraint->modifyGraph(static_cast< const ArcReversal& >(change));
1000 if (reinterpret_cast< STRUCTURAL_CONSTRAINT* >(
1001 &(__changes_generator->constraint()))
1003 __changes_generator->constraint().modifyGraph(
1004 static_cast< const ArcReversal& >(change));
1009 __changes_generator->modifyGraph(
1010 static_cast< const ArcReversal& >(change));
1024 "Method applyChangeWithoutScoreUpdate of " 1025 <<
"GraphChangesSelector4DiGraph " 1026 <<
"does not handle yet graph change of type " 1033 template <
typename STRUCTURAL_CONSTRAINT,
1034 typename GRAPH_CHANGES_GENERATOR,
1035 template <
typename >
1038 GRAPH_CHANGES_GENERATOR,
1046 new_legal_changes.
insert(*iter);
1056 __queues_to_update.clear();
1059 for (
const auto change_index : new_legal_changes) {
1060 const GraphChange& change =
__changes[change_index];
1062 __change_queue_per_node[change.node1()].insert(
1063 change_index, std::numeric_limits< double >::min());
1065 __change_queue_per_node[change.node2()].insert(
1066 change_index, std::numeric_limits< double >::min());
1068 changes_to_recompute.
insert(change_index);
1079 template <
typename STRUCTURAL_CONSTRAINT,
1080 typename GRAPH_CHANGES_GENERATOR,
1081 template <
typename >
1083 std::vector< std::pair< NodeId, double > >
1085 GRAPH_CHANGES_GENERATOR,
1093 std::sort(result.begin(),
1095 [](
const std::pair< NodeId, double >& a,
1096 const std::pair< NodeId, double >& b) ->
bool {
1097 return a.second > b.second;
1105 template <
typename STRUCTURAL_CONSTRAINT,
1106 typename GRAPH_CHANGES_GENERATOR,
1107 template <
typename >
1109 std::vector< std::pair< NodeId, double > >
1111 GRAPH_CHANGES_GENERATOR,
1124 template <
typename STRUCTURAL_CONSTRAINT,
1125 typename GRAPH_CHANGES_GENERATOR,
1126 template <
typename >
1129 GRAPH_CHANGES_GENERATOR,
1132 GRAPH_CHANGES_GENERATOR,
NodeProperty< double > __node_current_scores
the current score of each node
bool empty()
indicates whether the selector still contains graph changes
GeneratorType & graphChangeGenerator() const noexcept
returns the generator used by the selector
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
void __updateScores(const Set< std::size_t > &changes_to_recompute)
perform the necessary updates of the scores
STRUCTURAL_CONSTRAINT * __constraint
the set of constraints used to determine valid changes
const GraphChange & bestChange()
returns the best graph change to examine
const Val & top() const
returns the element at the top of the priority queue
void applyChange(const GraphChange &change)
indicate to the selector that a change has been applied
Set< std::size_t > __illegal_changes
the set of changes known to be currently illegal (due to the constraints)
void erase(const Key &k)
Erases an element from the set.
Score< ALLOC > * __score
the scoring function
~GraphChangesSelector4DiGraph()
destructor
const Priority & priorityByPos(Size index) const
Returns the priority of the value passed in argument.
gum is the global namespace for all aGrUM entities
PriorityQueue< NodeId, double, std::greater< double > > __node_queue
a global priority queue indicating for each node its best score
std::vector< std::pair< double, double > > __change_scores
the scores for the head and tail of all the changes
const iterator_safe & endSafe() const noexcept
The usual safe end iterator to parse the set.
void setPriority(const Val &elt, const Priority &new_priority)
Modifies the priority of each instance of a given element.
void applyChangeWithoutScoreUpdate(const GraphChange &change)
indicate to the selector that one of serveral changes has been applied
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
bool __isChangeValid(const std::size_t index) const
indicates whether a given change is valid or not
void resize(Size new_capacity)
Changes the size of the underlying hash table containing the set.
NodeProperty< std::vector< NodeId, ALLOC< NodeId > > > __parents
the set of parents of each node (speeds-up score computations)
Size insert(const Val &val, const Priority &priority)
Inserts a new (a copy) element in the priority queue.
Set< NodeId > __queues_to_update
the set of queues to update when applying several changes
double bestScore()
return the score of the best graph change
bool __queues_valid
indicates whether we need to recompute whether the queue is empty or not
GraphChangesSelector4DiGraph(Score< ALLOC > &score, STRUCTURAL_CONSTRAINT &constraint, GRAPH_CHANGES_GENERATOR &changes_generator)
default constructor
void updateScoresAfterAppliedChanges()
recompute all the scores after the application of several changes
std::vector< std::pair< NodeId, double > > nodesUnsortedWithScore() const
returns the set of queues top priorities
iterator_safe beginSafe() const
The usual safe begin iterator to parse the set.
Sequence< GraphChange > __changes
a sequence containing all the possible changes
std::vector< std::pair< NodeId, double > > nodesSortedByBestScore() const
returns the set of queues sorted by decreasing top priority
void clear()
Removes all the elements from the queue.
void __invalidateChange(const std::size_t change_index)
put a change into the illegal set
void __findLegalChangesNeedingUpdate(Set< std::size_t > &changes_to_recompute, const NodeId target_node)
finds the changes that are affected by a given node modification
void __illegal2LegalChanges(Set< std::size_t > &changes_to_recompute)
remove the now legal changes from the illegal set
void setGraph(DiGraph &graph)
sets the graph from which scores are computed
GRAPH_CHANGES_GENERATOR GeneratorType
the type of the generator
void clear()
Removes all the elements, if any, from the set.
GRAPH_CHANGES_GENERATOR * __changes_generator
the generator that returns the set of possible changes
void __getNewChanges()
get from the graph change generator a new set of changes
Size size() const noexcept
Returns the number of elements in the set.
bool isChangeValid(const GraphChange &change) const
indicates whether a given change is valid or not
const Priority & topPriority() const
Returns the priority of the top element.
Size NodeId
Type for node ids.
void insert(const Key &k)
Inserts a new element into the set.
NodeProperty< PriorityQueue< std::size_t, double, std::greater< double > > > __change_queue_per_node
for each node, a priority queue sorting GraphChanges by decreasing score
Size size() const noexcept
Returns the number of elements in the priority queue.
#define GUM_ERROR(type, msg)