Costruisci un tester di connessione a 4 vertici usando le porte NAND


12

Un grafico collegato è un grafico che contiene un percorso tra due vertici.

Sfida

Costruisci un circuito [2-NAND-gate] che determina se un grafico a 4 vertici è collegato.
(I 2 ingressi di un gate possono essere lo stesso bit di input o altro gate.)
Output True se il grafico è collegato e False in caso contrario.

Ingresso

I sei possibili bordi di un semplice grafico con 4 vertici:

[ 0 e 1 , 0 e 2 , 1 e 2 , 0 e 3 , 1 e 3 , 2 e 3 ]

dove un e b indica se esiste un arco tra i vertici di un e b

La connessione è equivalente alle seguenti condizioni:

  • Se meno di 3 input sono True, allora output False.

  • Se più di 3 input sono True, allora output True.

  • Se esattamente 3 input sono True e formano un triangolo, allora output False.

  • Altrimenti, output True.

Vince la risposta che utilizza il minor numero di porte. I legami verranno interrotti in base
alla profondità del circuito più bassa (lunghezza dei percorsi più lunghi dall'ingresso all'uscita).


Potresti specificare ulteriormente il formato di input?
LegionMammal978,

iej è Vero o Falso a seconda che esista o meno un margine dal vertice i al vertice j.

L'input può essere preso come 0e 1? Che ne dici di uscita?
TheCoffeeCup

3
@TheCoffeeCup Questo è un problema di progettazione di circuiti logici, non di code-golf .
lirtosiast,

@ThomasKwa Whoops, non ha notato.
TheCoffeeCup

Risposte:


4

30 NANDS

Invece di chiedere quando otteniamo un 1, ho posto la domanda quando otteniamo uno 0. È meglio chiederlo in questo modo perché ci sono meno 0 di 1.

Ecco la distribuzione in base al numero di spigoli (sesta fila del triangolo di Pascal)

Edges     0  1  2  3  4  5  6
Frequency 1  6 15 20 15  6  1 (total 64)
Output    0  0  0  *  1  1  1
* = 0 if triangle (4 possibilities) 1 if claw (4 possibilities) 
1 if two opposite edges and one other (12 possibilities)

Ponendo la domanda in questo modo, otteniamo il seguente diagramma ed espressione

 ___D___
|\     /|
| E   F |
|  \ /  |
A   X   C
|  / \  |
| /   \ |
|/__B__\|

(A|C|D|B)&(A|D|E)&(D|B|E|F)&(C|B|E)&(A|C|E|F)&(D|F|C)&(A|F|B) 

Partiamo dal presupposto che l'output sarà 1 per impostazione predefinita, ma cambierà a 0 in una delle seguenti condizioni

1.A 0 per tre bordi adiacenti (test 3 ingressi)

2.A 0 per due coppie contrapposte di bordi (test 4 ingressi)

I termini sopra sono già ordinati nel modo che consentirà di raggrupparli come di seguito. (Per inciso, questa versione dell'espressione è simmetrica in senso rotazionale rispetto al vertice AFB.)

((A|D)|((C|B)&E))&((B|E)|((D|F)&C))&((C|F)|((A|E)&D))&(A|F|B)    =6 inverters
   1      1  1       1      1  1       1      1  1      1        =10 (7 OR with both inputs inverted, 3 NAND)
      2                 2                 2               2      =8  (4 OR with one input inverted)
                 2                 2                 2           =6  (3 AND) 
                                                        Total    =30

Il punteggio per ciascuno &o |è posizionato sotto il simbolo e giustificato come segue:

Livello 0: investiamo in un inverter per ogni ingresso: 6 NANDS

Livello 1: Siamo in grado di costruire un OR da un gate NAND inserendo un inverter all'ingresso (in totale 3 NANDS) ma dato che abbiamo già investito in 6 NAND nel passaggio precedente, possiamo realizzare 7 gate OR da 7 gate NAND. Abbiamo anche bisogno di 3 porte AND. Per questi, useremo semplicemente le NAND e lasceremo l'output invertito. 10 NANDS

Livello 2: Ancora una volta costruiamo 4 porte OR da porte NAND. In ogni caso abbiamo 1 input da un gate OR, quindi dobbiamo invertirlo. Ma l'altro input è già invertito (proveniente da una delle NAND nel passaggio precedente che corrisponde a un &simbolo in tre casi e da un inverter nell'ultima) quindi abbiamo bisogno solo di 2 gate per ciascuna funzionalità OR. 4 * 2 = 8

Livello 3: ora dobbiamo ANDARE insieme le quattro uscite. Ciò richiede 3 porte AND, ognuna costruita da 2 NAND, 3 * 2 = 6

Sono in totale 30 porte NAND, con una profondità massima di 2 + 2 + 4 = 8 NAND per rami con |livello 1 o 3 + 1 + 4 = 8 NAND per rami con &livello 1.

Il seguente script Ruby conferma visivamente che l'espressione sopra è valida.

64.times{|i|
  a=i%2
  b=i/2%2
  c=i/4%2
  d=i/8%2
  e=i/16%2 
  f=i/32%2

puts i, ((a|d)|((c|b)&e))&((b|e)|((d|f)&c))&((c|f)|((a|e)&d))&(a|f|b)

puts " ___#{d}___
|\\     /|
| #{e}   #{f} |
|  \\ /  |
#{a}   X   #{c}
|  / \\  |
| /   \\ |
|/__#{b}__\\|


"
}

7

19 NAND

Non esiste un circuito più semplice di questo.

C'è un codice per testarlo sotto l'immagine. Per quanto riguarda la comprensione, è difficile. Ci sono un paio di porte IF lì, e gli input sono un po 'raggruppati in un triangolo con le linee d'angolo libere aggiunte per l'analisi una per una, ma non in modo semplice. Se qualcuno riuscirà a capirlo, rimarrò colpito.

inserisci qui la descrizione dell'immagine

Codice Verilog con test:

// 4-vertex Connectedness Tester                                                                  
// Minimal at 19 NANDs                                                                            
//                                                                                                
// By Kim Øyhus 2018 (c) into (CC BY-SA 3.0)                                                      
// This work is licensed under the Creative Commons Attribution 3.0                               
// Unported License. To view a copy of this license, visit                                        
// https://creativecommons.org/licenses/by-sa/3.0/                                                
//                                                                                                
// This is my entry to win this Programming Puzzle & Code Golf                                    
// at Stack Exchange:                                                                             
// /codegolf/69912/build-a-4-vertex-connectedness-tester-using-nand-gates/                                                                                      
//                                                                                                
// I am sure there are no simpler solutions to this problem.                                      
// It has a logical depth of 11, which is deeper than                                             
// circuits using a few more NANDs.                                                               

module counting6 ( in_000, in_001, in_002, in_003, in_004, in_005, in_006, out000 );
  input  in_000, in_001, in_002, in_003, in_004, in_005, in_006;
  output out000;
  wire   wir000, wir001, wir002, wir003, wir004, wir005, wir006, wir007, wir008, wir009, wir010, wir011, wir012, wir013, wir014, wir015, wir016, wir017;

  nand gate000 ( wir000, in_000, in_000 );
  nand gate001 ( wir001, in_001, in_003 );
  nand gate002 ( wir002, wir001, wir000 );
  nand gate003 ( wir003, in_002, wir002 );
  nand gate004 ( wir004, wir002, wir002 );
  nand gate005 ( wir005, wir004, in_002 );
  nand gate006 ( wir006, wir005, wir004 );
  nand gate007 ( wir007, in_005, wir006 );
  nand gate008 ( wir008, in_003, wir006 );    
  nand gate009 ( wir009, in_004, wir003 );
  nand gate010 ( wir010, wir003, wir009 );
  nand gate011 ( wir011, wir009, wir000 );
  nand gate012 ( wir012, wir011, in_001 );
  nand gate013 ( wir013, wir008, wir012 );
  nand gate014 ( wir014, wir013, in_005 );
  nand gate015 ( wir015, wir006, wir013 );
  nand gate016 ( wir016, wir015, wir007 );
  nand gate017 ( wir017, wir016, wir010 );
  nand gate018 ( out000, wir014, wir017 );
endmodule


module connecting6_test;
   reg [5:0] X;
   wire a;

  counting6 U1 (
  .in_000 (X[0]),
  .in_001 (X[1]),
  .in_002 (X[2]),
  .in_003 (X[3]),
  .in_004 (X[4]),
  .in_005 (X[5]),
  .in_006 (X[6]),
  .out000 (a )
  );

  initial begin
    X = 0;
  end

  always
    #10  X = X+1;

 initial  begin
    $display("\t\t     \t_");
    $display("\t\ttime,\t \\db/_,\tconnected");
    $monitor("%d,\t%b,\t%d",$time, X, a );
  end

  initial
   #630  $finish;

endmodule

// iverilog -o hello hello.v                                                                      
// vvp hello                                                                                      

Kim Øyhus


Hai dimostrato questo minimo, e se sì come?
Lirtosiast

Ho usato i test statistici per ottenere prove del fatto che è minimo. Per circuiti relativamente semplici, come questo, i test sono abbastanza certi.
KimOyhus,

1

Mathematica, 17 porte

Enumeriamo semplicemente tutte le regole, costruiamo la funzione booleana e la minimizziamo nella NANDforma.

#->If[Total@#<3||
       MemberQ[{{1,1,1,0,0,0},{1,0,0,1,1,0},{0,1,0,1,0,1},{0,0,1,0,1,1}},#]
       ,0,1] /.{1->True,0->False}& /@
     Tuples[{0,1},6];
BooleanMinimize[BooleanFunction[rule], "NAND"]

Risultato :

(#1⊼#2⊼#4)⊼(#1⊼#2⊼#5)⊼(#1⊼#2⊼#6)⊼(#1⊼#3⊼#4)⊼ \
(#1⊼#3⊼#5)⊼(#1⊼#3⊼#6)⊼(#1⊼#4⊼#6)⊼(#1⊼#5⊼#6)⊼ \
(#2⊼#3⊼#4)⊼(#2⊼#3⊼#5)⊼(#2⊼#3⊼#6)⊼(#2⊼#4⊼#5)⊼ \
(#2⊼#5⊼#6)⊼(#3⊼#4⊼#5)⊼(#3⊼#4⊼#6)⊼(#4⊼#5⊼#6)&

, dove #1...#6sono presenti 6 slot per gli argomenti.


Casi di prova :

f=%; (* assign the function to symbol f *)

f[True, True, True, True, False, False]
(* True *)

f[True, True, False, True, False, False]
(* True *) (*, three Trues do not form a triangle *)

f[True, True, True, False, False, False]
(* False *) (*, three Trues form a triangle *)

P⊼q⊼r significa not (p&q&r)? Cosa significa il tuo risultato finale e significa?

@RickyDemer Sì, p⊼q⊼rsignifica (p⊼q)⊼rche equivale a !(p&&q&&r).
njpipeorgan,

Collegare False, False, True sembra mostrare che (p⊼q)⊼rnon è equivalente a !(p&&q&&r).

@RickyDemer Questo è un problema ... L'ho dato per scontato.
njpipeorgan,

Inoltre, almeno la versione WolframAlpha di BooleanMinimize [expr, "NAND"] non non necessariamente ridurre al minimo il numero di NAND. (Prova BooleanMinimize [(((a NAND b) NAND (c NAND d)) NAND ((e NAND f) NAND (g NAND h))), "NAND"].) Esegue quello su Mathematica dà un output con al massimo 7 NANDS?

1

64 NAND

I sei bordi possono essere suddivisi in tre coppie di bordi opposti. Affinché un grafico sia collegato, devono esserci due bordi opposti nonché un terzo bordo o tre bordi collegati allo stesso vertice.

       •
       U

   Z   •   Y  
    V     W 
 •     X     •

Le coppie opposte sono UX, VY, WZ, quindi:

A = U+V   ;3 gates
B = W+X
C = Y+Z

D = UV(B+C)  ;2+2+3=7 gates
E = WX(A+C)
F = YZ(C+A)

Result = D+E+F+UVW+UYZ+XVZ+XWY ; 18 + 16 = 34 gates

Costruendo le porte AND e OR come di consueto, il numero totale di porte utilizzate è 3*3+7*3+34= 64.


[Vero, Vero, Falso, Vero, Falso, Falso] fornisce un grafico collegato senza bordi opposti.

@RickyDemer Penso che funzioni ora ...
lirtosiast
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.