CharlesCNorton commited on
Commit
cbfb6ee
·
1 Parent(s): e917a50

JK flip-flop

Browse files
Files changed (4) hide show
  1. README.md +92 -0
  2. config.json +9 -0
  3. create_safetensors.py +127 -0
  4. model.safetensors +0 -0
README.md ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ - sequential
9
+ - flipflop
10
+ ---
11
+
12
+ # threshold-jk-flipflop
13
+
14
+ JK flip-flop next-state logic as threshold circuit. Most versatile flip-flop with Set, Reset, Hold, and Toggle modes.
15
+
16
+ ## Circuit
17
+
18
+ ```
19
+ J ──┐
20
+ K ──┼──► JK-FF ──┬──► Q
21
+ Q_prev ──┘ └──► Qn
22
+ ```
23
+
24
+ ## Truth Table
25
+
26
+ | J | K | Q_prev | Q | Qn | Mode |
27
+ |---|---|--------|---|----|----|
28
+ | 0 | 0 | 0 | 0 | 1 | Hold |
29
+ | 0 | 0 | 1 | 1 | 0 | Hold |
30
+ | 0 | 1 | X | 0 | 1 | Reset |
31
+ | 1 | 0 | X | 1 | 0 | Set |
32
+ | 1 | 1 | 0 | 1 | 0 | Toggle |
33
+ | 1 | 1 | 1 | 0 | 1 | Toggle |
34
+
35
+ ## Modes
36
+
37
+ ```
38
+ J=0, K=0: Hold - Q stays same
39
+ J=0, K=1: Reset - Q becomes 0
40
+ J=1, K=0: Set - Q becomes 1
41
+ J=1, K=1: Toggle - Q flips
42
+ ```
43
+
44
+ ## Logic
45
+
46
+ ```
47
+ Q = J·~Q_prev + ~K·Q_prev
48
+ Qn = ~J·~Q_prev + K·Q_prev
49
+ ```
50
+
51
+ ## Architecture
52
+
53
+ | Component | Neurons |
54
+ |-----------|---------|
55
+ | Input inversions | 4 |
56
+ | AND gates | 4 |
57
+ | OR outputs | 2 |
58
+ | Passthroughs | 2 |
59
+
60
+ **Total: 12 neurons, 42 parameters, 3 layers**
61
+
62
+ ## Advantage Over SR
63
+
64
+ Unlike SR flip-flop, JK has no invalid state. When both inputs are high, it toggles instead of producing undefined behavior.
65
+
66
+ ## Usage
67
+
68
+ ```python
69
+ from safetensors.torch import load_file
70
+
71
+ w = load_file('model.safetensors')
72
+
73
+ # Counter using toggle mode:
74
+ q = 0
75
+ for _ in range(4):
76
+ q_next = compute(j=1, k=1, q_prev=q, w)
77
+ q = q_next # q toggles: 0,1,0,1,...
78
+ ```
79
+
80
+ ## Files
81
+
82
+ ```
83
+ threshold-jk-flipflop/
84
+ ├── model.safetensors
85
+ ├── create_safetensors.py
86
+ ├── config.json
87
+ └── README.md
88
+ ```
89
+
90
+ ## License
91
+
92
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-jk-flipflop",
3
+ "description": "JK flip-flop next-state logic as threshold circuit",
4
+ "inputs": 3,
5
+ "outputs": 2,
6
+ "neurons": 12,
7
+ "layers": 3,
8
+ "parameters": 42
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # JK Flip-Flop
7
+ # Inputs: J, K, Q_prev (3 inputs)
8
+ # Outputs: Q, Qn (2 outputs)
9
+ #
10
+ # J=0, K=0: Hold (Q = Q_prev)
11
+ # J=0, K=1: Reset (Q = 0)
12
+ # J=1, K=0: Set (Q = 1)
13
+ # J=1, K=1: Toggle (Q = ~Q_prev)
14
+ #
15
+ # Q = J·~Q_prev + ~K·Q_prev
16
+
17
+ # Input indices: J=0, K=1, Q_prev=2
18
+
19
+ # NOT Q_prev
20
+ weights['not_qprev.weight'] = torch.tensor([[0.0, 0.0, -1.0]], dtype=torch.float32)
21
+ weights['not_qprev.bias'] = torch.tensor([0.0], dtype=torch.float32)
22
+
23
+ # J passthrough
24
+ weights['j.weight'] = torch.tensor([[1.0, 0.0, 0.0]], dtype=torch.float32)
25
+ weights['j.bias'] = torch.tensor([0.0], dtype=torch.float32)
26
+
27
+ # NOT K
28
+ weights['not_k.weight'] = torch.tensor([[0.0, -1.0, 0.0]], dtype=torch.float32)
29
+ weights['not_k.bias'] = torch.tensor([0.0], dtype=torch.float32)
30
+
31
+ # Q_prev passthrough
32
+ weights['qprev.weight'] = torch.tensor([[0.0, 0.0, 1.0]], dtype=torch.float32)
33
+ weights['qprev.bias'] = torch.tensor([0.0], dtype=torch.float32)
34
+
35
+ # J AND NOT Q_prev
36
+ weights['j_and_notq.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
37
+ weights['j_and_notq.bias'] = torch.tensor([-2.0], dtype=torch.float32)
38
+
39
+ # NOT K AND Q_prev
40
+ weights['notk_and_q.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
41
+ weights['notk_and_q.bias'] = torch.tensor([-2.0], dtype=torch.float32)
42
+
43
+ # Q = (J AND NOT Q_prev) OR (NOT K AND Q_prev)
44
+ weights['q.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
45
+ weights['q.bias'] = torch.tensor([-1.0], dtype=torch.float32)
46
+
47
+ # Qn = ~J·~Q_prev + K·Q_prev
48
+ # NOT J
49
+ weights['not_j.weight'] = torch.tensor([[-1.0, 0.0, 0.0]], dtype=torch.float32)
50
+ weights['not_j.bias'] = torch.tensor([0.0], dtype=torch.float32)
51
+
52
+ # K passthrough
53
+ weights['k.weight'] = torch.tensor([[0.0, 1.0, 0.0]], dtype=torch.float32)
54
+ weights['k.bias'] = torch.tensor([0.0], dtype=torch.float32)
55
+
56
+ # NOT J AND NOT Q_prev
57
+ weights['notj_and_notq.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
58
+ weights['notj_and_notq.bias'] = torch.tensor([-2.0], dtype=torch.float32)
59
+
60
+ # K AND Q_prev
61
+ weights['k_and_q.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
62
+ weights['k_and_q.bias'] = torch.tensor([-2.0], dtype=torch.float32)
63
+
64
+ # Qn = (NOT J AND NOT Q_prev) OR (K AND Q_prev)
65
+ weights['qn.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
66
+ weights['qn.bias'] = torch.tensor([-1.0], dtype=torch.float32)
67
+
68
+ save_file(weights, 'model.safetensors')
69
+
70
+ def jk_ff(j, k, q_prev):
71
+ if j == 0 and k == 0:
72
+ return q_prev, 1 - q_prev
73
+ elif j == 0 and k == 1:
74
+ return 0, 1
75
+ elif j == 1 and k == 0:
76
+ return 1, 0
77
+ else:
78
+ return 1 - q_prev, q_prev
79
+
80
+ def eval_circuit(j, k, q_prev):
81
+ not_qprev = 1 - q_prev
82
+ not_k = 1 - k
83
+ j_and_notq = j and not_qprev
84
+ notk_and_q = not_k and q_prev
85
+ q = j_and_notq or notk_and_q
86
+ not_j = 1 - j
87
+ notj_and_notq = not_j and not_qprev
88
+ k_and_q = k and q_prev
89
+ qn = notj_and_notq or k_and_q
90
+ return q, qn
91
+
92
+ print("Verifying JK Flip-Flop...")
93
+ errors = 0
94
+ for j in range(2):
95
+ for k in range(2):
96
+ for q_prev in range(2):
97
+ expected_q, expected_qn = jk_ff(j, k, q_prev)
98
+ calc_q, calc_qn = eval_circuit(j, k, q_prev)
99
+ if expected_q != calc_q or expected_qn != calc_qn:
100
+ errors += 1
101
+ print(f"ERROR: J={j}, K={k}, Q_prev={q_prev}")
102
+
103
+ if errors == 0:
104
+ print("All 8 test cases passed!")
105
+ else:
106
+ print(f"FAILED: {errors} errors")
107
+
108
+ print("\nTruth Table:")
109
+ print("J K Q_prev | Q Qn | Mode")
110
+ print("-" * 30)
111
+ for j in range(2):
112
+ for k in range(2):
113
+ for q_prev in range(2):
114
+ q, qn = jk_ff(j, k, q_prev)
115
+ if j == 0 and k == 0:
116
+ mode = "Hold"
117
+ elif j == 0 and k == 1:
118
+ mode = "Reset"
119
+ elif j == 1 and k == 0:
120
+ mode = "Set"
121
+ else:
122
+ mode = "Toggle"
123
+ print(f"{j} {k} {q_prev} | {q} {qn} | {mode}")
124
+
125
+ mag = sum(t.abs().sum().item() for t in weights.values())
126
+ print(f"\nMagnitude: {mag:.0f}")
127
+ print(f"Parameters: {sum(t.numel() for t in weights.values())}")
model.safetensors ADDED
Binary file (1.8 kB). View file