Verifica se le lettere possono essere programmate per ottenere una parola in una lingua normale


23

Fisso un linguaggio regolare su un alfabeto , e considero il seguente problema che io chiamo la pianificazione lettera per . Informalmente, l'input mi dà lettere e un intervallo per ogni lettera (cioè una posizione minima e massima), e il mio obiettivo è quello di posizionare ogni lettera nel suo intervallo in modo tale che non ci siano due lettere mappate nella stessa posizione e in modo che il risultante n parola -Lettera è in L . formalmente:LΣLnnL

  • Input: n triple (ai,li,ri) dove aiΣ e 1lirin sono numeri interi
  • Output: esiste una biiezione f:{1,,n}{1,,n} tale che lif(i)ri per tutti i , e af1(1)af1(n)L .

Ovviamente questo problema è in NP, indovinando una biiezione f e controllando l'appartenenza a L in PTIME. La mia domanda: esiste un linguaggio L regolare in modo Ltale che il problema di pianificazione delle lettere per L sia NP-difficile?

Alcune osservazioni iniziali:

  • Sembra che problemi simili siano stati studiati nella pianificazione: potremmo vedere il problema come la pianificazione di attività a costo unitario su una singola macchina nel rispetto delle date di inizio e fine. Tuttavia, quest'ultimo problema è ovviamente in PTIME con un approccio avido, e non vedo nulla nella letteratura sulla pianificazione per il caso in cui le attività sono etichettate e vorremmo ottenere una parola in una lingua normale target.
  • Un altro modo di vedere il problema è come un caso speciale di un bipartito problema massima corrispondenza (tra lettere e posizioni), ma ancora una volta è difficile esprimere il vincolo che dobbiamo cadere in L .
  • Nel caso specifico in cui L è una lingua della forma u per qualche parola fissa u (ad esempio, (ab) ), il problema di pianificazione delle lettere per L è in PTIME con un algoritmo facile e avido: costruisci la parola da da sinistra a destra e inserisci in ciascuna posizione una delle lettere disponibili che è corretta rispetto a L e ha il tempo più piccolo ri . (Se non ci sono lettere disponibili che sono corrette, non riescono.) Tuttavia, ciò non si generalizza a lingue regolari arbitrarie L perché per tali lingue potremmo avere la scelta del tipo di lettera da usare.
  • Sembra che un algoritmo dinamico dovrebbe funzionare, ma in realtà non è così semplice: sembra che dovresti memorizzare quale serie di lettere hai preso così lontano. In effetti, quando costruisci una parola da sinistra a destra, quando hai raggiunto una posizione i , il tuo stato dipende da quali lettere hai consumato finora. Non è possibile memorizzare l'intero set perché in questo modo ci sarebbero esponenzialmente molti stati. Ma non è così facile "riassumerlo" (ad es. Per quante copie di ogni lettera sono state utilizzate), perché per sapere quali copie hai usato, sembra che devi ricordare quando le hai consumate (più tardi le hai consumate loro, più lettere erano disponibili). Anche con una lingua come (ab|ba) ,b aab e quando dovresti scegliere di prendere seconda delle lettere che ti serviranno in seguito e quando saranno disponibili.ba
  • Tuttavia, poiché la lingua normale è fissa e non è in grado di memorizzare così tante informazioni, sto facendo fatica a trovare un problema NP-difficile da cui potrei ridurre.L

Riesci a ottenere la completezza NP per alcune L in PTIME?
Lance Fortnow,

3
@LanceFortnow Certo. È possibile riempire un 3CNF in modo che ogni variabile si verifichi in un numero pari di letterali e ogni due occorrenze consecutive vengano annullate. Codifica in o , quindi nell'istanza di pianificazione delle lettere i simboli sono fissi mentre il resto è metà e metà . Nel tempo polinomiale si può verificare se la stringa codifica un 3CNF imbottito che restituisce true. 0 i 1 i ( , ) , , 0 1xi0i1i(,),,01
Willard Zhan,

Puoi anche generalizzare il problema in "posizioni arbitrarie" (non limitato a 1..n). Forse è più facile dimostrare la durezza (se è dura).
Marzio De Biasi

@MarzioDeBiasi: Non sono sicuro di aver capito, vuoi dire che la posizione delle lettere potrebbe essere un sottoinsieme arbitrario piuttosto che un intervallo? Non so se questo è difficile (inizia a somigliare un po ' all'esatto problema di abbinamento perfetto ), ma la versione con intervalli consente un algoritmo avido quando quindi ho qualche speranza che possa essere più facile. L=u
a3nm,

@ a3nm: no, intendo dire che potresti generalizzare l'eliminazione del vincolo ; chiedete una parola in L in cui vi sia almeno una lettera a i nell'intervallo [ l i . . r i ] ; in altre parole, non "costruisci" l'intera parola di lunghezza n , ma chiedi una parola di lunghezza arbitraria che contenga le lettere indicate negli intervalli consentiti. Non so se questo modifica la complessità del problema, ma in questo caso è necessario affrontare "indici" che probabilmente non sono limitati polinomialmente dalla lunghezza dell'input. rinai[li..ri]n
Marzio De Biasi

Risposte:


7

Il problema è NP-difficile per dove A è il linguaggio finito contenente le seguenti parole:L=AA

  • , x 000 ,x111x000
  • , y 010 , y 001 ,y100y010y001
  • , 01 c 10 , 10 c 01 e 11 c 0000c1101c1010c0111c00

La riduzione deriva dal problema Orientamento grafico, che è noto per essere NP-difficile (consultare https://link.springer.com/article/10.1007/s00454-017-9884-9 ). In questo problema, ci viene fornito un grafico non indiretto 3-regolare in cui ogni vertice è etichettato " " o " { 0 , 3 } ". L'obiettivo è dirigere i bordi del grafico in modo tale che il superamento di ogni vertice sia nell'insieme che identifica quel vertice.{1}{0,3}

La riduzione deve prendere come input un'istanza di orientamento del grafico e produrre un elenco di triple come output. In questa riduzione, le triple che produciamo soddisfano sempre determinati vincoli. Questi vincoli sono elencati di seguito e faremo riferimento a un elenco di triple come valido se e solo se soddisfano questi vincoli:

  • I caratteri , y e c ricevono solo intervalli contenenti esattamente un indice. In altre parole, ogni volta che questi personaggi vengono posizionati, vengono posizionati in posizioni specifiche.xyc
  • Per ogni tripla presente nell'istanza con i { 0 , 1 } , è presente anche la tripla ( 1 - i , l , r ) .(i,l,r)i{0,1}(1i,l,r)
  • Se e ( α , l , r ) sono entrambi tripli presenti nell'istanza, allora l < l r < r , oppure l < l r < r , oppure { α , α } = { 0 , 1 } con l = l(α,l,r)(α,l,r)l<lr<rl<lr<r{α,α}={0,1} .l=l<r=r
  • Se è un triplo, allora il numero di triple ( α , l , r ) con l l r r è esattamente r - l + 1 .(α,l,r)(α',l',r')ll'r'rr-l+1

Nota il seguente lemma, dimostrato alla fine di questo post.

Lemma: per un elenco valido di triple, i caratteri , y e c devono essere posizionati esattamente come indicato dalle triple, e per ogni coppia di triple ( 0 , l , r ) e ( 1 , l , r ) , il due caratteri per che tripla devono essere posizionati ad indici l e r .Xyc(0,l,r)(1,l,r)lr

Quindi l'idea della riduzione è la seguente.

Usiamo coppie di triple e ( 1 , l , r ) per rappresentare i bordi. Il bordo passa tra le terminazioni dall'indice l e all'indice r . Supponendo si produce un elenco valido di triple, i caratteri di queste due triple devono essere messi a l e r , in modo da poter trattare l'ordine in cui essi sono disposti come indica la direzione del bordo. Qui 1 è la "testa" del bordo e 0 è la "coda". In altre parole, se 1 è posizionato a r(0,l,r)(1,l,r)lrlr101rquindi il bordo punta da a r e se l' 1 viene posizionato su l allora il bordo punta da r a l .lr1lrl

Per rappresentare i vertici, posizioniamo un carattere o y in un indice e utilizziamo i tre caratteri successivi come punti finali dei tre bordi che toccano il vertice. Si noti che se poniamo una x , tutti i tre spigoli al vertice deve puntare nella stessa direzione (sempre nel vertice o tutti fuori del vertice) semplicemente dovuto alle corde che sono in linguaggio finita A . Tali vertici hanno un livello superiore a 0 o 3 , quindi posizioniamo una x esattamente per i vertici etichettati { 0 , 3 } . Se posizioniamo una yxyxA03x{0,3}y, Esattamente uno dei tre lati del punto di vertice mosto nella stessa direzione a causa delle stringhe in . Tali vertici hanno un livello inferiore a 1 , quindi posizioniamo una y esattamente per i vertici etichettati { 1 } .A1y{1}

In un certo senso, abbiamo finito. In particolare, la corrispondenza tra la risoluzione di questa istanza e la risoluzione dell'istanza di orientamento del grafico dovrebbe essere chiara. Sfortunatamente, l'elenco delle triple che produciamo potrebbe non essere valido, quindi i "bordi" descritti potrebbero non funzionare come previsto. In particolare, l'elenco delle triple potrebbe non essere valido perché la condizione che gli intervalli delle triple debbano sempre contenere l'un l'altro potrebbe non essere valida: gli intervalli tra i due bordi potrebbero sovrapporsi senza che uno contenga l'altro.

Per combattere questo, aggiungiamo qualche altra infrastruttura. In particolare, aggiungiamo "vertici crossover". Un vertice crossover è un vertice di grado cui bordi sono accoppiati in modo tale che all'interno di ciascuna coppia un bordo deve puntare nel vertice crossover e uno fuori. In altre parole, un vertice crossover si comporterà come due soli bordi "incrocio". Rappresentiamo un vertice crossover posizionando il carattere c in un indice i . Quindi nota che la lingua A limita i caratteri in i - 1 e i + 2 per essere opposti (uno 0 e uno 1 ) e i caratteri in i - 24ciAi1i+201i2e per essere opposto. Quindi, se usiamo questi indici come punti finali per i quattro spigoli nel vertice del crossover, il comportamento è esattamente come descritto: i quattro spigoli sono in coppia e tra ogni coppia uno punta dentro e uno punta.i+1

Come posizioniamo effettivamente questi crossover? Supponiamo di avere due intervalli e ( l , r ) che si sovrappongono. WLOG, l < l < r < r . Aggiungiamo il carattere crossover nel mezzo (tra l e r ). (Diciamo che da sempre abbiamo distanziato tutto così tanto che c'è sempre abbastanza spazio, e alla fine rimuoveremo qualsiasi spazio inutilizzato.) Lascia che l'indice del personaggio crossover sia io . Quindi sostituiamo le quattro triple ( 0(l,r)(l,r)l<l<r<rlri , ( 1 , l , r ) , ( 0 , l , r ) e ( 1 , l , r ) con otto triple con due ciascuna (una con carattere 0 e una con carattere 1 ) per i seguenti quattro intervalli ( l , i - 1 ) , ( i + 2 , r )(0,l,r)(1,l,r)(0,l,r)(1,l,r)01(l,i1)(i+2,r), , ( i + 1 , r ) . Nota che gli intervalli non si sovrappongono più nel modo sbagliato! (Dopo questa modifica, se due intervalli si sovrappongono, uno è strettamente all'interno dell'altro.) Inoltre, il bordo da l a r viene sostituito da un bordo da l al vertice del crossover seguito dal bordo da lì a r ; questi due bordi sono accoppiati al vertice del crossover in modo tale che uno sia puntato verso l'interno e uno sia sottolineato; in altre parole, i due bordi insieme si comportano esattamente come quello che stanno sostituendo.(l,i2)(i+1,r)lrlr

In un certo senso, inserendo questo vertice crossover "non incrociato" due bordi (i cui intervalli erano sovrapposti). È facile vedere che l'aggiunta del vertice crossover non può far incrociare eventuali bordi aggiuntivi. Pertanto, possiamo annullare l'attraversamento di ogni coppia di bordi incrociati inserendo abbastanza vertici di crossover. Il risultato finale corrisponde ancora all'istanza di Orientamento grafico, ma ora l'elenco di triple è valido (le proprietà sono tutte facili da verificare ora che abbiamo "non incrociato" eventuali bordi di attraversamento), quindi si applica il lemma, i bordi devono comportarsi come descritto e la corrispondenza è in realtà un'equivalenza. In altre parole, questa riduzione è corretta.


prova del lemma

Lemma: per un elenco valido di triple, i caratteri , y e c devono essere posizionati esattamente come indicato dalle triple, e per ogni coppia di triple ( 0 , l , r ) e ( 1 , l , r ) , il due caratteri per che tripla devono essere posizionati ad indici l e r .xyc(0,l,r)(1,l,r)lr

prova:

Procediamo per induzione sulle triple per lunghezza dell'intervallo. In particolare, la nostra affermazione è la seguente: per ogni se una tripla ha una lunghezza di intervallo k, il carattere in quella tripla deve essere posizionato come descritto nel lemma.kk

Caso di base: per , la tripla deve posizionare un carattere x , y o c nel singolo indice all'interno dell'intervallo. Questo è esattamente come descritto nel lemma.k=0xyc

Caso induttivo: supponiamo che l'affermazione valga per qualsiasi inferiore a qualche k . Consideriamo ora alcune triple con intervallo di lunghezza k . Quindi quel triplo deve essere della forma ( i , l , r ) con r = l + k - 1 e i { 0 , 1 } . Deve essere presente anche la tripla ( 1 - i , l , r ) . Il numero di triple ( αkkk(i,l,r)r=l+k1i{0,1}(1i,l,r) con l l r r è esattamente r - l + 1 = k . Queste triple comprendono le triple ( 0 , l , r ) e ( 1 , l , r ) ma anche k - 2 altre triple della forma ( α , l (α,l,r)llrrrl+1=k(0,l,r)(1,l,r)k2 con l < l r < r . Queste altre triple hanno una lunghezza dell'intervallo inferiore a k ' , quindi devono posizionare tutti i loro caratteri come specificato nel lemma. L'unico modo per far sì che ciò avvenga è se queste triple posizionano i caratteri in ogni indice iniziando dall'indice l + 1 e finendo all'indice r + 1 . Pertanto, le nostre due triple ( 0 , l , r ) e ( 1 , l , r )(α,l,r)l<lr<rkl+1r+1(0,l,r)(1,l,r)devono posizionare i loro caratteri agli indici e r , come descritto nel lemma, concludendo il caso induttivo.lr

Per induzione, il lemma è corretto.


Grazie mille per questa prova elaborata e con un linguaggio molto semplice! Penso che sia corretto, l'unica cosa di cui non sono sicuro è l'affermazione secondo cui "l'aggiunta del vertice crossover non può causare l'attraversamento di altri bordi". Non potrebbe essere il caso che l'intervallo includesse qualche altro intervallo ( l , r ) con l l r r , e ora uno di ( l , i - 1 ) e ( i + 2 ,(l,r)(l,r)llrr(l,i1) attraversa? Sembra che il processo debba ancora convergere perché gli intervalli si riducono, ma ciò non è del tutto chiaro a causa dell'inserimento di vertici crossover. Come dovrei vederlo? (i+2,r)
a3nm,

Se , è possibile inserire i nuovi indici per il nuovo vertice crossover immediatamente a destra di l . Questo fa sì che i nuovi indici ( i ± un bit) a trovarsi esattamente quegli intervalli che utilizzato per contenere l ' . Dovrebbe essere facile vedere che l'aggiunta di un vertice crossover può aggiungere un nuovo incrocio con qualche altro intervallo solo se i nuovi indici cadono nell'altro intervallo. Se l < l < r < r i nuovi indici non rientrano nell'intervallo (l<l<r<rli±ll<l<r<r . Se l < l < r < r allora i nuovi indici potrebbero rientrare nell'intervallo ( l , r ) , ma solo se l ′ fosse già caduto in quello(l,r)l<l<r<r(l,r)l
Mikhail Rudoy

intervallo (continua). In questo caso, in realtà non stai creando una nuova traversata, ma stai semplicemente trasformando una vecchia traversata con il vecchio intervallo in una nuova traversata con l'intervallo ( i + qualcosa , r )(l,r)(i+something,r)
Mikhail Rudoy

Immagino che nel tuo secondo messaggio intendevi "con il vecchio intervallo " anziché " ( l , r ) "? Ma OK, lo vedo: quando aggiungi il vertice di attraversamento, l'unico caso negativo sarebbe un intervallo I che si sovrappone con un nuovo intervallo senza sovrapporsi con l'intervallo corrispondente. Questo non può accadere per superset di ( l , r ) o di ( l , r ) : se si sovrappongono con un nuovo intervallo, si sovrappongono con quello vecchio. Allo stesso modo per sottoinsiemi di ( l(l,r)(l,r)I(l,r)(l,r) o ( l , r ) per il motivo spiegato. Quindi sono d'accordo che questa prova mi sembra corretta. Grazie ancora! (l,r)(l,r)
a3nm,

2

@MikhailRudoy è stato il primo a mostrare la durezza NP, ma Louis e io abbiamo avuto un'idea diversa, che ho pensato di poter delineare qui poiché funziona in modo leggermente diverso. Riduciamo direttamente da CNF-SAT il problema della soddisfacibilità booleana per i CNF . In cambio di ciò, il linguaggio regolare che usiamo è più complicato.L

La chiave per mostrare la durezza è progettare un linguaggio che ci permetta di indovinare una parola e ripeterla più volte. In particolare, per qualsiasi numero k di variabili e numero m di clausole, costruiremo intervalli che assicurino che tutte le parole w di L che possiamo formare debbano iniziare con una parola arbitraria u di lunghezza k sull'alfabeto { 0 , 1 } (intuitivamente codificando un'ipotesi della valutazione delle variabili), e quindi questa parola u viene ripetuta mLkmwLuk{0,1}um volte (che utilizzeremo in seguito per verificare che ogni clausola sia soddisfatta dalla valutazione indovinata).

Per raggiungere questo obiettivo, fisseremo l'alfabeto e la lingua: L : = ( 0 | 1 ) ( # ( 00 | 11 ) ) # ( 0 | 1 ) . L'affermazione formale è un po 'più complicata:A={0,1,#,0,1}L:=(0|1)(#(00|11))#(0|1)

Reclamo: per qualsiasi numero , possiamo costruire in PTIME un insieme di intervalli in modo tale che le parole in L che possono essere formate con questi intervalli siano precisamente:k,mNL

{u(#(u~u~)#(uu))m#u~u{0,1}k}

dove indica il risultato di invertire l'ordine di u e scambiare 0 's e 1 ' s, dove u ' indica il risultato della somma un primo a tutte le lettere u , e dove x y per due parole x di y di lunghezza p è la parola di lunghezza 2 p formata prendendo alternativamente una lettera da xe una lettera da y .u~u01uuxyxyp2pxy

Ecco una spiegazione intuitiva della costruzione che utilizziamo per dimostrarlo. Iniziamo con intervalli che codificano l'ipotesi iniziale di . Ecco il gadget per n = 4 (a sinistra) e una possibile soluzione (a destra):un=4

gadget di scelta

È facile mostrare la seguente osservazione (ignorando per ora): le possibili parole che possiamo formare con questi intervalli sono esattamente u # ˜ u per u { 0 , 1 } k . Questo è mostrato essenzialmente come il Lemma nella risposta di @ MikhailRudoy, ​​per induzione dagli intervalli più brevi a quelli più lunghi: la posizione centrale deve contenere # , le due posizioni vicine devono contenere uno 0 e uno 1 , ecc.Lu#u~u{0,1}k#01

Abbiamo visto come fare un'ipotesi, ora vediamo come duplicarlo. Per questo, faremo affidamento su e aggiungeremo più intervalli. Ecco un'illustrazione per k = 3 :Lk=3

gadget di duplicazione

Per ora prendi . Osserva come, oltre il primo # , dobbiamo enumerare alternativamente una lettera senza prima e una prima. Quindi, sul triangolo di intervalli non tratteggiato, la nostra osservazione sopra rimane valida: anche se sembra che questi intervalli abbiano più spazio a destra del primo #L:=(0|1)(#(00|11))#(0|1)##, è possibile utilizzare solo una posizione su due. Lo stesso vale per gli intervalli tratteggiati. Ora, impone inoltre che, quando enumeriamo una lettera senza elementi, la lettera innescata che segue deve essere la stessa. Quindi è facile vedere che le parole possibili sono esattamente: u # ( ˜ u˜ u ) # u per u { 0 , 1 } k .Lu#(u~u~)#uu{0,1}k

Ora, per mostrare l'affermazione, ripetiamo semplicemente questa costruzione volte. Ecco un esempio per k = 3 e m = 2 , usando ora la vera definizione di L sopra l'istruzione del reclamo:mk=3m=2L

gadget di duplicazione, ripetuto

Come prima, potremmo dimostrare (per induzione su ) che le parole possibili sono esattamente le seguenti: u ( # ˜ u˜ u # u u ) 2 # ˜ u per u { 0 , 1 } k . Quindi questa costruzione ottiene ciò che è stato promesso dall'affermazione.mu(#u~u~#uu)2#u~u{0,1}k

Grazie all'affermazione sappiamo che possiamo codificare un'ipotesi di una valutazione per le variabili e ripetere la valutazione più volte. L'unica cosa che manca è spiegare come verificare che la valutazione soddisfi la formula. Lo faremo controllando una clausola per occorrenza di . Per fare ciò, osserviamo che senza perdita di generalità possiamo supporre che ogni lettera della parola sia annotata da un simbolo fornito come input. (Più formalmente: potremmo supporre che nel problema forniamo anche come input una parola w di lunghezza n , e chiediamo se gli intervalli possono formare una parola u tale che w u è in LuwnuwuL.) Il motivo per cui possiamo ipotizzare questo è perché possiamo raddoppiare le dimensioni di ciascun intervallo e aggiungere intervalli di unità (nella parte inferiore dell'immagine) in posizioni dispari per portare l'annotazione della posizione pari corrispondente:

annotazioni di unità

Grazie a questa osservazione, per verificare le clausole, definiremo la nostra lingua regolare come intersezione di due lingue. La prima lingua impone che la parola secondaria su posizioni pari sia una parola in L , cioè se ignoriamo le annotazioni, allora la parola deve essere in L , quindi possiamo semplicemente usare la costruzione del reclamo e aggiungere alcune annotazioni. La seconda lingua L verificherà che le clausole siano soddisfatte. Per fare ciò, aggiungeremo tre lettere nel nostro alfabeto, da usare come annotazioni: + , - e ϵ . Alla clausola 1 i mLLLL+ϵ1im, Si aggiunge intervalli di unità a annotate da posizioni nella i ripetizione -esimo di u corrispondente alle variabili che si verificano positivamente al punto i , e annotate dai ~ - le posizioni corrispondenti alle variabili che si verificano negativamente. Annotiamo tutto il resto di ~ ϵ . Ora è chiaro che L può verificare che la valutazione indovinata soddisfi la formula, verificando che, tra ogni coppia di simboli # consecutivi che contengono una ricorrenza di u (cioè una coppia su due), c'è un valore letterale che soddisfa la clausola, ovvero deve esserci una ricorrenza della subword + 1+iuiϵL#u+1o della subword .0

Questo conclude la riduzione dal CNF-SAT e spettacoli NP-difficile del problema lettera di programmazione per il linguaggio .L

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.