вопросы относительно использования* с загадкой с 15 квадратами

Я пытаюсь создать* решатель для загадки с 15 квадратами.

alt text

Цель состоит в том, чтобы перестроить мозаики так, чтобы они появились в своих естественных положениях. Можно только двигать одну мозаику за один раз. Каждое возможное состояние загадки является узлом в поисковом графике.

Для h (x) функция, я использую совокупную сумму, через все мозаики, дислокации мозаики от целевого состояния. В вышеупомянутом изображении эти 5 в местоположении 0,0, и оно принадлежит в местоположении 1,0, поэтому оно способствует 1 h (x) функция. Следующая мозаика является этими 11, расположенными в 0,1, и принадлежит в 2,2, поэтому она способствует 3 h (x). И так далее.Править: Я теперь понимаю, что это - то, что они называют "манхэттенским расстоянием", или "расстоянием такси".

Я использовал счет шага g (x). В моей реализации, для любого узла в графе состояния, g всего +1 от g предшествующего узла.

Для нахождения последовательных узлов я просто исследую, куда я могу возможно переместить "дыру" в загадку. Существует 3 соседа к состоянию загадки (иначе узел), который отображен: дыра может переместиться на север, запад или восток.

Мой* поиск иногда сходится к решению в 20-х, иногда 180 с, и иногда не сходится вообще (ожидал 10 минут или больше). Я думаю, что h разумен. Я задаюсь вопросом, смоделировал ли я g правильно. Другими словами, действительно ли возможно, что мой* функция достигает узла в графике через путь, который не является кратчайшим путем?

Возможно, разве я не достаточно долго ждал? Возможно, 10 минут не достаточно долги?

Для полностью случайного расположения, (принимающий проблемы четности), Каково среднее количество перестановок*, решение исследует? (покажите математику),

Я собираюсь искать логические ошибки в своем коде, но тем временем, Какие-либо подсказки?

(PS: это сделано в JavaScript).

Кроме того, нет, это не домашняя работа CompSci. Это - просто персональная вещь исследования. Я просто пытаюсь изучить JavaScript.


Править: Я нашел, что время выполнения, высоко зависят от эвристики. Я видел 10x, фактор относился к эвристике от статьи, которую кто-то упомянул, и это заставило меня задаться вопросом - почему 10x? Почему линейный? Поскольку это сделано в JavaScript, я мог изменить код для динамичного обновления таблицы HTML узлом, в настоящее время будучи рассмотренным. Этот allowd меня для заглядывания на алгоритм, в то время как это прогрессировало. С регулярной эвристикой расстояния такси я смотрел, поскольку ей не удалось сходиться.

Были 5's и 12 в верхнем ряду, и они продолжали бродить вокруг. Я видел бы 1,2,3,4 сползания в верхний ряд, но затем они выбудут, и другие числа переместились бы вверх там. То, что я надеялся видеть, было 1,2,3,4 видами накопления к вершине и затем пребывания там.

Я думал мне - это не способ, которым я решаю это лично. Делая это вручную, я решаю верхний ряд, затем 2ne строка, затем 3-й и 4-й вид строк одновременно.

Таким образом, я настроил h (x), функция к в большей степени взвешивает более высокие строки и "lefter" столбцы. Результат состоял в том, что* сходился намного более быстро. Это теперь работает через 3 минуты вместо "неограниченно долго". С "быстрым взглядом" я говорил о, я вижу, что меньшие числа накапливаются к более высоким строкам и остаются там. Мало того, что это походит на правильную вещь, она работает намного быстрее.

Я нахожусь в процессе попытки набора изменений. Кажется довольно ясным, что* время выполнения очень чувствительно к эвристике. В настоящее время лучшая эвристика я находил использование суммированием dislocation * ((4-i) + (4-j)) где я и j - строка и столбец, и дислокация является расстоянием такси.

Одна интересная часть результата я добрался: с конкретной эвристикой я нахожу путь очень быстро, но это - очевидно, не кратчайший путь. Я думаю, что это вызвано тем, что я взвешиваю эвристику. В одном случае я получил путь 178 шагов в 10-х. Мое собственное ручное усилие производит решение в 87 перемещениях. (намного больше, чем 10-е). Больше расследования гарантировано.

Таким образом, результат, я вижу, что он сходиться должен быстрее, и путь является определенно не кратчайшим. Я должен думать об этом больше.


Код:

var stop = false; 
function Astar(start, goal, callback) {
    // start and goal are nodes in the graph, represented by 
    // an array of 16 ints.  The goal is:  [1,2,3,...14,15,0] 
    // Zero represents the hole. 

    // callback is a method to call when finished. This runs a long time, 
    // therefore we need to use setTimeout() to break it up, to avoid
    // the browser warning like "Stop running this script?"

    // g is the actual distance traveled from initial node to current node.
    // h is the heuristic estimate of distance from current to goal.
    stop = false;
    start.g = start.dontgo = 0;

    // calcHeuristic inserts an .h member into the array
    calcHeuristicDistance(start);

    // start the stack with one element
    var closed = [];       // set of nodes already evaluated.
    var open = [ start ];  // set of nodes to evaluate (start with initial node)

    var iteration = function() {
        if (open.length==0) {
            // no more nodes.  Fail. 
            callback(null);
            return;
        }
        var current = open.shift();  // get highest priority node

        // update the browser with a table representation of the 
        // node being evaluated
        $("#solution").html(stateToString(current));

        // check solution returns true if current == goal
        if (checkSolution(current,goal)) {
            // reconstructPath just records the position of the hole 
            // through each node
            var path= reconstructPath(start,current);
            callback(path);
            return;
        }

        closed.push(current);

        // get the set of neighbors.  This is 3 or fewer nodes.
        // (nextStates is optimized to NOT turn directly back on itself)
        var neighbors = nextStates(current, goal);

        for (var i=0; i

14
задан 16 revs, 3 users 62% 23 May 2019 в 16:04
поделиться

7 ответов

Поиск в форме звезды найдет оптимальное решение, доказав, что все пути, которые еще не решены, не могут быть решены за меньшее количество ходов, чем текущее решение. . Вы ищете не лучшее решение, а самое быстрое решение. Следовательно, вы можете оптимизировать свой алгоритм, вернув первое решение, путем взвешивания числа ходов ниже, чем ваша эвристическая функция, и эвристика может вернуть завышенную оценку.

Сама эвристическая функция обычно лучше всего моделируется Манхэттенским расстоянием и линейным конфликтом. Расстояние Манхэттена хорошо объясняется в других ответах и ​​в статье в Википедии, и вы, кажется, справляетесь с этим. Линейный конфликт добавляет два к манхэттенскому расстоянию для каждой пары блоков, которые необходимо поменять местами, чтобы найти решение. Например, если в строке содержится «3 2 1 4», то нужно поменять местами один и три, и для этого нужно будет переместить одну в другую строку.

Использование базы данных шаблонов является вариантом и может помочь вашему поиску избежать определенных тупиков, а использование памяти для решения головоломки из 15 должно быть управляемым.

и эвристика может вернуть завышенную оценку.

Сама эвристическая функция обычно лучше всего моделируется Манхэттенским расстоянием и линейным конфликтом. Расстояние Манхэттена хорошо объясняется в других ответах и ​​в статье в Википедии, и вы, кажется, справляетесь с этим. Линейный конфликт добавляет два к манхэттенскому расстоянию для каждой пары блоков, которые необходимо поменять местами, чтобы найти решение. Например, если в строке содержится «3 2 1 4», то нужно поменять местами один и три, и для этого нужно будет переместить одну в другую строку.

Использование базы данных шаблонов является вариантом и может помочь вашему поиску избежать определенных тупиков, а использование памяти для решения головоломки из 15 должно быть управляемым.

и эвристика может вернуть завышенную оценку.

Сама эвристическая функция обычно лучше всего моделируется Манхэттенским расстоянием и линейным конфликтом. Расстояние Манхэттена хорошо объясняется в других ответах и ​​в статье в Википедии, и вы, кажется, справляетесь с этим. Линейный конфликт добавляет два к манхэттенскому расстоянию для каждой пары блоков, которые необходимо поменять местами, чтобы найти решение. Например, если строка содержит «3 2 1 4», то нужно поменять местами один и три, и для этого нужно будет переместить одну в другую строку.

Использование базы данных шаблонов является вариантом и может помочь вашему поиску избежать определенных тупиков, и использование памяти для решения головоломки из 15 должно быть управляемым.

Сама эвристическая функция обычно лучше всего моделируется Манхэттенским расстоянием и линейным конфликтом. Расстояние Манхэттена хорошо объясняется в других ответах и ​​в статье в Википедии, и вы, кажется, справляетесь с этим. Линейный конфликт добавляет два к манхэттенскому расстоянию для каждой пары блоков, которые необходимо поменять местами, чтобы найти решение. Например, если строка содержит «3 2 1 4», то нужно поменять местами один и три, и для этого нужно будет переместить одну в другую строку.

Использование базы данных шаблонов является вариантом и может помочь вашему поиску избежать определенных тупиков, а использование памяти для решения головоломки из 15 должно быть управляемым.

Сама эвристическая функция обычно лучше всего моделируется Манхэттенским расстоянием и линейным конфликтом. Расстояние Манхэттена хорошо объясняется в других ответах и ​​в статье в Википедии, и вы, кажется, справляетесь с этим. Линейный конфликт добавляет два к манхэттенскому расстоянию для каждой пары блоков, которые необходимо поменять местами, чтобы найти решение. Например, если строка содержит «3 2 1 4», то нужно поменять местами один и три, и для этого нужно будет переместить одну в другую строку.

Использование базы данных шаблонов является вариантом и может помочь вашему поиску избежать определенных тупиков, а использование памяти для решения головоломки из 15 должно быть управляемым.

Линейный конфликт добавляет два к манхэттенскому расстоянию для каждой пары блоков, которые необходимо поменять местами, чтобы найти решение. Например, если строка содержит «3 2 1 4», то нужно поменять местами один и три, и для этого нужно будет переместить одну в другую строку.

Использование базы данных шаблонов является вариантом и может помочь вашему поиску избежать определенных тупиков, а использование памяти для решения головоломки из 15 должно быть управляемым.

Линейный конфликт добавляет два к манхэттенскому расстоянию для каждой пары блоков, которые необходимо поменять местами, чтобы найти решение. Например, если строка содержит «3 2 1 4», то нужно поменять местами один и три, и для этого нужно будет переместить одну в другую строку.

Использование базы данных шаблонов является вариантом и может помочь вашему поиску избежать определенных тупиков, и использование памяти для решения головоломки из 15 должно быть управляемым.

5
ответ дан 1 December 2019 в 14:44
поделиться

Может быть, он сойдется быстрее, если вы сначала будете стрелять по промежуточным целям. Например, засчитывайте только верхнюю и правую строки. Уложить эти ряды не займет много времени, тогда вы сможете собрать оставшиеся 3x3.

0
ответ дан 1 December 2019 в 14:44
поделиться

Да, именно так я слышал об этой проблеме. g(x) - это количество слайдов плитки, которые имели место, а h(x) - это общее расстояние, на котором все плитки находятся от требуемых квадратов. До сегодняшнего дня я не видел ничего, кроме этого подхода (манхэттенский эвристический ), но только что нашел этот так называемый диагональный ярлык - возможно, вы захотите проверить его.

.
2
ответ дан 1 December 2019 в 14:44
поделиться

Что вы используете для тестовых данных? Если они случайны, вы не сможете решить головоломку примерно в половине случаев. Невозможно поменять две плитки, оставляя остальные в одной позиции, поэтому если вы достигнете почти конечной позиции, но две плитки будут поменяны, вы не сможете поставить их в желаемую позицию, и ни один алгоритм поиска не сможет успешно завершить головоломку.

В 19 веке американский пасьянсный мастер Сэм Лойд продал эти игрушки с 15 и 14 перевернутыми, и предложил большой приз любому, кто мог бы продемонстрировать решение, поменяв плитку (предположительно, кроме той, что у меня есть, маленькая отвертка). В сегодняшнем правовом климате, я не знаю, посмел бы он.

Одной из возможностей было бы попытаться вставить его в правильную конфигурацию или в конфигурацию 15-14.

.
1
ответ дан 1 December 2019 в 14:44
поделиться

То, что я узнал

1
ответ дан 1 December 2019 в 14:44
поделиться

Я однажды запрограммировал такой алгоритм (windowsApp) и у меня есть следующий опыт

1]) самое большое удовольствие видеть робота в действии, если он использует (близкое) оптимальное решение. (Для человеческого наблюдателя невозможно понять, как робот "думает" и сделка из хаоса в порядок внезапно)

2) Если вы хотите найти оптимальное решение, то ваша функция h() должна недооценивать истинное расстояние. Если вы ее переоцениваете, то не найдете оптимального.

3) Потенциальное пространство состояний огромно, 15!/2 (10^12). Если Вы используете плохую эвристическую функцию, то Ваши наборы данных будут расти намного больше, чем размер Вашей основной памяти, и каждый доступ к данным будет требовать множества дисковых обращений. Если это произойдет, то время выполнения будет "бесконечным".

.
1
ответ дан 1 December 2019 в 14:44
поделиться
check this
import javax.swing.*; 
import java.awt.*;
import java.awt.event.*;
import java.lang.Object;

class Puzzle extends JPanel implements ActionListener
{
    JButton[] b = new JButton[16];
    Puzzle()
    {
        b[0] = new JButton("4");
        b[1] = new JButton("11");
        b[2] = new JButton("5");
        b[3] = new JButton("9");
        b[4] = new JButton("1");
        b[5] = new JButton("10");
        b[6] = new JButton("12");
        b[7] = new JButton("13");
        b[8] = new JButton("15");
        b[9] = new JButton("14");
        b[10] = new JButton("3");
        b[11] = new JButton("2"); 
        b[12] = new JButton("7");
        b[13] = new JButton("8");
        b[14] = new JButton("6");
        b[15] = new JButton("");
        GridLayout grid = new GridLayout(4,4);
        setLayout(grid);
        for(int i=0;i<16;i++)
            add(b[i]);
        for(int i=0;i<16;i++)
            b[i].addActionListener(this);
    }
    public void actionPerformed(ActionEvent e)
    {
        /*if(e.getSource()==b[11])
        {
            if(b[15].getText()=="")
            {
                b[15].setText("");
            }
        }
        else if(e.getSource()==b[3])
        {
            if(b[2].getText()=="")
            {
                b[2].setText("");
            }
        }*/
        for(int i=0;i<16;i++)
        {
            System.out.println(e.getSource());
            if(e.getSource()==b[i])
            {
                if(i==5 || i==6 || i==9 || i==10)
                {   
                    if(b[i-1].getText()=="")
                    {
                        b[i-1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i+1].getText()=="")
                    {
                        b[i+1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i-4].getText()=="")
                    {
                        b[i-4].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i+4].getText()=="")
                    {
                        b[i+4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                else if(i==4 || i==8)
                {   
                    if(b[i+1].getText()=="")
                    {
                        b[i+1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i-4].getText()=="")
                    {
                        b[i-4].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i+4].getText()=="")
                    {
                        b[i+4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                else if(i==7 || i==11)
                {   
                    if(b[i-1].getText()=="")
                    {
                        b[i-1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i-4].getText()=="")
                    {
                        b[i-4].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i+4].getText()=="")
                    {
                        b[i+4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                if(i==0)
                {   
                    if(b[i+1].getText()=="")
                    {
                        b[i+1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i+4].getText()=="")
                    {
                        b[i+4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                if(i==3)
                {   
                    if(b[i-1].getText()=="")
                    {
                        b[i-1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i+4].getText()=="")
                    {
                        b[i+4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                if(i==15)
                {   
                    if(b[i-1].getText()=="")
                    {
                        b[i-1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i-4].getText()=="")
                    {
                        b[i-4].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i+4].getText()=="")
                    {
                        b[i+4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                if(i==12)
                {   
                    if(b[i+1].getText()=="")
                    {
                        b[i+1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i-4].getText()=="")
                    {
                        b[i-4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                if(i==1 || i==2)
                {   
                    if(b[i+1].getText()=="")
                    {
                        b[i+1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i-1].getText()=="")
                    {
                        b[i-1].setText(b[i].getText());
                        b[i].setText("");
                    }                   
                    else if(b[i+4].getText()=="")
                    {
                        b[i+4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
                if(i==13 || i==14)
                {   
                    if(b[i+1].getText()=="")
                    {
                        b[i+1].setText(b[i].getText());
                        b[i].setText("");
                    }
                    else if(b[i-1].getText()=="")
                    {
                        b[i-1].setText(b[i].getText());
                        b[i].setText("");
                    }                   
                    else if(b[i-4].getText()=="")
                    {
                        b[i-4].setText(b[i].getText());
                        b[i].setText("");
                    }
                }
            }
        }
        //System.out.println(e.getActionCommand());
        }

    public static void main(String[] args)
    {
        JFrame frame = new JFrame("15-Puzzle");             

        //frame.setContentPane(panel);

JComponent newContentPane = new Puzzle();
        //newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);





        //panel.add(button);  
        frame.setSize(400,400);


        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
-2
ответ дан 1 December 2019 в 14:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: