89 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|  * CSP.cpp
 | |
|  * @brief Constraint Satisfaction Problem class
 | |
|  * @date Feb 6, 2012
 | |
|  * @author Frank Dellaert
 | |
|  */
 | |
| 
 | |
| #include <gtsam/base/Testable.h>
 | |
| #include <gtsam/discrete/DiscreteBayesNet.h>
 | |
| #include <gtsam_unstable/discrete/CSP.h>
 | |
| #include <gtsam_unstable/discrete/Domain.h>
 | |
| 
 | |
| using namespace std;
 | |
| 
 | |
| namespace gtsam {
 | |
| 
 | |
| bool CSP::runArcConsistency(const VariableIndex& index,
 | |
|                             Domains* domains) const {
 | |
|   bool changed = false;
 | |
| 
 | |
|   // iterate over all variables in the index
 | |
|   for (auto entry : index) {
 | |
|     // Get the variable's key and associated factors:
 | |
|     const Key key = entry.first;
 | |
|     const FactorIndices& factors = entry.second;
 | |
| 
 | |
|     // If this domain is already a singleton, we do nothing.
 | |
|     if (domains->at(key).isSingleton()) continue;
 | |
| 
 | |
|     // Otherwise, loop over all factors/constraints for variable with given key.
 | |
|     for (size_t f : factors) {
 | |
|       // If this factor is a constraint, call its ensureArcConsistency method:
 | |
|       auto constraint = std::dynamic_pointer_cast<Constraint>((*this)[f]);
 | |
|       if (constraint) {
 | |
|         changed = constraint->ensureArcConsistency(key, domains) || changed;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return changed;
 | |
| }
 | |
| 
 | |
| // TODO(dellaert): This is AC1, which is inefficient as any change will cause
 | |
| // the algorithm to revisit *all* variables again. Implement AC3.
 | |
| Domains CSP::runArcConsistency(size_t cardinality, size_t maxIterations) const {
 | |
|   // Create VariableIndex
 | |
|   VariableIndex index(*this);
 | |
| 
 | |
|   // Initialize domains
 | |
|   Domains domains;
 | |
|   for (auto entry : index) {
 | |
|     const Key key = entry.first;
 | |
|     domains.emplace(key, DiscreteKey(key, cardinality));
 | |
|   }
 | |
| 
 | |
|   // Iterate until convergence or not a single domain changed.
 | |
|   for (size_t it = 0; it < maxIterations; it++) {
 | |
|     bool changed = runArcConsistency(index, &domains);
 | |
|     if (!changed) break;
 | |
|   }
 | |
|   return domains;
 | |
| }
 | |
| 
 | |
| CSP CSP::partiallyApply(const Domains& domains) const {
 | |
|   // Create new problem with all singleton variables removed
 | |
|   // We do this by adding simplifying all factors using partial application.
 | |
|   // TODO: create a new ordering as we go, to ensure a connected graph
 | |
|   // KeyOrdering ordering;
 | |
|   // vector<Index> dkeys;
 | |
|   CSP new_csp;
 | |
| 
 | |
|   // Add tightened domains as new factors:
 | |
|   for (auto key_domain : domains) {
 | |
|     new_csp.emplace_shared<Domain>(key_domain.second);
 | |
|   }
 | |
| 
 | |
|   // Reduce all existing factors:
 | |
|   for (const DiscreteFactor::shared_ptr& f : factors_) {
 | |
|     auto constraint = std::dynamic_pointer_cast<Constraint>(f);
 | |
|     if (!constraint)
 | |
|       throw runtime_error("CSP:runArcConsistency: non-constraint factor");
 | |
|     Constraint::shared_ptr reduced = constraint->partiallyApply(domains);
 | |
|     if (reduced->size() > 1) {
 | |
|       new_csp.push_back(reduced);
 | |
|     }
 | |
|   }
 | |
|   return new_csp;
 | |
| }
 | |
| }  // namespace gtsam
 |