Tôi nhận được khá quan tâm đến các thuật toán tìm kiếm và lập trình quay vòng. Bây giờ, tôi đã thực hiện thuật toán X (xem bài viết khác của tôi ở đây: Determine conflict-free sets?) để giải quyết một vấn đề chính xác bao gồm. Điều này hoạt động rất tốt nhưng bây giờ tôi quan tâm đến việc giải quyết vấn đề này với một biến thể cơ bản hơn của tính năng backtracking. Tôi chỉ không thể hiểu được làm thế nào điều này có thể được thực hiện. Mô tả sự cố giống như trước:Thực hiện tìm kiếm quay lại bằng heuristic?
Giả sử bạn có một nhóm bộ, trong khi mỗi bộ có một vài tập con.
set1 = {(chuối, dứa, cam), (táo, cải xoăn, dưa chuột), (hành tây, tỏi)}
set2 = {(chuối, dưa chuột, tỏi), (bơ, cà chua)}
...
SetN = {...}
mục tiêu bây giờ là chọn một tập hợp con từ mỗi bộ, trong khi mỗi tập con phải mâu thuẫn miễn phí với bất kỳ tập con chọn khác (một phần tử là không chứa trong bất kỳ tập con nào đã chọn).
Ví dụ, tôi đã viết hai lớp Java. Các bộ được xác định bởi một ký tự đơn và các phần tử là số đơn giản.
Tôi đặc biệt có hai vấn đề:
- Làm thế nào để lặp qua tất cả các bộ/tập con theo cách như vậy mà việc sử dụng một heuristic là có thể (chọn tập con với các yếu tố tối thiểu, chi phí tối thiểu, ...)
- Cách duy trì các tập hợp con đã chọn + tập hợp con và các phần tử được chứa của chúng.
Tất cả các ví dụ khác tôi có thể tìm thấy là Sudoku hoặc n-Queens và tất cả đều sử dụng các vòng lặp cố định. Thêm vào đó, tôi đã suy nghĩ về một cách tiếp cận khá chung chung, trong đó một hàm "isPossiblePartialSolution" có thể được sử dụng để kiểm tra, nếu một path/set đã chọn có thể xung đột với một tập con/phần tử đã được chọn trước đó.
Dưới đây là hai lớp Java:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Set> allSets = buildRandomTest();
for(Set r : allSets) {
System.out.print("Set with id: " + r.id + " is subset in collection: " + r.name + " and contains: ");
for(Integer n : r.listOfElements) {
System.out.print(" " + n + " ");
}
System.out.println();
}
}
public static int myRandomRange(int low, int high) {
return (int) (Math.random() * (++high - low) + low);
}
public static ArrayList<Set> buildRandomTest() {
ArrayList<Set> mySet = new ArrayList<Set>();
int numberOfSets = myRandomRange(10, 12);
for(int i=0; i<numberOfSets; i++) {
String nameOfSet = Character.toString((char) myRandomRange(65, 67));
Set tmp = new Set(nameOfSet, i);
ArrayList<Integer> listOfElements = new ArrayList<Integer>();
int elementsInList = myRandomRange(2, 4);
for(int j=0; j<elementsInList; j++) {
listOfElements.add(myRandomRange(1,30));
}
tmp.listOfElements = listOfElements;
mySet.add(tmp);
}
return mySet;
}
}
và
import java.util.ArrayList;
public class Set {
public String name;
public int id;
public ArrayList<Integer> listOfElements;
public Set(String name, int id) {
this.name = name;
this.id = id;
listOfElements = new ArrayList<Integer>();
}
}
Ý tưởng quay lại khá chung chung và có thể áp dụng cho nhiều sự cố. Dancing Links chỉ có thể được áp dụng cho các vấn đề chính xác. Nó sẽ có thể thực hiện điều này bằng cách sử dụng một cách tiếp cận backtracking 'bình thường' (tôi biết, điều này sẽ chậm hơn so với DLX!). Từ sự hiểu biết của tôi, chúng tôi cần một chức năng sau đó cho chúng tôi biết nếu có xung đột hay không với bất kỳ quyết định nào trước đó. Thêm vào đó, điều này cho phép sử dụng một heuristic khác nhau! – user26372
Sử dụng một heuristic khác là những gì tôi đang cố gắng để đạt được. Chỉ cần hình ảnh, 'mua' một bộ hoặc khác là rẻ hơn (do đó, không giống như Dancing Liên kết, chúng tôi sẽ chọn các thiết lập với chi phí tối thiểu và không phải là một, với các yếu tố tối thiểu). Điều này không thể được thực hiện bằng cách sử dụng Dancing Links. – user26372
@ user26372 Liên kết khiêu vũ * thường * sử dụng heuristic "kiểm tra cột với số ít nhất 1s đầu tiên" (tức là, thử các hàng sẽ thỏa mãn ràng buộc khó khăn nhất trước), nhưng bạn chắc chắn có thể sử dụng một heuristic khác nếu bạn don ' t như thế. Xem [triển khai Dancing Links của riêng tôi ở C, tại đây] (http://www.club.cc.cmu.edu/~ajo/free-software/snippets/dance.c) và tưởng tượng cách bạn có thể thay đổi mã theo '#if USE_HEURISTIC' để sử dụng một heuristic khác. – Quuxplusone