Come posso testare un algoritmo euristico?


10

Supponiamo di avere il nostro algoritmo di ricerca del percorso:

def myHeuristicTSP(graph):
    /*implementation*/
    return route

Ora vogliamo provare questo:

class TestMyHeuristicTSP:
    def testNullGraphRaiseValueError(self):
        self.assertRaises(ValueError, myHueristicTSP(None))

    def testSimpleTwoNodeGraphReturnsRoute:
        self.assertEquals(expectedResult, myHeuristicTSP(input))

La domanda è, per un algoritmo TSP non euristico, che possiamo fornire una varietà di grafici e verificare che restituiscano sempre assolutamente il percorso più breve.

Ma perché un algoritmo euristico, sebbene sia ancora deterministico, è meno prevedibile, ha semplicemente lo scopo di capire come funziona l'algoritmo e trovare quei casi limite?


Risposte:


11

Per un algoritmo euristico che non dovrebbe restituire l'ideale ma una soluzione "abbastanza buona", avresti vari casi di test e verifica

  1. la soluzione è effettivamente valida? Sicuramente vuoi assicurarti che il tuo algoritmo di ricerca del percorso non restituisca percorsi impossibili o che in realtà non conducono dall'inizio alla fine. Potresti non essere in grado di dimostrare che la soluzione è ideale, ma dovresti almeno essere in grado di verificare che il valore restituito sia effettivamente una soluzione.
  2. la soluzione è "abbastanza buona"? Dovresti avere alcuni requisiti che definiscono quanto peggio potrebbe essere l'algoritmo rispetto alla soluzione ideale. Dovresti avere casi di test in cui è nota la soluzione ideale (o almeno una soluzione che è considerata abbastanza buona per essere utilizzata come standard di confronto) e confermare che la soluzione fornita dall'algoritmo non è peggiore di oltre il x%.
  3. L'algoritmo è abbastanza veloce? Spesso si utilizza un approccio euristico quando si presume che compensino la loro mancanza di precisione essendo molto più veloci. Per verificarlo, dovresti misurare il loro tempo di esecuzione e assicurarti che siano effettivamente più veloci di un algoritmo che ottiene la soluzione esatta. Le misure di runtime sono sempre un po 'sfocate, quindi superare il runtime previsto dovrebbe essere un avvertimento, non un errore (quando il framework di test dell'unità consente di differire tra avvisi ed errori).

Puoi forse fornire un suggerimento per testare come determineresti la validità di un percorso?
dwjohnston,

@dwjohnston Basta prendere il tuo grafico, prendere il tuo percorso e provare a percorrere il percorso sopra il tuo grafico. Verificare che ciascun bordo del percorso sia in vantaggio dal nodo corrente e che il percorso inizi e termini ai nodi corretti. È inoltre possibile verificare che il nodo finale non sia raggiunto prima della fine.
Philipp

È inoltre possibile verificare che nessun nodo nel percorso venga utilizzato due volte, poiché ciò indica un ciclo non necessario. A meno che, naturalmente, non vi siano alcune regole speciali che rendono utili i loop, come il sistema di ricerca del percorso UPS che preferisce tre svolte a destra rispetto a una a sinistra .
Philipp

3

La maggior parte degli algoritmi di ottimizzazione (inclusa l'euristica) lavora su alcune configurazioni (nel tuo esempio un percorso) applicando operazioni su di esse. Le operazioni in sé dovrebbero garantire che forniscano solo configurazioni valide, quindi prima dovrebbero esserci test unitari per ognuna di esse. Quando si è certi che l'algoritmo di ottimizzazione utilizza solo tali operazioni, in genere non è necessario un test di validità del risultato dell'algoritmo.

Per creare buoni test unitari per qualsiasi tipo di algoritmo più complesso, è necessario conoscere l'algoritmo stesso in dettaglio . Per euristiche semplici come l'arrampicata in collina, in genere è possibile prevedere il risultato per piccoli input. Ad esempio, per percorsi iniziali da 3 a 5 punti, se indicati in un determinato ordine, è possibile prevedere cosa accadrà. Ciò rimarrà vero per la maggior parte degli algoritmi euristici deterministici che conosco, quindi è probabilmente un buon punto di partenza.

Per algoritmi più complessi e dimensioni maggiori dell'input, quando si inserisce l'input nell'algoritmo e si tenta di controllare l'output, in realtà non si esegue più un test unitario, si sta eseguendo un test di accettazione o integrazione. Il motivo per cui si hanno problemi a "test unitari" di tale algo è perché in genere consiste in una manciata di parti più piccole (singole unità). Quindi, per testare davvero un tale algoritmo, dovrai identificare quelle parti e testarle individualmente. Inoltre, è possibile utilizzare la copertura del codice o le tecniche di copertura delle filiali per assicurarsi di avere sufficienti casi di test.

Se non stai cercando unit test, ma test di accettazione o integrazione automatizzati, puoi provare ciò che @Phillip ha suggerito in (2) o (3) .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.