/* * ===================================================================================== * * Filename: csp++.cpp * * Description: * * Version: 0.1 * Created: 17/05/2010 09:17:13 * Revision: none * Compiler: gcc * * Author: BlackLight (http://0x00.ath.cx), * Licence: GNU GPL v.3 * Company: lulz * * ===================================================================================== */ #include #define __CSPPP_CPP #include "csp++-def.h" #undef __CSPPP_CPP using std::vector; template void CSP::__init (int n, bool (*c)(vector< CSPvariable >)) { variables = vector< CSPvariable >(n); __default_domains = vector< vector >(n); for (size_t i=0; i < variables.size(); i++) { variables[i].index = i; variables[i].fixed = false; } constraints = vector< bool (*)(std::vector< CSPvariable >) >(1); constraint = c; __has_default_value = false; } template CSP::CSP (int n, bool (*c)(vector< CSPvariable >)) { __init (n, c); } template CSP::CSP ( int n, T default_value, bool set_value, bool (*c)(std::vector< CSPvariable >) ) { __init (n, c); for ( size_t i=0; i < variables.size(); i++ ) { variables[i].value = default_value; variables[i].fixed = set_value; } __default_value = default_value; __has_default_value = true; } template void CSP::setDomain (size_t index, vector domain) { if (index >= variables.size()) throw CSPexception("Index out of range"); variables[index].domain = domain; __default_domains[index] = domain; } template void CSP::setDomain (size_t index, T domain[], int size) { if (index >= variables.size()) throw CSPexception("Index out of range"); if (size < 0) throw CSPexception("Invalid domain size"); variables[index].domain = vector(size); for (int i=0; i < size; i++) { variables[index].domain[i] = domain[i]; __default_domains[index].push_back(domain[i]); } } template void CSP::setConstraint ( bool (*c)(vector< CSPvariable >)) { constraints = vector< bool(*)(vector< CSPvariable >) >(1); constraint = c; } template void CSP::setConstraint ( std::vector< bool(*)(std::vector< CSPvariable >) > c ) { constraints = c; } template void CSP::appendConstraint ( bool (*c)(vector< CSPvariable >)) { constraints.push_back(c); } template void CSP::dropConstraint ( size_t index ) { if (index >= constraints.size()) throw CSPexception("Index out of range"); constraints.erase( constraints.begin() + index ); } template void CSP::restoreDomains ( void ) { for (int i=0; i < variables.size(); i++) variables[i].domain = __default_domains[i]; } template void CSP::refreshDomains ( void ) { vector< arc > arcs; restoreDomains(); for (typename vector< CSPvariable >::iterator x = variables.begin(); x != variables.end(); x++) { for (typename vector< CSPvariable >::iterator y = variables.begin(); y != variables.end(); y++) { T xOrigValue = x->value; T yOrigValue = y->value; for (size_t i=0; i < x->domain.size(); i++) { if ( x->fixed ) { if ( x->domain[i] != x->value ) continue; } x->value = x->domain[i]; for (size_t j=0; j < y->domain.size(); j++) { if ( y->fixed ) { if ( y->domain[j] != y->value ) continue; } y->value = y->domain[j]; bool isConfigurationValid = true; for ( typename std::vector< bool (*)(std::vector< CSPvariable >) >::iterator c = constraints.begin(); c != constraints.end() && isConfigurationValid; c++ ) { if (!(*c)(variables)) isConfigurationValid = false; } if (isConfigurationValid) { arc a; a.var[0] = *x; a.var[1] = *y; a.value[0] = x->value; a.value[1] = y->value; arcs.push_back(a); } } y->value = yOrigValue; } x->value = xOrigValue; } vector domain = vector(); for (size_t i=0; i < arcs.size(); i++) { if (arcs[i].var[0].index == x->index || arcs[i].var[1].index == x->index) { T value = (arcs[i].var[0].index == x->index) ? arcs[i].value[0] : arcs[i].value[1]; bool found = false; for (size_t j=0; j < domain.size() && !found; j++) { if (domain[j] == value) found = true; } if (!found) { domain.push_back(value); } } } sort(domain.begin(), domain.end()); x->domain = domain; } } template std::vector CSP::getDomain ( size_t index ) { if (index >= variables.size()) throw CSPexception("Index out of range"); return variables[index].domain; } template size_t CSP::getSize( void ) { return variables.size(); } template void CSP::setValue ( size_t index, T value ) { if (index >= variables.size()) throw CSPexception("Index out of range"); variables[index].value = value; variables[index].fixed = true; } template void CSP::unsetValue ( size_t index ) { if (index >= variables.size()) throw CSPexception("Index out of range"); if (__has_default_value) variables[index].value = __default_value; variables[index].fixed = false; } template bool CSP::isSatisfiable ( void ) { for ( size_t i=0; i < variables.size(); i++ ) { if ( variables[i].domain.empty() ) return false; } return true; } template bool CSP::hasUniqueSolution ( void ) { for ( size_t i=0; i < variables.size(); i++ ) { if (variables[i].domain.size() != 1) return false; } return true; } template void CSP::assignUniqueDomains ( void ) { for ( int i=0; i < getSize(); i++ ) { if (getDomain(i).size() == 1) setValue( i, getDomain(i)[0] ); } } template bool CSP::isSet ( size_t index ) { if (index >= variables.size()) throw CSPexception("Index out of range"); return variables[index].fixed; } template T CSP::value ( size_t index ) { if (index >= variables.size()) throw CSPexception("Index out of range"); return variables[index].value; }