File size: 8,848 Bytes
9df07fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
"""
abc_model.py - ABC Model with Displacement Matrices (CORRECTED FOR KAPPA)

KEY INSIGHT:
    - B_i represents the DISPLACEMENT from current MB position to new position
    - If MB is at (x₁, y₁) and we place piece at (x₂, y₂):
    - Δx = x₂ - x₁
    - Δy = y₂ - y₁
    - B has right column (Δx, Δy, 1)ᵀ

Example:
    - Stage 0: MB at (0, 0, 1)
    - Stage 1: Place at (-1, -1) → Δ = (-1-0, -1-0) = (-1, -1)
    - B₁ right column: (-1, -1, 1)ᵀ
    - Stage 2: Place at (0, 0) → Δ = (0-(-1), 0-(-1)) = (1, 1)
    - B₂ right column: (1, 1, 1)ᵀ ✓

Author: Chaim Duchovny
Date: January 25, 2026 (FIXED FOR KAPPA SUPPORT)
"""

import numpy as np

class ABCModelDynamic:
    """ABC Model with displacement-based B matrices."""
    
    def __init__(self, n: int = 2, t: float = 1.0, T: float = 1.41):
        """
        Initialize for 2D board.
        
        Args:
            n: Dimension (2 for 2D board)
            t: Minimum distance threshold for adjacency
            T: Maximum distance threshold for adjacency
        """
        self.n = n
        self.t = t
        self.T = T
        self.c0 = np.array([0.0, 0.0, 1.0])
        self.B_blocks = []        # Displacement matrices
        self.piece_positions = [] # Actual positions on SB
        self.a_product = np.eye(3) # Accumulated product
        self.delta = {}           # Delta values for each piece
        self.kappa = {}           # Tokenized vectors for each piece (ADDED)
        self.stage = 0
        
        # MB position tracking
        self.MB_current = self.c0.copy()  # Current MB center
        self.MB_previous = self.c0.copy() # Previous MB center
        self.history = []
    
    def create_B_displacement(self, dx: float, dy: float) -> np.ndarray:
        """
        Create displacement matrix B.
        
        Moves MB by (dx, dy) displacement.
        
        B · current_MB = new_MB
        
        B = [1 0 dx]
            [0 1 dy]
            [0 0 1]
        
        Right column: (dx, dy, 1)ᵀ
        """
        B = np.array([
            [1.0, 0.0, dx],
            [0.0, 1.0, dy],
            [0.0, 0.0, 1.0]
        ])
        return B
    
    def add_piece(self, position: tuple, delta_values: tuple, kappa_vector: np.ndarray = None):
        """
        Add a piece at position with delta values and optional kappa vector.
        
        Args:
            position: (x, y) tuple
            delta_values: (Δ₁, Δ₂, Δ₃) tuple
            kappa_vector: Tokenized feature vector (optional, defaults to delta_values)
        """
        x, y = position
        
        # Current MB position
        current_MB = self.MB_current.copy()
        
        # Calculate displacement
        dx = x - current_MB[0]
        dy = y - current_MB[1]
        
        # Create displacement matrix
        B_i = self.create_B_displacement(dx, dy)
        
        # Store
        idx = len(self.B_blocks)
        self.B_blocks.append(B_i)
        self.piece_positions.append((x, y))
        
        # Update accumulated product: a_t = a_{t-1} · B_t
        self.a_product = self.a_product @ B_i
        
        # Track MB positions
        self.MB_previous = self.MB_current.copy()
        self.MB_current = self.a_product @ self.c0  # Should equal (x, y, 1)
        
        # Store differential vector
        self.delta[idx] = delta_values
        
        # Store tokenized vector (or use delta_values as default)
        if kappa_vector is None:
            kappa_vector = np.array(delta_values)
        self.kappa[idx] = kappa_vector
        
        # Increment stage
        self.stage += 1
        
        # Record move
        self.history.append({
            'stage': self.stage,
            'SB_position': (x, y),
            'displacement': (dx, dy),
            'B_i': B_i.copy(),
            'a_t': self.a_product.copy(),
            'MB_prev': self.MB_previous.copy(),
            'MB_curr': self.MB_current.copy(),
            'delta': delta_values,
            'kappa': kappa_vector.copy()
        })
    
    def add_move(self, x: float, y: float, player: int):
        """
        Convenience method: Add a move with automatic delta values.
        
        Args:
            x, y: Position coordinates
            player: 1 for X (Δ₂=1.0), 2 for O (Δ₂=1.1)
        """
        delta_1 = 1.0  # Occupied
        delta_2 = 1.0 if player == 1 else 1.1  # Player color
        delta_3 = 1.0  # Same value for all pieces
        
        self.add_piece((x, y), (delta_1, delta_2, delta_3))
    
    def get_board_state(self) -> str:
        """Visual board state."""
        pos_map = {
            (-1, 1): 0, (0, 1): 1, (1, 1): 2,
            (-1, 0): 3, (0, 0): 4, (1, 0): 5,
            (-1, -1): 6, (0, -1): 7, (1, -1): 8
        }
        
        board = [' '] * 9
        for i, pos in enumerate(self.piece_positions):
            if pos in pos_map:
                player = 'X' if self.delta[i][1] == 1.0 else 'O'
                board[pos_map[pos]] = player
        
        s = f" {board[0]} | {board[1]} | {board[2]} \n"
        s += "---|---|---\n"
        s += f" {board[3]} | {board[4]} | {board[5]} \n"
        s += "---|---|---\n"
        s += f" {board[6]} | {board[7]} | {board[8]} \n"
        return s
    
    def describe_move(self, stage: int):
        """Describe a specific move."""
        if stage < 1 or stage > len(self.history):
            return "Invalid stage"
        
        move = self.history[stage - 1]
        desc = "=" * 70 + "\n"
        desc += f"MOVE {stage}: {move['SB_position']}\n"
        desc += "=" * 70 + "\n\n"
        
        idx = stage - 1
        B_i = self.B_blocks[idx]
        
        desc += f"Mobile Board (MB) movement:\n"
        desc += f" Previous MB: {move['MB_prev']}\n"
        desc += f" Target (SB): {move['SB_position']}\n"
        desc += f" Displacement: Δ = {move['displacement']}\n"
        desc += f" New MB: {move['MB_curr']}\n\n"
        
        desc += f"Displacement matrix B_{stage}:\n{B_i}\n"
        desc += f"Right column: {B_i[:, 2]} = (Δx={move['displacement'][0]}, Δy={move['displacement'][1]}, 1)\n\n"
        
        desc += f"Accumulated product a_{stage}:\n{move['a_t']}\n"
        desc += f"Right column: {move['a_t'][:, 2]}\n\n"
        
        desc += f"Delta values: {move['delta']}\n"
        desc += f"Kappa vector: {move['kappa']}\n\n"
        
        desc += f"Verification:\n"
        desc += f" a_{stage} · c₀ = {move['a_t'] @ self.c0}\n"
        desc += f" Should equal: {np.array([move['SB_position'][0], move['SB_position'][1], 1.0])}\n\n"
        
        desc += "Board state:\n"
        desc += self.get_board_state()
        
        return desc


if __name__ == "__main__":
    print("\n" + "=" * 70)
    print("TIC-TAC-TOE - DISPLACEMENT-BASED B MATRICES")
    print("=" * 70 + "\n")
    
    game = ABCModelDynamic(n=2, t=1.0, T=1.41)
    
    # Play complete game
    moves = [
        ((-1, -1), 1),  # Move 1: X at (-1,-1)
        ((0, 0), 2),    # Move 2: O at (0,0)
        ((0, -1), 1),   # Move 3: X at (0,-1)
        ((1, 0), 2),    # Move 4: O at (1,0)
    ]
    
    for pos, player in moves:
        game.add_move(pos[0], pos[1], player)
    
    # Show first 4 moves in detail
    for i in range(1, 5):
        print(game.describe_move(i))
        print()
    
    # Verification
    print("=" * 70)
    print("VERIFICATION")
    print("=" * 70 + "\n")
    
    print("Key property: MB position tracks piece positions on SB")
    for i in range(1, len(game.history) + 1):
        move = game.history[i - 1]
        MB_curr = move['MB_curr']
        SB_pos = move['SB_position']
        matches = np.allclose(MB_curr[:2], SB_pos)
        print(f"Move {i}: MB={MB_curr} SB={SB_pos} Match? {matches} {'✓' if matches else '❌'}")
    
    print(f"\nB matrices (right columns = displacements):")
    for i in range(1, len(game.history) + 1):
        move = game.history[i - 1]
        B_i = game.B_blocks[i - 1]
        disp = move['displacement']
        right_col = B_i[:, 2]
        print(f" Move {i}: Δ={disp} → B right column = {right_col} ✓")
    
    print(f"\nKappa vectors (tokenized features):")
    for i in range(len(game.history)):
        kappa = game.kappa[i]
        print(f" Piece {i}: κ = {kappa}")
    
    print(f"\nSpecial case - Move 2:")
    move2 = game.history[1]
    print(f" From (-1, -1) to (0, 0)")
    print(f" Displacement: {move2['displacement']}")
    print(f" B₂ right column: {game.B_blocks[1][:, 2]} = (1, 1, 1)ᵀ ✓✓✓")
    
    print("\n✓ MB position correctly tracks SB piece positions!")
    print("✓ B matrices represent displacements!")
    print("✓ B₂ has right column (1, 1, 1)ᵀ as expected!")
    print("✓ Kappa vectors initialized correctly!")
    print("=" * 70 + "\n")