【问题标题】:Genetic Algorithm for Sudoku [closed]数独的遗传算法[关闭]
【发布时间】:2012-07-04 18:20:59
【问题描述】:

谁能教我如何使用遗传算法解决下面源代码生成的数独?新创建的数独遗传算法求解器应该使用下面源代码中的实例。

import java.util.Random;
//Generates a Sudoku puzzle through brute-force

public class SudokuPuzzle
{
    public int[][] puzzle = new int[9][9];        // Generated puzzle.
    public int[][] solved_puzzle = new int[9][9]; // The solved puzzle.

private int[][] _tmp_grid = new int[9][9]; // For the solver
private Random rand = new Random();
private short solution_count; // Should be 1

/**
 * Constructor generates a new puzzle, and its solution
 */
public SudokuPuzzle()
{
    generateSolvedPuzzle(0);
    generatePuzzle();
}

/**
 * Finds a solved puzzle through depth-first search
 */
private boolean generateSolvedPuzzle(int cur_cell)
{
    if (cur_cell > 80)
        return true;

    int col = cur_cell % 9;
    int row = cur_cell / 9;

    // create a sequence of the integers {1,...,9} of random order
    int [] numbers = new int[9];
    for (int i=0; i < 9; i++)
        numbers[i] = 1+i;
    shuffle_array(numbers);

    for (int i=0; i < 9; i++)
    {
        int n = numbers[i]; // for the next number in the array
        // if number is acceptable by Sudoku rules
        if (!existsInColumn(solved_puzzle, n, col)
                && !existsInRow(solved_puzzle, n, row)
                && !existsInSubGrid(solved_puzzle, n, row, col))
        {
            // attempt to fill in the next cell with the current cell set to number
            solved_puzzle[row][col] = n;
            if (generateSolvedPuzzle(cur_cell + 1))
                return true;
            solved_puzzle[row][col] = 0; // didn't work, reset cell and try the next number in sequence
        }
    }
    return false; // unreachable (since search is exhaustive and a solved puzzle must exist)
}

/**
 * Solves the Sudoku puzzle through depth-first, exhaustive search, and store the number of
 * solutions in solution_count. Currently, we want to use this only to detect if two solutions
 * exist. Hence, we stop the search as soon as two solutions have been found.
 *
 *
 */
private boolean _solvePuzzle(int cur_cell)
{
    if (cur_cell > 80)
    {
        solution_count++;
        if (solution_count > 1) // two solutions detected. notify caller to abort search
            return true;
        return false;
    }

    int col = cur_cell % 9;
    int row = cur_cell / 9;

    if (_tmp_grid[row][col] == 0) // if cell is unfilled
    {
        for (int n=1; n <= 9; n++) // for each number
        {
            // if number is acceptable by Sudoku rules
            if (!existsInColumn(_tmp_grid, n, col)
                    && !existsInRow(_tmp_grid, n, row)
                    && !existsInSubGrid(_tmp_grid, n, row, col))
            {
                // attempt to fill in the next cell with the current cell set to number
                _tmp_grid[row][col] = n;
                if (_solvePuzzle(cur_cell + 1)) // notified of two solutions being detected
                    return true; // notify caller to abort search
                _tmp_grid[row][col] = 0; // try with other numbers
            }
        }
    }
    else
        if (_solvePuzzle(cur_cell + 1)) // notified of two solutions being detected
            return true; // notify caller to abort search

    return false;
}

private void shuffle_array(int array[])
{
    // swap the first size elements with other elements from the whole array
    for (int i = 0; i < array.length; i++)
    {
        // find an index j (i<j<=array_length) to swap with the element i
        int j = i + rand.nextInt(array.length - i);
        int t = array[j];
        array[j] = array[i];
        array[i] = t;
    }
}

/**
 * Returns whether a given number exists in a given column.
 *
 * @param col    column to check.
 * @param number number to check.
 * @return       true iff number exists in row.
 */
private boolean existsInColumn(int[][] puzzle, int number, int col)
{
    for (int row = 0; row < 9; row++)
        if (puzzle[row][col] == number)
            return true;
    return false;
}

/**
 * Returns whether a given number exists in a given row.
 *
 * @param row    row to check.
 * @param number number to check.
 * @return       true iff number exists in row.
 */
private boolean existsInRow(int[][] puzzle, int number, int row)
{
    for (int col = 0; col < 9; col++)
        if (puzzle[row][col] == number)
            return true;
    return false;
}

/**
 * Returns whether if the 3x3 sub-grid which includes (row, col) contains a
 * cell with the given number.
 *
 * @param row    a row in the sub-grid.
 * @param col    a col in the sub-grid.
 * @param number number to check.
 * @return       true iff sub-grid contains number.
 */
private boolean existsInSubGrid(int[][] puzzle, int number, int row, int col)
{
    int sub_grid_start_row = (row / 3)*3;
    int sub_grid_start_col = (col / 3)*3;
    for (int _row = sub_grid_start_row; _row < sub_grid_start_row + 3; _row++)
        for (int _col = sub_grid_start_col; _col < sub_grid_start_col + 3; _col++)
            if (puzzle[_row][_col] == number)
                return true;
    return false;
}

/**
 * Generates a Sudoku puzzle from a solved puzzle by setting up to 64 cells to 0.
 * (We cannot set more than 64 cells to 0. See http://www.math.ie/McGuire_V1.pdf)
 */
private void generatePuzzle()
{
    // copy solved_puzzle to puzzle
    for (int row = 0; row < 9; row++)
        for (int col = 0; col < 9; col++)
            puzzle[row][col] = solved_puzzle[row][col];

    // create a sequence of the integers {0,...,80} of random order
    int [] cell_sequence = new int[81];
    for (int i=0; i < 81; i++)
        cell_sequence[i] = i;
    shuffle_array(cell_sequence);

    // attempt to set each cell in the sequence to 0
    int count_set_to_zero = 0;
    for (int i=0; i < 81 && count_set_to_zero < 64; i++)
    {
        int cur_cell = cell_sequence[i];
        int col = cur_cell % 9;
        int row = cur_cell / 9;
        int sav = puzzle[row][col];
        puzzle[row][col] = 0;
        solution_count = 0;

        // copy puzzle to _tmp_grid for the solver to work on
        for (int r = 0; r < 9; r++)
            for (int c = 0; c < 9; c++)
                _tmp_grid[r][c] = puzzle[r][c];

        if (_solvePuzzle(0)) // Puzzle allows more than 1 solution
            puzzle[row][col] = sav; // Revert to original puzzle
        else
            count_set_to_zero++;
    }
}

public void showSolution()
{
    for (int row = 0; row < 9; row++)
    {
        System.out.print("  ");
        for (int col = 0; col < 9; col++)
            System.out.print(" " + solved_puzzle[row][col]);
        System.out.println();
    }
}

public void show()
{
    for (int row = 0; row < 9; row++)
    {
        System.out.print("  ");
        for (int col = 0; col < 9; col++)
            System.out.print(" " + puzzle[row][col]);
        System.out.println();
    }
}

public static void main(String[] args)
{
    SudokuPuzzle sudoku_puzzle = new SudokuPuzzle();
    System.out.println("Puzzle:");
    sudoku_puzzle.show();
    System.out.println();
    System.out.println("Solution:");
    sudoku_puzzle.showSolution();
}

}

【问题讨论】:

  • 到底是什么问题?
  • 您是在谈论维基百科 (en.wikipedia.org/wiki/Genetic_algorithm) 上描述的遗传算法吗?我不认为你可以将这段代码翻译成这样的算法,你说的是完全重写。这是一个完全不同的概念。
  • 阿米特,我必须制作一个使用遗传算法解决数独的程序。数独的问题将由我在上面发布的程序生成,我必须为它创建一个求解器。
  • mizipzor,是的,它在维基百科上的描述。不能将此代码翻译成遗传算法吗?如果我为它重写一个新程序怎么样?这个程序实际上会生成一个数独问题,我必须创建一个求解器来使用遗传算法来解决它。我在互联网上搜索了几个小时,但仍然找不到解决方案:(请帮助..

标签: java genetic-algorithm sudoku


【解决方案1】:

您可以先看看herehere。这些不是基于 Java 的解决方案,但应该能让您走上正轨。

仅仅因为您可以访问生成谜题的程序,您不能只是将其转换为基于 GA 的应用程序,原因是您拥有的程序和您要构建的程序执行不同的任务。

【讨论】:

  • 感谢您的回复。请问我必须根据上面的代码生成一个新的谜题(问题),并在Java中编写一个基于遗传算法的函数来解决它吗?
  • @Alan:我不太明白你的问题,但是,你需要写一个好的fitness function。一旦你解决了这个问题,实施 GA 应该不会那么困难。
  • 感谢您的帮助,先生 :) 我会尽力做到的。
  • @Alan:不用担心。一旦你拥有了健身功能,其余的就不难了。祝你好运。
猜你喜欢
  • 2013-05-29
  • 2010-10-19
  • 2011-04-16
  • 2012-03-27
  • 2012-03-16
  • 2019-08-19
  • 1970-01-01
  • 2010-10-03
  • 2013-01-24
相关资源
最近更新 更多