Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab 数独解算器求值函数_Matlab_Evaluation_Sudoku - Fatal编程技术网

Matlab 数独解算器求值函数

Matlab 数独解算器求值函数,matlab,evaluation,sudoku,Matlab,Evaluation,Sudoku,所以我正试图写一个简单的遗传算法来解决数独问题(我知道这不是最有效的方法,但它只是为了练习进化算法)。我遇到了一些问题,需要一个有效的评估函数来测试这个难题是否得到解决,以及有多少错误。我的第一反应是检查矩阵的每一行和每一列(以倍频程进行,类似于matlab)是否有唯一的元素,方法是对它们进行排序,检查重复的元素,然后将它们放回原来的状态,这似乎很冗长。有什么想法吗 很抱歉,如果之前有人问过这个问题…我会使用网格的数字作为索引,并增加9个元素长度数组的相应元素=>s_数组[x]++,其中x是从网

所以我正试图写一个简单的遗传算法来解决数独问题(我知道这不是最有效的方法,但它只是为了练习进化算法)。我遇到了一些问题,需要一个有效的评估函数来测试这个难题是否得到解决,以及有多少错误。我的第一反应是检查矩阵的每一行和每一列(以倍频程进行,类似于matlab)是否有唯一的元素,方法是对它们进行排序,检查重复的元素,然后将它们放回原来的状态,这似乎很冗长。有什么想法吗


很抱歉,如果之前有人问过这个问题…

我会使用网格的数字作为索引,并增加9个元素长度数组的相应元素=>s_数组[x]++,其中
x
是从网格中获取的数字。 在检查一行结束时,数组中的每个元素都必须是1。如果0出现在数组中的某个位置,则该行是错误的

然而,这只是一个简单的健全检查,如果没有问题,逐行检查


PS:如果是10年前,我会建议使用位操作的组装解决方案(1位、2位、3位等,用于值1、2或3),并检查结果是否为2^10-1。

听起来不错,除了“放回”部分。你可以把拼图中任何一行、一列或一个正方形的数字放在一个列表中,然后按你想要的方式检查双倍数字。如果有双精度,则存在错误。如果所有数字都是唯一的,那么就没有了。您不需要从拼图中取出实际数字,因此也不需要将它们放回原处

此外,如果您正在编写解算器,它不应该执行任何无效的移动,因此根本不需要进行此检查。

加速:
使用按位操作而不是排序

我用c语言制作了100行数独解算器,速度相当快。对于实现DLX algorhitm所需的高速或超高速,在matlab exchange上也有相关文件。


s_算法

#include "stdio.h"
int rec_sudoku(int (&mat)[9][9],int depth)
{
    int sol[9][9][10]; //for eliminating
    if(depth == 0) return 1;
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
            sol[i][j][9]=9;
            for(int k=0;k<9;k++)
            {
                if(mat[i][j]) sol[i][j][k]=0;
                else sol[i][j][k]=1;
            }
        }
    }
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
            if(mat[i][j] == 0) continue;
            for(int k=0;k<9;k++)
            {
                if(sol[i][k][mat[i][j]-1])
                {
                    if(--sol[i][k][9]==0) return 0;
                    sol[i][k][mat[i][j]-1]=0;
                }
                if(sol[k][j][mat[i][j]-1])
                {
                    if(--sol[k][j][9]==0) return 0;
                    sol[k][j][mat[i][j]-1]=0;
                }
            }
            for(int k=(i/3)*3;k<(i/3+1)*3;k++)
            {
                for(int kk=(j/3)*3;kk<(j/3+1)*3;kk++)
                {
                    if(sol[k][kk][mat[i][j]-1])
                    {
                        if(--sol[k][kk][9]==0) return 0;
                        sol[k][kk][mat[i][j]-1]=0;
                    }
                }
            }
        }
    }
    for(int c=1;c<=9;c++)
    {
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                if(sol[i][j][9] != c) continue;
                for(int k=0;k<9;k++)
                {
                    if(sol[i][j][k] != 1) continue;
                    mat[i][j]=k+1;
                    if(rec_sudoku(mat,depth-1)) return 1;
                    mat[i][j]=0;
                }
                return 0;
            }
        }
    }
    return 0;
}
int main(void)
{
    int matrix[9][9] =
    {
        {1,0,0,0,0,7,0,9,0},
        {0,3,0,0,2,0,0,0,8},
        {0,0,9,6,0,0,5,0,0},
        {0,0,5,3,0,0,9,0,0},
        {0,1,0,0,8,0,0,0,2},
        {6,0,0,0,0,4,0,0,0},
        {3,0,0,0,0,0,0,1,0},
        {0,4,0,0,0,0,0,0,7},
        {0,0,7,0,0,0,3,0,0}
    };
    int d=0;
    for(int i=0;i<9;i++) for(int j=0;j<9;j++) if(matrix[i][j] == 0) d++;
    if(rec_sudoku(matrix,d)==0)
    {
        printf("no solution");
        return 0;
    }
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
            printf("%i ",matrix[i][j]);
        }
        printf("\n");
    }
    return 1;
}
#包括“stdio.h”
int rec_数独(int(&mat)[9][9],int深度)
{
int sol[9][9][10];//用于消除
如果(深度==0)返回1;

对于(int i=0;i检查很容易,您将为行、列和3x3创建集合,如果不存在,则添加一个数字,如果不存在,则相应地更改适合度

然而,真正的诀窍是相应地“改变你的适应度”。有些问题似乎非常适合GA和ES(进化策略),也就是说,我们在宽容中寻找解决方案,数独有一个确切的答案……很棘手

我的第一个难题可能是创建具有可变长度染色体的解决方案(它们可以是固定长度的,但9x9带有空白)。适应度函数应该能够确定解决方案的哪一部分有保证,哪一部分没有保证(有时候你必须在一个非常难玩的数独游戏中在黑暗中猜测,如果不成功的话,你必须回溯),为每个可能的分支创建子元素是一个好主意

这是一个递归解决方案。但是,您可以从电路板上的不同位置开始扫描。重组将组合解决方案,这些解决方案组合具有重叠解决方案的未验证部分

只要以这种高层次的轻松方式思考一下,我就能看出这将是多么令人费解


只有当有多条路径可供选择时才会应用变异,毕竟变异是一种猜测。

当我解决这个问题时,我只计算了每行、每列和子网格中重复的数量(事实上,我只需要在列和子网格中计算重复项,因为我的进化运算符的设计从未将重复项引入行)。我只是使用哈希集来检测重复项。有更快的方法,但这对我来说足够快了

您可以在中看到这一点(如果速度太快,请增加人口规模以降低速度)。彩色方块是重复的。黄色方块与另一个方块冲突,橙色方块与另外两个方块冲突,红色方块与三个或更多个方块冲突。

这是我的解决方案。

这是我的使用集。如果一条线、一个块或一列的设置长度(比方说)为7,则适合度为9-7

  • 如果您操作的是一小组整数,则可以使用桶排序在
    O(n)
    中进行排序

  • 您可以使用
    tmp
    数组在matlab中执行此任务:

    功能tf=检查子集(电路板、sel) % %给定一个9x9板和一个选择(使用逻辑9x9 sel矩阵) %验证电路板(sel)是否有9个唯一的元件 % %作出的假设: %-电路板为9x9,编号为1,2,…,9 %-sel只有9个“真”条目:nnz(sel)=9 % tmp=零(1,9); tmp(板(sel))=1;%穷人桶分拣 tf=all(tmp==1)&&nnz(sel)==9&&numel(tmp)==9;%检查有效性

  • 现在我们可以使用
    checkSubSet
    来验证电路板是否正确

    function isCorrect = checkSudokuBoard( board )
    %
    % assuming board is 9x9 matrix with entries 1,2,...,9
    %
    
    isCorrect = true;
    % check rows and columns
    for ii = 1:9
        sel = false( 9 );
        sel(:,ii) = true;
        isCorrect = checkSubSet( board, sel );
        if ~isCorrect
            return;
        end
        sel = false( 9 );
        sel( ii, : ) = true;
        isCorrect = checkSubSet( board, sel );
        if ~isCorrect
            return;
        end
    end
    % check all 3x3 
    for ii=1:3:9
        for jj=1:3:9
            sel = false( 9 );
            sel( ii + (0:2) , jj + (0:2) ) = true;
            isCorrect = checkSubSet( board, sel );
            if ~isCorrect
                return;
            end
        end
    end