Professional Documents
Culture Documents
лаба4 гл
лаба4 гл
Ім'я: Микола
Група: КН-304
Кафедра: САПР
Дисципліна: Методи та системи штучного інтелекту
Перевірив: Головацький Р. І.
ЗВІТ
до лабораторної роботи №4
“Неінформовані методи пошуку рішення задач в просторі й стані. Алгоритм А*”
Мета роботи – розглянути метод оціночних функцій А*, набути практичні
навички у його використанні та програмуванні.
2 4 5
8 11 14 9
3 1 7 13
12 15 10 6
Теоретичні відомості
Неінформований пошук – стратегія пошуку рішення в просторі
станів, в якій не використовується додаткова інформація про стани, крім тієї,
яка представлена в конкретній задачі. Все, на що здатен метод не
інформованого пошуку, – створювати синів та відрізняти цільовий стан від
нецільового.
На відміну від алгоритмів повного перебору (пошук в
глибину/ширину) алгоритм A* дозволяє суттєво зменшити кількість станів
для перебору шляхом застосування деякої додаткової інформації, евристики.
В якості такої інформації пропонується брати передбачувану кількість
перестановок, необхідних для отримання цільового стану.
Алгоритм A* передбачає наявність двох списків вершин графа:
відкритого та закритого. В першому знаходяться вершини, які ще не
перевірені алгоритмом, а в другому – ті вершини, які вже зустрічались під
час пошуку рішення.
На кожному новому кроці, із списку відкритих вершин вибирається
вершина з найменшою вагою. Вага (F) кожної вершини обчислюється як
сума відстані від початкової вершини до поточної (G) та евристичне
припущення про відстань від поточної вершини до цільової (H). Fi = Gi + Hi,
де i – поточна вершина (стан ігрового поля).
Для обчислення евристичного припущення H можна використати
наступні метрики:
Евклідова відстань:
Відстань Чебішева:
Код програми
package Lab5;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
class State {
final static int UP = 4, DOWN = 1, LEFT = 2, RIGHT = 3;
final static int N = 4;
int[][] mas = new int[N][N];
public int depth = 0;
public double H = 0;
public double F = 0;
public State(State s) {
this.mas = s.mas;
updateH();
}
if (p) {
return true;
} else
return false;
}
// H = 0;
// H = Math.max(mas[0][0] - 1, H);H = Math.max(mas[0][1] - 2, H);H =
// Math.max(mas[0][2] - 3, H);H = Math.max(mas[0][3] - 4, H);
// H = Math.max(mas[1][0] - 5, H);H = Math.max(mas[1][1] - 6, H);H =
// Math.max(mas[1][2] - 7, H);H = Math.max(mas[1][3] - 8, H);
// H = Math.max(mas[2][0] - 9, H);H = Math.max(mas[2][1] - 10, H);H =
// Math.max(mas[2][2] - 11, H);H = Math.max(mas[2][3] - 12, H);
// H = Math.max(mas[3][0] - 13, H);H = Math.max(mas[3][1] - 14, H);H =
// Math.max(mas[3][2] - 15, H);
// H = 0;
// H = (mas[0][0] != 1) ? H + 1 : H;
// H = (mas[0][1] != 2) ? H + 1 : H;
// H = (mas[0][2] != 3) ? H + 1 : H;
// H = (mas[0][3] != 4) ? H + 1 : H;
// H = (mas[1][0] != 5) ? H + 1 : H;
// H = (mas[1][1] != 6) ? H + 1 : H;
// H = (mas[1][2] != 7) ? H + 1 : H;
// H = (mas[1][3] != 8) ? H + 1 : H;
// H = (mas[2][0] != 9) ? H + 1 : H;
// H = (mas[2][1] != 10) ? H + 1 : H;
// H = (mas[2][2] != 11) ? H + 1 : H;
// H = (mas[2][3] != 12) ? H + 1 : H;
// H = (mas[3][0] != 13) ? H + 1 : H;
// H = (mas[3][1] != 14) ? H + 1 : H;
// H = (mas[3][2] != 15) ? H + 1 : H;
}
@Override
public boolean equals(Object o) {
State s = (State) o;
if (arrayEquals(getMas(), s.getMas())) {
return true;
} else {
return false;
}
}
public MyFrame() {
super("GameEight");
setBounds(100, 100, 250, 450);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout(FlowLayout.CENTER));
JTextField s11 = new JTextField("8", 4); JTextField s12 = new
JTextField("2", 4);
JTextField s13 = new JTextField("7", 4); JTextField s14 = new
JTextField("1", 4);
JTextField s21 = new JTextField("15", 4); JTextField s22 = new
JTextField("14", 4);
JTextField s23 = new JTextField("5", 4); JTextField s24 = new
JTextField("9", 4);
JTextField s31 = new JTextField("5", 4); JTextField s32 = new
JTextField("1", 4);
JTextField s33 = new JTextField("0", 4); JTextField s34 = new
JTextField("10", 4);
JTextField s41 = new JTextField("14", 4); JTextField s42 = new
JTextField("6", 4);
JTextField s43 = new JTextField("9", 4); JTextField s44 = new
JTextField("12", 4);
add(s11); add(s12); add(s13);
add(s14);
add(s21); add(s22); add(s23);
add(s24);
add(s31); add(s32); add(s33);
add(s34);
add(s41); add(s42); add(s43);
add(s44);
start.depth = 0;
start.updateF();
OPEN.add(start);
btnStep.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
State tmp = null, s = null;
if (!OPEN.isEmpty()) {
ta.setText("");
tmp = OPEN.poll();
CLOSED.add(tmp.toString());
ta.append("Current: (depth=" + tmp.depth + ", F=" +
tmp.F + ")\n" + tmp);
ta.append("\nSons:\n");
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.UP)) {
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
ta.append(s.toString() + "\n");
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.LEFT)) {
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
ta.append(s.toString() + "\n");
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.RIGHT)) {
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
ta.append(s.toString() + "\n");
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.DOWN)) {
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
ta.append(s.toString() + "\n");
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
ta.append("OPEN: " + OPEN.size() + "\nCLOSED: " +
CLOSED.size());
}
}
});
btnCalc.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
State tmp = null, s = null;
int i = 0;
try {
while (!OPEN.isEmpty()) {
tmp = OPEN.poll();
CLOSED.add(tmp.toString());
if (check(tmp, result) || check(tmp,
result1))
throw new IndexOutOfBoundsException();
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.UP)) {
if (check(s, result) || check(s,
result1))
throw new
IllegalArgumentException();
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.LEFT)) {
if (check(s, result) || check(s,
result1))
throw new
IllegalArgumentException();
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.RIGHT)) {
if (check(s, result) || check(s,
result1))
throw new
IllegalArgumentException();
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
s = new State(tmp.getMas());
s.depth = tmp.depth + 1;
if (s.move(State.DOWN)) {
if (check(s, result) || check(s,
result1))
throw new
IllegalArgumentException();
if (!CLOSED.contains(s.toString())) {
if (!OPEN.contains(s)) {
s.updateH();
s.updateF();
OPEN.add(s);
}
}
}
System.out.println("Number of checked state:
" + i++);
}
ta.setText("Sorry, program could not\nfind the
solution");
} catch (IndexOutOfBoundsException e1) {
ta.setText(tmp + "\nDepth: " + tmp.depth + "\nOPEN
states: " + OPEN.size() + "\nCLOSED states: "
+ CLOSED.size() + "\nALL states: " +
(CLOSED.size() + OPEN.size()));
} catch (IllegalArgumentException e2) {
ta.setText(s + "\nDepth: " + s.depth + "\nOPEN
states: " + OPEN.size() + "\nCLOSED states: "
+ CLOSED.size() + "\nALL states: " +
(CLOSED.size() + OPEN.size()));
}
}
});
setVisible(true);
}