public CSP(CSP cspToBeCopied) { this.vars = new List<Variable>(); cspToBeCopied.vars.ForEach(v=>this.vars.Add(new Variable(v.pos,v.val,v.remDomain))); this.domain = cspToBeCopied.domain.ToList(); this.neighbours = new Dictionary<Vector2, List<Variable>>(); foreach (var key in cspToBeCopied.neighbours.Keys) { var listNeigh = new List<Variable>(); foreach (var neighSour in cspToBeCopied.neighbours[key]) { var variableDest = this.vars.First(v => v.pos == neighSour.pos); listNeigh.Add(variableDest); } this.neighbours[key] = listNeigh; } this.assignments = new List<Assignment>(); foreach (var ass in cspToBeCopied.assignments) { var variableDest = this.vars.First(v => v.pos == ass.variable.pos); var assignDest = new Assignment(variableDest, ass.value); assignDest.domainPrune = new Dictionary<Vector2, List<OverFloorType>>(); foreach (var domPruneKey in ass.domainPrune.Keys) { var listOfdomainprune = new List<OverFloorType>(); foreach (var valuePruned in ass.domainPrune[domPruneKey]) { listOfdomainprune.Add(valuePruned); } assignDest.domainPrune[domPruneKey] = listOfdomainprune; } this.assignments.Add(assignDest); } this.toleranceFM = cspToBeCopied.toleranceFM; this.toleranceFW = cspToBeCopied.toleranceFW; this.MAC3 = cspToBeCopied.MAC3; }
/// <summary> /// Maintenance Arc Consistency, this algorithm will check how many domain prunes are done when a assignemnt is executed /// </summary> /// <param name="assign">Assignment to be evaluated and updated</param> /// <param name="neighbours">List of neighbours to start with (difference between AC3 and MAC3)</param> /// <returns></returns> public static bool MAC3(ref Assignment assign,CSP problem) { var position = assign.variable.pos; var variableInLocalProblem = problem.vars.First(v => v.pos == position); //Add the assignment to the problem problem.AssignValue(variableInLocalProblem, assign.value,false); List<Variable> queueToPrune = new List<Variable>(); queueToPrune.Add(variableInLocalProblem); while (queueToPrune.Any()) { //Get the first variable var headVariable = queueToPrune.First(); queueToPrune.Remove(headVariable); //Get the neighbours of the variable List<Variable> neighbours = problem.GetNeighbours(headVariable).Where(n => !problem.IsVariableAssigned(n)).ToList(); //Loop over neighbours foreach (var neigh in neighbours) { //Get the list of values to delete for conflict List<OverFloorType> valuesToPrune = new List<OverFloorType>(); //Check if value is compatible with remaining values in head foreach (var valPruned in MAC3HeadTailChecker(headVariable, neigh, problem)) { if (!valuesToPrune.Any(v => v == valPruned)) valuesToPrune.Add(valPruned); } //Remove the value from the variable domain in temporal CSP and add to the domain prune foreach (var prunedVal in valuesToPrune) { //Remove domain from variable in problem problem.RemoveDomainElementFromVariable(neigh, prunedVal); //remove domain from variable in current variable neigh.removeDomainElement(prunedVal); if (!neigh.remDomain.Any()) return false; //Add prune action to assignment assign.AddDomainPrune(neigh.pos, prunedVal); } if (valuesToPrune.Any()) { queueToPrune.Add(neigh); } } } return true; }
/// <summary> /// Return the number of remaining values that the assignment will let after being executed /// </summary> /// <param name="assign">Assignment to be evaluated </param> /// <returns>Number of remaining domains values in all remaining variables</returns> public int ConflictAssignment(Assignment assign) { int ret; if (AssignValue(assign.variable, assign.value)) { ret = vars.Sum(v => v.remDomain.Count()); RemoveValue(assign.variable); } else ret = int.MaxValue; return ret; }
/// <summary> /// Creates the assignment and prunes other variables /// </summary> /// <param name="var">Variable.</param> /// <param name="val">Value.</param> /// <returns>True if the assignment is legal</returns> public bool AssignValue(Variable var,OverFloorType val, bool inference = true) { //Create a new assignment Assignment assign = new Assignment (var, val); //Get current domain before MAC3 to store posible values to prune List<OverFloorType> domainBeformMAC = var.remDomain.ToList(); //Get variable prunes var validAssignment = true; if (inference) validAssignment = Search.MAC3(ref assign, new CSP(this) ); if (validAssignment) { //Prune all values that are not a variable assign.domainPrune.Add(var.pos, domainBeformMAC.Where(r => r != val).ToList()); //Go over variable domain prunes to remove from variables foreach (var varPrune in assign.domainPrune.Keys) { List<OverFloorType> valuesToPrune = assign.domainPrune[varPrune]; Variable varToPrune = vars.First(v => v.pos == varPrune); foreach (var vPrune in valuesToPrune) { varToPrune.removeDomainElement(vPrune); } } //Save the assignment assignments.Add(assign); } return validAssignment; }