@@ -378,3 +378,135 @@ def __init__(self):
378378 J_from_sparse [i , j ] = w
379379
380380 assert np .allclose (J_dense , J_from_sparse )
381+
382+
383+
384+ # ── XOR Gate Tests ────────────────────────────────────────────────────────────
385+
386+ def test_xor_gate_structure ():
387+ """Test XOR gate has correct structure."""
388+ from p_kit .psl .gates import XORGate
389+
390+ gate = XORGate ()
391+ assert gate .input1 .width == 1
392+ assert gate .input2 .width == 1
393+ assert gate .output .width == 1
394+ assert gate .aux .width == 1
395+ assert gate .J .shape == (4 , 4 )
396+ assert gate .h .shape == (4 , 1 )
397+
398+
399+ def test_xor_gate_truth_table ():
400+ """Test XOR gate produces correct truth table with high i0."""
401+ from p_kit .psl .gates import XORGate
402+ from p_kit .solver .csd_solver import CaSuDaSolver
403+
404+ gate = XORGate ()
405+ solver = CaSuDaSolver (Nt = 5000 , dt = 0.1667 , i0 = 0.95 , seed = 42 )
406+
407+ test_cases = [
408+ ([- 1 , - 1 ], - 1 ), # 0 XOR 0 = 0
409+ ([- 1 , 1 ], 1 ), # 0 XOR 1 = 1
410+ ([1 , - 1 ], 1 ), # 1 XOR 0 = 1
411+ ([1 , 1 ], - 1 ), # 1 XOR 1 = 0
412+ ]
413+
414+ for inputs , expected_output in test_cases :
415+ gate .h [0 ] = inputs [0 ] * 10
416+ gate .h [1 ] = inputs [1 ] * 10
417+ _ , output , _ = solver .solve (gate )
418+
419+ # Output is at index 2 (order: input1, input2, output, aux)
420+ output_states = output [:, 2 ]
421+ most_common = 1 if np .mean (output_states ) > 0 else - 1
422+ assert most_common == expected_output , \
423+ f"XOR({ inputs [0 ]} , { inputs [1 ]} ) expected { expected_output } , got { most_common } "
424+
425+
426+ # ── XNOR Gate Tests ───────────────────────────────────────────────────────────
427+
428+ def test_xnor_gate_structure ():
429+ """Test XNOR gate has correct structure."""
430+ from p_kit .psl .gates import XNORGate
431+
432+ gate = XNORGate ()
433+ assert gate .input1 .width == 1
434+ assert gate .input2 .width == 1
435+ assert gate .output .width == 1
436+ assert gate .aux .width == 1
437+ assert gate .J .shape == (4 , 4 )
438+ assert gate .h .shape == (4 , 1 )
439+
440+
441+ def test_xnor_gate_truth_table ():
442+ """Test XNOR gate produces correct truth table with high i0."""
443+ from p_kit .psl .gates import XNORGate
444+ from p_kit .solver .csd_solver import CaSuDaSolver
445+
446+ gate = XNORGate ()
447+ solver = CaSuDaSolver (Nt = 5000 , dt = 0.1667 , i0 = 0.95 , seed = 42 )
448+
449+ test_cases = [
450+ ([- 1 , - 1 ], 1 ), # 0 XNOR 0 = 1
451+ ([- 1 , 1 ], - 1 ), # 0 XNOR 1 = 0
452+ ([1 , - 1 ], - 1 ), # 1 XNOR 0 = 0
453+ ([1 , 1 ], 1 ), # 1 XNOR 1 = 1
454+ ]
455+
456+ for inputs , expected_output in test_cases :
457+ gate .h [0 ] = inputs [0 ] * 10
458+ gate .h [1 ] = inputs [1 ] * 10
459+ _ , output , _ = solver .solve (gate )
460+
461+ # Output is at index 2 (order: input1, input2, output, aux)
462+ output_states = output [:, 2 ]
463+ most_common = 1 if np .mean (output_states ) > 0 else - 1
464+ assert most_common == expected_output , \
465+ f"XNOR({ inputs [0 ]} , { inputs [1 ]} ) expected { expected_output } , got { most_common } "
466+
467+
468+ # ── Half Adder Tests ──────────────────────────────────────────────────────────
469+
470+ def test_half_adder_structure ():
471+ """Test Half Adder has correct structure."""
472+ from p_kit .psl .gates import HalfAdder
473+
474+ gate = HalfAdder ()
475+ assert gate .input1 .width == 1
476+ assert gate .input2 .width == 1
477+ assert gate .sumout .width == 1
478+ assert gate .carryout .width == 1
479+ assert gate .J .shape == (4 , 4 )
480+ assert gate .h .shape == (4 , 1 )
481+
482+
483+ def test_half_adder_truth_table ():
484+ """Test Half Adder produces correct sum and carry outputs."""
485+ from p_kit .psl .gates import HalfAdder
486+ from p_kit .solver .csd_solver import CaSuDaSolver
487+
488+ gate = HalfAdder ()
489+ solver = CaSuDaSolver (Nt = 5000 , dt = 0.1667 , i0 = 0.95 , seed = 42 )
490+
491+ test_cases = [
492+ ([- 1 , - 1 ], - 1 , - 1 ),
493+ ([- 1 , 1 ], 1 , - 1 ),
494+ ([1 , - 1 ], 1 , - 1 ),
495+ ([1 , 1 ], - 1 , 1 ),
496+ ]
497+
498+ for inputs , expected_sum , expected_carry in test_cases :
499+ gate .h [0 ] = inputs [0 ] * 10
500+ gate .h [1 ] = inputs [1 ] * 10
501+ _ , output , _ = solver .solve (gate )
502+
503+ sum_states = output [:, 2 ]
504+ carry_states = output [:, 3 ]
505+
506+ sum_result = 1 if np .mean (sum_states ) > 0 else - 1
507+ carry_result = 1 if np .mean (carry_states ) > 0 else - 1
508+
509+ assert sum_result == expected_sum
510+ assert carry_result == expected_carry
511+
512+
0 commit comments