Zaczynam interesować się algorytmami wyszukiwania i programowaniem wstecznym. Na razie zaimplementowałem Algorithm X (zobacz mój drugi post tutaj: Determine conflict-free sets?), aby rozwiązać dokładny problem z okładką. Działa to bardzo dobrze, ale teraz jestem zainteresowany rozwiązaniem tego problemu z bardziej podstawowym wariantem backtrackingu. Po prostu nie mogę zrozumieć, jak można to zrobić. Opis problemu jest taki sam jak wcześniej:Wdrażanie przeszukiwania wstecznego z heurystyką?
Załóżmy, że masz kilka zestawów, podczas gdy każdy zestaw ma kilka podzbiorów.
Set1 = {(bananów, ananasów, pomarańczy), (jabłka, kapusta, ogórek) (cebula, czosnek)}
zestaw2 = {(banan, ogórek, czosnek), (awokado, pomidor)}
...
SetN = {...}
celem jest teraz wybrać jeden podzbiór z każdego zestawu, natomiast każdy podzbiór muszą być konflikt darmo z dowolnego innego wybranego podzbioru (jeden element jest nie zawarte w żadnym z pozostałych wybranych podzbiorów).
Jako przykład napisałem dwie klasy Javy, które. Zestawy są oznaczone pojedynczym znakiem, a elementy są zwykłymi liczbami.
I konkretnie mają dwa problemy:
- Jak iteracyjne nad wszystkie zbiory/podzbiory w taki sposób, że zastosowanie heurystyki jest możliwe (wyboru podzbioru z elementów obowiązkowych, minimalny koszt, ...)
- Jak konserwować wybrane zestawy + podzbiory i ich zawarte elementy.
Wszystkie inne przykłady, które mogę znaleźć, to Sudoku lub n-Queens i wszystkie używają stałych pętli for. Oprócz tego myślałem o raczej ogólnym podejściu, w którym funkcja "isPossiblePartialSolution" może być używana do sprawdzenia, czy wybrana ścieżka/zestaw może być w konflikcie z wcześniej wybranym podzbiorem/elementem.
Oto dwie klasy 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;
}
}
i
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>();
}
}
Pomysł na wycofanie jest dość ogólny i można go zastosować do wielu problemów. Tańczące linki można stosować tylko w przypadku dokładnych problemów z okładką. Powinno być możliwe wdrożenie tego przy użyciu "normalnego" podejścia do cofania (wiem, że będzie to wolniejsze w porównaniu z DLX!). Z mojego rozumienia potrzebujemy funkcji, która mówi nam, czy istnieje konflikt z którąkolwiek z poprzednich decyzji. Poza tym pozwala to na użycie innej heurystyki! – user26372
Użycie innej heurystyki jest tym, co próbuję osiągnąć. Po prostu obraz, "kupowanie" jednego lub drugiego zestawu jest tańsze (w odróżnieniu od Dancing Links, wybieralibyśmy zestaw z minimalnym kosztem, a nie z minimalnymi elementami). Nie można tego zrobić za pomocą Dancing Links. – user26372
@ user26372 Dancing Links * zwykle * używa heurystycznego "sprawdź kolumnę z najmniejszą liczbą pierwszych 1" (np. Spróbuj wierszy, które najpierw spełniają najtrudniejsze ograniczenia), ale z pewnością możesz użyć innej heurystyki, jeśli nie robisz tego. tak to lubię. Zobacz [moja własna implementacja Dancing Links w C, tutaj] (http://www.club.cc.cmu.edu/~ajo/free-software/snippets/dance.c) i wyobraź sobie, jak możesz zmienić kod pod '#if USE_HEURISTIC' używa innej heurystyki. – Quuxplusone