Come misurare il livello di soluzione di un cubo di Rubik non risolto?

4

Sto cercando di capire come misurare il relativo livello di successo di un dato (ma irrisolto!) stato di Cubo di Rubik. La mia prima idea era di calcolare il numero di "celle" sovrapposte nello stato di destinazione (risolto) e lo stato dato (non risolto), e presentarlo come segue:

number of actual correct cell positions / number of all positions (6x9)

Ma ho la sensazione che questo rapporto non sia necessariamente correlato con il livello di successo effettivo (quindi non sei necessariamente più vicino alla soluzione completa con un livello relativamente alto di posizioni corrette della cella). C'è un modo più elegante (e calcolabile) per misurare questo?

    
posta Hendrik 07.02.2018 - 10:24
fonte

4 risposte

7

Se potessi misurare la distanza da qualsiasi stato allo stato risolto, avresti un algoritmo di soluzione banale: fai semplicemente qualsiasi mossa che riduca la distanza! Pertanto, una misura della distanza non può essere più semplice di un algoritmo di risoluzione dei cubi.

    
risposta data 07.02.2018 - 10:28
fonte
2

Se per qualsiasi ragione non è possibile utilizzare una delle implementazioni del solutore esistenti, è possibile migliorare l'euristica della stima non solo contando quante celle sono posizionate in modo errato ma piuttosto sommando la distanza (qualunque cosa possa essere ) dalle loro posizioni corrette.

0. Rappresentazione dello stato

Puoi rappresentare la posizione di una cella mediante il vettore 3D (= array) di 3 valori nell'intervallo < -1,1 > cioè da -1 a sinistra / in basso, a 0 per il centro a destra / in alto per +1. Ad esempio [1,1,0] è per la cella in alto a destra della faccia anteriore. Il centro del cubo è l'origine. Nota: le celle del centro del viso sono fisse, quindi la posizione è invariante di orientamento purché si orienti sempre i centri del viso allo stesso modo.

1. Distanza di Manhattan

Una delle metriche più semplici è la cosiddetta distanza di Manhattan, in cui si aggiungono solo le differenze assolute degli elementi corrispondenti. Ad esempio la distanza di manhattan da int[] v0 = [0,1,-1] a int[] v1 = int [1,1,1] è

var manhattan = abs(v0[0]-v1[0]) + abs(v0[1]-v1[1]) + abs(v0[2]-v1[2])

la stima del livello della soluzione è semplicemente la somma della distanza di Manhattan per correggere la posizione per ogni cella. Sebbene questo sia probabilmente un grande miglioramento, non tiene ancora conto del fatto che il cubo si avvolge. Se non sbaglio, la distanza di Manhattan è stata utilizzata come euristica per IDA *, uno dei primi risolutori ottimali (in termini di giri minimi).

2. Scambia e amp; negare

Come potresti notare, la distanza effettiva dalla soluzione corrisponde a turni di numero (quarti) anziché a distanze fisiche sul cubo. Invece, dovremmo eseguire giri stessi - Rotazione 3D dei vettori di posizione della cella attorno agli assi che porterebbero alla moltiplicazione della matrice ...
... Tuttavia, a quanto pare, il nostro caso può essere notevolmente semplificato. Grazie alla scelta di < -1,1 > invece di < 0,2 > possiamo usare il ben noto swap & negare "trucco", un modo per calcolare i vettori perpendicolari. Fissando un elemento del vettore, scambiando gli altri due e negando uno (quale controlla la direzione) di quelli eseguirà il quarto di giro sulla faccia perpendicolare all'elemento fisso. La procedura potrebbe apparire come questa.

//calculates position of cell after a quarter-turn around given axis
void Rotate3DAligned(int[] vec, int axis, bool ccw)
{
  var first = vec[(i-1)%3];
  var second = vec[(i+1)%3];
  if(ccw) first = -first;
  else second = -second;
  vec[(i-1)%3] = second;
  vec[(i+1)%3] = first ;
}

Prendendo la posizione corrente di ogni cella e quella corretta è necessario determinare quanti turni (rotazioni, swap e amp; negati) devi prendere per portarlo nella posizione corretta. Questo può essere banalmente risolto da bruteforce poiché il numero massimo è piuttosto basso, o meglio algoritmico - quanti segni devi scambiare e quanti valori "spostare".

2.1. Hash it

Conta solo serie di turno distinte, ad esempio, salva la serie di giri in un HashSet o simile. Ciò consentirà di rilevare molti casi di celle mobili "batch", risolvendo il problema della soluzione a una svolta.

disclaimer: algoritmo non testato dall'implementazione, codice non controllato

    
risposta data 07.02.2018 - 16:17
fonte
1

Per un approccio sovrastimato, è possibile implementare un algoritmo di risoluzione dei cubi più o meno semplice e contare quanti spostamenti ha bisogno da una determinata posizione. Quindi eseguilo con diversi orientamenti iniziali del cubo e scegli il minimo tra quei conteggi.

Questo approccio può essere esteso provando diverse varianti dell'algoritmo o diversi algoritmi. Ad esempio, puoi generare tutte le configurazioni che possono essere raggiunte da n di turni di trimestre con n tra 0 e un massimo, quindi eseguire il risolutore, contare il numero totale di svolte e scegliere il minimo.

Misurare il numero di "cubetti" posizionati correttamente e anche il numero di quelli orientati correttamente può darti almeno una misura approssimativa del "livello di soluzione". Un alto valore di correttezza ti dirà che probabilmente c'è un algoritmo del risolutore che ha bisogno di "non troppi" giri più. Qualsiasi algoritmo di risoluzione standard che ho visto in passato aumenta il numero di "cubetti" posizionati correttamente. Se ci sono due o tre cubetti "non correlati" scambiati, non è troppo difficile costruire una sequenza di mosse breve per scambiare solo quei due o tre cubetti.

Sfortunatamente, non è vero il contrario: un basso livello di correttezza non ti dice che non può esserci un algoritmo che può risolvere il cubo in pochi turni. Quindi tutti questi suggerimenti sopra sono solo euristiche imperfette - se queste ti aiutano o meno dipende dal tuo caso d'uso specifico, che in realtà non hai menzionato nella tua domanda.

    
risposta data 07.02.2018 - 11:52
fonte
0

Ogni cubo di Rubik può essere risolto in massimo di 26 quarti di giro.

S = (26-N)/26

dove N è il numero di restanti quarto di giro necessari per risolvere il cubo. Questa potrebbe essere la metrica più pertinente per misurare quanto sei lontano nel risolvere il cubo.

    
risposta data 07.02.2018 - 10:35
fonte

Leggi altre domande sui tag