private Assignment recursiveBackTrackingSearch(CSP csp,Assignment assignment){
  Assignment result=null;
  if (assignment.isComplete(csp.getVariables())) {
    result=assignment;
  }
 else {
    Variable var=selectUnassignedVariable(assignment,csp);
    for (    Object value : orderDomainValues(var,assignment,csp)) {
      assignment.setAssignment(var,value);
      fireStateChanged(assignment,csp);
      if (assignment.isConsistent(csp.getConstraints(var))) {
        DomainRestoreInfo info=inference(var,assignment,csp);
        if (!info.isEmpty())         fireStateChanged(csp);
        if (!info.isEmptyDomainFound()) {
          result=recursiveBackTrackingSearch(csp,assignment);
          if (result != null)           break;
        }
        info.restoreDomains(csp);
      }
      assignment.removeAssignment(var);
    }
  }
  return result;
}

private Assignment recursiveBackTrackingSearch ( CSP csp , Assignment assignment ) { Assignment result = null ; if ( assignment . isComplete ( csp . getVariables ( ) ) ) { result = assignment ; } else { Variable var = selectUnassignedVariable ( assignment , csp ) ; for ( Object value : orderDomainValues ( var , assignment , csp ) ) { assignment . setAssignment ( var , value ) ; fireStateChanged ( assignment , csp ) ; if ( assignment . isConsistent ( csp . getConstraints ( var ) ) ) { DomainRestoreInfo info = inference ( var , assignment , csp ) ; if ( ! info . isEmpty ( ) ) fireStateChanged ( csp ) ; if ( ! info . isEmptyDomainFound ( ) ) { result = recursiveBackTrackingSearch ( csp , assignment ) ; if ( result != null ) break ; } info . restoreDomains ( csp ) ; } assignment . removeAssignment ( var ) ; } } return result ; }
template method , which can be configured by overriding the three primitive operations below .
