1 /** 2 * 3 * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(_at_LIP6) & Christophe GONZALES(_at_AMU) 4 * info_at_agrum_dot_org 5 * 6 * This library is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 22 /** @file 23 * @brief the structural constraint imposing a partial order over nodes 24 * 25 * In DBNs, it is forbidden to add arcs from nodes at time slice t to nodes at 26 * time slice s, where s < t. This class allows for taking this kind of 27 *constraint 28 * into account by imposing a partial order over the nodes: arcs (X,Y) can then 29 * only be added if X <= Y in the partial order. 30 * @warning: there may exist free variables, that is variables whose order 31 * w.r.t. the other variables is unspecified. In this case, arcs adjacent 32 * to them can be constructed. The partial order is specified by assigning 33 * numbers to nodes (through a NodeProperty). Nodes without number (i.e., that 34 * do not belong to the property) are free. 35 * 36 * @author Christophe GONZALES(_at_AMU) and Pierre-Henri WUILLEMIN(_at_LIP6) 37 */ 38 39 #ifndef DOXYGEN_SHOULD_SKIP_THIS 40 41 namespace gum { 42 43 namespace learning { 44 45 /// sets a new graph from which we will perform checkings setGraphAlone(const DiGraph & graph)46 INLINE void StructuralConstraintSliceOrder::setGraphAlone(const DiGraph& graph) {} 47 48 /// checks whether the constraints enable to add arc (x,y) checkArcAdditionAlone(NodeId x,NodeId y)49 INLINE bool StructuralConstraintSliceOrder::checkArcAdditionAlone(NodeId x, NodeId y) const { 50 try { 51 return _SliceOrder_order_[x] <= _SliceOrder_order_[y]; 52 } catch (const Exception&) { return true; } 53 } 54 55 /// checks whether the constraints enable to remove arc (x,y) checkArcDeletionAlone(NodeId x,NodeId y)56 INLINE bool StructuralConstraintSliceOrder::checkArcDeletionAlone(NodeId x, NodeId y) const { 57 return true; 58 } 59 60 /// checks whether the constraints enable to reverse arc (x,y) checkArcReversalAlone(NodeId x,NodeId y)61 INLINE bool StructuralConstraintSliceOrder::checkArcReversalAlone(NodeId x, NodeId y) const { 62 try { 63 return _SliceOrder_order_[x] == _SliceOrder_order_[y]; 64 } catch (const Exception&) { return true; } 65 } 66 67 /// notify the constraint of a modification of the graph modifyGraphAlone(const ArcAddition & change)68 INLINE void StructuralConstraintSliceOrder::modifyGraphAlone(const ArcAddition& change) {} 69 70 /// notify the constraint of a modification of the graph modifyGraphAlone(const ArcDeletion & change)71 INLINE void StructuralConstraintSliceOrder::modifyGraphAlone(const ArcDeletion& change) {} 72 73 /// notify the constraint of a modification of the graph modifyGraphAlone(const ArcReversal & change)74 INLINE void StructuralConstraintSliceOrder::modifyGraphAlone(const ArcReversal& change) {} 75 76 /// notify the constraint of a modification of the graph modifyGraphAlone(const GraphChange & change)77 INLINE void StructuralConstraintSliceOrder::modifyGraphAlone(const GraphChange& change) {} 78 79 /// indicates whether a change will always violate the constraint 80 INLINE bool isAlwaysInvalidAlone(const GraphChange & change)81 StructuralConstraintSliceOrder::isAlwaysInvalidAlone(const GraphChange& change) const { 82 switch (change.type()) { 83 case GraphChangeType::ARC_ADDITION: 84 try { 85 return (_SliceOrder_order_[change.node1()] > _SliceOrder_order_[change.node2()]); 86 } catch (const Exception&) { return false; } 87 88 case GraphChangeType::ARC_DELETION: 89 return false; 90 91 case GraphChangeType::ARC_REVERSAL: 92 try { 93 return (_SliceOrder_order_[change.node1()] != _SliceOrder_order_[change.node2()]); 94 } catch (const Exception&) { return false; } 95 96 default: 97 GUM_ERROR(OperationNotAllowed, 98 "edge modifications are not " 99 "supported by SliceOrder constraints"); 100 } 101 } 102 103 /// checks whether the constraints enable to add an arc 104 INLINE bool checkModificationAlone(const ArcAddition & change)105 StructuralConstraintSliceOrder::checkModificationAlone(const ArcAddition& change) const { 106 return checkArcAdditionAlone(change.node1(), change.node2()); 107 } 108 109 /// checks whether the constraints enable to remove an arc 110 INLINE bool checkModificationAlone(const ArcDeletion & change)111 StructuralConstraintSliceOrder::checkModificationAlone(const ArcDeletion& change) const { 112 return checkArcDeletionAlone(change.node1(), change.node2()); 113 } 114 115 /// checks whether the constraints enable to reverse an arc 116 INLINE bool checkModificationAlone(const ArcReversal & change)117 StructuralConstraintSliceOrder::checkModificationAlone(const ArcReversal& change) const { 118 return checkArcReversalAlone(change.node1(), change.node2()); 119 } 120 121 /// checks whether the constraints enable to perform a graph change 122 INLINE bool checkModificationAlone(const GraphChange & change)123 StructuralConstraintSliceOrder::checkModificationAlone(const GraphChange& change) const { 124 switch (change.type()) { 125 case GraphChangeType::ARC_ADDITION: 126 return checkArcAdditionAlone(change.node1(), change.node2()); 127 128 case GraphChangeType::ARC_DELETION: 129 return checkArcDeletionAlone(change.node1(), change.node2()); 130 131 case GraphChangeType::ARC_REVERSAL: 132 return checkArcReversalAlone(change.node1(), change.node2()); 133 134 default: 135 GUM_ERROR(OperationNotAllowed, 136 "edge modifications are not " 137 "supported by StructuralConstraintSliceOrder"); 138 } 139 } 140 141 /// sets the time slices of all the nodes in the property setSliceOrder(const NodeProperty<NodeId> & order)142 INLINE void StructuralConstraintSliceOrder::setSliceOrder(const NodeProperty< NodeId >& order) { 143 _SliceOrder_order_ = order; 144 } 145 146 /// sets the default time slice setDefaultSlice(NodeId slice)147 INLINE void StructuralConstraintSliceOrder::setDefaultSlice(NodeId slice) { 148 for (auto& node: _SliceOrder_order_) { 149 node.second = slice; 150 } 151 } 152 153 /// adds a new node in the slice order addNode(NodeId node,NodeId slice)154 INLINE void StructuralConstraintSliceOrder::addNode(NodeId node, NodeId slice) { 155 _SliceOrder_order_.set(node, slice); 156 } 157 158 /// returns the current slice order sliceOrder()159 INLINE const NodeProperty< NodeId >& StructuralConstraintSliceOrder::sliceOrder() const { 160 return _SliceOrder_order_; 161 } 162 163 // include all the methods applicable to the whole class hierarchy 164 # define GUM_CONSTRAINT_CLASS_NAME StructuralConstraintSliceOrder 165 # include <agrum/BN/learning/constraints/structuralConstraintPatternInline.h> 166 # undef GUM_CONSTRAINT_CLASS_NAME 167 168 } /* namespace learning */ 169 170 } /* namespace gum */ 171 172 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 173