Recursion 多解递归回溯

Recursion 多解递归回溯,recursion,backtracking,Recursion,Backtracking,这是来自AIMA的回溯递归算法伪代码。然而,我不明白它是返回所有可能的解决方案,还是只返回第一个找到的解决方案。如果这是最后一个选项,请您帮助我修改它以返回可能的解决方案列表(或至少更新一些全局列表) 编辑:我用Java实现了这个算法。然而,有一个问题: 如果我不返回赋值,而是将其保存在结果中,则递归停止条件将失败(即它不再存在)。如何实现另一个停止条件?也许我最终应该返回真的 这是我的密码: function BACKTRACKING-SEARCH(csp) returns a solutio

这是来自AIMA的回溯递归算法伪代码。然而,我不明白它是返回所有可能的解决方案,还是只返回第一个找到的解决方案。如果这是最后一个选项,请您帮助我修改它以返回可能的解决方案列表(或至少更新一些全局列表)

编辑:我用Java实现了这个算法。然而,有一个问题:

如果我不返回赋值,而是将其保存在结果中,则递归停止条件将失败(即它不再存在)。如何实现另一个停止条件?也许我最终应该返回真的

这是我的密码:

function BACKTRACKING-SEARCH(csp) returns a solution, or failure 
       return RECURSIVE-  BACKTRACKING({ }, csp)
function RECURSIVE-BACKTRACKING(assignment,csp) returns a solution, or failure 
       if assignment is complete then 
                 return assignment
       var ←SELECT-UNASSIGNED-VARIABLE(VARIABLES[csp],assignment,csp)
       for each value in ORDER-DOMAIN-VALUES(var,assignment,csp) do
                 if value is consistent with assignment according to CONSTRAINTS[csp] then
                           add {var = value} to assignment
                           result ← RECURSIVE-BACKTRACKING(assignment, csp)
                           if result ̸= failure then 
                                            return result
                           remove {var = value} from assignment 
       return failure
/**
*实际回溯。不幸的是,我没有时间实施LCV或MCV,
*因此,它将只是普通变量逐变量搜索。
*@param行
*@param one可能性假设
*@param结果
*/
公共静态布尔递归回溯(Line-Line、ArrayList-OnePossibleSitation、ArrayList-result){
if(onepossibleSitation.size()==line.getNumOfVars()){
//代替返回(分配)
ArrayList situationCopy=新建ArrayList();
情景副本.addAll(一个可能情景);
结果。添加(情景副本);
一个可能的初始化。清除();
}
块变量ToAssign=null;
//遍历所有变量并选择一个未赋值变量
对于(int i=0;i这段代码检查是否找到了解决方案,如果找到了,则返回解决方案。否则,继续回溯。这意味着,它返回找到的第一个解决方案

/**
 * The actual backtracking. Unfortunately, I don't have time to implement LCV or MCV,
 * therefore it will be just ordinary variable-by-variable search.
 * @param line
 * @param onePossibleSituation
 * @param result
 */
public static boolean recursiveBacktrack(Line line, ArrayList<Integer> onePossibleSituation, ArrayList<ArrayList<Integer>> result){


if (onePossibleSituation.size() == line.getNumOfVars()){
    // instead of return(assignment)
    ArrayList<Integer> situationCopy = new ArrayList<Integer>();
    situationCopy.addAll(onePossibleSituation);
    result.add(situationCopy);
    onePossibleSituation.clear();
}

Block variableToAssign = null;
// iterate through all variables and choose one unassigned
for(int i = 0; i < line.getNumOfVars(); i++){
     if(!line.getCspMiniTaskVariables().get(i).isAssigned()){
         variableToAssign = line.getCspMiniTaskVariables().get(i);
         break;
     }
}

// for each domain value for given block   
for (int i = line.getCspMiniTaskDomains().get(variableToAssign.getID())[0]; 
        i <= line.getCspMiniTaskDomains().get(variableToAssign.getID())[0]; i++){

    if(!areThereConflicts(line, onePossibleSituation)){
        //complete the assignment
        variableToAssign.setStartPositionTemporary(i);
        variableToAssign.setAssigned(true);
        onePossibleSituation.add(i);
        //do backtracking
        boolean isPossibleToPlaceIt = recursiveBacktrack(line,onePossibleSituation,result);
        if(!isPossibleToPlaceIt){
            return(false);
        }
    }

    // unassign
    variableToAssign.setStartPositionTemporary(-1);
    variableToAssign.setAssigned(false);
    onePossibleSituation.remove(i);

}

// end of backtracking
return(false);

}
您可以这样修改它:

if result ̸= failure then 
    return result
remove {var = value} from assignment 
或者,最好修改此部分:

if result ̸= failure then 
    PRINT result // do not return, just save the result
remove {var = value} from assignment 
关于编辑的问题:

首先,在第一个
if
中返回
true
,这样递归就知道它找到了解决方案。第二步,可能是错误:

if assignment is complete then 
    print assignment
    return assignment // print it and return
应该是

if(!isPossibleToPlaceIt){
    return(false);
}
因为如果回溯发现了什么,它将返回
true
,这意味着您不必再检查任何其他内容

编辑#2:如果要继续回溯以查找所有解决方案,只需使用
返回删除前面的整个
If
部分:

if(isPossibleToPlaceIt){
    return(true);
}

因此,我们将以任何方式继续搜索。

此代码检查是否找到解决方案,如果找到,则返回该解决方案。否则,继续回溯。这意味着,它将返回找到的第一个解决方案

/**
 * The actual backtracking. Unfortunately, I don't have time to implement LCV or MCV,
 * therefore it will be just ordinary variable-by-variable search.
 * @param line
 * @param onePossibleSituation
 * @param result
 */
public static boolean recursiveBacktrack(Line line, ArrayList<Integer> onePossibleSituation, ArrayList<ArrayList<Integer>> result){


if (onePossibleSituation.size() == line.getNumOfVars()){
    // instead of return(assignment)
    ArrayList<Integer> situationCopy = new ArrayList<Integer>();
    situationCopy.addAll(onePossibleSituation);
    result.add(situationCopy);
    onePossibleSituation.clear();
}

Block variableToAssign = null;
// iterate through all variables and choose one unassigned
for(int i = 0; i < line.getNumOfVars(); i++){
     if(!line.getCspMiniTaskVariables().get(i).isAssigned()){
         variableToAssign = line.getCspMiniTaskVariables().get(i);
         break;
     }
}

// for each domain value for given block   
for (int i = line.getCspMiniTaskDomains().get(variableToAssign.getID())[0]; 
        i <= line.getCspMiniTaskDomains().get(variableToAssign.getID())[0]; i++){

    if(!areThereConflicts(line, onePossibleSituation)){
        //complete the assignment
        variableToAssign.setStartPositionTemporary(i);
        variableToAssign.setAssigned(true);
        onePossibleSituation.add(i);
        //do backtracking
        boolean isPossibleToPlaceIt = recursiveBacktrack(line,onePossibleSituation,result);
        if(!isPossibleToPlaceIt){
            return(false);
        }
    }

    // unassign
    variableToAssign.setStartPositionTemporary(-1);
    variableToAssign.setAssigned(false);
    onePossibleSituation.remove(i);

}

// end of backtracking
return(false);

}
您可以这样修改它:

if result ̸= failure then 
    return result
remove {var = value} from assignment 
或者,最好修改此部分:

if result ̸= failure then 
    PRINT result // do not return, just save the result
remove {var = value} from assignment 
关于编辑的问题:

首先,在第一个
if
中返回
true
,这样递归就知道它找到了解决方案。第二步,可能是错误:

if assignment is complete then 
    print assignment
    return assignment // print it and return
应该是

if(!isPossibleToPlaceIt){
    return(false);
}
因为如果回溯发现了什么,它将返回
true
,这意味着您不必再检查任何其他内容

编辑#2:如果要继续回溯以查找所有解决方案,只需使用
返回删除前面的整个
If
部分:

if(isPossibleToPlaceIt){
    return(true);
}

因此,我们将以任何方式继续搜索。

对不起,在这种情况下,我们如何停止递归?返回(分配)被用作最终停止条件。是的,不要删除返回,同时使用返回和打印,如答案所示:)它有效吗?不幸的是,我不需要在这里打印。我需要的是将这个找到的一个可能的解决方案存储在结果字段中不,我没有编辑你的答案,甚至没有一封信。对不起,如果有问题…我的意思是问题:)只需在第一个
if
块中返回
true
,那么递归将停止。对不起,我们如何停止递归在这种情况下是否打开?返回(分配)被用作最终停止条件。是的,不要删除返回,同时使用返回和打印,如答案:)是否有效?很遗憾,我不需要在此处打印。我需要的是将此找到的一个可能的解决方案存储在结果字段中否,我没有编辑您的答案,甚至没有一封信。很抱歉,如果出现问题…我的意思是问题:)请重试rn
true
在第一个
if
块中,因此递归将停止。更新了关于您的实现的我的答案。更新了关于您的实现的我的答案。