private Result SolveRecursively(NodeState currentState) { // check if done: var collaboratingSensorGroups = currentState.Variables.Where(v => v.IsAssigned).GroupBy(v => v.AssignedValue).ToArray(); var done = collaboratingSensorGroups.Length == DomainValues.Count && collaboratingSensorGroups.All(group => group.Count() == NeededSensorsForEachTargetNo); if (done) { return new Result() { AssignedVariables = currentState.Variables.ToDictionary(v => v.Name) } } ; var variableToAssign = GetNextVariable(currentState); if (variableToAssign is null) { throw new CspPathFailure(currentState); } var stateBeforeGoingDeeper = currentState.Clone(); foreach (var value in GetValueFor(variableToAssign)) { if (!IsConsistent(currentState, variableToAssign, value)) { continue; } variableToAssign.AssignedValue = value.Value; variableToAssign.IsAssigned = true; // forward checking UpdateCandidates(currentState.Variables, value); try { return(SolveRecursively(currentState)); } catch (CspPathFailure) { currentState.GoBackToState(stateBeforeGoingDeeper); } } // try going deep leaving variableToAssign unassigned! variableToAssign.IsAncestorWithoutValue = true; try { return(SolveRecursively(currentState)); } catch (CspPathFailure) { currentState.GoBackToState(stateBeforeGoingDeeper); throw; } }