kececinumbers 0.6.7__py3-none-any.whl → 0.6.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ specific algorithm for creating Keçeci Number sequences. High-level functions
12
12
  are available for easy interaction, parameter-based generation, and plotting.
13
13
 
14
14
  Key Features:
15
- - Generation of 11 types of Keçeci Numbers.
15
+ - Generation of 16 types of Keçeci Numbers.
16
16
  - A robust, unified algorithm for all number types.
17
17
  - Helper functions for mathematical properties like primality and divisibility.
18
18
  - Advanced plotting capabilities tailored to each number system.
@@ -35,8 +35,10 @@ from fractions import Fraction
35
35
  import math
36
36
  from matplotlib.gridspec import GridSpec
37
37
  import matplotlib.pyplot as plt
38
+ import numbers
39
+ #from numbers import Real
38
40
  import numpy as np
39
- import quaternion
41
+ import quaternion # pip instal numpy-quaternion # conda install -c conda-forge quaternion
40
42
  import random
41
43
  import re
42
44
  from scipy.fft import fft, fftfreq
@@ -45,9 +47,23 @@ from scipy.stats import ks_2samp
45
47
  import sympy
46
48
  from typing import Any, Dict, List, Optional, Tuple
47
49
 
50
+ # numpy ve diğer Keçeci tipleri için gerekli importlar
51
+ # Eğer bu kütüphaneler yüklü değilse, pip install numpy gibi komutlarla yüklemeniz gerekebilir.
52
+ try:
53
+ import numpy as np
54
+ # numpy.quaternion'ın eski adı np.quaternion. Yeni versiyonlarda quaternion modülü ayrı olabilir.
55
+ # Eğer sorun yaşarsanız, 'pip install numpy-quaternion' ve 'import quaternion as np_quaternion' kullanabilirsiniz.
56
+ except ImportError:
57
+ print("NumPy not found. Quaternion functionality might be limited.")
58
+ class DummyQuaternion: # Placeholder for np.quaternion
59
+ def __init__(self, w, x, y, z): self.w = w
60
+ def __add__(self, other): return self
61
+ np = type('module', (object,), {'quaternion': DummyQuaternion})
62
+
63
+
48
64
 
49
65
  # ==============================================================================
50
- # --- MODULE CONSTANTS: KEÇECI NUMBER TYPES ---
66
+ # --- MODULE CONSTANTS: Keçeci NUMBER TYPES ---
51
67
  # ==============================================================================
52
68
  TYPE_POSITIVE_REAL = 1
53
69
  TYPE_NEGATIVE_REAL = 2
@@ -60,57 +76,210 @@ TYPE_NEUTROSOPHIC_COMPLEX = 8
60
76
  TYPE_HYPERREAL = 9
61
77
  TYPE_BICOMPLEX = 10
62
78
  TYPE_NEUTROSOPHIC_BICOMPLEX = 11
79
+ TYPE_OCTONION = 12
80
+ TYPE_SEDENION = 13
81
+ TYPE_CLIFFORD = 14
82
+ TYPE_DUAL = 15
83
+ TYPE_SPLIT_COMPLEX = 16
63
84
 
64
85
  # ==============================================================================
65
86
  # --- CUSTOM NUMBER CLASS DEFINITIONS ---
66
87
  # ==============================================================================
67
88
 
89
+ @dataclass
90
+ class OctonionNumber:
91
+ """
92
+ Represents an octonion number with 8 components.
93
+ Implements octonion multiplication rules.
94
+ """
95
+ def __init__(self, *args):
96
+ # Varsayılan
97
+ self.w = self.x = self.y = self.z = self.e = self.f = self.g = self.h = 0.0
98
+
99
+ if len(args) == 8:
100
+ self.w, self.x, self.y, self.z, self.e, self.f, self.g, self.h = args
101
+ elif len(args) == 1:
102
+ if isinstance(args[0], (list, tuple)):
103
+ if len(args[0]) == 8:
104
+ self.w, self.x, self.y, self.z, self.e, self.f, self.g, self.h = args[0]
105
+ else:
106
+ components = list(args[0]) + [0.0] * (8 - len(args[0]))
107
+ self.w, self.x, self.y, self.z, self.e, self.f, self.g, self.h = components
108
+ elif isinstance(args[0], (int, float)):
109
+ self.w = float(args[0])
110
+ elif len(args) == 0:
111
+ pass
112
+ else:
113
+ raise ValueError("Invalid arguments for OctonionNumber")
114
+
115
+ @property
116
+ def coeffs(self):
117
+ """Octonion bileşenlerini liste olarak döner."""
118
+ return [self.w, self.x, self.y, self.z, self.e, self.f, self.g, self.h]
119
+
120
+ def __add__(self, other):
121
+ if isinstance(other, OctonionNumber):
122
+ return OctonionNumber(
123
+ self.w + other.w, self.x + other.x, self.y + other.y, self.z + other.z,
124
+ self.e + other.e, self.f + other.f, self.g + other.g, self.h + other.h
125
+ )
126
+ return NotImplemented
127
+
128
+ def __sub__(self, other):
129
+ if isinstance(other, OctonionNumber):
130
+ return OctonionNumber(
131
+ self.w - other.w, self.x - other.x, self.y - other.y, self.z - other.z,
132
+ self.e - other.e, self.f - other.f, self.g - other.g, self.h - other.h
133
+ )
134
+ return NotImplemented
135
+
136
+ def __mul__(self, other):
137
+ if isinstance(other, OctonionNumber):
138
+ # Mevcut octonion çarpımı (7-boyutlu çapraz çarpım kuralları)
139
+ w = self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z \
140
+ - self.e * other.e - self.f * other.f - self.g * other.g - self.h * other.h
141
+ x = self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y \
142
+ + self.e * other.f - self.f * other.e + self.g * other.h - self.h * other.g
143
+ y = self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.x \
144
+ + self.e * other.g - self.g * other.e - self.f * other.h + self.h * other.f
145
+ z = self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w \
146
+ + self.e * other.h - self.h * other.e + self.f * other.g - self.g * other.f
147
+ e = self.w * other.e - self.x * other.f - self.y * other.g - self.z * other.h \
148
+ + self.e * other.w + self.f * other.x + self.g * other.y + self.h * other.z
149
+ f = self.w * other.f + self.x * other.e - self.y * other.h + self.z * other.g \
150
+ - self.e * other.x + self.f * other.w - self.g * other.z + self.h * other.y
151
+ g = self.w * other.g + self.x * other.h + self.y * other.e - self.z * other.f \
152
+ - self.e * other.y + self.f * other.z + self.g * other.w - self.h * other.x
153
+ h = self.w * other.h - self.x * other.g + self.y * other.f + self.z * other.e \
154
+ - self.e * other.z - self.f * other.y + self.g * other.x + self.h * other.w
155
+
156
+ return OctonionNumber(w, x, y, z, e, f, g, h)
157
+
158
+ elif isinstance(other, (int, float)):
159
+ # Skaler çarpım: tüm bileşenler other ile çarpılır
160
+ return OctonionNumber(
161
+ self.w * other, self.x * other, self.y * other, self.z * other,
162
+ self.e * other, self.f * other, self.g * other, self.h * other
163
+ )
164
+
165
+ return NotImplemented
166
+
167
+ def __rmul__(self, other):
168
+ # Skaler çarpımda değişme özelliği vardır: other * self == self * other
169
+ if isinstance(other, (int, float)):
170
+ return self.__mul__(other) # self * other
171
+ return NotImplemented
172
+
173
+
174
+ def __truediv__(self, scalar):
175
+ if isinstance(scalar, (int, float)):
176
+ if scalar == 0:
177
+ raise ZeroDivisionError("Cannot divide by zero.")
178
+ return OctonionNumber(
179
+ self.w / scalar, self.x / scalar, self.y / scalar, self.z / scalar,
180
+ self.e / scalar, self.f / scalar, self.g / scalar, self.h / scalar
181
+ )
182
+ return NotImplemented
183
+
184
+ def __eq__(self, other):
185
+ if not isinstance(other, OctonionNumber):
186
+ return False
187
+ tol = 1e-12
188
+ return all(abs(getattr(self, attr) - getattr(other, attr)) < tol
189
+ for attr in ['w', 'x', 'y', 'z', 'e', 'f', 'g', 'h'])
190
+
191
+ def __ne__(self, other):
192
+ return not self.__eq__(other)
193
+
194
+ def __str__(self):
195
+ return f"Octonion({self.w:.3f}, {self.x:.3f}, {self.y:.3f}, {self.z:.3f}, {self.e:.3f}, {self.f:.3f}, {self.g:.3f}, {self.h:.3f})"
196
+
197
+ def __repr__(self):
198
+ return str(self)
199
+
200
+
201
+ @property
202
+ def coeffs(self):
203
+ return [self.w, self.x, self.y, self.z, self.e, self.f, self.g, self.h]
204
+
205
+ class Constants:
206
+ """Oktonyon sabitleri."""
207
+ ZERO = OctonionNumber(0, 0, 0, 0, 0, 0, 0, 0)
208
+ ONE = OctonionNumber(1, 0, 0, 0, 0, 0, 0, 0)
209
+ I = OctonionNumber(0, 1, 0, 0, 0, 0, 0, 0)
210
+ J = OctonionNumber(0, 0, 1, 0, 0, 0, 0, 0)
211
+ K = OctonionNumber(0, 0, 0, 1, 0, 0, 0, 0)
212
+ E = OctonionNumber(0, 0, 0, 0, 1, 0, 0, 0)
213
+ F = OctonionNumber(0, 0, 0, 0, 0, 1, 0, 0)
214
+ G = OctonionNumber(0, 0, 0, 0, 0, 0, 1, 0)
215
+ H = OctonionNumber(0, 0, 0, 0, 0, 0, 0, 1)
216
+
217
+
68
218
  @dataclass
69
219
  class NeutrosophicNumber:
70
- """Represents a neutrosophic number of the form a + bI where I^2 = I."""
71
- a: float
72
- b: float
220
+ """Represents a neutrosophic number of the form t + iI + fF."""
221
+ t: float # truth
222
+ i: float # indeterminacy
223
+ f: float # falsity
224
+
225
+ def __init__(self, t: float, i: float, f: float = 0.0):
226
+ self.t = t
227
+ self.i = i
228
+ self.f = f
73
229
 
74
230
  def __add__(self, other: Any) -> "NeutrosophicNumber":
75
231
  if isinstance(other, NeutrosophicNumber):
76
- return NeutrosophicNumber(self.a + other.a, self.b + other.b)
232
+ return NeutrosophicNumber(self.t + other.t, self.i + other.i, self.f + other.f)
77
233
  if isinstance(other, (int, float)):
78
- return NeutrosophicNumber(self.a + other, self.b)
234
+ return NeutrosophicNumber(self.t + other, self.i, self.f)
79
235
  return NotImplemented
80
236
 
81
237
  def __sub__(self, other: Any) -> "NeutrosophicNumber":
82
238
  if isinstance(other, NeutrosophicNumber):
83
- return NeutrosophicNumber(self.a - other.a, self.b - other.b)
239
+ return NeutrosophicNumber(self.t - other.t, self.i - other.i, self.f - other.f)
84
240
  if isinstance(other, (int, float)):
85
- return NeutrosophicNumber(self.a - other, self.b)
241
+ return NeutrosophicNumber(self.t - other, self.i, self.f)
86
242
  return NotImplemented
87
243
 
88
244
  def __mul__(self, other: Any) -> "NeutrosophicNumber":
89
245
  if isinstance(other, NeutrosophicNumber):
90
246
  return NeutrosophicNumber(
91
- self.a * other.a,
92
- self.a * other.b + self.b * other.a + self.b * other.b,
247
+ self.t * other.t,
248
+ self.t * other.i + self.i * other.t + self.i * other.i,
249
+ self.t * other.f + self.f * other.t + self.f * other.f
93
250
  )
94
251
  if isinstance(other, (int, float)):
95
- return NeutrosophicNumber(self.a * other, self.b * other)
252
+ return NeutrosophicNumber(self.t * other, self.i * other, self.f * other)
96
253
  return NotImplemented
97
254
 
98
255
  def __truediv__(self, divisor: float) -> "NeutrosophicNumber":
99
256
  if isinstance(divisor, (int, float)):
100
257
  if divisor == 0:
101
258
  raise ZeroDivisionError("Cannot divide by zero.")
102
- return NeutrosophicNumber(self.a / divisor, self.b / divisor)
259
+ return NeutrosophicNumber(self.t / divisor, self.i / divisor, self.f / divisor)
103
260
  raise TypeError("Only scalar division is supported.")
104
261
 
105
262
  def __str__(self) -> str:
106
- return f"{self.a} + {self.b}I"
263
+ parts = []
264
+ if self.t != 0:
265
+ parts.append(f"{self.t}")
266
+ if self.i != 0:
267
+ parts.append(f"{self.i}I")
268
+ if self.f != 0:
269
+ parts.append(f"{self.f}F")
270
+ return " + ".join(parts) if parts else "0"
107
271
 
108
272
  @dataclass
109
273
  class NeutrosophicComplexNumber:
110
- """Represents a number with a complex part and an indeterminacy level."""
111
- real: float = 0.0
112
- imag: float = 0.0
113
- indeterminacy: float = 0.0
274
+ """
275
+ Represents a number with a complex part and an indeterminacy level.
276
+ z = (a + bj) + cI, where I = indeterminacy.
277
+ """
278
+
279
+ def __init__(self, real: float = 0.0, imag: float = 0.0, indeterminacy: float = 0.0):
280
+ self.real = float(real)
281
+ self.imag = float(imag)
282
+ self.indeterminacy = float(indeterminacy)
114
283
 
115
284
  def __repr__(self) -> str:
116
285
  return f"NeutrosophicComplexNumber(real={self.real}, imag={self.imag}, indeterminacy={self.indeterminacy})"
@@ -121,71 +290,121 @@ class NeutrosophicComplexNumber:
121
290
  def __add__(self, other: Any) -> "NeutrosophicComplexNumber":
122
291
  if isinstance(other, NeutrosophicComplexNumber):
123
292
  return NeutrosophicComplexNumber(
124
- self.real + other.real, self.imag + other.imag, self.indeterminacy + other.indeterminacy
293
+ self.real + other.real,
294
+ self.imag + other.imag,
295
+ self.indeterminacy + other.indeterminacy
125
296
  )
126
297
  if isinstance(other, (int, float)):
127
298
  return NeutrosophicComplexNumber(self.real + other, self.imag, self.indeterminacy)
299
+ if isinstance(other, complex):
300
+ return NeutrosophicComplexNumber(self.real + other.real, self.imag + other.imag, self.indeterminacy)
128
301
  return NotImplemented
129
302
 
130
303
  def __sub__(self, other: Any) -> "NeutrosophicComplexNumber":
131
304
  if isinstance(other, NeutrosophicComplexNumber):
132
305
  return NeutrosophicComplexNumber(
133
- self.real - other.real, self.imag - other.imag, self.indeterminacy - other.indeterminacy
306
+ self.real - other.real,
307
+ self.imag - other.imag,
308
+ self.indeterminacy - other.indeterminacy
134
309
  )
135
310
  if isinstance(other, (int, float)):
136
311
  return NeutrosophicComplexNumber(self.real - other, self.imag, self.indeterminacy)
312
+ if isinstance(other, complex):
313
+ return NeutrosophicComplexNumber(self.real - other.real, self.imag - other.imag, self.indeterminacy)
137
314
  return NotImplemented
138
315
 
139
316
  def __mul__(self, other: Any) -> "NeutrosophicComplexNumber":
140
317
  if isinstance(other, NeutrosophicComplexNumber):
141
318
  new_real = self.real * other.real - self.imag * other.imag
142
319
  new_imag = self.real * other.imag + self.imag * other.real
143
- new_indeterminacy = self.indeterminacy + other.indeterminacy + (self.magnitude_sq() * other.indeterminacy)
320
+ # Indeterminacy: basitleştirilmiş model
321
+ new_indeterminacy = (self.indeterminacy + other.indeterminacy +
322
+ self.magnitude_sq() * other.indeterminacy +
323
+ other.magnitude_sq() * self.indeterminacy)
144
324
  return NeutrosophicComplexNumber(new_real, new_imag, new_indeterminacy)
145
325
  if isinstance(other, complex):
146
326
  new_real = self.real * other.real - self.imag * other.imag
147
327
  new_imag = self.real * other.imag + self.imag * other.real
148
328
  return NeutrosophicComplexNumber(new_real, new_imag, self.indeterminacy)
149
329
  if isinstance(other, (int, float)):
150
- return NeutrosophicComplexNumber(self.real * other, self.imag * other, self.indeterminacy * other)
330
+ return NeutrosophicComplexNumber(
331
+ self.real * other,
332
+ self.imag * other,
333
+ self.indeterminacy * other
334
+ )
151
335
  return NotImplemented
152
336
 
153
- def __truediv__(self, divisor: float) -> "NeutrosophicComplexNumber":
337
+ def __truediv__(self, divisor: Any) -> "NeutrosophicComplexNumber":
154
338
  if isinstance(divisor, (int, float)):
155
339
  if divisor == 0:
156
340
  raise ZeroDivisionError("Cannot divide by zero.")
157
341
  return NeutrosophicComplexNumber(
158
- self.real / divisor, self.imag / divisor, self.indeterminacy / divisor
342
+ self.real / divisor,
343
+ self.imag / divisor,
344
+ self.indeterminacy / divisor
159
345
  )
160
- raise TypeError("Only scalar division is supported.")
346
+ return NotImplemented # complex / NeutrosophicComplex desteklenmiyor
161
347
 
162
348
  def __radd__(self, other: Any) -> "NeutrosophicComplexNumber":
163
349
  return self.__add__(other)
164
350
 
165
351
  def __rsub__(self, other: Any) -> "NeutrosophicComplexNumber":
166
352
  if isinstance(other, (int, float)):
167
- return NeutrosophicComplexNumber(other - self.real, -self.imag, -self.indeterminacy)
353
+ return NeutrosophicComplexNumber(
354
+ other - self.real,
355
+ -self.imag,
356
+ -self.indeterminacy
357
+ )
168
358
  return NotImplemented
169
359
 
170
360
  def __rmul__(self, other: Any) -> "NeutrosophicComplexNumber":
171
361
  return self.__mul__(other)
172
362
 
173
363
  def magnitude_sq(self) -> float:
364
+ """Returns the squared magnitude of the complex part."""
174
365
  return self.real**2 + self.imag**2
175
366
 
367
+ def __eq__(self, other: Any) -> bool:
368
+ if isinstance(other, NeutrosophicComplexNumber):
369
+ return (abs(self.real - other.real) < 1e-12 and
370
+ abs(self.imag - other.imag) < 1e-12 and
371
+ abs(self.indeterminacy - other.indeterminacy) < 1e-12)
372
+ return False
373
+
176
374
  @dataclass
177
375
  class HyperrealNumber:
178
376
  """Represents a hyperreal number as a sequence of real numbers."""
179
- sequence: list
377
+ sequence: List[float]
378
+
379
+ def __init__(self, *args):
380
+ if len(args) == 1 and isinstance(args[0], list):
381
+ self.sequence = args[0]
382
+ else:
383
+ self.sequence = list(args)
180
384
 
181
385
  def __add__(self, other: Any) -> "HyperrealNumber":
182
386
  if isinstance(other, HyperrealNumber):
183
- return HyperrealNumber([a + b for a, b in zip(self.sequence, other.sequence)])
387
+ # Sequence'leri eşit uzunluğa getir
388
+ max_len = max(len(self.sequence), len(other.sequence))
389
+ seq1 = self.sequence + [0.0] * (max_len - len(self.sequence))
390
+ seq2 = other.sequence + [0.0] * (max_len - len(other.sequence))
391
+ return HyperrealNumber([a + b for a, b in zip(seq1, seq2)])
392
+ elif isinstance(other, (int, float)):
393
+ new_seq = self.sequence.copy()
394
+ new_seq[0] += other # Sadece finite part'a ekle
395
+ return HyperrealNumber(new_seq)
184
396
  return NotImplemented
185
397
 
186
398
  def __sub__(self, other: Any) -> "HyperrealNumber":
187
399
  if isinstance(other, HyperrealNumber):
188
- return HyperrealNumber([a - b for a, b in zip(self.sequence, other.sequence)])
400
+ max_len = max(len(self.sequence), len(other.sequence))
401
+ seq1 = self.sequence + [0.0] * (max_len - len(self.sequence))
402
+ seq2 = other.sequence + [0.0] * (max_len - len(other.sequence))
403
+ return HyperrealNumber([a - b for a, b in zip(seq1, seq2)])
404
+ elif isinstance(other, (int, float)):
405
+ new_seq = self.sequence.copy()
406
+ new_seq[0] -= other
407
+ return HyperrealNumber(new_seq)
189
408
  return NotImplemented
190
409
 
191
410
  def __mul__(self, scalar: float) -> "HyperrealNumber":
@@ -203,538 +422,1367 @@ class HyperrealNumber:
203
422
  return HyperrealNumber([x / divisor for x in self.sequence])
204
423
  raise TypeError("Only scalar division is supported.")
205
424
 
206
- def __mod__(self, divisor: float) -> List[float]:
425
+ def __mod__(self, divisor: float) -> "HyperrealNumber":
207
426
  if isinstance(divisor, (int, float)):
208
- return [x % divisor for x in self.sequence]
427
+ return HyperrealNumber([x % divisor for x in self.sequence])
209
428
  raise TypeError("Modulo only supported with a scalar divisor.")
210
429
 
211
430
  def __str__(self) -> str:
212
- return f"Hyperreal({self.sequence[:30]}...)"
431
+ if len(self.sequence) <= 5:
432
+ return f"Hyperreal{self.sequence}"
433
+ return f"Hyperreal({self.sequence[:3]}...)"
434
+
435
+ @property
436
+ def finite(self):
437
+ """Returns the finite part (first component)"""
438
+ return self.sequence[0] if self.sequence else 0.0
439
+
440
+ @property
441
+ def infinitesimal(self):
442
+ """Returns the first infinitesimal part (second component)"""
443
+ return self.sequence[1] if len(self.sequence) > 1 else 0.0
213
444
 
214
445
  @dataclass
215
446
  class BicomplexNumber:
216
- """Represents a bicomplex number z1 + j*z2, where i^2 = j^2 = -1."""
217
- z1: complex
218
- z2: complex
447
+ """Represents a bicomplex number with two complex components."""
448
+ z1: complex # First complex component
449
+ z2: complex # Second complex component
219
450
 
220
451
  def __add__(self, other: Any) -> "BicomplexNumber":
221
452
  if isinstance(other, BicomplexNumber):
222
453
  return BicomplexNumber(self.z1 + other.z1, self.z2 + other.z2)
223
- return NotImplemented
454
+ elif isinstance(other, (int, float, complex)):
455
+ return BicomplexNumber(self.z1 + other, self.z2)
456
+ else:
457
+ raise TypeError(f"Unsupported operand type(s) for +: 'BicomplexNumber' and '{type(other).__name__}'")
224
458
 
225
459
  def __sub__(self, other: Any) -> "BicomplexNumber":
226
460
  if isinstance(other, BicomplexNumber):
227
461
  return BicomplexNumber(self.z1 - other.z1, self.z2 - other.z2)
228
- return NotImplemented
462
+ elif isinstance(other, (int, float, complex)):
463
+ return BicomplexNumber(self.z1 - other, self.z2)
464
+ else:
465
+ raise TypeError(f"Unsupported operand type(s) for -: 'BicomplexNumber' and '{type(other).__name__}'")
229
466
 
230
467
  def __mul__(self, other: Any) -> "BicomplexNumber":
231
468
  if isinstance(other, BicomplexNumber):
469
+ # Bicomplex multiplication: (z1 + z2j) * (w1 + w2j) = (z1*w1 - z2*w2) + (z1*w2 + z2*w1)j
232
470
  return BicomplexNumber(
233
- (self.z1 * other.z1) - (self.z2 * other.z2),
234
- (self.z1 * other.z2) + (self.z2 * other.z1),
471
+ self.z1 * other.z1 - self.z2 * other.z2,
472
+ self.z1 * other.z2 + self.z2 * other.z1
235
473
  )
236
- return NotImplemented
474
+ elif isinstance(other, (int, float, complex)):
475
+ return BicomplexNumber(self.z1 * other, self.z2 * other)
476
+ else:
477
+ raise TypeError(f"Unsupported operand type(s) for *: 'BicomplexNumber' and '{type(other).__name__}'")
237
478
 
238
- def __truediv__(self, scalar: float) -> "BicomplexNumber":
239
- if isinstance(scalar, (int, float)):
240
- if scalar == 0:
241
- raise ZeroDivisionError("Cannot divide by zero.")
242
- return BicomplexNumber(self.z1 / scalar, self.z2 / scalar)
243
- raise TypeError("Only scalar division is supported.")
479
+ def __truediv__(self, divisor: float) -> "BicomplexNumber":
480
+ if isinstance(divisor, (int, float)):
481
+ if divisor == 0:
482
+ raise ZeroDivisionError("Division by zero")
483
+ return BicomplexNumber(self.z1 / divisor, self.z2 / divisor)
484
+ else:
485
+ raise TypeError("Only scalar division is supported")
244
486
 
245
487
  def __str__(self) -> str:
246
- return f"Bicomplex({self.z1}, {self.z2})"
488
+ parts = []
489
+ if self.z1 != 0j:
490
+ parts.append(f"({self.z1.real}+{self.z1.imag}j)")
491
+ if self.z2 != 0j:
492
+ parts.append(f"({self.z2.real}+{self.z2.imag}j)j")
493
+ return " + ".join(parts) if parts else "0"
494
+
495
+ def __abs__(self) -> float:
496
+ """Returns the magnitude of the bicomplex number."""
497
+ return abs(self.z1) + abs(self.z2) # Basit magnitude
498
+
499
+ def _parse_bicomplex(s: str) -> BicomplexNumber:
500
+ """Parses a string into a BicomplexNumber."""
501
+ s_clean = s.strip().replace(" ", "")
502
+
503
+ # VİRGÜL formatı: z1_real,z1_imag,z2_real,z2_imag (4 parametre)
504
+ if ',' in s_clean:
505
+ parts = [float(p.strip()) for p in s_clean.split(',')]
506
+ if len(parts) == 4:
507
+ return BicomplexNumber(complex(parts[0], parts[1]), complex(parts[2], parts[3]))
508
+ elif len(parts) == 2:
509
+ # Sadece z1 verilmiş, z2 = 0
510
+ return BicomplexNumber(complex(parts[0], parts[1]), complex(0, 0))
511
+ elif len(parts) == 1:
512
+ # Sadece real kısım
513
+ return BicomplexNumber(complex(parts[0], 0), complex(0, 0))
514
+
515
+ # Eğer virgül yoksa, complex olarak parsing dene
516
+ try:
517
+ # Önce complex olarak parse et
518
+ c = _parse_complex(s_clean)
519
+ return BicomplexNumber(c, complex(0, 0))
520
+ except ValueError:
521
+ # Son çare: sadece real kısım
522
+ try:
523
+ real_val = float(_extract_numeric_part(s_clean))
524
+ return BicomplexNumber(complex(real_val, 0), complex(0, 0))
525
+ except ValueError:
526
+ return BicomplexNumber(complex(0, 0), complex(0, 0)) # Default
527
+
528
+ def _has_bicomplex_format(s: str) -> bool:
529
+ """Checks if string has bicomplex format (comma-separated)."""
530
+ return ',' in s and s.count(',') in [1, 3] # 2 or 4 components
247
531
 
248
532
  @dataclass
249
533
  class NeutrosophicBicomplexNumber:
250
- """Represents a simplified neutrosophic-bicomplex number."""
251
- real: float
252
- imag: float
253
- neut_real: float
254
- neut_imag: float
255
- j_real: float
256
- j_imag: float
257
- j_neut_real: float
258
- j_neut_imag: float
259
-
260
- def __add__(self, other: Any) -> "NeutrosophicBicomplexNumber":
534
+ def __init__(self, a, b, c, d, e, f, g, h):
535
+ self.a = float(a)
536
+ self.b = float(b)
537
+ self.c = float(c)
538
+ self.d = float(d)
539
+ self.e = float(e)
540
+ self.f = float(f)
541
+ self.g = float(g)
542
+ self.h = float(h)
543
+
544
+ def __repr__(self):
545
+ return f"NeutrosophicBicomplexNumber({self.a}, {self.b}, {self.c}, {self.d}, {self.e}, {self.f}, {self.g}, {self.h})"
546
+
547
+ def __str__(self):
548
+ return f"({self.a} + {self.b}i) + ({self.c} + {self.d}i)I + ({self.e} + {self.f}i)j + ({self.g} + {self.h}i)Ij"
549
+
550
+ def __add__(self, other):
261
551
  if isinstance(other, NeutrosophicBicomplexNumber):
262
- return NeutrosophicBicomplexNumber(*(a + b for a, b in zip(self.__dict__.values(), other.__dict__.values())))
552
+ return NeutrosophicBicomplexNumber(
553
+ self.a + other.a, self.b + other.b, self.c + other.c, self.d + other.d,
554
+ self.e + other.e, self.f + other.f, self.g + other.g, self.h + other.h
555
+ )
263
556
  return NotImplemented
264
557
 
265
- def __sub__(self, other: Any) -> "NeutrosophicBicomplexNumber":
266
- if isinstance(other, NeutrosophicBicomplexNumber):
267
- return NeutrosophicBicomplexNumber(*(a - b for a, b in zip(self.__dict__.values(), other.__dict__.values())))
558
+ def __mul__(self, other):
559
+ # Basitleştirilmiş çarpım (tam bicomplex kuralı karmaşık)
560
+ if isinstance(other, (int, float)):
561
+ return NeutrosophicBicomplexNumber(
562
+ *(other * x for x in [self.a, self.b, self.c, self.d, self.e, self.f, self.g, self.h])
563
+ )
268
564
  return NotImplemented
269
565
 
270
- def __truediv__(self, scalar: float) -> "NeutrosophicBicomplexNumber":
566
+ def __truediv__(self, scalar):
271
567
  if isinstance(scalar, (int, float)):
272
568
  if scalar == 0:
273
- raise ZeroDivisionError("Cannot divide by zero.")
274
- return NeutrosophicBicomplexNumber(*(val / scalar for val in self.__dict__.values()))
275
- raise TypeError("Only scalar division supported.")
569
+ raise ZeroDivisionError("Division by zero")
570
+ return NeutrosophicBicomplexNumber(
571
+ self.a / scalar, self.b / scalar, self.c / scalar, self.d / scalar,
572
+ self.e / scalar, self.f / scalar, self.g / scalar, self.h / scalar
573
+ )
574
+ return NotImplemented
276
575
 
277
- def __str__(self) -> str:
278
- return f"NeutroBicomplex(r={self.real}, i={self.imag}, Ir={self.neut_real}, ...)"
576
+ def __eq__(self, other):
577
+ """Equality with tolerance for float comparison."""
578
+ if not isinstance(other, NeutrosophicBicomplexNumber):
579
+ return False
580
+ tol = 1e-12
581
+ return all(abs(getattr(self, attr) - getattr(other, attr)) < tol
582
+ for attr in ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
279
583
 
280
- # ==============================================================================
281
- # --- HELPER FUNCTIONS ---
282
- # ==============================================================================
584
+ def __ne__(self, other):
585
+ return not self.__eq__(other)
283
586
 
284
- def _get_integer_representation(n_input: Any) -> Optional[int]:
285
- """Extracts the primary integer component from any supported number type."""
286
- try:
287
- if isinstance(n_input, (int, float, Fraction)):
288
- return abs(int(n_input))
289
- if isinstance(n_input, complex):
290
- return abs(int(n_input.real))
291
- if isinstance(n_input, np.quaternion):
292
- return abs(int(n_input.w))
293
- if isinstance(n_input, NeutrosophicNumber):
294
- return abs(int(n_input.a))
295
- if isinstance(n_input, NeutrosophicComplexNumber):
296
- return abs(int(n_input.real))
297
- if isinstance(n_input, HyperrealNumber):
298
- return abs(int(n_input.sequence[0])) if n_input.sequence else 0
299
- if isinstance(n_input, BicomplexNumber):
300
- return abs(int(n_input.z1.real))
301
- if isinstance(n_input, NeutrosophicBicomplexNumber):
302
- return abs(int(n_input.real))
303
- return abs(int(n_input))
304
- except (ValueError, TypeError, IndexError):
305
- return None
587
+ @dataclass
588
+ class SedenionNumber:
589
+ def __init__(self, coeffs):
590
+ if len(coeffs) != 16:
591
+ raise ValueError("Sedenion must have 16 components")
592
+ self.coeffs = list(map(float, coeffs))
593
+
594
+ def __add__(self, other):
595
+ if isinstance(other, SedenionNumber):
596
+ return SedenionNumber([s + o for s, o in zip(self.coeffs, other.coeffs)])
597
+ elif isinstance(other, (int, float)):
598
+ return SedenionNumber([self.coeffs[0] + other] + self.coeffs[1:])
599
+ return NotImplemented
306
600
 
307
- def is_prime(n_input: Any) -> bool:
308
- """
309
- Checks if a given number (or its principal component) is prime
310
- using the robust sympy.isprime function.
311
- """
312
- # Adım 1: Karmaşık sayı türünden tamsayıyı çıkarma (Bu kısım aynı kalıyor)
313
- value_to_check = _get_integer_representation(n_input)
601
+ def __sub__(self, other):
602
+ if isinstance(other, SedenionNumber):
603
+ return SedenionNumber([s - o for s, o in zip(self.coeffs, other.coeffs)])
604
+ elif isinstance(other, (int, float)):
605
+ return SedenionNumber([self.coeffs[0] - other] + self.coeffs[1:])
606
+ return NotImplemented
314
607
 
315
- # Adım 2: Tamsayı geçerli değilse False döndür
316
- if value_to_check is None:
317
- return False
318
-
319
- # Adım 3: Asallık testini sympy'ye bırak
320
- # sympy.isprime, 2'den küçük sayılar (1, 0, negatifler) için zaten False döndürür.
321
- return sympy.isprime(value_to_check)
608
+ def __mul__(self, other):
609
+ # Sedenion çarpımı Cayley-Dickson yapısı ile tanımlanır ama oldukça karmaşıktır.
610
+ # Basitleştirme: skaler çarpım veya element-wise çarpım DEĞİL.
611
+ # Gerçek sedenion çarpımı 16x16 çarpım tablosu gerektirir.
612
+ # Bu örnekte, yalnızca skaler çarpım ve Sedenion-Sedenion için çarpım tablosuz basitleştirilmiş hâli (örnek amaçlı) verilir.
613
+ # Gerçek uygulama için sedenion multiplication table kullanılmalıdır.
614
+ if isinstance(other, (int, float)):
615
+ return SedenionNumber([c * other for c in self.coeffs])
616
+ elif isinstance(other, SedenionNumber):
617
+ # NOT: Gerçek sedenion çarpımı burada eksik (çok karmaşık).
618
+ # Element-wise çarpım matematiksel olarak doğru değildir ama örnek olsun diye konuldu.
619
+ # Gerçek hâli için: https://en.wikipedia.org/wiki/Sedenion
620
+ return NotImplemented # Gerçek sedenion çarpımı oldukça karmaşıktır
621
+ return NotImplemented
622
+
623
+ def __truediv__(self, other):
624
+ if isinstance(other, (int, float)):
625
+ if other == 0:
626
+ raise ZeroDivisionError("Division by zero")
627
+ return SedenionNumber([c / other for c in self.coeffs])
628
+ return NotImplemented
629
+
630
+ def __str__(self):
631
+ return "(" + ", ".join(f"{c:.2f}" for c in self.coeffs) + ")"
632
+
633
+ def __repr__(self):
634
+ return f"({', '.join(map(str, self.coeffs))})"
635
+
636
+ @dataclass
637
+ class CliffordNumber:
638
+
639
+ def __init__(self, basis_dict):
640
+ """
641
+ CliffordNumber constructor - sadece basis_dict alır.
642
+ Dimension property olarak hesaplanabilir.
643
+ """
644
+ self.basis = {k: float(v) for k, v in basis_dict.items()}
322
645
 
323
- """
324
- def is_prime(n_input: Any) -> bool:
325
- #Checks if a given number (or its principal component) is prime.
326
- value_to_check = _get_integer_representation(n_input)
327
- if value_to_check is None or value_to_check < 2:
328
- return False
329
- if value_to_check == 2:
330
- return True
331
- if value_to_check % 2 == 0:
332
- return False
333
- for i in range(3, int(math.sqrt(value_to_check)) + 1, 2):
334
- if value_to_check % i == 0:
335
- return False
336
- return True
337
- """
646
+ @property
647
+ def dimension(self):
648
+ """Vector space dimension'ını otomatik hesaplar."""
649
+ if not self.basis:
650
+ return 0
651
+ max_index = 0
652
+ for key in self.basis.keys():
653
+ if key: # scalar değilse
654
+ indices = [int(c) for c in key if c.isdigit()]
655
+ if indices:
656
+ max_index = max(max_index, max(indices))
657
+ return max_index
658
+
659
+ def __add__(self, other):
660
+ if isinstance(other, CliffordNumber):
661
+ new_basis = self.basis.copy()
662
+ for k, v in other.basis.items():
663
+ new_basis[k] = new_basis.get(k, 0.0) + v
664
+ return CliffordNumber(new_basis)
665
+ elif isinstance(other, (int, float)):
666
+ new_basis = self.basis.copy()
667
+ new_basis[''] = new_basis.get('', 0.0) + other
668
+ return CliffordNumber(new_basis)
669
+ return NotImplemented
338
670
 
339
- def _is_divisible(value: Any, divisor: int, kececi_type: int) -> bool:
340
- """Helper to check divisibility for different number types."""
341
- try:
342
- if kececi_type in [TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL]:
343
- return value % divisor == 0
344
- if kececi_type == TYPE_FLOAT:
345
- return math.isclose(value % divisor, 0)
346
- if kececi_type == TYPE_RATIONAL:
347
- return (value / divisor).denominator == 1
348
- if kececi_type == TYPE_COMPLEX:
349
- return math.isclose(value.real % divisor, 0) and math.isclose(value.imag % divisor, 0)
350
- if kececi_type == TYPE_QUATERNION:
351
- return all(math.isclose(c % divisor, 0) for c in [value.w, value.x, value.y, value.z])
352
- if kececi_type == TYPE_NEUTROSOPHIC:
353
- return math.isclose(value.a % divisor, 0) and math.isclose(value.b % divisor, 0)
354
- if kececi_type == TYPE_NEUTROSOPHIC_COMPLEX:
355
- return all(math.isclose(c % divisor, 0) for c in [value.real, value.imag, value.indeterminacy])
356
- if kececi_type == TYPE_HYPERREAL:
357
- return all(math.isclose(x % divisor, 0) for x in value.sequence)
358
- if kececi_type == TYPE_BICOMPLEX:
359
- return _is_divisible(value.z1, divisor, TYPE_COMPLEX) and _is_divisible(value.z2, divisor, TYPE_COMPLEX)
360
- if kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX:
361
- return all(math.isclose(c % divisor, 0) for c in value.__dict__.values())
362
- except (TypeError, ValueError):
363
- return False
364
- return False
671
+ def __sub__(self, other):
672
+ if isinstance(other, CliffordNumber):
673
+ new_basis = self.basis.copy()
674
+ for k, v in other.basis.items():
675
+ new_basis[k] = new_basis.get(k, 0.0) - v
676
+ return CliffordNumber(new_basis)
677
+ elif isinstance(other, (int, float)):
678
+ new_basis = self.basis.copy()
679
+ new_basis[''] = new_basis.get('', 0.0) - other
680
+ return CliffordNumber(new_basis)
681
+ return NotImplemented
365
682
 
366
- def _parse_complex(s: str) -> complex:
367
- """Parses a string into a complex number. '3' becomes 3+3j."""
368
- s_clean = s.strip().lower()
369
- try:
370
- c = complex(s_clean)
371
- if c.imag == 0 and 'j' not in s_clean:
372
- return complex(c.real, c.real)
373
- return c
374
- except ValueError as e:
375
- raise ValueError(f"Invalid complex number format: '{s}'") from e
683
+ def __mul__(self, other):
684
+ if isinstance(other, (int, float)):
685
+ return CliffordNumber({k: v * other for k, v in self.basis.items()})
686
+ elif isinstance(other, CliffordNumber):
687
+ # Clifford çarpımı: e_i * e_i = +1 veya -1 olabilir ama burada basitleştirme
688
+ # Genel durum için çarpım kuralları tanımlanmalı (örneğin e1^2 = 1, e2^2 = -1 vs)
689
+ # Burada sadece cebirsel çarpım desteklenmiyor çünkü kurallar eksik.
690
+ return NotImplemented # Gerçek Clifford çarpımı için kurallar gerekir
691
+ return NotImplemented
376
692
 
377
- def _parse_neutrosophic(s: str) -> Tuple[float, float]:
378
- """Parses a neutrosophic string 'a+bI' into a tuple (a, b)."""
379
- s = s.strip().replace(" ", "").upper()
380
- if not s:
381
- return 0.0, 0.0
693
+ def __truediv__(self, other):
694
+ if isinstance(other, (int, float)):
695
+ if other == 0:
696
+ raise ZeroDivisionError("Division by zero")
697
+ return CliffordNumber({k: v / other for k, v in self.basis.items()})
698
+ return NotImplemented
382
699
 
383
- if 'I' not in s:
384
- return float(s), 0.0
700
+ def __str__(self):
701
+ parts = []
702
+ if '' in self.basis and self.basis[''] != 0.0:
703
+ parts.append(f"{self.basis['']:.2f}")
704
+
705
+ sorted_keys = sorted([k for k in self.basis if k != ''], key=lambda x: (len(x), x))
706
+ for k in sorted_keys:
707
+ v = self.basis[k]
708
+ if abs(v) > 1e-10: # sıfıra çok yakın olanları atla
709
+ sign = '+' if v > 0 and parts else ''
710
+ parts.append(f"{sign}{v:.2f}e{k}")
711
+
712
+ result = "".join(parts).replace("+-", "-")
713
+ return result if result else "0.0"
385
714
 
386
- pattern = re.compile(r"^(?P<a>[+-]?\d+\.?\d*)?(?P<b>[+-]?)I$")
387
- match = re.match(r"^(?P<val>[+-]?\d+\.?\d*)$", s)
388
- if match: # Just a number
389
- return float(match.group('val')), 0.0
715
+ def __repr__(self):
716
+ parts = []
717
+ if '' in self.basis and self.basis[''] != 0.0:
718
+ parts.append(str(self.basis['']))
390
719
 
391
- pattern = re.compile(r"^(?P<a>[+-]?\d+\.?\d*)?(?P<b>[+-]?\d*\.?\d*)I$")
392
- full_match = pattern.match(s)
393
- if not full_match:
394
- raise ValueError(f"Invalid neutrosophic format: {s}")
395
-
396
- parts = full_match.groupdict()
397
- a_part = parts.get('a') or "0"
398
- b_part = parts.get('b')
399
-
400
- if b_part in (None, "", "+"):
401
- b_val = 1.0
402
- elif b_part == "-":
403
- b_val = -1.0
404
- else:
405
- b_val = float(b_part)
720
+ sorted_keys = sorted([k for k in self.basis if k != ''], key=lambda x: (len(x), x))
721
+ for k in sorted_keys:
722
+ v = self.basis[k]
723
+ if v != 0.0:
724
+ sign = '+' if v > 0 and parts else ''
725
+ parts.append(f"{sign}{v}e{k}")
406
726
 
407
- return float(a_part), b_val
727
+ if not parts:
728
+ return "0.0"
729
+ return "".join(parts).replace("+-", "-")
408
730
 
409
731
 
410
- def _parse_hyperreal(s: str) -> Tuple[float, float]:
411
- """Parses 'a+be' string into a tuple (a, b)."""
412
- s = s.strip().replace(" ", "").lower()
413
- if not s:
414
- return 0.0, 0.0
415
- if 'e' not in s:
416
- return float(s), 0.0
732
+ @dataclass
733
+ class DualNumber:
417
734
 
418
- pattern = re.compile(r"^(?P<a>[+-]?\d+\.?\d*)?(?P<b>[+-]?\d*\.?\d*)e$")
419
- match = pattern.match(s)
420
- if not match:
421
- raise ValueError(f"Invalid hyperreal format: {s}")
735
+ real: float
736
+ dual: float
737
+
738
+ def __init__(self, real, dual):
739
+ self.real = float(real)
740
+ self.dual = float(dual)
741
+ def __add__(self, other):
742
+ if isinstance(other, DualNumber): return DualNumber(self.real + other.real, self.dual + other.dual)
743
+ elif isinstance(other, (int, float)): return DualNumber(self.real + other, self.dual)
744
+ raise TypeError
745
+ def __sub__(self, other):
746
+ if isinstance(other, DualNumber): return DualNumber(self.real - other.real, self.dual - other.dual)
747
+ elif isinstance(other, (int, float)): return DualNumber(self.real - other, self.dual)
748
+ raise TypeError
749
+ def __mul__(self, other):
750
+ if isinstance(other, DualNumber): return DualNumber(self.real * other.real, self.real * other.dual + self.dual * other.real)
751
+ elif isinstance(other, (int, float)): return DualNumber(self.real * other, self.dual * other)
752
+ raise TypeError
753
+ def __rmul__(self, other): return self.__mul__(other)
754
+ def __truediv__(self, other):
755
+ if isinstance(other, (int, float)):
756
+ if other == 0: raise ZeroDivisionError
757
+ return DualNumber(self.real / other, self.dual / other)
758
+ elif isinstance(other, DualNumber):
759
+ if other.real == 0: raise ZeroDivisionError
760
+ return DualNumber(self.real / other.real, (self.dual * other.real - self.real * other.dual) / (other.real ** 2))
761
+ raise TypeError
762
+ def __floordiv__(self, other):
763
+ if isinstance(other, (int, float)):
764
+ if other == 0: raise ZeroDivisionError
765
+ return DualNumber(self.real // other, self.dual // other)
766
+ raise TypeError
767
+ def __eq__(self, other):
768
+ if isinstance(other, DualNumber): return self.real == other.real and self.dual == other.dual
769
+ elif isinstance(other, (int, float)): return self.real == other and self.dual == 0
770
+ return False
771
+ def __str__(self): return f"{self.real} + {self.dual}ε"
772
+ def __repr__(self): return self.__str__() # __repr__ eklenmiş
773
+ def __int__(self): return int(self.real) # int() dönüşümü eklenmiş
774
+ def __radd__(self, other):
775
+ return self.__add__(other) # commutative
776
+ def __rsub__(self, other):
777
+ if isinstance(other, (int, float)):
778
+ return DualNumber(other - self.real, -self.dual)
779
+ return NotImplemented
422
780
 
423
- parts = match.groupdict()
424
- a_part = parts.get('a') or "0"
425
- b_part = parts.get('b')
426
-
427
- if b_part in (None, "", "+"):
428
- b_val = 1.0
429
- elif b_part == "-":
430
- b_val = -1.0
431
- else:
432
- b_val = float(b_part)
433
-
434
- return float(a_part), b_val
781
+ def __neg__(self):
782
+ return DualNumber(-self.real, -self.dual)
435
783
 
436
- def _parse_quaternion(s: str) -> np.quaternion:
437
- """Parses user string ('a+bi+cj+dk' or scalar) into a quaternion."""
438
- s_clean = s.replace(" ", "").lower()
439
- if not s_clean:
440
- raise ValueError("Input cannot be empty.")
784
+ def __hash__(self):
785
+ return hash((self.real, self.dual))
441
786
 
442
- try:
443
- val = float(s_clean)
444
- return np.quaternion(val, val, val, val)
445
- except ValueError:
446
- pass
787
+
788
+ @dataclass
789
+ class SplitcomplexNumber:
790
+ def __init__(self, real, split):
791
+ self.real = float(real)
792
+ self.split = float(split)
793
+
794
+ def __add__(self, other):
795
+ if isinstance(other, SplitcomplexNumber):
796
+ return SplitcomplexNumber(self.real + other.real, self.split + other.split)
797
+ elif isinstance(other, (int, float)):
798
+ return SplitcomplexNumber(self.real + other, self.split)
799
+ return NotImplemented
800
+
801
+ def __sub__(self, other):
802
+ if isinstance(other, SplitcomplexNumber):
803
+ return SplitcomplexNumber(self.real - other.real, self.split - other.split)
804
+ elif isinstance(other, (int, float)):
805
+ return SplitcomplexNumber(self.real - other, self.split)
806
+ return NotImplemented
807
+
808
+ def __mul__(self, other):
809
+ if isinstance(other, SplitcomplexNumber):
810
+ # (a + bj) * (c + dj) = (ac + bd) + (ad + bc)j, çünkü j² = +1
811
+ real = self.real * other.real + self.split * other.split
812
+ split = self.real * other.split + self.split * other.real
813
+ return SplitcomplexNumber(real, split)
814
+ elif isinstance(other, (int, float)):
815
+ return SplitcomplexNumber(self.real * other, self.split * other)
816
+ return NotImplemented
817
+
818
+ def __truediv__(self, other):
819
+ if isinstance(other, (int, float)):
820
+ if other == 0:
821
+ raise ZeroDivisionError("Division by zero")
822
+ return SplitcomplexNumber(self.real / other, self.split / other)
823
+ elif isinstance(other, SplitcomplexNumber):
824
+ # (a + bj) / (c + dj) = ?
825
+ # Payda: (c + dj)(c - dj) = c² - d² (çünkü j² = 1)
826
+ # Yani bölme yalnızca c² ≠ d² ise tanımlıdır.
827
+ a, b = self.real, self.split
828
+ c, d = other.real, other.split
829
+ norm = c * c - d * d
830
+ if abs(norm) < 1e-10:
831
+ raise ZeroDivisionError("Split-complex division by zero (null divisor)")
832
+ real = (a * c - b * d) / norm
833
+ split = (b * c - a * d) / norm
834
+ return SplitcomplexNumber(real, split)
835
+ return NotImplemented
836
+
837
+ def __str__(self):
838
+ return f"{self.real:.2f} + {self.split:.2f}j'"
839
+
840
+ def __repr__(self):
841
+ return f"({self.real}, {self.split}j')"
842
+
843
+
844
+ # Yardımcı fonksiyonlar
845
+ def _extract_numeric_part(s: str) -> str:
846
+ """Bir string'den sadece sayısal kısmı ayıklar.
847
+ Bilimsel gösterimi ve karmaşık formatları destekler.
848
+ """
849
+ s = s.strip()
447
850
 
448
- s_temp = re.sub(r'([+-])([ijk])', r'\g<1>1\g<2>', s_clean)
449
- if s_temp.startswith(('i', 'j', 'k')):
450
- s_temp = '1' + s_temp
851
+ # Bilimsel gösterim için pattern
852
+ scientific_pattern = r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?"
853
+ match = re.match(scientific_pattern, s)
451
854
 
452
- pattern = re.compile(r'([+-]?\d*\.?\d*)([ijk])?')
453
- matches = pattern.findall(s_temp)
855
+ if match:
856
+ return match.group(0)
454
857
 
455
- parts = {'w': 0.0, 'x': 0.0, 'y': 0.0, 'z': 0.0}
456
- for value_str, component in matches:
457
- if not value_str:
458
- continue
459
- value = float(value_str)
460
- if component == 'i':
461
- parts['x'] += value
462
- elif component == 'j':
463
- parts['y'] += value
464
- elif component == 'k':
465
- parts['z'] += value
466
- else:
467
- parts['w'] += value
468
-
469
- return np.quaternion(parts['w'], parts['x'], parts['y'], parts['z'])
470
-
471
- def get_random_type(num_iterations: int, fixed_start_raw: str = "0", fixed_add_base_scalar: float = 9.0) -> List[Any]:
472
- """Generates Keçeci Numbers for a randomly selected type."""
473
- random_type_choice = random.randint(1, 11)
474
- type_names_list = [
475
- "Positive Real", "Negative Real", "Complex", "Float", "Rational",
476
- "Quaternion", "Neutrosophic", "Neutro-Complex", "Hyperreal",
477
- "Bicomplex", "Neutro-Bicomplex"
478
- ]
479
- print(f"\nRandomly selected Keçeci Number Type: {random_type_choice} ({type_names_list[random_type_choice-1]})")
858
+ # Eğer bilimsel gösterim bulunamazsa, basit sayı ara
859
+ simple_match = re.search(r"[-+]?\d*\.?\d+", s)
860
+ if simple_match:
861
+ return simple_match.group(0)
480
862
 
481
- return get_with_params(
482
- kececi_type_choice=random_type_choice,
483
- iterations=num_iterations,
484
- start_value_raw=fixed_start_raw,
485
- add_value_raw=fixed_add_base_scalar
486
- )
863
+ # Hiç sayı bulunamazsa orijinal string'i döndür
864
+ return s
487
865
 
488
- def generate_kececi_vectorial(q0_str, c_str, u_str, iterations):
866
+ def _parse_complex(s: str) -> complex:
867
+ """Bir string'i complex sayıya dönüştürür.
868
+ "real,imag", "real+imag(i/j)", "real", "imag(i/j)" formatlarını destekler.
489
869
  """
490
- Keçeci Haritası' tam vektörel toplama ile üreten geliştirilmiş fonksiyon.
491
- Bu, kütüphanenin ana üretim fonksiyonu olabilir.
492
- Tüm girdileri metin (string) olarak alarak esneklik sağlar.
870
+ s = s.strip().replace('J', 'j').replace('i', 'j') # Hem J hem i yerine j kullan
871
+
872
+ # 1. Eğer "real,imag" formatındaysa
873
+ if ',' in s:
874
+ parts = s.split(',')
875
+ if len(parts) == 2:
876
+ try:
877
+ return complex(float(parts[0]), float(parts[1]))
878
+ except ValueError:
879
+ pass # Devam et
880
+
881
+ # 2. Python'ın kendi complex() dönüştürücüsünü kullanmayı dene (örn: "1+2j", "3j", "-5")
882
+ try:
883
+ return complex(s)
884
+ except ValueError:
885
+ # 3. Sadece real kısmı varsa (örn: "5")
886
+ try:
887
+ return complex(float(s), 0)
888
+ except ValueError:
889
+ # 4. Sadece sanal kısmı varsa (örn: "2j", "j")
890
+ if s.endswith('j'):
891
+ try:
892
+ imag_val = float(s[:-1]) if s[:-1] else 1.0 # "j" -> 1.0j
893
+ return complex(0, imag_val)
894
+ except ValueError:
895
+ pass
896
+
897
+ raise ValueError(f"Geçersiz kompleks sayı formatı: '{s}'")
898
+
899
+ def convert_to_float(value):
900
+ """Convert various Keçeci number types to a float or raise an error if not possible."""
901
+ if isinstance(value, (int, float)):
902
+ return float(value)
903
+ elif hasattr(value, 'real') and hasattr(value, 'imag'):
904
+ return value.real # For complex-like types
905
+ elif hasattr(value, 'w'): # For quaternions or similar
906
+ return value.w # Assuming w is the real part
907
+ elif hasattr(value, 'coeffs') and isinstance(value.coeffs, list): # For Sedenion or similar
908
+ return value.coeffs[0] # Assuming first coefficient is the real part
909
+ elif hasattr(value, 'real_part'): # For DualNumber or similar
910
+ return value.real_part # Assuming this is how you access the real part
911
+ elif hasattr(value, 'value'): # For CliffordNumber or similar
912
+ return value.value # Assuming this returns the appropriate value
913
+ else:
914
+ raise TypeError(f"Cannot convert {type(value).__name__} to float.")
915
+
916
+ def safe_add(added_value, ask_unit, direction):
917
+ """
918
+ Adds ±ask_unit to added_value using native algebraic operations.
919
+
920
+ This function performs: `added_value + (ask_unit * direction)`
921
+ It assumes that both operands support algebraic addition and scalar multiplication.
922
+
923
+ Parameters
924
+ ----------
925
+ added_value : Any
926
+ The base value (e.g., DualNumber, OctonionNumber, CliffordNumber).
927
+ ask_unit : Same type as added_value
928
+ The unit increment to add or subtract.
929
+ direction : int
930
+ Either +1 or -1, determining the sign of the increment.
931
+
932
+ Returns
933
+ -------
934
+ Same type as added_value
935
+ Result of `added_value + (ask_unit * direction)`.
936
+
937
+ Raises
938
+ ------
939
+ TypeError
940
+ If `ask_unit` does not support multiplication by an int,
941
+ or if `added_value` does not support addition with `ask_unit`.
493
942
  """
494
943
  try:
495
- # Girdi metinlerini kuaterniyon nesnelerine dönüştür
496
- w, x, y, z = map(float, q0_str.split(','))
497
- q0 = np.quaternion(w, x, y, z)
498
-
499
- cw, cx, cy, cz = map(float, c_str.split(','))
500
- c = np.quaternion(cw, cx, cy, cz)
944
+ # Scale the unit: ask_unit * (+1 or -1)
945
+ if not hasattr(ask_unit, '__mul__'):
946
+ raise TypeError(f"Type '{type(ask_unit).__name__}' does not support scalar multiplication (missing __mul__).")
947
+ scaled_unit = ask_unit * direction
501
948
 
502
- uw, ux, uy, uz = map(float, u_str.split(','))
503
- u = np.quaternion(uw, ux, uy, uz)
949
+ # Add to the current value
950
+ if not hasattr(added_value, '__add__'):
951
+ raise TypeError(f"Type '{type(added_value).__name__}' does not support addition (missing __add__).")
952
+ result = added_value + scaled_unit
504
953
 
505
- except (ValueError, IndexError):
506
- raise ValueError("Girdi metinleri 'w,x,y,z' formatında olmalıdır.")
954
+ return result
507
955
 
508
- trajectory = [q0]
509
- prime_events = []
510
- current_q = q0
956
+ except Exception as e:
957
+ # Daha açıklayıcı hata mesajı
958
+ msg = f"safe_add failed: Cannot compute {repr(added_value)} + ({direction} * {repr(ask_unit)})"
959
+ raise TypeError(f"{msg} → {type(e).__name__}: {e}") from e
511
960
 
512
- for i in range(iterations):
513
- y = current_q + c
514
- processing_val = y
515
961
 
516
- while True:
517
- scalar_int = int(processing_val.w)
962
+ def _parse_neutrosophic(s: str) -> Tuple[float, float, float]:
963
+ """Parses neutrosophic string into (t, i, f) tuple."""
964
+ s_clean = s.strip().replace(" ", "").upper()
965
+
966
+ # VİRGÜL formatı: t,i,f (3 parametre)
967
+ if ',' in s_clean:
968
+ parts = s_clean.split(',')
969
+ try:
970
+ if len(parts) >= 3:
971
+ return float(parts[0]), float(parts[1]), float(parts[2])
972
+ elif len(parts) == 2:
973
+ return float(parts[0]), float(parts[1]), 0.0
974
+ elif len(parts) == 1:
975
+ return float(parts[0]), 0.0, 0.0
976
+ except ValueError:
977
+ pass
518
978
 
519
- if scalar_int % 2 == 0:
520
- next_q = processing_val / 2.0
521
- break
522
- elif scalar_int % 3 == 0:
523
- next_q = processing_val / 3.0
524
- break
525
- elif is_prime(scalar_int):
526
- if processing_val == y:
527
- prime_events.append((i, scalar_int))
528
- processing_val += u
529
- continue
979
+ # Eski formatları destekle
980
+ try:
981
+ if 'I' in s_clean or 'F' in s_clean:
982
+ # Basit parsing
983
+ t_part = s_clean
984
+ i_val, f_val = 0.0, 0.0
985
+
986
+ if 'I' in s_clean:
987
+ parts = s_clean.split('I')
988
+ t_part = parts[0]
989
+ i_val = float(parts[1]) if parts[1] and parts[1] not in ['', '+', '-'] else 1.0
990
+
991
+ if 'F' in t_part:
992
+ parts = t_part.split('F')
993
+ t_val = float(parts[0]) if parts[0] and parts[0] not in ['', '+', '-'] else 0.0
994
+ f_val = float(parts[1]) if len(parts) > 1 and parts[1] not in ['', '+', '-'] else 1.0
530
995
  else:
531
- next_q = processing_val
532
- break
533
-
534
- trajectory.append(next_q)
535
- current_q = next_q
536
-
537
- return trajectory, prime_events
996
+ t_val = float(t_part) if t_part not in ['', '+', '-'] else 0.0
997
+
998
+ return t_val, i_val, f_val
999
+ else:
1000
+ # Sadece sayısal değer
1001
+ return float(s_clean), 0.0, 0.0
1002
+ except ValueError:
1003
+ return 0.0, 0.0, 0.0 # Default
1004
+
1005
+ def _parse_hyperreal(s: str) -> Tuple[float, float]:
1006
+ """Parses hyperreal string into (finite, infinitesimal) tuple."""
1007
+ s_clean = s.strip().replace(" ", "")
1008
+
1009
+ # VİRGÜL formatı: finite,infinitesimal
1010
+ if ',' in s_clean:
1011
+ parts = s_clean.split(',')
1012
+ if len(parts) >= 2:
1013
+ try:
1014
+ return float(parts[0]), float(parts[1])
1015
+ except ValueError:
1016
+ pass
1017
+ elif len(parts) == 1:
1018
+ try:
1019
+ return float(parts[0]), 0.0
1020
+ except ValueError:
1021
+ pass
1022
+
1023
+ # Eski 'a+be' formatını destekle
1024
+ if 'e' in s_clean:
1025
+ try:
1026
+ parts = s_clean.split('e')
1027
+ finite = float(parts[0]) if parts[0] not in ['', '+', '-'] else 0.0
1028
+ infinitesimal = float(parts[1]) if len(parts) > 1 and parts[1] not in ['', '+', '-'] else 1.0
1029
+ return finite, infinitesimal
1030
+ except ValueError:
1031
+ pass
1032
+
1033
+ # Sadece sayısal değer
1034
+ try:
1035
+ return float(s_clean), 0.0
1036
+ except ValueError:
1037
+ return 0.0, 0.0 # Default
538
1038
 
539
1039
  def _parse_quaternion_from_csv(s: str) -> np.quaternion:
540
- """Parses a comma-separated string 'w,x,y,z' into a quaternion."""
1040
+ """Virgülle ayrılmış string'i Quaternion'a dönüştürür.
1041
+ "w,x,y,z" veya sadece "w" (skaler) formatlarını destekler.
1042
+ """
1043
+ s = s.strip()
1044
+ parts_str = s.split(',')
1045
+
1046
+ # Tüm parçaları float'a dönüştürmeyi dene
541
1047
  try:
542
- parts = [float(p.strip()) for p in s.split(',')]
543
- if len(parts) != 4:
544
- raise ValueError("Girdi 4 bileşen içermelidir.")
545
- # *parts -> (parts[0], parts[1], parts[2], parts[3])
546
- return np.quaternion(*parts)
547
- except (ValueError, IndexError) as e:
548
- raise ValueError(f"Geçersiz virgülle ayrılmış kuaterniyon formatı: '{s}'.") from e
1048
+ parts_float = [float(p.strip()) for p in parts_str]
1049
+ except ValueError:
1050
+ raise ValueError(f"Quaternion bileşenleri sayı olmalı: '{s}'")
549
1051
 
550
- def _load_zeta_zeros(filename="zeta.txt"):
1052
+ if len(parts_float) == 4:
1053
+ return np.quaternion(*parts_float)
1054
+ elif len(parts_float) == 1: # Sadece skaler değer
1055
+ return np.quaternion(parts_float[0], 0, 0, 0)
1056
+ else:
1057
+ raise ValueError(f"Geçersiz quaternion formatı. 1 veya 4 bileşen bekleniyor: '{s}'")
1058
+
1059
+
1060
+ def _has_comma_format(s: str) -> bool:
1061
+ """String'in virgül içerip içermediğini kontrol eder."""
1062
+ return ',' in s
1063
+
1064
+ def _parse_neutrosophic_bicomplex(s: str) -> NeutrosophicBicomplexNumber:
551
1065
  """
552
- Loads Riemann zeta zeros from a text file.
553
- Each line should contain one floating-point number representing the imaginary part of a zeta zero.
554
- Lines that are empty or start with '#' are ignored.
555
- Returns:
556
- numpy.ndarray: Array of zeta zeros, or empty array if file not found.
1066
+ Parses string like "a,b,c,d,e,f,g,h" into 8 components.
557
1067
  """
558
1068
  try:
559
- with open(filename, 'r', encoding='utf-8') as file:
560
- lines = file.readlines()
561
- zeta_zeros = []
562
- for line in lines:
563
- line = line.strip()
564
- if not line or line.startswith("#"):
1069
+ parts = s.split(',')
1070
+ if len(parts) != 8:
1071
+ raise ValueError(f"Expected 8 components, got {len(parts)}")
1072
+ values = [float(part.strip()) for part in parts]
1073
+ return NeutrosophicBicomplexNumber(*values)
1074
+ except Exception as e:
1075
+ raise ValueError(f"Invalid NeutrosophicBicomplex format: '{s}' → {e}")
1076
+
1077
+ def _parse_octonion(s: str) -> OctonionNumber:
1078
+ """'w,x,y,z,e,f,g,h' formatındaki stringi OctonionNumber'a çevirir."""
1079
+ s_clean = s.strip()
1080
+
1081
+ # Eğer virgül içermiyorsa, skaler olarak kabul et
1082
+ if ',' not in s_clean:
1083
+ try:
1084
+ scalar = float(s_clean)
1085
+ return OctonionNumber(scalar, 0, 0, 0, 0, 0, 0, 0)
1086
+ except ValueError:
1087
+ raise ValueError(f"Invalid octonion format: '{s}'")
1088
+
1089
+ # Virgülle ayrılmışsa
1090
+ try:
1091
+ parts = [float(p.strip()) for p in s_clean.split(',')]
1092
+ if len(parts) == 8:
1093
+ return OctonionNumber(*parts) # 8 parametre olarak gönder
1094
+ else:
1095
+ # Eksik veya fazla bileşen için default
1096
+ scalar = parts[0] if parts else 0.0
1097
+ return OctonionNumber(scalar, 0, 0, 0, 0, 0, 0, 0)
1098
+ except ValueError as e:
1099
+ raise ValueError(f"Invalid octonion format: '{s}'") from e
1100
+
1101
+
1102
+ def _parse_sedenion(s: str) -> SedenionNumber:
1103
+ """String'i SedenionNumber'a dönüştürür."""
1104
+ s = s.strip()
1105
+ parts = [p.strip() for p in s.split(',')]
1106
+
1107
+ if len(parts) == 16:
1108
+ try:
1109
+ return SedenionNumber(list(map(float, parts)))
1110
+ except ValueError as e:
1111
+ raise ValueError(f"Geçersiz sedenion bileşen değeri: '{s}' -> {e}") from e
1112
+ elif len(parts) == 1: # Sadece skaler değer girildiğinde
1113
+ try:
1114
+ scalar_val = float(parts[0])
1115
+ return SedenionNumber([scalar_val] + [0.0] * 15)
1116
+ except ValueError as e:
1117
+ raise ValueError(f"Geçersiz skaler sedenion değeri: '{s}' -> {e}") from e
1118
+
1119
+ raise ValueError(f"Sedenion için 16 bileşen veya tek skaler bileşen gerekir. Verilen: '{s}' ({len(parts)} bileşen)")
1120
+
1121
+ def _parse_clifford(s: str) -> CliffordNumber:
1122
+ """Algebraik string'i CliffordNumber'a dönüştürür (ör: '1.0+2.0e1')."""
1123
+ s = s.strip().replace(' ', '')
1124
+ basis_dict = {'': 0.0} # Skaler kısım
1125
+
1126
+ terms_pattern = re.compile(r"([+-]?)(\d*\.?\d+(?:[eE][+-]?\d+)?)?(e\d*)?")
1127
+ remaining_s = s
1128
+
1129
+ while remaining_s:
1130
+ match = terms_pattern.match(remaining_s)
1131
+ if not match or (match.group(2) is None and match.group(3) is None):
1132
+ if remaining_s.startswith('+') or remaining_s.startswith('-'):
1133
+ current_sign = remaining_s[0]
1134
+ remaining_s = remaining_s[1:]
1135
+ if not remaining_s:
1136
+ coeff = 1.0 if current_sign == '+' else -1.0
1137
+ basis_dict[''] = basis_dict.get('', 0.0) + coeff
565
1138
  continue
566
- try:
567
- zeta_zeros.append(float(line))
568
- except ValueError:
569
- print(f"Invalid line skipped: {line}")
570
- print(f"{len(zeta_zeros)} zeta zeros loaded.")
571
- return np.array(zeta_zeros)
572
- except FileNotFoundError:
573
- print(f"'{filename}' not found.")
574
- return np.array([])
1139
+ raise ValueError(f"Geçersiz Clifford terim formatı: '{remaining_s}'")
575
1140
 
1141
+ sign_str, coeff_str, basis_str_with_e = match.groups()
1142
+ current_sign = 1.0
1143
+ if sign_str == '-': current_sign = -1.0
1144
+
1145
+ coeff = 1.0
1146
+ if coeff_str: coeff = float(coeff_str)
1147
+ elif not sign_str: coeff = 1.0
1148
+ elif sign_str and not coeff_str: coeff = 1.0
576
1149
 
577
- def _compute_gue_similarity(sequence, tolerance=0.5):
578
- """
579
- Measures how closely the frequency spectrum of a Keçeci sequence matches the GUE (Gaussian Unitary Ensemble) statistics.
580
- Uses Kolmogorov-Smirnov test against Wigner-Dyson distribution.
581
- Args:
582
- sequence (list): The Keçeci number sequence.
583
- tolerance (float): Not used here; kept for interface consistency.
584
- Returns:
585
- tuple: (similarity_score, p_value)
586
- """
587
- from . import _get_integer_representation
1150
+ coeff *= current_sign
588
1151
 
589
- values = [val for z in sequence if (val := _get_integer_representation(z)) is not None]
590
- if len(values) < 10:
591
- return 0.0, 0.0
1152
+ if basis_str_with_e:
1153
+ basis_key = basis_str_with_e.lstrip('e')
1154
+ basis_dict[basis_key] = basis_dict.get(basis_key, 0.0) + coeff
1155
+ else:
1156
+ basis_dict[''] = basis_dict.get('', 0.0) + coeff
1157
+
1158
+ remaining_s = remaining_s[match.end():]
592
1159
 
593
- values = np.array(values) - np.mean(values)
594
- N = len(values)
595
- powers = np.abs(fft(values))**2
596
- freqs = fftfreq(N)
1160
+ return CliffordNumber(basis_dict)
597
1161
 
598
- mask = (freqs > 0)
599
- freqs_pos = freqs[mask]
600
- powers_pos = powers[mask]
1162
+ def _parse_dual(s: str) -> DualNumber:
1163
+ """Virgülle ayrılmış string'i DualNumber'a dönüştürür."""
1164
+ s = s.strip()
1165
+ parts = [p.strip() for p in s.split(',')]
1166
+
1167
+ # Sadece ilk iki bileşeni al
1168
+ if len(parts) >= 2:
1169
+ try:
1170
+ return DualNumber(float(parts[0]), float(parts[1]))
1171
+ except ValueError:
1172
+ pass
1173
+ elif len(parts) == 1: # Sadece real kısım verilmiş
1174
+ try:
1175
+ return DualNumber(float(parts[0]), 0.0)
1176
+ except ValueError:
1177
+ pass
1178
+
1179
+ raise ValueError(f"Geçersiz Dual sayı formatı: '{s}' (Real, Dual veya sadece Real bekleniyor)")
601
1180
 
602
- if len(powers_pos) == 0:
603
- return 0.0, 0.0
1181
+ def _parse_splitcomplex(s: str) -> SplitcomplexNumber:
1182
+ """Virgülle ayrılmış string'i SplitcomplexNumber'a dönüştürür."""
1183
+ s = s.strip()
1184
+ parts = [p.strip() for p in s.split(',')]
604
1185
 
605
- peaks, _ = find_peaks(powers_pos, height=np.max(powers_pos)*1e-7)
606
- strong_freqs = freqs_pos[peaks]
1186
+ if len(parts) == 2:
1187
+ try:
1188
+ return SplitcomplexNumber(float(parts[0]), float(parts[1]))
1189
+ except ValueError:
1190
+ pass
1191
+ elif len(parts) == 1: # Sadece real kısım verilmiş
1192
+ try:
1193
+ return SplitcomplexNumber(float(parts[0]), 0.0)
1194
+ except ValueError:
1195
+ pass
1196
+
1197
+ raise ValueError(f"Geçersiz Split-Complex sayı formatı: '{s}' (Real, Split veya sadece Real bekleniyor)")
607
1198
 
608
- if len(strong_freqs) < 2:
609
- return 0.0, 0.0
610
1199
 
611
- # Scale so the strongest peak aligns with the first Riemann zeta zero
612
- peak_freq = strong_freqs[np.argmax(powers_pos[peaks])]
613
- scale_factor = 14.134725 / peak_freq
614
- scaled_freqs = np.sort(strong_freqs * scale_factor)
1200
+ class Constants:
1201
+ """Oktonyon sabitleri."""
1202
+ ZERO = OctonionNumber(0, 0, 0, 0, 0, 0, 0, 0)
1203
+ ONE = OctonionNumber(1, 0, 0, 0, 0, 0, 0, 0)
1204
+ I = OctonionNumber(0, 1, 0, 0, 0, 0, 0, 0)
1205
+ J = OctonionNumber(0, 0, 1, 0, 0, 0, 0, 0)
1206
+ K = OctonionNumber(0, 0, 0, 1, 0, 0, 0, 0)
1207
+ E = OctonionNumber(0, 0, 0, 0, 1, 0, 0, 0)
1208
+ F = OctonionNumber(0, 0, 0, 0, 0, 1, 0, 0)
1209
+ G = OctonionNumber(0, 0, 0, 0, 0, 0, 1, 0)
1210
+ H = OctonionNumber(0, 0, 0, 0, 0, 0, 0, 1)
615
1211
 
616
- # Compute level spacings
617
- if len(scaled_freqs) < 2:
618
- return 0.0, 0.0
619
- diffs = np.diff(scaled_freqs)
620
- if np.mean(diffs) == 0:
621
- return 0.0, 0.0
622
- diffs_norm = diffs / np.mean(diffs)
623
1212
 
624
- # Generate GUE sample using Wigner-Dyson distribution
625
- def wigner_dyson(s):
626
- return (32 / np.pi) * s**2 * np.exp(-4 * s**2 / np.pi)
627
1213
 
628
- s_gue = np.linspace(0.01, 3.0, 1000)
629
- p_gue = wigner_dyson(s_gue)
630
- p_gue = p_gue / np.sum(p_gue)
631
- sample_gue = np.random.choice(s_gue, size=1000, p=p_gue)
1214
+ def generate_octonion(w, x, y, z, e, f, g, h):
1215
+ """8 bileşenden bir oktonyon oluşturur."""
1216
+ return OctonionNumber(w, x, y, z, e, f, g, h)
632
1217
 
633
- # Perform KS test
634
- ks_stat, ks_p = ks_2samp(diffs_norm, sample_gue)
635
- similarity_score = 1.0 - ks_stat
1218
+ # Bazı önemli oktonyon sabitleri
1219
+ ZERO = OctonionNumber(0, 0, 0, 0, 0, 0, 0, 0)
1220
+ ONE = OctonionNumber(1, 0, 0, 0, 0, 0, 0, 0)
1221
+ I = OctonionNumber(0, 1, 0, 0, 0, 0, 0, 0)
1222
+ J = OctonionNumber(0, 0, 1, 0, 0, 0, 0, 0)
1223
+ K = OctonionNumber(0, 0, 0, 1, 0, 0, 0, 0)
1224
+ E = OctonionNumber(0, 0, 0, 0, 1, 0, 0, 0)
1225
+ F = OctonionNumber(0, 0, 0, 0, 0, 1, 0, 0)
1226
+ G = OctonionNumber(0, 0, 0, 0, 0, 0, 1, 0)
1227
+ H = OctonionNumber(0, 0, 0, 0, 0, 0, 0, 1)
636
1228
 
637
- return similarity_score, ks_p
1229
+
1230
+ def _parse_quaternion(s: str) -> np.quaternion:
1231
+ """Parses user string ('a+bi+cj+dk' or scalar) into a quaternion."""
1232
+ s_clean = s.replace(" ", "").lower()
1233
+ if not s_clean:
1234
+ raise ValueError("Input cannot be empty.")
1235
+
1236
+ try:
1237
+ val = float(s_clean)
1238
+ return np.quaternion(val, val, val, val)
1239
+ except ValueError:
1240
+ pass
1241
+
1242
+ s_temp = re.sub(r'([+-])([ijk])', r'\g<1>1\g<2>', s_clean)
1243
+ if s_temp.startswith(('i', 'j', 'k')):
1244
+ s_temp = '1' + s_temp
1245
+
1246
+ pattern = re.compile(r'([+-]?\d*\.?\d*)([ijk])?')
1247
+ matches = pattern.findall(s_temp)
1248
+
1249
+ parts = {'w': 0.0, 'x': 0.0, 'y': 0.0, 'z': 0.0}
1250
+ for value_str, component in matches:
1251
+ if not value_str:
1252
+ continue
1253
+ value = float(value_str)
1254
+ if component == 'i':
1255
+ parts['x'] += value
1256
+ elif component == 'j':
1257
+ parts['y'] += value
1258
+ elif component == 'k':
1259
+ parts['z'] += value
1260
+ else:
1261
+ parts['w'] += value
1262
+
1263
+ return np.quaternion(parts['w'], parts['x'], parts['y'], parts['z'])
1264
+
1265
+ def get_random_type(num_iterations: int, fixed_start_raw: str = "0", fixed_add_base_scalar: float = 9.0) -> List[Any]:
1266
+ """Generates Keçeci Numbers for a randomly selected type."""
1267
+ random_type_choice = random.randint(1, 16)
1268
+ type_names_list = [
1269
+ "Positive Real", "Negative Real", "Complex", "Float", "Rational",
1270
+ "Quaternion", "Neutrosophic", "Neutro-Complex", "Hyperreal",
1271
+ "Bicomplex", "Neutro-Bicomplex", "Octonion", "Sedenion", "Clifford", "Dual", "Split-Complex",
1272
+ ]
1273
+ print(f"\nRandomly selected Keçeci Number Type: {random_type_choice} ({type_names_list[random_type_choice-1]})")
1274
+
1275
+ return get_with_params(
1276
+ kececi_type_choice=random_type_choice,
1277
+ iterations=num_iterations,
1278
+ start_value_raw=fixed_start_raw,
1279
+ add_value_raw=fixed_add_base_scalar
1280
+ )
1281
+
1282
+ def find_kececi_prime_number(kececi_numbers_list: List[Any]) -> Optional[int]:
1283
+ """Finds the Keçeci Prime Number from a generated sequence."""
1284
+ if not kececi_numbers_list:
1285
+ return None
1286
+
1287
+ integer_prime_reps = [
1288
+ rep for num in kececi_numbers_list
1289
+ if is_prime(num) and (rep := _get_integer_representation(num)) is not None
1290
+ ]
1291
+
1292
+ if not integer_prime_reps:
1293
+ return None
1294
+
1295
+ counts = collections.Counter(integer_prime_reps)
1296
+ repeating_primes = [(freq, prime) for prime, freq in counts.items() if freq > 1]
1297
+ if not repeating_primes:
1298
+ return None
1299
+
1300
+ _, best_prime = max(repeating_primes)
1301
+ return best_prime
1302
+
1303
+ def print_detailed_report(sequence: List[Any], params: Dict[str, Any]):
1304
+ """Generates and prints a detailed report of the sequence results."""
1305
+ if not sequence:
1306
+ print("\n--- REPORT ---\nSequence could not be generated.")
1307
+ return
1308
+
1309
+ print("\n\n" + "="*50)
1310
+ print("--- DETAILED SEQUENCE REPORT ---")
1311
+ print("="*50)
1312
+
1313
+ print("\n[Parameters Used]")
1314
+ print(f" - Keçeci Type: {params.get('type_name', 'N/A')} ({params['type_choice']})")
1315
+ print(f" - Start Value: '{params['start_val']}'")
1316
+ print(f" - Increment: {params['add_val']}")
1317
+ print(f" - Keçeci Steps: {params['steps']}")
1318
+
1319
+ print("\n[Sequence Summary]")
1320
+ print(f" - Total Numbers Generated: {len(sequence)}")
1321
+
1322
+ kpn = find_kececi_prime_number(sequence)
1323
+ print(f" - Keçeci Prime Number (KPN): {kpn if kpn is not None else 'Not found'}")
1324
+
1325
+ print("\n[Sequence Preview]")
1326
+ preview_count = min(len(sequence), 40)
1327
+ print(f" --- First {preview_count} Numbers ---")
1328
+ for i in range(preview_count):
1329
+ print(f" {i}: {sequence[i]}")
1330
+
1331
+ if len(sequence) > preview_count:
1332
+ print(f"\n --- Last {preview_count} Numbers ---")
1333
+ for i in range(len(sequence) - preview_count, len(sequence)):
1334
+ print(f" {i}: {sequence[i]}")
1335
+
1336
+ print("\n" + "="*50)
1337
+
1338
+ while True:
1339
+ show_all = input("Do you want to print the full sequence? (y/n): ").lower().strip()
1340
+ if show_all in ['y', 'n']:
1341
+ break
1342
+
1343
+ if show_all == 'y':
1344
+ print("\n--- FULL SEQUENCE ---")
1345
+ for i, num in enumerate(sequence):
1346
+ print(f"{i}: {num}")
1347
+ print("="*50)
1348
+
1349
+
1350
+ def _is_divisible(value: Any, divisor: int, kececi_type: int) -> bool:
1351
+ TOLERANCE = 1e-12
1352
+
1353
+ try:
1354
+ if kececi_type == TYPE_DUAL:
1355
+ if isinstance(value, DualNumber):
1356
+ return math.isclose(value.real % divisor, 0.0, abs_tol=TOLERANCE)
1357
+ return math.isclose(value % divisor, 0.0, abs_tol=TOLERANCE)
1358
+ elif kececi_type in [TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL]:
1359
+ # Tam sayılar için, sadece int tipinde ve kalansız bölünebilir mi
1360
+ # float değerlerin int'e yuvarlanarak kontrol edilmesi gerekebilir
1361
+ if isinstance(value, (int, float)) and is_near_integer(value):
1362
+ return int(round(float(value))) % divisor == 0
1363
+ return False
1364
+ elif kececi_type == TYPE_FLOAT:
1365
+ mod = value % divisor
1366
+ return math.isclose(mod, 0.0, abs_tol=TOLERANCE)
1367
+ elif kececi_type == TYPE_RATIONAL:
1368
+ quotient = value / divisor
1369
+ return quotient.denominator == 1
1370
+ elif kececi_type == TYPE_COMPLEX:
1371
+ real_mod = value.real % divisor
1372
+ imag_mod = value.imag % divisor
1373
+ return (math.isclose(real_mod, 0.0, abs_tol=TOLERANCE) and
1374
+ math.isclose(imag_mod, 0.0, abs_tol=TOLERANCE))
1375
+ elif kececi_type == TYPE_QUATERNION:
1376
+ components = [value.w, value.x, value.y, value.z]
1377
+ return all(math.isclose(c % divisor, 0.0, abs_tol=TOLERANCE) for c in components)
1378
+ elif kececi_type == TYPE_NEUTROSOPHIC:
1379
+ return (math.isclose(value.a % divisor, 0.0, abs_tol=TOLERANCE) and
1380
+ math.isclose(value.b % divisor, 0.0, abs_tol=TOLERANCE))
1381
+ elif kececi_type == TYPE_NEUTROSOPHIC_COMPLEX:
1382
+ components = [value.real, value.imag, value.indeterminacy]
1383
+ return all(math.isclose(c % divisor, 0.0, abs_tol=TOLERANCE) for c in components)
1384
+ elif kececi_type == TYPE_HYPERREAL:
1385
+ return all(math.isclose(x % divisor, 0.0, abs_tol=TOLERANCE) for x in value.sequence)
1386
+ elif kececi_type == TYPE_BICOMPLEX:
1387
+ return (_is_divisible(value.z1, divisor, TYPE_COMPLEX) and
1388
+ _is_divisible(value.z2, divisor, TYPE_COMPLEX))
1389
+ elif kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX:
1390
+ components = [
1391
+ value.a, value.b, value.c, value.d,
1392
+ value.e, value.f, value.g, value.h
1393
+ ]
1394
+ return all(math.isclose(c % divisor, 0.0, abs_tol=TOLERANCE) for c in components)
1395
+ elif kececi_type == TYPE_OCTONION:
1396
+ components = [
1397
+ value.w, value.x, value.y, value.z,
1398
+ value.e, value.f, value.g, value.h
1399
+ ]
1400
+ return all(math.isclose(c % divisor, 0.0, abs_tol=TOLERANCE) for c in components)
1401
+ elif kececi_type == TYPE_SEDENION:
1402
+ if hasattr(value, 'coeffs'):
1403
+ coeffs = value.coeffs
1404
+ else:
1405
+ coeffs = list(value)
1406
+ return all(math.isclose(c % divisor, 0.0, abs_tol=TOLERANCE) for c in coeffs)
1407
+ elif kececi_type == TYPE_CLIFFORD:
1408
+ if hasattr(value, 'basis') and isinstance(value.basis, dict):
1409
+ components = value.basis.values()
1410
+ else:
1411
+ components = []
1412
+ return all(math.isclose(c % divisor, 0.0, abs_tol=TOLERANCE) for c in components)
1413
+ elif kececi_type == TYPE_SPLIT_COMPLEX:
1414
+ real_mod = value.real % divisor
1415
+ split_mod = value.split % divisor
1416
+ return (math.isclose(real_mod, 0.0, abs_tol=TOLERANCE) and
1417
+ math.isclose(split_mod, 0.0, abs_tol=TOLERANCE))
1418
+ else:
1419
+ return False
1420
+ except (TypeError, AttributeError, ValueError, ZeroDivisionError):
1421
+ return False
1422
+
1423
+ def _get_integer_representation(n_input: Any) -> Optional[int]:
1424
+ """Extracts the primary integer component from any supported number type."""
1425
+ try:
1426
+ if isinstance(n_input, (int, float, Fraction)):
1427
+ # is_near_integer kontrolü eklendi, çünkü float'tan int'e direkt dönüş hassasiyet sorunları yaratabilir
1428
+ if is_near_integer(n_input):
1429
+ return abs(int(round(float(n_input))))
1430
+ return None # Tam sayıya yakın değilse None döndür
1431
+
1432
+ if isinstance(n_input, complex):
1433
+ if is_near_integer(n_input.real):
1434
+ return abs(int(round(n_input.real)))
1435
+ return None
1436
+
1437
+ # NumPy Quaternion özel kontrolü
1438
+ if hasattr(np, 'quaternion') and isinstance(n_input, np.quaternion):
1439
+ if is_near_integer(n_input.w):
1440
+ return abs(int(round(n_input.w)))
1441
+ return None
1442
+
1443
+ # Keçeci Sayı Tipleri
1444
+ if isinstance(n_input, NeutrosophicNumber):
1445
+ if is_near_integer(n_input.t):
1446
+ return abs(int(round(n_input.t)))
1447
+ return None
1448
+
1449
+ if isinstance(n_input, NeutrosophicComplexNumber):
1450
+ if is_near_integer(n_input.real):
1451
+ return abs(int(round(n_input.real)))
1452
+ return None
1453
+
1454
+ if isinstance(n_input, HyperrealNumber):
1455
+ if n_input.sequence and is_near_integer(n_input.sequence[0]):
1456
+ return abs(int(round(n_input.sequence[0])))
1457
+ return None
1458
+
1459
+ if isinstance(n_input, BicomplexNumber):
1460
+ if is_near_integer(n_input.z1.real):
1461
+ return abs(int(round(n_input.z1.real)))
1462
+ return None
1463
+
1464
+ if isinstance(n_input, NeutrosophicBicomplexNumber):
1465
+ if is_near_integer(n_input.real): # Varsayım: .real metodu var
1466
+ return abs(int(round(n_input.real)))
1467
+ return None
1468
+
1469
+ if isinstance(n_input, OctonionNumber):
1470
+ if is_near_integer(n_input.w):
1471
+ return abs(int(round(n_input.w)))
1472
+ return None
1473
+
1474
+ if isinstance(n_input, SedenionNumber):
1475
+ if n_input.coefficients and is_near_integer(n_input.coefficients[0]):
1476
+ return abs(int(round(n_input.coefficients[0])))
1477
+ return None
1478
+
1479
+ if isinstance(n_input, CliffordNumber):
1480
+ scalar_part = n_input.basis.get('', 0)
1481
+ if is_near_integer(scalar_part):
1482
+ return abs(int(round(scalar_part)))
1483
+ return None
1484
+
1485
+ if isinstance(n_input, DualNumber):
1486
+ if is_near_integer(n_input.real):
1487
+ return abs(int(round(n_input.real)))
1488
+ return None
1489
+
1490
+ if isinstance(n_input, SplitcomplexNumber):
1491
+ if is_near_integer(n_input.real):
1492
+ return abs(int(round(n_input.real)))
1493
+ return None
1494
+
1495
+ # Fallback (Bu satırın çoğu durumda ulaşılmaması beklenir)
1496
+ if is_near_integer(n_input):
1497
+ return abs(int(round(float(n_input))))
1498
+ return None
1499
+
1500
+ except (ValueError, TypeError, IndexError, AttributeError):
1501
+ return None
638
1502
 
639
1503
 
640
- def _find_kececi_zeta_zeros(sequence, tolerance=0.5):
1504
+ def is_prime(n_input: Any) -> bool:
641
1505
  """
642
- Estimates the zeros of the Keçeci Zeta Function from the spectral peaks of the sequence.
643
- Compares them to known Riemann zeta zeros.
644
- Args:
645
- sequence (list): The Keçeci number sequence.
646
- tolerance (float): Maximum distance for a match between Keçeci and Riemann zeros.
647
- Returns:
648
- tuple: (list of Keçeci zeta zeros, matching score)
1506
+ Checks if a given number (or its principal component) is prime
1507
+ using the robust sympy.isprime function.
649
1508
  """
650
- from . import _get_integer_representation
651
-
652
- values = [val for z in sequence if (val := _get_integer_representation(z)) is not None]
653
- if len(values) < 10:
654
- return [], 0.0
1509
+ # Adım 1: Karmaşık sayı türünden tamsayıyı çıkarma (Bu kısım aynı kalıyor)
1510
+ value_to_check = _get_integer_representation(n_input)
655
1511
 
656
- values = np.array(values) - np.mean(values)
657
- N = len(values)
658
- powers = np.abs(fft(values))**2
659
- freqs = fftfreq(N)
1512
+ # Adım 2: Tamsayı geçerli değilse False döndür
1513
+ if value_to_check is None:
1514
+ return False
1515
+
1516
+ # Adım 3: Asallık testini sympy'ye bırak
1517
+ # sympy.isprime, 2'den küçük sayılar (1, 0, negatifler) için zaten False döndürür.
1518
+ return sympy.isprime(value_to_check)
660
1519
 
661
- mask = (freqs > 0)
662
- freqs_pos = freqs[mask]
663
- powers_pos = powers[mask]
664
1520
 
665
- if len(powers_pos) == 0:
666
- return [], 0.0
1521
+ def is_near_integer(x, tol=1e-12):
1522
+ """
1523
+ Checks if a number (or its real part) is close to an integer.
1524
+ Useful for float-based primality and divisibility checks.
1525
+ """
1526
+ try:
1527
+ if isinstance(x, complex):
1528
+ # Sadece gerçek kısım önemli, imajiner sıfıra yakın olmalı
1529
+ if abs(x.imag) > tol:
1530
+ return False
1531
+ x = x.real
1532
+ elif isinstance(x, (list, tuple)):
1533
+ return False # Desteklenmeyen tip
1534
+
1535
+ # Genel durum: float veya int
1536
+ x = float(x)
1537
+ return abs(x - round(x)) < tol
1538
+ except:
1539
+ return False
667
1540
 
668
- peaks, _ = find_peaks(powers_pos, height=np.max(powers_pos)*1e-7)
669
- strong_freqs = freqs_pos[peaks]
1541
+ def is_prime_like(value, kececi_type: int) -> bool:
1542
+ """
1543
+ Checks if the value should be treated as a "prime" in Keçeci logic,
1544
+ by examining its principal (scalar/real) component.
1545
+ """
1546
+ try:
1547
+ if kececi_type == TYPE_DUAL:
1548
+ if isinstance(value, DualNumber):
1549
+ return is_prime(int(value.real))
1550
+ else:
1551
+ return is_prime(int(value))
1552
+ elif kececi_type in [TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL, TYPE_FLOAT]:
1553
+ if is_near_integer(value):
1554
+ n = int(round(float(value)))
1555
+ return is_prime(n)
1556
+ return False
1557
+ elif kececi_type == TYPE_COMPLEX:
1558
+ if is_near_integer(value.real):
1559
+ return is_prime(value.real)
1560
+ return False
1561
+ elif kececi_type == TYPE_SPLIT_COMPLEX:
1562
+ if is_near_integer(value.real):
1563
+ return is_prime(value.real)
1564
+ return False
1565
+ elif kececi_type in [TYPE_QUATERNION, TYPE_OCTONION, TYPE_SEDENION]:
1566
+ scalar = getattr(value, 'w', None) # Quaternion için .w, diğerleri için de varsa
1567
+ if scalar is None and hasattr(value, 'coeffs') and value.coeffs: # Sedenion için
1568
+ scalar = value.coeffs[0]
1569
+ if scalar is None and hasattr(value, 'coefficients') and value.coefficients: # Alternatif Sedenion için
1570
+ scalar = value.coefficients[0]
1571
+ if scalar is not None and is_near_integer(scalar):
1572
+ return is_prime(scalar)
1573
+ return False
1574
+ elif kececi_type == TYPE_CLIFFORD:
1575
+ scalar = value.basis.get('', 0.0)
1576
+ if is_near_integer(scalar):
1577
+ return is_prime(scalar)
1578
+ return False
1579
+ else: # Diğer tipler için genel kural, önceki else bloğu yerine
1580
+ main_part = getattr(value, 'real', None)
1581
+ if main_part is None:
1582
+ main_part = getattr(value, 'a', None) # Neutrosophic için
1583
+ if main_part is None:
1584
+ main_part = getattr(value, 'w', None) # Diğer bazı tipler için
1585
+ if main_part is not None and is_near_integer(main_part):
1586
+ return is_prime(main_part)
1587
+ return False
1588
+ except Exception as e: # Geniş yakalama yerine spesifik yakalama önerilir
1589
+ # print(f"Error in is_prime_like: {e}") # Hata ayıklama için
1590
+ return False
670
1591
 
671
- if len(strong_freqs) < 2:
672
- return [], 0.0
1592
+ def generate_kececi_vectorial(q0_str, c_str, u_str, iterations):
1593
+ """
1594
+ Keçeci Haritası'nı tam vektörel toplama ile üreten geliştirilmiş fonksiyon.
1595
+ Bu, kütüphanenin ana üretim fonksiyonu olabilir.
1596
+ Tüm girdileri metin (string) olarak alarak esneklik sağlar.
1597
+ """
1598
+ try:
1599
+ # Girdi metinlerini kuaterniyon nesnelerine dönüştür
1600
+ w, x, y, z = map(float, q0_str.split(','))
1601
+ q0 = np.quaternion(w, x, y, z)
1602
+
1603
+ cw, cx, cy, cz = map(float, c_str.split(','))
1604
+ c = np.quaternion(cw, cx, cy, cz)
673
1605
 
674
- # Scale so the strongest peak aligns with the first Riemann zeta zero
675
- peak_freq = strong_freqs[np.argmax(powers_pos[peaks])]
676
- scale_factor = 14.134725 / peak_freq
677
- scaled_freqs = np.sort(strong_freqs * scale_factor)
1606
+ uw, ux, uy, uz = map(float, u_str.split(','))
1607
+ u = np.quaternion(uw, ux, uy, uz)
678
1608
 
679
- # Find candidate zeros by analyzing the Keçeci Zeta Function
680
- t_vals = np.linspace(0, 650, 10000)
681
- zeta_vals = np.array([sum((scaled_freqs + 1e-10)**(- (0.5 + 1j * t))) for t in t_vals])
682
- minima, _ = find_peaks(-np.abs(zeta_vals), height=-0.5*np.max(np.abs(zeta_vals)), distance=5)
683
- kececi_zeta_zeros = t_vals[minima]
1609
+ except (ValueError, IndexError):
1610
+ raise ValueError("Girdi metinleri 'w,x,y,z' formatında olmalıdır.")
684
1611
 
685
- # Load Riemann zeta zeros for comparison
686
- zeta_zeros_imag = _load_zeta_zeros("zeta.txt")
687
- if len(zeta_zeros_imag) == 0:
688
- return kececi_zeta_zeros, 0.0
1612
+ trajectory = [q0]
1613
+ prime_events = []
1614
+ current_q = q0
689
1615
 
690
- # Calculate matching score
691
- close_matches = [kz for kz in kececi_zeta_zeros if min(abs(kz - zeta_zeros_imag)) < tolerance]
692
- score = len(close_matches) / len(kececi_zeta_zeros) if kececi_zeta_zeros.size > 0 else 0.0
1616
+ for i in range(iterations):
1617
+ y = current_q + c
1618
+ processing_val = y
693
1619
 
694
- return kececi_zeta_zeros, score
1620
+ while True:
1621
+ scalar_int = int(processing_val.w)
695
1622
 
1623
+ if scalar_int % 2 == 0:
1624
+ next_q = processing_val / 2.0
1625
+ break
1626
+ elif scalar_int % 3 == 0:
1627
+ next_q = processing_val / 3.0
1628
+ break
1629
+ elif is_prime(scalar_int):
1630
+ if processing_val == y:
1631
+ prime_events.append((i, scalar_int))
1632
+ processing_val += u
1633
+ continue
1634
+ else:
1635
+ next_q = processing_val
1636
+ break
1637
+
1638
+ trajectory.append(next_q)
1639
+ current_q = next_q
1640
+
1641
+ return trajectory, prime_events
696
1642
 
697
- def analyze_all_types(iterations=120):
1643
+ def analyze_all_types(iterations=120, additional_params=None):
698
1644
  """
699
- Performs automated analysis on all 11 Keçeci number types.
700
- For each type, it tests multiple parameter sets, computes similarity to Riemann zeta zeros and GUE statistics,
701
- then reports and plots the results.
1645
+ Performs automated analysis on all Keçeci number types.
702
1646
  Args:
703
1647
  iterations (int): Number of Keçeci steps to generate for each sequence.
1648
+ additional_params (list): List of tuples for additional parameter sets.
704
1649
  Returns:
705
1650
  tuple: (sorted_by_zeta, sorted_by_gue) - Lists of results sorted by performance.
706
1651
  """
1652
+
707
1653
  from . import (
1654
+ NeutrosophicNumber,
1655
+ NeutrosophicComplexNumber,
1656
+ HyperrealNumber,
1657
+ BicomplexNumber,
1658
+ NeutrosophicBicomplexNumber,
1659
+ OctonionNumber,
1660
+ SedenionNumber,
1661
+ CliffordNumber,
1662
+ DualNumber,
1663
+ SplitcomplexNumber,
1664
+ analyze_all_types,
708
1665
  get_with_params,
709
- TYPE_POSITIVE_REAL,
710
- TYPE_NEGATIVE_REAL,
711
- TYPE_COMPLEX,
712
- TYPE_FLOAT,
713
- TYPE_RATIONAL,
714
- TYPE_QUATERNION,
715
- TYPE_NEUTROSOPHIC,
716
- TYPE_NEUTROSOPHIC_COMPLEX,
717
- TYPE_HYPERREAL,
718
- TYPE_BICOMPLEX,
719
- TYPE_NEUTROSOPHIC_BICOMPLEX
1666
+ _find_kececi_zeta_zeros,
1667
+ _compute_gue_similarity,
1668
+ _plot_comparison,
720
1669
  )
721
-
722
- print("Automated Analysis for 11 Keçeci Types")
1670
+
1671
+ print("Automated Analysis for Keçeci Types")
723
1672
  print("=" * 80)
724
1673
 
725
1674
  include_intermediate = True
726
1675
  results = []
727
1676
 
1677
+ # Default parameter sets
728
1678
  # Parameter sets to test
729
1679
  param_sets = [
730
- ('0.0', '9.0'),
731
- ('1.0', '7.0'),
732
- ('2.0', '5.0'),
733
- ('3.0', '11.0'),
734
- ('1+1j', '9.0'),
735
- ('0.0001412', '0.037')
1680
+ # 1. Positive Real - SADECE sayısal değerler
1681
+ ('5.0', '2.0'),
1682
+ ('10', '3.0'),
1683
+ ('0.0', '1.5'),
1684
+ ('3.14', '0.5'),
1685
+
1686
+ # 2. Negative Real - SADECE sayısal değerler
1687
+ ('-3.0', '-1.0'),
1688
+ ('-5.0', '-2.0'),
1689
+ ('-1.5', '-0.5'),
1690
+ ('-2.718', '-1.0'),
1691
+
1692
+ # 3. Complex - DOĞRU formatında
1693
+ ('1+2j', '0.5+0.5j'),
1694
+ ('3-4j', '1-2j'),
1695
+ ('0.0+0.0j', '1.0+2.0j'),
1696
+ ('-1.5+2.5j', '0.2-0.3j'),
1697
+
1698
+ # Diğer complex örnekleri
1699
+ ('2j', '1j'), # Sadece imaginary
1700
+ ('-3j', '-2j'), # Negatif imaginary
1701
+ ('1.5', '0.5'), # Sadece real (otomatik complex olur)
1702
+ ('0+1j', '0+0.5j'), # Explicit format
1703
+
1704
+ # 4. Float - SADECE sayısal değerler
1705
+ ('0.0001412', '0.037'),
1706
+ ('3.14159', '0.01'),
1707
+ ('2.71828', '0.1'),
1708
+ ('0.0', '0.001'),
1709
+
1710
+ # 5. Rational - SADECE sayısal/rational değerler
1711
+ ('1/2', '1/4'),
1712
+ ('3/4', '1/8'),
1713
+ ('0', '2/3'),
1714
+ ('5/6', '1/12'),
1715
+
1716
+ # 6. Quaternion - VİRGÜL formatında
1717
+ ('1.0,0.0,0.0,0.0', '0.1,0.0,0.0,0.0'), # Scalar addition
1718
+ ('0.0,1.0,0.0,0.0', '0.0,0.1,0.0,0.0'), # i component
1719
+ ('0.0,0.0,1.0,0.0', '0.0,0.0,0.1,0.0'), # j component
1720
+ ('0.0,0.0,0.0,1.0', '0.0,0.0,0.0,0.1'), # k component
1721
+ ('0.5,0.5,0.5,0.5', '0.05,0.05,0.05,0.05'), # All components
1722
+ ('1.0', '0.5'), # Sadece skaler (otomatik 0,0,0 eklenir)
1723
+ ('2.0,3.0,4.0,5.0', '0.1,-0.2,0.3,-0.4'), # Karışık değerler
1724
+
1725
+ # 7. Neutrosophic - DOĞRU formatında (t, i, f)
1726
+ ('0.8,0.1,0.1', '0.0,0.05,0.0'),
1727
+ ('0.6,0.2,0.2', '0.1,0.0,0.0'),
1728
+ ('0.9,0.05,0.05', '0.0,0.0,0.02'),
1729
+ ('0.7,0.15,0.15', '0.05,0.0,0.0'),
1730
+ ('3.0', '0.5'), # Sadece T değeri
1731
+ ('1.0,0.0,0.0', '0.2'), # TIF ve sadece T değeri
1732
+
1733
+ # 8. Neutro-Complex - Format: "complex_part_str,t,i"
1734
+ # complex_part_str, t, i
1735
+ ('1.0+2.0j,0.5,0.2', '0.1+0.1j,0.0,0.1'),
1736
+ ('0.0+1.0j,1.0,0.3', '0.1+0.0j,0.0,0.0'),
1737
+ ('2.0,0.0,0.1', '0.0+0.5j,0.5,0.0'), # complex_part olarak sadece real
1738
+ ('0.5+0.5j,0.5,0.4', '0.1+0.1j,0.1,0.05'),
1739
+ ('1+2j', '0.5+0.5j'), # Sadece complex kısım, diğerleri varsayılan 0
1740
+
1741
+ # 9. Hyperreal - VİRGÜL formatında: finite,infinitesimal
1742
+ ('3.0,0.001', '0.1,0.0001'),
1743
+ ('0.0,0.0005', '1.0,0.0'),
1744
+ ('2.0', '0.5'), # Sadece finite kısmı
1745
+ ('1.0,0.0', '0.001'), # Finite, Infinitesimal ve sadece finite
1746
+
1747
+ # 10. Bicomplex - Format: "z1_str,z2_str"
1748
+ ('1.0+0.5j,0.2+0.1j', '0.1+0.0j,0.0+0.0j'),
1749
+ ('2.0,3.0j', '0.5,0.1j'), # z1 sadece real, z2 sadece imag
1750
+ ('1+2j', '0.5'), # Sadece z1, z2 ve increment sadece real
1751
+
1752
+ # 11. Neutrosophic Bicomplex - 8 PARÇALI VİRGÜL: r1,i1,r2,i2,T,I,F,G
1753
+ ('1.0,2.0,0.1,0.2,0.3,0.4,0.5,0.6', '0.1,0.0,0.0,0.0,0.0,0.0,0.0,0.0'),
1754
+ ('1.0', '0.5'), # Sadece skaler
1755
+
1756
+ # 12. Octonion - 8 PARÇALI VİRGÜL
1757
+ ('1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0', '0.1,0.0,0.0,0.0,0.0,0.0,0.0,0.0'),
1758
+ ('1.0', '0.5'), # Sadece skaler
1759
+ ('2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0', '0.1,-0.2,0.3,-0.4,0.5,-0.6,0.7,-0.8'),
1760
+
1761
+ # 13. Sedenion - 16 PARÇALI VİRGÜL
1762
+ ('1.0' + ',0.0'*15, '0.1' + ',0.0'*15),
1763
+ ('1.0', '0.1'), # Sadece skaler
1764
+
1765
+ # 14. Clifford - ALGEBRAIC format: scalar+e1+e2+e12
1766
+ ('1.0+2.0e1', '0.1+0.2e1'),
1767
+ ('2.0e1+3.0e12', '0.1e1-0.2e12'),
1768
+ ('5.0', '0.5'), # Sadece skaler
1769
+ ('-1.0e1', '2.0e1'),
1770
+
1771
+ # 15. Dual - VİRGÜL formatında: real,dual
1772
+ ('2.0,0.5', '0.1,0.0'),
1773
+ ('1.0', '0.5'), # Sadece real kısım
1774
+ ('3.0,1.0', '0.2'),
1775
+
1776
+ # 16. Split-Complex - VİRGÜL formatında: real,split
1777
+ ('1.0,0.8', '0.1,0.0'),
1778
+ ('2.0', '0.3'), # Sadece real kısım
1779
+ ('4.0,1.0', '0.5'),
736
1780
  ]
737
1781
 
1782
+ # If additional parameters are provided, extend the default set
1783
+ if additional_params:
1784
+ param_sets.extend(additional_params)
1785
+
738
1786
  type_names = {
739
1787
  1: "Positive Real",
740
1788
  2: "Negative Real",
@@ -746,11 +1794,16 @@ def analyze_all_types(iterations=120):
746
1794
  8: "Neutro-Complex",
747
1795
  9: "Hyperreal",
748
1796
  10: "Bicomplex",
749
- 11: "Neutro-Bicomplex"
1797
+ 11: "Neutro-Bicomplex",
1798
+ 12: "Octonion",
1799
+ 13: "Sedenion",
1800
+ 14: "Clifford",
1801
+ 15: "Dual",
1802
+ 16: "Split-Complex",
750
1803
  }
751
1804
 
752
- for kececi_type in range(1, 12):
753
- name = type_names[kececi_type]
1805
+ for kececi_type in range(1, 16):
1806
+ name = type_names.get(kececi_type, "Unknown Type")
754
1807
  best_zeta_score = 0.0
755
1808
  best_gue_score = 0.0
756
1809
  best_params = None
@@ -774,6 +1827,7 @@ def analyze_all_types(iterations=120):
774
1827
  )
775
1828
 
776
1829
  if not sequence or len(sequence) < 50:
1830
+ print(f"Skipped type {kececi_type} with params {start}, {add}: insufficient sequence length")
777
1831
  continue
778
1832
 
779
1833
  _, zeta_score = _find_kececi_zeta_zeros(sequence, tolerance=0.5)
@@ -785,6 +1839,7 @@ def analyze_all_types(iterations=120):
785
1839
  best_params = (start, add)
786
1840
 
787
1841
  except Exception as e:
1842
+ print(f"Error analyzing type {kececi_type} with params {start}, {add}: {e}")
788
1843
  continue
789
1844
 
790
1845
  if best_params:
@@ -797,31 +1852,142 @@ def analyze_all_types(iterations=120):
797
1852
  'gue_score': best_gue_score
798
1853
  })
799
1854
 
800
- # Sort results
1855
+ # Sort and display results
801
1856
  sorted_by_zeta = sorted(results, key=lambda x: x['zeta_score'], reverse=True)
802
1857
  sorted_by_gue = sorted(results, key=lambda x: x['gue_score'], reverse=True)
803
1858
 
804
- print("\n" + "=" * 100)
805
- print("HIGHEST RIEMANN ZETA MATCHING SCORES (TOP 11)")
806
- print("=" * 100)
807
- print(f"{'Type':<20} {'Score':<8} {'Start':<12} {'Increment':<12}")
808
- print("-" * 100)
809
- for r in sorted_by_zeta:
1859
+ print("\nHIGHEST RIEMANN ZETA MATCHING SCORES (TOP 12)")
1860
+ print("=" * 80)
1861
+ for r in sorted_by_zeta[:12]:
810
1862
  print(f"{r['name']:<20} {r['zeta_score']:<8.3f} {r['start']:<12} {r['add']:<12}")
811
1863
 
812
- print("\n" + "=" * 100)
813
- print("HIGHEST GUE SIMILARITY SCORES (TOP 11)")
814
- print("=" * 100)
815
- print(f"{'Type':<20} {'Score':<8} {'Start':<12} {'Increment':<12}")
816
- print("-" * 100)
817
- for r in sorted_by_gue:
818
- print(f"{r['name']:<20} {r['gue_score']:<8.3f} {r['start']:<12} {r['add']:<12}")
1864
+ print("\nHIGHEST GUE SIMILARITY SCORES (TOP 12)")
1865
+ print("=" * 80)
1866
+ for r in sorted_by_gue[:12]:
1867
+ print(f"{r['name']:<20} {r['gue_score']:<8.3f} {r['start']:<12} {r['add']:<12}")
1868
+
1869
+ # Plot results
1870
+ _plot_comparison(sorted_by_zeta, sorted_by_gue)
1871
+
1872
+ return sorted_by_zeta, sorted_by_gue
1873
+
1874
+
1875
+ def _parse_quaternion_from_csv(s: str) -> np.quaternion:
1876
+ """Parses a comma-separated string 'w,x,y,z' into a quaternion."""
1877
+ try:
1878
+ parts = [float(p.strip()) for p in s.split(',')]
1879
+ if len(parts) != 4:
1880
+ raise ValueError("Girdi 4 bileşen içermelidir.")
1881
+ # *parts -> (parts[0], parts[1], parts[2], parts[3])
1882
+ return np.quaternion(*parts)
1883
+ except (ValueError, IndexError) as e:
1884
+ raise ValueError(f"Geçersiz virgülle ayrılmış kuaterniyon formatı: '{s}'.") from e
1885
+
1886
+ def _extract_numeric_part(s: str) -> str:
1887
+ """String'den sadece sayısal kısmı çıkarır"""
1888
+ import re
1889
+ # Sayısal kısmı bul (negatif işaretli olabilir)
1890
+ match = re.search(r'[-+]?\d*\.?\d+', s)
1891
+ if match:
1892
+ return match.group()
1893
+ return "0" # Default
1894
+
1895
+ def _has_comma_format(s: str) -> bool:
1896
+ """String'in virgülle ayrılmış formatı olup olmadığını kontrol eder"""
1897
+ return ',' in s and not any(c in s for c in ['+', '-', 'j', 'i', 'ε'])
1898
+
1899
+ def _is_complex_like(s: str) -> bool:
1900
+ """String'in complex sayı formatına benzer olup olmadığını kontrol eder"""
1901
+ return any(c in s for c in ['j', 'i', '+', '-']) and ',' not in s
1902
+
1903
+ def _load_zeta_zeros(filename="zeta.txt"):
1904
+ """
1905
+ Loads Riemann zeta zeros from a text file.
1906
+ Each line should contain one floating-point number representing the imaginary part of a zeta zero.
1907
+ Lines that are empty or start with '#' are ignored.
1908
+ Returns:
1909
+ numpy.ndarray: Array of zeta zeros, or empty array if file not found.
1910
+ """
1911
+ try:
1912
+ with open(filename, 'r', encoding='utf-8') as file:
1913
+ lines = file.readlines()
1914
+ zeta_zeros = []
1915
+ for line in lines:
1916
+ line = line.strip()
1917
+ if not line or line.startswith("#"):
1918
+ continue
1919
+ try:
1920
+ zeta_zeros.append(float(line))
1921
+ except ValueError:
1922
+ print(f"Invalid line skipped: {line}")
1923
+ print(f"{len(zeta_zeros)} zeta zeros loaded.")
1924
+ return np.array(zeta_zeros)
1925
+ except FileNotFoundError:
1926
+ print(f"'{filename}' not found.")
1927
+ return np.array([])
1928
+
1929
+
1930
+ def _compute_gue_similarity(sequence, tolerance=0.5):
1931
+ """
1932
+ Measures how closely the frequency spectrum of a Keçeci sequence matches the GUE (Gaussian Unitary Ensemble) statistics.
1933
+ Uses Kolmogorov-Smirnov test against Wigner-Dyson distribution.
1934
+ Args:
1935
+ sequence (list): The Keçeci number sequence.
1936
+ tolerance (float): Not used here; kept for interface consistency.
1937
+ Returns:
1938
+ tuple: (similarity_score, p_value)
1939
+ """
1940
+ from . import _get_integer_representation
1941
+
1942
+ values = [val for z in sequence if (val := _get_integer_representation(z)) is not None]
1943
+ if len(values) < 10:
1944
+ return 0.0, 0.0
1945
+
1946
+ values = np.array(values) - np.mean(values)
1947
+ N = len(values)
1948
+ powers = np.abs(fft(values))**2
1949
+ freqs = fftfreq(N)
1950
+
1951
+ mask = (freqs > 0)
1952
+ freqs_pos = freqs[mask]
1953
+ powers_pos = powers[mask]
1954
+
1955
+ if len(powers_pos) == 0:
1956
+ return 0.0, 0.0
1957
+
1958
+ peaks, _ = find_peaks(powers_pos, height=np.max(powers_pos)*1e-7)
1959
+ strong_freqs = freqs_pos[peaks]
1960
+
1961
+ if len(strong_freqs) < 2:
1962
+ return 0.0, 0.0
1963
+
1964
+ # Scale so the strongest peak aligns with the first Riemann zeta zero
1965
+ peak_freq = strong_freqs[np.argmax(powers_pos[peaks])]
1966
+ scale_factor = 14.134725 / peak_freq
1967
+ scaled_freqs = np.sort(strong_freqs * scale_factor)
1968
+
1969
+ # Compute level spacings
1970
+ if len(scaled_freqs) < 2:
1971
+ return 0.0, 0.0
1972
+ diffs = np.diff(scaled_freqs)
1973
+ if np.mean(diffs) == 0:
1974
+ return 0.0, 0.0
1975
+ diffs_norm = diffs / np.mean(diffs)
1976
+
1977
+ # Generate GUE sample using Wigner-Dyson distribution
1978
+ def wigner_dyson(s):
1979
+ return (32 / np.pi) * s**2 * np.exp(-4 * s**2 / np.pi)
819
1980
 
820
- # Plot results
821
- _plot_comparison(sorted_by_zeta, sorted_by_gue)
1981
+ s_gue = np.linspace(0.01, 3.0, 1000)
1982
+ p_gue = wigner_dyson(s_gue)
1983
+ p_gue = p_gue / np.sum(p_gue)
1984
+ sample_gue = np.random.choice(s_gue, size=1000, p=p_gue)
822
1985
 
823
- return sorted_by_zeta, sorted_by_gue
1986
+ # Perform KS test
1987
+ ks_stat, ks_p = ks_2samp(diffs_norm, sample_gue)
1988
+ similarity_score = 1.0 - ks_stat
824
1989
 
1990
+ return similarity_score, ks_p
825
1991
 
826
1992
  def _plot_comparison(zeta_results, gue_results):
827
1993
  """
@@ -866,6 +2032,64 @@ def _plot_comparison(zeta_results, gue_results):
866
2032
  plt.tight_layout()
867
2033
  plt.show()
868
2034
 
2035
+
2036
+ def _find_kececi_zeta_zeros(sequence, tolerance=0.5):
2037
+ """
2038
+ Estimates the zeros of the Keçeci Zeta Function from the spectral peaks of the sequence.
2039
+ Compares them to known Riemann zeta zeros.
2040
+ Args:
2041
+ sequence (list): The Keçeci number sequence.
2042
+ tolerance (float): Maximum distance for a match between Keçeci and Riemann zeros.
2043
+ Returns:
2044
+ tuple: (list of Keçeci zeta zeros, matching score)
2045
+ """
2046
+ from . import _get_integer_representation
2047
+
2048
+ values = [val for z in sequence if (val := _get_integer_representation(z)) is not None]
2049
+ if len(values) < 10:
2050
+ return [], 0.0
2051
+
2052
+ values = np.array(values) - np.mean(values)
2053
+ N = len(values)
2054
+ powers = np.abs(fft(values))**2
2055
+ freqs = fftfreq(N)
2056
+
2057
+ mask = (freqs > 0)
2058
+ freqs_pos = freqs[mask]
2059
+ powers_pos = powers[mask]
2060
+
2061
+ if len(powers_pos) == 0:
2062
+ return [], 0.0
2063
+
2064
+ peaks, _ = find_peaks(powers_pos, height=np.max(powers_pos)*1e-7)
2065
+ strong_freqs = freqs_pos[peaks]
2066
+
2067
+ if len(strong_freqs) < 2:
2068
+ return [], 0.0
2069
+
2070
+ # Scale so the strongest peak aligns with the first Riemann zeta zero
2071
+ peak_freq = strong_freqs[np.argmax(powers_pos[peaks])]
2072
+ scale_factor = 14.134725 / peak_freq
2073
+ scaled_freqs = np.sort(strong_freqs * scale_factor)
2074
+
2075
+ # Find candidate zeros by analyzing the Keçeci Zeta Function
2076
+ t_vals = np.linspace(0, 650, 10000)
2077
+ zeta_vals = np.array([sum((scaled_freqs + 1e-10)**(- (0.5 + 1j * t))) for t in t_vals])
2078
+ minima, _ = find_peaks(-np.abs(zeta_vals), height=-0.5*np.max(np.abs(zeta_vals)), distance=5)
2079
+ kececi_zeta_zeros = t_vals[minima]
2080
+
2081
+ # Load Riemann zeta zeros for comparison
2082
+ zeta_zeros_imag = _load_zeta_zeros("zeta.txt")
2083
+ if len(zeta_zeros_imag) == 0:
2084
+ return kececi_zeta_zeros, 0.0
2085
+
2086
+ # Calculate matching score
2087
+ close_matches = [kz for kz in kececi_zeta_zeros if min(abs(kz - zeta_zeros_imag)) < tolerance]
2088
+ score = len(close_matches) / len(kececi_zeta_zeros) if kececi_zeta_zeros.size > 0 else 0.0
2089
+
2090
+ return kececi_zeta_zeros, score
2091
+
2092
+
869
2093
  def _pair_correlation(ordered_zeros, max_gap=3.0, bin_size=0.1):
870
2094
  """
871
2095
  Computes the pair correlation of a list of ordered zeros.
@@ -992,231 +2216,217 @@ def analyze_pair_correlation(sequence, title="Pair Correlation of Keçeci Zeta Z
992
2216
  # ==============================================================================
993
2217
  # --- CORE GENERATOR ---
994
2218
  # ==============================================================================
995
-
996
2219
  def unified_generator(kececi_type: int, start_input_raw: str, add_input_raw: str, iterations: int, include_intermediate_steps: bool = False) -> List[Any]:
997
- """
998
- Core engine to generate Keçeci Number sequences.
999
2220
 
1000
- Bu nihai versiyon, tüm sayı tipleri için esnek girdi işleme, kuaterniyonlar
1001
- için tam vektörel toplama desteği sunar ve isteğe bağlı olarak ara
1002
- hesaplama adımlarını da, veri tekrarı olmadan doğru bir şekilde döndürür.
1003
-
1004
- Args:
1005
- kececi_type (int): Keçeci Sayı türü (1-11).
1006
- start_input_raw (str): Başlangıç değerini temsil eden metin.
1007
- add_input_raw (str): Her adımda eklenecek sabiti temsil eden metin.
1008
- iterations (int): Üretilecek Keçeci adımı sayısı.
1009
- include_intermediate_steps (bool, optional): True ise, ara hesaplama
1010
- değerlerini de son listeye ekler. Varsayılan: False.
1011
-
1012
- Returns:
1013
- List[Any]: Oluşturulan Keçeci Sayıları dizisi.
1014
- """
1015
-
1016
- if not (TYPE_POSITIVE_REAL <= kececi_type <= TYPE_NEUTROSOPHIC_BICOMPLEX):
1017
- raise ValueError(f"Invalid Keçeci Number Type: {kececi_type}. Must be between {TYPE_POSITIVE_REAL} and {TYPE_NEUTROSOPHIC_BICOMPLEX}.")
2221
+ if not (TYPE_POSITIVE_REAL <= kececi_type <= TYPE_SPLIT_COMPLEX):
2222
+ raise ValueError(f"Invalid Keçeci Number Type: {kececi_type}")
1018
2223
 
1019
- # --- 1. Değişkenlerin Başlatılması ---
1020
- # Varsayılan bölme türünü ondalıklı olarak ayarla.
1021
- # Tamsayı tipleri (POSITIVE/NEGATIVE_REAL) bu değeri kendi blokları içinde ezecektir.
1022
2224
  use_integer_division = False
1023
-
2225
+ current_value = None
2226
+ add_value_typed = None
2227
+ ask_unit = None
2228
+
1024
2229
  try:
1025
- # Her sayı tipi, kendi `elif` bloğu içinde kendi girdisini işler.
2230
+ # --- SAYI TİPİNE GÖRE PARSING ---
1026
2231
  if kececi_type in [TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL]:
1027
- current_value = int(float(start_input_raw));
1028
- add_value_typed = int(float(add_input_raw));
1029
- ask_unit = 1;
2232
+ current_value = int(float(start_input_raw))
2233
+ add_value_typed = int(float(add_input_raw))
2234
+ ask_unit = 1
1030
2235
  use_integer_division = True
2236
+
1031
2237
  elif kececi_type == TYPE_FLOAT:
1032
- current_value = float(start_input_raw);
1033
- add_value_typed = float(add_input_raw);
2238
+ current_value = float(start_input_raw)
2239
+ add_value_typed = float(add_input_raw)
1034
2240
  ask_unit = 1.0
2241
+
1035
2242
  elif kececi_type == TYPE_RATIONAL:
1036
- current_value = Fraction(start_input_raw);
1037
- add_value_typed = Fraction(add_input_raw);
2243
+ current_value = Fraction(start_input_raw)
2244
+ add_value_typed = Fraction(add_input_raw)
1038
2245
  ask_unit = Fraction(1)
2246
+
1039
2247
  elif kececi_type == TYPE_COMPLEX:
1040
- current_value = _parse_complex(start_input_raw);
1041
- a_float = float(add_input_raw);
1042
- add_value_typed = complex(a_float, a_float);
2248
+ current_value = _parse_complex(start_input_raw)
2249
+ add_value_typed = _parse_complex(add_input_raw)
1043
2250
  ask_unit = 1 + 1j
2251
+
1044
2252
  elif kececi_type == TYPE_QUATERNION:
1045
- current_value = _parse_quaternion_from_csv(start_input_raw);
1046
- add_value_typed = _parse_quaternion_from_csv(add_input_raw);
2253
+ current_value = _parse_quaternion_from_csv(start_input_raw)
2254
+ add_value_typed = _parse_quaternion_from_csv(add_input_raw)
1047
2255
  ask_unit = np.quaternion(1, 1, 1, 1)
2256
+
1048
2257
  elif kececi_type == TYPE_NEUTROSOPHIC:
1049
- a, b = _parse_neutrosophic(start_input_raw);
1050
- current_value = NeutrosophicNumber(a, b);
1051
- a_float = float(add_input_raw);
1052
- add_value_typed = NeutrosophicNumber(a_float, 0);
1053
- ask_unit = NeutrosophicNumber(1, 1)
2258
+ t, i, f = _parse_neutrosophic(start_input_raw)
2259
+ current_value = NeutrosophicNumber(t, i, f)
2260
+ t_inc, i_inc, f_inc = _parse_neutrosophic(add_input_raw)
2261
+ add_value_typed = NeutrosophicNumber(t_inc, i_inc, f_inc)
2262
+ ask_unit = NeutrosophicNumber(1, 1, 1)
2263
+
1054
2264
  elif kececi_type == TYPE_NEUTROSOPHIC_COMPLEX:
1055
- s_complex = _parse_complex(start_input_raw);
1056
- current_value = NeutrosophicComplexNumber(s_complex.real, s_complex.imag, 0.0);
1057
- a_float = float(add_input_raw);
1058
- add_value_typed = NeutrosophicComplexNumber(a_float, 0.0, 0.0);
2265
+ s_complex = _parse_complex(start_input_raw)
2266
+ current_value = NeutrosophicComplexNumber(s_complex.real, s_complex.imag, 0.0)
2267
+ a_complex = _parse_complex(add_input_raw)
2268
+ add_value_typed = NeutrosophicComplexNumber(a_complex.real, a_complex.imag, 0.0)
1059
2269
  ask_unit = NeutrosophicComplexNumber(1, 1, 1)
2270
+
1060
2271
  elif kececi_type == TYPE_HYPERREAL:
1061
- a, b = _parse_hyperreal(start_input_raw);
1062
- sequence_list = [a + b / n for n in range(1, 11)];
1063
- current_value = HyperrealNumber(sequence_list);
1064
- a_float = float(add_input_raw);
1065
- add_sequence = [a_float] + [0.0] * 9;
1066
- add_value_typed = HyperrealNumber(add_sequence);
1067
- ask_unit = HyperrealNumber([1.0] * 10)
2272
+ finite, infinitesimal = _parse_hyperreal(start_input_raw)
2273
+ current_value = HyperrealNumber([finite, infinitesimal])
2274
+
2275
+ finite_inc, infinitesimal_inc = _parse_hyperreal(add_input_raw)
2276
+ add_value_typed = HyperrealNumber([finite_inc, infinitesimal_inc])
2277
+
2278
+ ask_unit = HyperrealNumber([1.0, 1.0])
2279
+
1068
2280
  elif kececi_type == TYPE_BICOMPLEX:
1069
- s_complex = _parse_complex(start_input_raw);
1070
- a_float = float(add_input_raw);
1071
- a_complex = complex(a_float);
1072
- current_value = BicomplexNumber(s_complex, s_complex / 2);
1073
- add_value_typed = BicomplexNumber(a_complex, a_complex / 2);
1074
- ask_unit = BicomplexNumber(complex(1, 1), complex(0.5, 0.5))
2281
+ current_value = _parse_bicomplex(start_input_raw)
2282
+ add_value_typed = _parse_bicomplex(add_input_raw)
2283
+ ask_unit = BicomplexNumber(complex(1, 1), complex(1, 1))
2284
+
1075
2285
  elif kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX:
1076
- s_complex = _parse_complex(start_input_raw);
1077
- current_value = NeutrosophicBicomplexNumber(s_complex.real, s_complex.imag, 0, 0, 0, 0, 0, 0);
1078
- a_float = float(add_input_raw);
1079
- add_value_typed = NeutrosophicBicomplexNumber(a_float, 0, 0, 0, 0, 0, 0, 0);
1080
- ask_unit = NeutrosophicBicomplexNumber(*([1.0] * 8))
2286
+ current_value = _parse_neutrosophic_bicomplex(start_input_raw)
2287
+ add_value_typed = _parse_neutrosophic_bicomplex(add_input_raw)
2288
+ ask_unit = NeutrosophicBicomplexNumber(1, 1, 1, 1, 1, 1, 1, 1)
2289
+
2290
+ elif kececi_type == TYPE_OCTONION:
2291
+ current_value = _parse_octonion(start_input_raw)
2292
+ add_value_typed = _parse_octonion(add_input_raw)
2293
+ ask_unit = OctonionNumber(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
2294
+
2295
+ elif kececi_type == TYPE_SEDENION:
2296
+ current_value = _parse_sedenion(start_input_raw)
2297
+ add_value_typed = _parse_sedenion(add_input_raw)
2298
+ ask_unit = SedenionNumber([1.0] * 16)
2299
+
2300
+ elif kececi_type == TYPE_CLIFFORD:
2301
+ current_value = _parse_clifford(start_input_raw)
2302
+ add_value_typed = _parse_clifford(add_input_raw)
2303
+ ask_unit = CliffordNumber({'': 1.0})
2304
+
2305
+ elif kececi_type == TYPE_DUAL:
2306
+ current_value = _parse_dual(start_input_raw)
2307
+ add_value_typed = _parse_dual(add_input_raw)
2308
+ ask_unit = DualNumber(1.0, 1.0)
2309
+
2310
+ elif kececi_type == TYPE_SPLIT_COMPLEX:
2311
+ current_value = _parse_splitcomplex(start_input_raw)
2312
+ add_value_typed = _parse_splitcomplex(add_input_raw)
2313
+ ask_unit = SplitcomplexNumber(1.0, 1.0)
2314
+
2315
+ else:
2316
+ raise ValueError(f"Unsupported Keçeci type: {kececi_type}")
2317
+
1081
2318
  except (ValueError, TypeError) as e:
1082
2319
  print(f"ERROR: Failed to initialize type {kececi_type} with start='{start_input_raw}' and increment='{add_input_raw}': {e}")
1083
2320
  return []
1084
2321
 
1085
- # --- 2. Üreteç Döngüsü ---
2322
+ # Log ve temizleme listelerini başlatın
1086
2323
  clean_trajectory = [current_value]
1087
2324
  full_log = [current_value]
1088
-
1089
2325
  last_divisor_used = None
1090
- ask_counter = 0
1091
-
1092
- for _ in range(iterations):
1093
- # --- Bir Sonraki Adımın Değerini (next_q) Hesapla ---
2326
+ ask_counter = 0 # 0: +ask_unit, 1: -ask_unit
2327
+
2328
+ for step in range(iterations):
2329
+ # 1. Topla
1094
2330
  added_value = current_value + add_value_typed
1095
-
1096
2331
  next_q = added_value
1097
2332
  divided_successfully = False
1098
2333
  modified_value = None
1099
2334
 
2335
+ # primary_divisor ve alternative_divisor hesaplama
1100
2336
  primary_divisor = 3 if last_divisor_used == 2 or last_divisor_used is None else 2
1101
2337
  alternative_divisor = 2 if primary_divisor == 3 else 3
1102
-
2338
+
2339
+ # 2. Bölme dene
1103
2340
  for divisor in [primary_divisor, alternative_divisor]:
1104
2341
  if _is_divisible(added_value, divisor, kececi_type):
1105
2342
  next_q = added_value // divisor if use_integer_division else added_value / divisor
1106
2343
  last_divisor_used = divisor
1107
2344
  divided_successfully = True
1108
2345
  break
1109
-
1110
- if not divided_successfully and is_prime(added_value):
1111
- modified_value = (added_value + ask_unit) if ask_counter == 0 else (added_value - ask_unit)
1112
- ask_counter = 1 - ask_counter
1113
-
1114
- next_q = modified_value
2346
+
2347
+ # 3. Eğer bölünemediyse ve "asalsa", ask_unit ile değiştir
2348
+ if not divided_successfully and is_prime_like(added_value, kececi_type):
2349
+ direction = 1 if ask_counter == 0 else -1
1115
2350
 
2351
+ try:
2352
+ modified_value = safe_add(added_value, ask_unit, direction)
2353
+ except TypeError as e:
2354
+ print(f"Error converting ask_unit: {e}")
2355
+ continue # veya uygun bir hata yönetimi yapabilirsiniz
2356
+
2357
+ ask_counter = 1 - ask_counter
2358
+ next_q = modified_value
2359
+
2360
+ # Bölme denemelerini burada yap
1116
2361
  for divisor in [primary_divisor, alternative_divisor]:
1117
2362
  if _is_divisible(modified_value, divisor, kececi_type):
1118
2363
  next_q = modified_value // divisor if use_integer_division else modified_value / divisor
1119
2364
  last_divisor_used = divisor
1120
2365
  break
1121
-
1122
- # --- Sonuçları Ayrı ve Doğru Listelere Kaydet ---
2366
+
2367
+ # 4. Loglara ekle
1123
2368
  full_log.append(added_value)
1124
2369
  if modified_value is not None:
1125
2370
  full_log.append(modified_value)
1126
-
1127
- # Nihai sonucu, eğer bir önceki ara adımdan farklıysa log'a ekle.
1128
- # Bu, `(12.3, ...), (12.3, ...)` tekrarını önler.
1129
- if not full_log or next_q != full_log[-1]:
1130
- full_log.append(next_q)
1131
-
2371
+ if not full_log or next_q != full_log[-1]: # next_q zaten full_log'a eklenmişse tekrar ekleme
2372
+ full_log.append(next_q)
2373
+
1132
2374
  clean_trajectory.append(next_q)
1133
-
1134
- # --- Durumu Güncelle ---
1135
2375
  current_value = next_q
1136
-
1137
- # --- 3. İsteğe Göre Doğru Listeyi Döndür ---
1138
- if include_intermediate_steps:
1139
- return full_log
1140
- else:
1141
- return clean_trajectory
1142
2376
 
1143
- def print_detailed_report(sequence: List[Any], params: Dict[str, Any]):
1144
- """Generates and prints a detailed report of the sequence results."""
1145
- if not sequence:
1146
- print("\n--- REPORT ---\nSequence could not be generated.")
1147
- return
1148
-
1149
- print("\n\n" + "="*50)
1150
- print("--- DETAILED SEQUENCE REPORT ---")
1151
- print("="*50)
2377
+ # --- SONUÇ ---
2378
+ return full_log if include_intermediate_steps else clean_trajectory
1152
2379
 
1153
- print("\n[Parameters Used]")
1154
- print(f" - Keçeci Type: {params.get('type_name', 'N/A')} ({params['type_choice']})")
1155
- print(f" - Start Value: '{params['start_val']}'")
1156
- print(f" - Increment: {params['add_val']}")
1157
- print(f" - Keçeci Steps: {params['steps']}")
2380
+ def get_with_params(
2381
+ kececi_type_choice: int,
2382
+ iterations: int,
2383
+ start_value_raw: str,
2384
+ add_value_raw: str,
2385
+ include_intermediate_steps: bool = False
2386
+ ) -> List[Any]:
2387
+ """
2388
+ Tüm 16 sayı sistemi için ortak arayüz.
2389
+ Keçeci mantığı (ask, bölme, asallık) unified_generator ile uygulanır.
2390
+ Sadece toplama değil, koşullu değişimler de yapılır.
2391
+ """
2392
+ print(f"\n--- Generating Sequence: Type {kececi_type_choice}, Steps {iterations} ---")
2393
+ print(f"Start: '{start_value_raw}', Addition: '{add_value_raw}'")
1158
2394
 
1159
- print("\n[Sequence Summary]")
1160
- print(f" - Total Numbers Generated: {len(sequence)}")
1161
-
1162
- kpn = find_kececi_prime_number(sequence)
1163
- print(f" - Keçeci Prime Number (KPN): {kpn if kpn is not None else 'Not found'}")
2395
+ # --- unified_generator'ı doğrudan çağır ---
2396
+ # (İlk başta basit toplama döngüsü yapma!)
1164
2397
 
1165
- print("\n[Sequence Preview]")
1166
- preview_count = min(len(sequence), 30)
1167
- print(f" --- First {preview_count} Numbers ---")
1168
- for i in range(preview_count):
1169
- print(f" {i}: {sequence[i]}")
1170
2398
 
1171
- if len(sequence) > preview_count:
1172
- print(f"\n --- Last {preview_count} Numbers ---")
1173
- for i in range(len(sequence) - preview_count, len(sequence)):
1174
- print(f" {i}: {sequence[i]}")
2399
+ try:
2400
+ generated_sequence = unified_generator(
2401
+ kececi_type=kececi_type_choice,
2402
+ start_input_raw=start_value_raw,
2403
+ add_input_raw=add_value_raw,
2404
+ iterations=iterations,
2405
+ include_intermediate_steps=include_intermediate_steps
2406
+ )
2407
+
2408
+ if generated_sequence:
2409
+ print(f"Generated {len(generated_sequence)} numbers.")
2410
+ preview = [str(x) for x in generated_sequence[:40]] # okunabilirlik için
2411
+ print(f"Preview: {preview}...")
1175
2412
 
1176
- print("\n" + "="*50)
2413
+ # Keçeci Prime Number kontrolü (varsa)
2414
+ kpn = find_kececi_prime_number(generated_sequence)
2415
+ if kpn is not None:
2416
+ print(f"Keçeci Prime Number found: {kpn}")
2417
+ else:
2418
+ print("No Keçeci Prime Number found.")
2419
+ else:
2420
+ print("Sequence generation failed or returned empty.")
1177
2421
 
1178
- while True:
1179
- show_all = input("Do you want to print the full sequence? (y/n): ").lower().strip()
1180
- if show_all in ['y', 'n']:
1181
- break
1182
-
1183
- if show_all == 'y':
1184
- print("\n--- FULL SEQUENCE ---")
1185
- for i, num in enumerate(sequence):
1186
- print(f"{i}: {num}")
1187
- print("="*50)
2422
+ return generated_sequence
1188
2423
 
1189
- # ==============================================================================
1190
- # --- HIGH-LEVEL CONTROL FUNCTIONS ---
1191
- # ==============================================================================
2424
+ except Exception as e:
2425
+ print(f"ERROR during sequence generation: {e}")
2426
+ import traceback
2427
+ traceback.print_exc()
2428
+ return []
1192
2429
 
1193
- def get_with_params(kececi_type_choice: int, iterations: int, start_value_raw: str, add_value_raw: str, include_intermediate_steps: bool = False) -> List[Any]:
1194
- """Generates Keçeci Numbers with specified parameters, supporting full vectorial addition."""
1195
- print(f"\n--- Generating Sequence: Type {kececi_type_choice}, Steps {iterations} ---")
1196
- print(f"Start: '{start_value_raw}', Increment: '{add_value_raw}'")
1197
- if include_intermediate_steps:
1198
- print("Mode: Detailed (including intermediate steps)")
1199
-
1200
- generated_sequence = unified_generator(
1201
- kececi_type_choice,
1202
- start_value_raw,
1203
- add_value_raw,
1204
- iterations,
1205
- # Yeni parametreyi aktar
1206
- include_intermediate_steps=include_intermediate_steps
1207
- )
1208
-
1209
- if generated_sequence:
1210
- print(f"Generated {len(generated_sequence)} numbers. Preview: {generated_sequence[:30]}...")
1211
- kpn = find_kececi_prime_number(generated_sequence)
1212
- if kpn is not None:
1213
- print(f"Keçeci Prime Number for this sequence: {kpn}")
1214
- else:
1215
- print("No repeating Keçeci Prime Number found.")
1216
- else:
1217
- print("Sequence generation failed.")
1218
-
1219
- return generated_sequence
1220
2430
 
1221
2431
  def get_interactive() -> Tuple[List[Any], Dict[str, Any]]:
1222
2432
  """
@@ -1224,50 +2434,99 @@ def get_interactive() -> Tuple[List[Any], Dict[str, Any]]:
1224
2434
  This version is improved for code clarity and compatibility with the module's
1225
2435
  current interface.
1226
2436
  """
2437
+
2438
+ # Tip sabitleri
2439
+ TYPE_POSITIVE_REAL = 1
2440
+ TYPE_NEGATIVE_REAL = 2
2441
+ TYPE_COMPLEX = 3
2442
+ TYPE_FLOAT = 4
2443
+ TYPE_RATIONAL = 5
2444
+ TYPE_QUATERNION = 6
2445
+ TYPE_NEUTROSOPHIC = 7
2446
+ TYPE_NEUTROSOPHIC_COMPLEX = 8
2447
+ TYPE_HYPERREAL = 9
2448
+ TYPE_BICOMPLEX = 10
2449
+ TYPE_NEUTROSOPHIC_BICOMPLEX = 11
2450
+ TYPE_OCTONION = 12
2451
+ TYPE_SEDENION = 13
2452
+ TYPE_CLIFFORD = 14
2453
+ TYPE_DUAL = 15
2454
+ TYPE_SPLIT_COMPLEX = 16
2455
+
2456
+
1227
2457
  print("\n--- Keçeci Numbers Interactive Generator ---")
1228
- print(" 1: Positive Real 2: Negative Real 3: Complex")
1229
- print(" 4: Float 5: Rational 6: Quaternion")
1230
- print(" 7: Neutrosophic 8: Neutro-Complex 9: Hyperreal")
1231
- print(" 10: Bicomplex 11: Neutro-Bicomplex")
2458
+ print(" 1: Positive Real 2: Negative Real 3: Complex")
2459
+ print(" 4: Float 5: Rational 6: Quaternion")
2460
+ print(" 7: Neutrosophic 8: Neutro-Complex 9: Hyperreal")
2461
+ print(" 10: Bicomplex 11: Neutro-Bicomplex 12: Octonion")
2462
+ print(" 13: Sedenion 14: Clifford 15: Dual")
2463
+ print(" 16: Split-Complex")
1232
2464
 
1233
2465
  # Get a valid number type from the user
1234
2466
  while True:
1235
2467
  try:
1236
- type_choice = int(input("Select a Keçeci Number Type (1-11): "))
1237
- if 1 <= type_choice <= 11:
2468
+ type_choice = int(input("Select a Keçeci Number Type (1-16): "))
2469
+ if 1 <= type_choice <= 16:
1238
2470
  break
1239
- print("Invalid type. Please enter a number between 1 and 11.")
2471
+ print("Invalid type. Please enter a number between 1 and 16.")
1240
2472
  except ValueError:
1241
2473
  print("Invalid input. Please enter a number.")
1242
2474
 
1243
2475
  # User prompts for the starting value
1244
2476
  start_prompts = {
1245
- 1: "Enter positive integer start (e.g., '10.0'): ",
1246
- 2: "Enter negative integer start (e.g., '-5.0'): ",
1247
- 3: "Enter complex start (e.g., '3+4j'): ",
1248
- 4: "Enter float start (e.g., '3.14'): ",
1249
- 5: "Enter rational start (e.g., '7/2'): ",
1250
- 6: "Enter quaternion start (in 'w,x,y,z' format, e.g., '1.0,2.0,-3.0,1.0'): ",
1251
- 7: "Enter neutrosophic start (e.g., '5+2I'): ",
1252
- 8: "Enter complex base for neutro-complex (e.g., '1-2j'): ",
1253
- 9: "Enter hyperreal start (e.g., '5+3e'): ",
1254
- 10: "Enter complex base for bicomplex (e.g., '2+1j'): ",
1255
- 11: "Enter complex base for neutro-bicomplex (e.g., '1+2j'): "
2477
+ 1: "Enter Positive Real start (e.g., '10.0', '5', '3.14'): ",
2478
+ 2: "Enter Negative Real start (e.g., '-5.0', '-2', '-1.5'): ",
2479
+ 3: "Enter Complex start (e.g., '1.0+1.0j', '3+4j'): ",
2480
+ 4: "Enter Float start (e.g., '0.0001412', '3.14', '2.718'): ",
2481
+ 5: "Enter Rational start (e.g., '0.5', '7/2', '3/4'): ",
2482
+ 6: "Enter Quaternion start (in 'w,x,y,z' format, e.g., '1.0,2.0,-3.0,1.0'): ",
2483
+ 7: "Enter Neutrosophic start (in 't,i,f' format, e.g., '0.1,0.0,0.0'): ",
2484
+ 8: "Enter Neutro-Complex start (in 'real,imag,neut' format, e.g., '2+3j'): ",
2485
+ 9: "Enter Hyperreal start (in 'finite,infinitesimal' format, e.g., '0.0,0.0001'): ",
2486
+ 10: "Enter Bicomplex start (in 'z1_real,z1_imag,z2_real,z2_imag' format, e.g., '1.0,2.0,3.0,4.0', '1.0,2.0', '3.0', '1.0+1.0j'): ",
2487
+ 11: "Enter Neutro-Bicomplex start (in 'r,i,nr,ni,jr,ji,jnr,jni' format, e.g., '1,2,0.1,0.2,0.3,0.4,0.5,0.6', '0.1'): ",
2488
+ 12: "Enter Octonion start (in 'e0,e1,e2,e3,e4,e5,e6,e7' format, e.g., '1.0,0.5,-0.2,0.3,0.1,-0.4,0.2,0.0'): ",
2489
+ 13: "Enter Sedenion start (in 'e0,e1,...,e15' format, e.g., '1.0', '0.0'): ",
2490
+ 14: "Enter Clifford start (in 'scalar,e1,e2,e12,...' format, e.g., '0.1+0.2e1', '1.0+2.0e1+3.0e12'): ",
2491
+ 15: "Enter Dual start (in 'real,dual' format, e.g., '2.0,0.5'): ",
2492
+ 16: "Enter Split-Complex start (in 'real,split' format, e.g., '1.0,0.8'): ",
1256
2493
  }
1257
2494
 
1258
2495
  # User prompts for the increment value
1259
2496
  add_prompts = {
1260
- TYPE_QUATERNION: "Enter quaternion increment (in 'w,x,y,z' format, e.g., '1.3,-2.1,0.5,3.4'): "
2497
+ 1: "Enter Positive Real increment (e.g., '2.0', '1.5'): ",
2498
+ 2: "Enter Negative Real increment (e.g., '-1.0', '-0.5'): ",
2499
+ 3: "Enter Complex increment (e.g., '0.5+0.5j', '3+4j'): ",
2500
+ 4: "Enter Float increment (e.g., '0.1', '2.5'): ",
2501
+ 5: "Enter Rational increment (e.g., '1/3', '0.25'): ",
2502
+ 6: "Enter Quaternion increment (in 'w,x,y,z' format, e.g., '0.1,-0.2,0.3,0.0'): ",
2503
+ 7: "Enter Neutrosophic increment (in 't,i,f' format, e.g., '0.1,0.0,0.0'): ",
2504
+ 8: "Enter Neutro-Complex increment (in 'real,imag,neut' format, e.g., '2+3j', 5): ",
2505
+ 9: "Enter Hyperreal increment (in 'finite,infinitesimal' format, e.g., '0.0,0.0001'): ",
2506
+ 10: "Enter Bicomplex increment (in 'z1_real,z1_imag,z2_real,z2_imag' format, e.g., '1.0,2.0,3.0,4.0', '1.0,2.0', '3.0', '1.0+1.0j'): ",
2507
+ 11: "Enter Neutro-Bicomplex increment (in 'r,i,nr,ni,jr,ji,jnr,jni' format, e.g., '1,2,0.1,0.2,0.3,0.4,0.5,0.6', '0.1')): ",
2508
+ 12: "Enter Octonion increment (in 'e0,e1,e2,e3,e4,e5,e6,e7' format, e.g., '0.1', '0.0'): ",
2509
+ 13: "Enter Sedenion increment (in 'e0,e1,...,e15' format, e.g., '0.1', '0.0'): ",
2510
+ 14: "Enter Clifford increment (in 'scalar,e1,e2,e12,...' format, e.g., '0.1+0.2e1', '1.0+2.0e1+3.0e12'): ",
2511
+ 15: "Enter Dual increment (in 'real,dual' format, e.g., 1.0, '0.1,0.0'): ",
2512
+ 16: "Enter Split-Complex increment (in 'real,split' format, e.g., '0.1,0.0'): ",
1261
2513
  }
1262
- default_add_prompt = "Enter increment value (e.g., '9.0'): "
1263
2514
 
1264
2515
  # Get inputs from the user
1265
2516
  start_input_val_raw = input(start_prompts.get(type_choice, "Enter starting value: "))
1266
- add_input_val_raw = input(add_prompts.get(type_choice, default_add_prompt))
1267
- num_kececi_steps = int(input("Enter number of Keçeci steps (e.g., 30): "))
2517
+ add_input_val_raw = input(add_prompts.get(type_choice, "Enter increment value: "))
2518
+
2519
+ while True:
2520
+ try:
2521
+ num_kececi_steps = int(input("Enter number of Keçeci steps (e.g., 40, 60): "))
2522
+ if num_kececi_steps > 0:
2523
+ break
2524
+ print("Please enter a positive integer.")
2525
+ except ValueError:
2526
+ print("Invalid input. Please enter a number.")
1268
2527
 
1269
2528
  show_details_input = input("Do you want to include the intermediate calculation steps? (y/n): ").lower().strip()
1270
- show_details = (show_details_input == 'y')
2529
+ show_details = (show_details_input == 'y' or show_details_input == 'yes')
1271
2530
 
1272
2531
  # Generate the sequence with the correct parameter names and values
1273
2532
  sequence = get_with_params(
@@ -1303,7 +2562,7 @@ def find_period(sequence: List[Any], min_repeats: int = 3) -> Optional[List[Any]
1303
2562
  Returns:
1304
2563
  The repeating cycle as a list if found, otherwise None.
1305
2564
  """
1306
- if len(sequence) < 10: # Çok kısa dizilerde periyot aramak anlamsız
2565
+ if len(sequence) < 4: # Çok kısa dizilerde periyot aramak anlamsız
1307
2566
  return None
1308
2567
 
1309
2568
  # Olası periyot uzunluklarını dizinin yarısına kadar kontrol et
@@ -1332,119 +2591,497 @@ def find_period(sequence: List[Any], min_repeats: int = 3) -> Optional[List[Any]
1332
2591
  # Hiçbir periyot bulunamadı
1333
2592
  return None
1334
2593
 
1335
- def find_kececi_prime_number(kececi_numbers_list: List[Any]) -> Optional[int]:
1336
- """Finds the Keçeci Prime Number from a generated sequence."""
1337
- if not kececi_numbers_list:
1338
- return None
1339
-
1340
- integer_prime_reps = [
1341
- rep for num in kececi_numbers_list
1342
- if is_prime(num) and (rep := _get_integer_representation(num)) is not None
1343
- ]
1344
-
1345
- if not integer_prime_reps:
1346
- return None
2594
+ def is_quaternion_like(obj):
2595
+ if isinstance(obj, np.quaternion):
2596
+ return True
2597
+ if hasattr(obj, 'components'):
2598
+ comp = np.array(obj.components)
2599
+ return comp.size == 4
2600
+ if all(hasattr(obj, attr) for attr in ['w', 'x', 'y', 'z']):
2601
+ return True
2602
+ if hasattr(obj, 'scalar') and hasattr(obj, 'vector') and isinstance(obj.vector, (list, np.ndarray)) and len(obj.vector) == 3:
2603
+ return True
2604
+ return False
1347
2605
 
1348
- counts = collections.Counter(integer_prime_reps)
1349
- repeating_primes = [(freq, prime) for prime, freq in counts.items() if freq > 1]
1350
- if not repeating_primes:
1351
- return None
1352
-
1353
- _, best_prime = max(repeating_primes)
1354
- return best_prime
2606
+ def is_neutrosophic_like(obj):
2607
+ """NeutrosophicNumber gibi görünen objeleri tanır (t,i,f veya a,b vs.)"""
2608
+ return (hasattr(obj, 't') and hasattr(obj, 'i') and hasattr(obj, 'f')) or \
2609
+ (hasattr(obj, 'a') and hasattr(obj, 'b')) or \
2610
+ (hasattr(obj, 'value') and hasattr(obj, 'indeterminacy')) or \
2611
+ (hasattr(obj, 'determinate') and hasattr(obj, 'indeterminate'))
1355
2612
 
1356
2613
  def plot_numbers(sequence: List[Any], title: str = "Keçeci Number Sequence Analysis"):
1357
- """Plots the generated sequence with detailed visualizations for each type."""
1358
- plt.style.use('seaborn-v0_8-whitegrid')
1359
-
2614
+ """
2615
+ Tüm 16 Keçeci Sayı türü için detaylı görselleştirme sağlar.
2616
+ """
1360
2617
  if not sequence:
1361
- print("Sequence is empty, nothing to plot.")
2618
+ print("Sequence is empty. Nothing to plot.")
1362
2619
  return
1363
2620
 
1364
- fig = plt.figure(figsize=(16, 9))
1365
- plt.suptitle(title, fontsize=16, y=0.98)
2621
+ fig = plt.figure(figsize=(18, 14), constrained_layout=True)
2622
+ fig.suptitle(title, fontsize=18, fontweight='bold')
2623
+
1366
2624
  first_elem = sequence[0]
1367
-
1368
- if isinstance(first_elem, (int, float, Fraction)):
2625
+
2626
+ # --- 1. Fraction (Rational)
2627
+ if isinstance(first_elem, Fraction):
2628
+ float_vals = [float(x) for x in sequence]
2629
+ numerators = [x.numerator for x in sequence]
2630
+ denominators = [x.denominator for x in sequence]
2631
+ gs = GridSpec(2, 2, figure=fig)
2632
+
2633
+ ax1 = fig.add_subplot(gs[0, 0])
2634
+ ax1.plot(float_vals, 'o-', color='tab:blue')
2635
+ ax1.set_title("Fraction as Float")
2636
+ ax1.set_ylabel("Value")
2637
+
2638
+ ax2 = fig.add_subplot(gs[0, 1])
2639
+ ax2.plot(numerators, 's-', label='Numerator', color='tab:orange')
2640
+ ax2.plot(denominators, '^-', label='Denominator', color='tab:green')
2641
+ ax2.set_title("Numerator & Denominator")
2642
+ ax2.legend()
2643
+
2644
+ ax3 = fig.add_subplot(gs[1, 0])
2645
+ ax3.plot([n/d for n, d in zip(numerators, denominators)], 'o-', color='tab:purple')
2646
+ ax3.set_title("Computed Ratio")
2647
+ ax3.set_ylabel("n/d")
2648
+
2649
+ ax4 = fig.add_subplot(gs[1, 1])
2650
+ sc = ax4.scatter(numerators, denominators, c=range(len(sequence)), cmap='plasma', s=30)
2651
+ ax4.set_title("Num vs Den Trajectory")
2652
+ ax4.set_xlabel("Numerator")
2653
+ ax4.set_ylabel("Denominator")
2654
+ plt.colorbar(sc, ax=ax4, label="Step")
2655
+
2656
+ # --- 2. int, float (Positive/Negative Real, Float)
2657
+ elif isinstance(first_elem, (int, float)):
1369
2658
  ax = fig.add_subplot(1, 1, 1)
1370
- ax.plot([float(x) for x in sequence], 'o-', label="Value")
1371
- ax.set_title("Value over Iterations")
1372
- ax.set_xlabel("Index"), ax.set_ylabel("Value"), ax.legend()
2659
+ ax.plot([float(x) for x in sequence], 'o-', color='tab:blue', markersize=5)
2660
+ ax.set_title("Real Number Sequence")
2661
+ ax.set_xlabel("Iteration")
2662
+ ax.set_ylabel("Value")
2663
+ ax.grid(True, alpha=0.3)
1373
2664
 
2665
+ # --- 3. Complex
1374
2666
  elif isinstance(first_elem, complex):
2667
+ real_parts = [z.real for z in sequence]
2668
+ imag_parts = [z.imag for z in sequence]
2669
+ magnitudes = [abs(z) for z in sequence]
2670
+ gs = GridSpec(2, 2, figure=fig)
2671
+
2672
+ ax1 = fig.add_subplot(gs[0, 0])
2673
+ ax1.plot(real_parts, 'o-', color='tab:blue')
2674
+ ax1.set_title("Real Part")
2675
+
2676
+ ax2 = fig.add_subplot(gs[0, 1])
2677
+ ax2.plot(imag_parts, 'o-', color='tab:red')
2678
+ ax2.set_title("Imaginary Part")
2679
+
2680
+ ax3 = fig.add_subplot(gs[1, 0])
2681
+ ax3.plot(magnitudes, 'o-', color='tab:purple')
2682
+ ax3.set_title("Magnitude |z|")
2683
+
2684
+ ax4 = fig.add_subplot(gs[1, 1])
2685
+ ax4.plot(real_parts, imag_parts, '.-', alpha=0.7)
2686
+ ax4.scatter(real_parts[0], imag_parts[0], c='g', s=100, label='Start')
2687
+ ax4.scatter(real_parts[-1], imag_parts[-1], c='r', s=100, label='End')
2688
+ ax4.set_title("Complex Plane")
2689
+ ax4.set_xlabel("Re(z)")
2690
+ ax4.set_ylabel("Im(z)")
2691
+ ax4.legend()
2692
+ ax4.axis('equal')
2693
+ ax4.grid(True, alpha=0.3)
2694
+
2695
+ # --- 4. Quaternion
2696
+ elif hasattr(first_elem, 'components') and len(getattr(first_elem, 'components', [])) == 4:
2697
+ try:
2698
+ comp = np.array([getattr(q, 'components', [q.w, q.x, q.y, q.z]) for q in sequence])
2699
+ w, x, y, z = comp.T
2700
+ magnitudes = np.linalg.norm(comp, axis=1)
2701
+ gs = GridSpec(2, 2, figure=fig)
2702
+
2703
+ ax1 = fig.add_subplot(gs[0, 0])
2704
+ labels = ['w', 'x', 'y', 'z']
2705
+ for i, label in enumerate(labels):
2706
+ ax1.plot(comp[:, i], label=label, alpha=0.8)
2707
+ ax1.set_title("Quaternion Components")
2708
+ ax1.legend()
2709
+
2710
+ ax2 = fig.add_subplot(gs[0, 1])
2711
+ ax2.plot(magnitudes, 'o-', color='tab:purple')
2712
+ ax2.set_title("Magnitude |q|")
2713
+
2714
+ ax3 = fig.add_subplot(gs[1, :], projection='3d')
2715
+ ax3.plot(x, y, z, alpha=0.7)
2716
+ ax3.scatter(x[0], y[0], z[0], c='g', s=100, label='Start')
2717
+ ax3.scatter(x[-1], y[-1], z[-1], c='r', s=100, label='End')
2718
+ ax3.set_title("3D Trajectory (x,y,z)")
2719
+ ax3.set_xlabel("x"); ax3.set_ylabel("y"); ax3.set_zlabel("z")
2720
+ ax3.legend()
2721
+ except Exception as e:
2722
+ ax = fig.add_subplot(1, 1, 1)
2723
+ ax.text(0.5, 0.5, f"Error: {e}", ha='center', va='center', color='red')
2724
+
2725
+ # --- 5. OctonionNumber
2726
+ elif hasattr(first_elem, 'coeffs') and len(first_elem.coeffs) == 8:
2727
+ coeffs = np.array([x.coeffs for x in sequence])
2728
+ magnitudes = np.linalg.norm(coeffs, axis=1)
1375
2729
  gs = GridSpec(2, 2, figure=fig)
1376
- ax1, ax2, ax3 = fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[0, 1]), fig.add_subplot(gs[1, :])
1377
- real_parts, imag_parts = [c.real for c in sequence], [c.imag for c in sequence]
1378
- ax1.plot(real_parts, 'o-', label='Real Part'), ax1.set_title("Real Part"), ax1.legend()
1379
- ax2.plot(imag_parts, 'o-', color='red', label='Imaginary Part'), ax2.set_title("Imaginary Part"), ax2.legend()
1380
- ax3.plot(real_parts, imag_parts, '.-', label='Trajectory')
1381
- ax3.scatter(real_parts[0], imag_parts[0], c='g', s=100, label='Start', zorder=5)
1382
- ax3.scatter(real_parts[-1], imag_parts[-1], c='r', s=100, label='End', zorder=5)
1383
- ax3.set_title("Trajectory in Complex Plane"), ax3.set_xlabel("Real"), ax3.set_ylabel("Imaginary"), ax3.legend(), ax3.axis('equal')
1384
-
1385
- elif isinstance(first_elem, np.quaternion):
1386
- gs = GridSpec(2, 1, figure=fig)
2730
+
1387
2731
  ax1 = fig.add_subplot(gs[0, 0])
1388
- ax2 = fig.add_subplot(gs[1, 0], sharex=ax1)
1389
- ax1.plot([q.w for q in sequence], 'o-', label='w (scalar)'), ax1.plot([q.x for q in sequence], 's--', label='x')
1390
- ax1.plot([q.y for q in sequence], '^--', label='y'), ax1.plot([q.z for q in sequence], 'd--', label='z')
1391
- ax1.set_title("Quaternion Components"), ax1.legend()
1392
- magnitudes = [abs(q) for q in sequence]
1393
- ax2.plot(magnitudes, 'o-', color='purple', label='Magnitude'), ax2.set_title("Magnitude"), ax2.legend(), ax2.set_xlabel("Index")
1394
-
1395
- elif isinstance(first_elem, BicomplexNumber):
2732
+ for i in range(4):
2733
+ ax1.plot(coeffs[:, i], label=f'e{i}', alpha=0.7)
2734
+ ax1.set_title("e0-e3 Components")
2735
+ ax1.legend(ncol=2)
2736
+
2737
+ ax2 = fig.add_subplot(gs[0, 1])
2738
+ for i in range(4, 8):
2739
+ ax2.plot(coeffs[:, i], label=f'e{i}', alpha=0.7)
2740
+ ax2.set_title("e4-e7 Components")
2741
+ ax2.legend(ncol=2)
2742
+
2743
+ ax3 = fig.add_subplot(gs[1, 0])
2744
+ ax3.plot(magnitudes, 'o-', color='tab:purple')
2745
+ ax3.set_title("Magnitude |o|")
2746
+
2747
+ ax4 = fig.add_subplot(gs[1, 1], projection='3d')
2748
+ ax4.plot(coeffs[:, 1], coeffs[:, 2], coeffs[:, 3], alpha=0.7)
2749
+ ax4.set_title("3D (e1,e2,e3)")
2750
+ ax4.set_xlabel("e1"); ax4.set_ylabel("e2"); ax4.set_zlabel("e3")
2751
+
2752
+ # --- 6. SedenionNumber
2753
+ elif hasattr(first_elem, 'coeffs') and len(first_elem.coeffs) == 16:
2754
+ coeffs = np.array([x.coeffs for x in sequence])
2755
+ magnitudes = np.linalg.norm(coeffs, axis=1)
1396
2756
  gs = GridSpec(2, 2, figure=fig)
1397
- ax1, ax2, ax3, ax4 = fig.add_subplot(gs[0,0]), fig.add_subplot(gs[0,1]), fig.add_subplot(gs[1,0]), fig.add_subplot(gs[1,1])
1398
- z1r, z1i = [x.z1.real for x in sequence], [x.z1.imag for x in sequence]
1399
- z2r, z2i = [x.z2.real for x in sequence], [x.z2.imag for x in sequence]
1400
- ax1.plot(z1r, label='z1.real'), ax1.plot(z1i, label='z1.imag'), ax1.set_title("Component z1"), ax1.legend()
1401
- ax2.plot(z2r, label='z2.real'), ax2.plot(z2i, label='z2.imag'), ax2.set_title("Component z2"), ax2.legend()
1402
- ax3.plot(z1r, z1i, '.-'), ax3.set_title("z1 Trajectory"), ax3.set_xlabel("Real"), ax3.set_ylabel("Imaginary")
1403
- ax4.plot(z2r, z2i, '.-'), ax4.set_title("z2 Trajectory"), ax4.set_xlabel("Real"), ax4.set_ylabel("Imaginary")
1404
-
1405
- elif isinstance(first_elem, NeutrosophicNumber):
1406
- gs = GridSpec(1, 2, figure=fig)
1407
- ax1, ax2 = fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[0, 1])
1408
- a, b = [x.a for x in sequence], [x.b for x in sequence]
1409
- ax1.plot(a, label='Determinate (a)'), ax1.plot(b, label='Indeterminate (b)'), ax1.set_title("Components"), ax1.legend()
1410
- sc = ax2.scatter(a, b, c=range(len(a)), cmap='viridis')
1411
- ax2.set_title("Trajectory"), ax2.set_xlabel("Determinate"), ax2.set_ylabel("Indeterminate"), fig.colorbar(sc, ax=ax2, label="Iteration")
1412
-
1413
- elif isinstance(first_elem, NeutrosophicComplexNumber):
1414
- gs = GridSpec(2, 1, figure=fig)
1415
- ax1, ax2 = fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[1, 0])
1416
- r, i, ind = [x.real for x in sequence], [x.imag for x in sequence], [x.indeterminacy for x in sequence]
1417
- ax1.plot(r, label='Real'), ax1.plot(i, label='Imag'), ax1.plot(ind, label='Indeterminacy', linestyle=':')
1418
- ax1.set_title("Components"), ax1.legend()
1419
- sc = ax2.scatter(r, i, c=ind, cmap='magma', s=20)
1420
- ax2.set_title("Trajectory (colored by Indeterminacy)"), ax2.set_xlabel("Real"), ax2.set_ylabel("Imaginary")
1421
- fig.colorbar(sc, ax=ax2, label='Indeterminacy'), ax2.axis('equal')
1422
-
1423
- elif isinstance(first_elem, HyperrealNumber):
1424
- gs = GridSpec(2, 1, figure=fig)
1425
- ax1, ax2 = fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[1, 0])
1426
- num_components = min(len(first_elem.sequence), 4)
1427
- for i in range(num_components):
1428
- ax1.plot([h.sequence[i] for h in sequence], label=f'Comp {i}')
1429
- ax1.set_title("Hyperreal Components"), ax1.legend()
1430
- comp0, comp1 = [h.sequence[0] for h in sequence], [h.sequence[1] for h in sequence]
1431
- sc = ax2.scatter(comp0, comp1, c=range(len(comp0)), cmap='plasma')
1432
- ax2.set_title("Trajectory (C0 vs C1)"), ax2.set_xlabel("C0"), ax2.set_ylabel("C1"), fig.colorbar(sc, ax=ax2, label="Iteration")
2757
+
2758
+ ax1 = fig.add_subplot(gs[0, 0])
2759
+ for i in range(8):
2760
+ ax1.plot(coeffs[:, i], label=f'e{i}', alpha=0.6, linewidth=0.8)
2761
+ ax1.set_title("Sedenion e0-e7")
2762
+ ax1.legend(ncol=2, fontsize=6)
2763
+
2764
+ ax2 = fig.add_subplot(gs[0, 1])
2765
+ for i in range(8, 16):
2766
+ ax2.plot(coeffs[:, i], label=f'e{i}', alpha=0.6, linewidth=0.8)
2767
+ ax2.set_title("e8-e15")
2768
+ ax2.legend(ncol=2, fontsize=6)
2769
+
2770
+ ax3 = fig.add_subplot(gs[1, 0])
2771
+ ax3.plot(magnitudes, 'o-', color='tab:purple')
2772
+ ax3.set_title("Magnitude |s|")
2773
+
2774
+ try:
2775
+ from sklearn.decomposition import PCA
2776
+ pca = PCA(n_components=2)
2777
+ if len(sequence) > 2:
2778
+ proj = pca.fit_transform(coeffs)
2779
+ ax4 = fig.add_subplot(gs[1, 1])
2780
+ sc = ax4.scatter(proj[:, 0], proj[:, 1], c=range(len(proj)), cmap='viridis', s=25)
2781
+ ax4.set_title(f"PCA Projection (Var: {sum(pca.explained_variance_ratio_):.3f})")
2782
+ plt.colorbar(sc, ax=ax4, label="Iteration")
2783
+ except ImportError:
2784
+ ax4 = fig.add_subplot(gs[1, 1])
2785
+ ax4.text(0.5, 0.5, "Install sklearn\nfor PCA", ha='center', va='center', fontsize=10)
2786
+
2787
+ # --- 7. CliffordNumber
2788
+ elif hasattr(first_elem, 'basis') and isinstance(first_elem.basis, dict):
2789
+ all_keys = sorted(first_elem.basis.keys(), key=lambda x: (len(x), x))
2790
+ values = {k: [elem.basis.get(k, 0.0) for elem in sequence] for k in all_keys}
2791
+ scalar = values.get('', [0]*len(sequence))
2792
+ vector_keys = [k for k in all_keys if len(k) == 1]
2793
+ gs = GridSpec(2, 2, figure=fig)
2794
+
2795
+ ax1 = fig.add_subplot(gs[0, 0])
2796
+ ax1.plot(scalar, 'o-', label='Scalar', color='black')
2797
+ for k in vector_keys[:3]:
2798
+ ax1.plot(values[k], label=f'Vec {k}', alpha=0.7)
2799
+ ax1.set_title("Scalar & Vectors")
2800
+ ax1.legend()
2801
+
2802
+ ax2 = fig.add_subplot(gs[0, 1])
2803
+ bivector_mags = [sum(v**2 for k, v in elem.basis.items() if len(k) == 2)**0.5 for elem in sequence]
2804
+ ax2.plot(bivector_mags, 'o-', color='tab:green')
2805
+ ax2.set_title("Bivector Magnitude")
2806
+
2807
+ try:
2808
+ from sklearn.decomposition import PCA
2809
+ matrix = np.array([list(v.values()) for v in values.values()]).T
2810
+ pca = PCA(n_components=2)
2811
+ if len(sequence) > 1:
2812
+ proj = pca.fit_transform(matrix)
2813
+ ax3 = fig.add_subplot(gs[1, :])
2814
+ sc = ax3.scatter(proj[:, 0], proj[:, 1], c=range(len(proj)), cmap='plasma')
2815
+ ax3.set_title("Clifford PCA")
2816
+ plt.colorbar(sc, ax=ax3, label="Component")
2817
+ except:
2818
+ ax3 = fig.add_subplot(gs[1, :])
2819
+ ax3.text(0.5, 0.5, "Install sklearn for PCA", ha='center')
2820
+
2821
+ # --- 8. DualNumber
2822
+ elif hasattr(first_elem, 'real') and hasattr(first_elem, 'dual'):
2823
+ real_vals = [x.real for x in sequence]
2824
+ dual_vals = [x.dual for x in sequence]
2825
+ gs = GridSpec(2, 2, figure=fig)
2826
+
2827
+ ax1 = fig.add_subplot(gs[0, 0])
2828
+ ax1.plot(real_vals, 'o-', color='tab:blue')
2829
+ ax1.set_title("Real Part")
2830
+
2831
+ ax2 = fig.add_subplot(gs[0, 1])
2832
+ ax2.plot(dual_vals, 'o-', color='tab:orange')
2833
+ ax2.set_title("Dual Part (ε)")
2834
+
2835
+ ax3 = fig.add_subplot(gs[1, 0])
2836
+ ax3.plot(real_vals, dual_vals, '.-')
2837
+ ax3.set_title("Real vs Dual")
2838
+ ax3.set_xlabel("Real")
2839
+ ax3.set_ylabel("Dual")
2840
+
2841
+ ax4 = fig.add_subplot(gs[1, 1])
2842
+ ratios = [d/r if r != 0 else 0 for r, d in zip(real_vals, dual_vals)]
2843
+ ax4.plot(ratios, 'o-', color='tab:purple')
2844
+ ax4.set_title("Dual/Real Ratio")
2845
+
2846
+ # --- 9. SplitcomplexNumber
2847
+ elif hasattr(first_elem, 'real') and hasattr(first_elem, 'split'):
2848
+ real_vals = [x.real for x in sequence]
2849
+ split_vals = [x.split for x in sequence]
2850
+ u_vals = [r + s for r, s in zip(real_vals, split_vals)]
2851
+ v_vals = [r - s for r, s in zip(real_vals, split_vals)]
2852
+ gs = GridSpec(2, 2, figure=fig)
2853
+
2854
+ ax1 = fig.add_subplot(gs[0, 0])
2855
+ ax1.plot(real_vals, 'o-', color='tab:green')
2856
+ ax1.set_title("Real Part")
2857
+
2858
+ ax2 = fig.add_subplot(gs[0, 1])
2859
+ ax2.plot(split_vals, 'o-', color='tab:brown')
2860
+ ax2.set_title("Split Part (j)")
2861
+
2862
+ ax3 = fig.add_subplot(gs[1, 0])
2863
+ ax3.plot(real_vals, split_vals, '.-')
2864
+ ax3.set_title("Trajectory (Real vs Split)")
2865
+ ax3.grid(True, alpha=0.3)
2866
+
2867
+ ax4 = fig.add_subplot(gs[1, 1])
2868
+ ax4.plot(u_vals, label='u = r+j')
2869
+ ax4.plot(v_vals, label='v = r-j')
2870
+ ax4.set_title("Light-Cone Coordinates")
2871
+ ax4.legend()
2872
+
2873
+ # --- 10. NeutrosophicNumber
2874
+ elif is_neutrosophic_like(first_elem):
2875
+ # t, i, f değerlerini al
2876
+ if hasattr(first_elem, 't'):
2877
+ t_vals = [x.t for x in sequence]
2878
+ i_vals = [x.i for x in sequence]
2879
+ f_vals = [x.f for x in sequence]
2880
+ elif hasattr(first_elem, 'a'):
2881
+ t_vals = [x.a for x in sequence]
2882
+ i_vals = [x.b for x in sequence]
2883
+ f_vals = [0] * len(sequence) # f yoksa sıfır
2884
+ elif hasattr(first_elem, 'value'):
2885
+ t_vals = [x.value for x in sequence]
2886
+ i_vals = [x.indeterminacy for x in sequence]
2887
+ f_vals = [0] * len(sequence)
2888
+ else:
2889
+ t_vals = i_vals = f_vals = []
2890
+
2891
+ gs = GridSpec(2, 2, figure=fig)
2892
+
2893
+ # 1. t, i, f zaman içinde
2894
+ ax1 = fig.add_subplot(gs[0, 0])
2895
+ ax1.plot(t_vals, 'o-', label='Truth (t)', color='tab:blue')
2896
+ ax1.plot(i_vals, 's-', label='Indeterminacy (i)', color='tab:orange')
2897
+ ax1.plot(f_vals, '^-', label='Falsity (f)', color='tab:red')
2898
+ ax1.set_title("Neutrosophic Components")
2899
+ ax1.set_xlabel("Iteration")
2900
+ ax1.set_ylabel("Value")
2901
+ ax1.legend()
2902
+ ax1.grid(True, alpha=0.3)
2903
+
2904
+ # 2. t vs i
2905
+ ax2 = fig.add_subplot(gs[0, 1])
2906
+ ax2.scatter(t_vals, i_vals, c=range(len(t_vals)), cmap='viridis', s=30)
2907
+ ax2.set_title("t vs i Trajectory")
2908
+ ax2.set_xlabel("Truth (t)")
2909
+ ax2.set_ylabel("Indeterminacy (i)")
2910
+ plt.colorbar(ax2.collections[0], ax=ax2, label="Step")
2911
+
2912
+ # 3. t vs f
2913
+ ax3 = fig.add_subplot(gs[1, 0])
2914
+ ax3.scatter(t_vals, f_vals, c=range(len(t_vals)), cmap='plasma', s=30)
2915
+ ax3.set_title("t vs f Trajectory")
2916
+ ax3.set_xlabel("Truth (t)")
2917
+ ax3.set_ylabel("Falsity (f)")
2918
+ plt.colorbar(ax3.collections[0], ax=ax3, label="Step")
2919
+
2920
+ # 4. Magnitude (t² + i² + f²)
2921
+ magnitudes = [np.sqrt(t**2 + i**2 + f**2) for t, i, f in zip(t_vals, i_vals, f_vals)]
2922
+ ax4 = fig.add_subplot(gs[1, 1])
2923
+ ax4.plot(magnitudes, 'o-', color='tab:purple')
2924
+ ax4.set_title("Magnitude √(t²+i²+f²)")
2925
+ ax4.set_ylabel("|n|")
2926
+
2927
+ # --- 11. NeutrosophiccomplexNumber
2928
+ elif (hasattr(first_elem, 'real') and hasattr(first_elem, 'imag') and
2929
+ hasattr(first_elem, 'indeterminacy')):
1433
2930
 
1434
- elif isinstance(first_elem, NeutrosophicBicomplexNumber):
2931
+ real_parts = [x.real for x in sequence]
2932
+ imag_parts = [x.imag for x in sequence]
2933
+ indeter_parts = [x.indeterminacy for x in sequence]
2934
+ magnitudes_z = [abs(complex(x.real, x.imag)) for x in sequence]
2935
+
2936
+ gs = GridSpec(2, 2, figure=fig)
2937
+
2938
+ # 1. Complex Plane
2939
+ ax1 = fig.add_subplot(gs[0, 0])
2940
+ ax1.plot(real_parts, imag_parts, '.-', alpha=0.7)
2941
+ ax1.scatter(real_parts[0], imag_parts[0], c='g', s=100, label='Start')
2942
+ ax1.scatter(real_parts[-1], imag_parts[-1], c='r', s=100, label='End')
2943
+ ax1.set_title("Complex Plane")
2944
+ ax1.set_xlabel("Re(z)")
2945
+ ax1.set_ylabel("Im(z)")
2946
+ ax1.legend()
2947
+ ax1.axis('equal')
2948
+
2949
+ # 2. Indeterminacy over time
2950
+ ax2 = fig.add_subplot(gs[0, 1])
2951
+ ax2.plot(indeter_parts, 'o-', color='tab:purple')
2952
+ ax2.set_title("Indeterminacy Level")
2953
+ ax2.set_ylabel("I")
2954
+
2955
+ # 3. |z| vs Indeterminacy
2956
+ ax3 = fig.add_subplot(gs[1, 0])
2957
+ sc = ax3.scatter(magnitudes_z, indeter_parts, c=range(len(magnitudes_z)), cmap='viridis', s=30)
2958
+ ax3.set_title("Magnitude vs Indeterminacy")
2959
+ ax3.set_xlabel("|z|")
2960
+ ax3.set_ylabel("I")
2961
+ plt.colorbar(sc, ax=ax3, label="Step")
2962
+
2963
+ # 4. Real vs Imag colored by I
2964
+ ax4 = fig.add_subplot(gs[1, 1])
2965
+ sc2 = ax4.scatter(real_parts, imag_parts, c=indeter_parts, cmap='plasma', s=40)
2966
+ ax4.set_title("Real vs Imag (colored by I)")
2967
+ ax4.set_xlabel("Re(z)")
2968
+ ax4.set_ylabel("Im(z)")
2969
+ plt.colorbar(sc2, ax=ax4, label="Indeterminacy")
2970
+
2971
+ # --- 12. HyperrealNumber
2972
+ elif hasattr(first_elem, 'sequence') and isinstance(first_elem.sequence, (list, np.ndarray)):
2973
+ seq_len = min(len(first_elem.sequence), 5) # İlk 5 bileşen
2974
+ data = np.array([x.sequence[:seq_len] for x in sequence])
2975
+ gs = GridSpec(2, 2, figure=fig)
2976
+
2977
+ ax1 = fig.add_subplot(gs[0, 0])
2978
+ for i in range(seq_len):
2979
+ ax1.plot(data[:, i], label=f'ε^{i}', alpha=0.8)
2980
+ ax1.set_title("Hyperreal Components")
2981
+ ax1.legend(ncol=2)
2982
+
2983
+ ax2 = fig.add_subplot(gs[0, 1])
2984
+ magnitudes = np.linalg.norm(data, axis=1)
2985
+ ax2.plot(magnitudes, 'o-', color='tab:purple')
2986
+ ax2.set_title("Magnitude")
2987
+
2988
+ ax3 = fig.add_subplot(gs[1, 0])
2989
+ ax3.plot(data[:, 0], 'o-', label='Standard Part')
2990
+ ax3.set_title("Standard Part (ε⁰)")
2991
+ ax3.legend()
2992
+
2993
+ ax4 = fig.add_subplot(gs[1, 1])
2994
+ sc = ax4.scatter(data[:, 0], data[:, 1], c=range(len(data)), cmap='viridis')
2995
+ ax4.set_title("Standard vs Infinitesimal")
2996
+ ax4.set_xlabel("Standard")
2997
+ ax4.set_ylabel("ε¹")
2998
+ plt.colorbar(sc, ax=ax4, label="Step")
2999
+
3000
+ # --- 13. BicomplexNumber
3001
+ elif hasattr(first_elem, 'z1') and hasattr(first_elem, 'z2'):
3002
+ z1_real = [x.z1.real for x in sequence]
3003
+ z1_imag = [x.z1.imag for x in sequence]
3004
+ z2_real = [x.z2.real for x in sequence]
3005
+ z2_imag = [x.z2.imag for x in sequence]
1435
3006
  gs = GridSpec(2, 2, figure=fig)
1436
- ax1, ax2 = fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[0, 1])
1437
- ax3, ax4 = fig.add_subplot(gs[1, 0]), fig.add_subplot(gs[1, 1])
1438
- ax1.plot([n.real for n in sequence], [n.imag for n in sequence], '.-'), ax1.set_title("Primary Deterministic")
1439
- ax2.plot([n.neut_real for n in sequence], [n.neut_imag for n in sequence], '.-'), ax2.set_title("Primary Neutrosophic")
1440
- ax3.plot([n.j_real for n in sequence], [n.j_imag for n in sequence], '.-'), ax3.set_title("Secondary Deterministic")
1441
- ax4.plot([n.j_neut_real for n in sequence], [n.j_neut_imag for n in sequence], '.-'), ax4.set_title("Secondary Neutrosophic")
1442
3007
 
3008
+ ax1 = fig.add_subplot(gs[0, 0])
3009
+ ax1.plot(z1_real, label='Re(z1)')
3010
+ ax1.plot(z1_imag, label='Im(z1)')
3011
+ ax1.set_title("Bicomplex z1")
3012
+ ax1.legend()
3013
+
3014
+ ax2 = fig.add_subplot(gs[0, 1])
3015
+ ax2.plot(z2_real, label='Re(z2)')
3016
+ ax2.plot(z2_imag, label='Im(z2)')
3017
+ ax2.set_title("Bicomplex z2")
3018
+ ax2.legend()
3019
+
3020
+ ax3 = fig.add_subplot(gs[1, 0])
3021
+ ax3.plot(z1_real, z1_imag, '.-')
3022
+ ax3.set_title("z1 Trajectory")
3023
+ ax3.set_xlabel("Re(z1)")
3024
+ ax3.set_ylabel("Im(z1)")
3025
+
3026
+ ax4 = fig.add_subplot(gs[1, 1])
3027
+ ax4.plot(z2_real, z2_imag, '.-')
3028
+ ax4.set_title("z2 Trajectory")
3029
+ ax4.set_xlabel("Re(z2)")
3030
+ ax4.set_ylabel("Im(z2)")
3031
+
3032
+ # --- 13. NeutrosophicBicomplexNumber ---
3033
+ elif hasattr(first_elem, 'real') and hasattr(first_elem, 'neut_real'):
3034
+ try:
3035
+ # Güvenli float dönüşümü
3036
+ comps = np.array([
3037
+ [float(getattr(x, attr))
3038
+ for attr in ['real', 'imag', 'neut_real', 'neut_imag',
3039
+ 'j_real', 'j_imag', 'j_neut_real', 'j_neut_imag']]
3040
+ for x in sequence
3041
+ ])
3042
+ magnitudes = np.linalg.norm(comps, axis=1)
3043
+ gs = GridSpec(2, 2, figure=fig)
3044
+
3045
+ ax1 = fig.add_subplot(gs[0, 0])
3046
+ for i, label in enumerate(['a', 'b', 'c', 'd']):
3047
+ ax1.plot(comps[:, i], label=label, alpha=0.7)
3048
+ ax1.set_title("First 4 Components")
3049
+ ax1.legend()
3050
+
3051
+ ax2 = fig.add_subplot(gs[0, 1])
3052
+ for i, label in enumerate(['e', 'f', 'g', 'h']):
3053
+ ax2.plot(comps[:, i + 4], label=label, alpha=0.7)
3054
+ ax2.set_title("Last 4 Components")
3055
+ ax2.legend()
3056
+
3057
+ ax3 = fig.add_subplot(gs[1, 0])
3058
+ ax3.plot(magnitudes, 'o-', color='tab:purple')
3059
+ ax3.set_title("Magnitude")
3060
+
3061
+ ax4 = fig.add_subplot(gs[1, 1])
3062
+ sc = ax4.scatter(comps[:, 0], comps[:, 1], c=range(len(comps)), cmap='plasma')
3063
+ ax4.set_title("a vs b Trajectory")
3064
+ ax4.set_xlabel("a")
3065
+ ax4.set_ylabel("b")
3066
+ plt.colorbar(sc, ax=ax4, label="Step")
3067
+
3068
+ except Exception as e:
3069
+ ax = fig.add_subplot(1, 1, 1)
3070
+ ax.text(0.5, 0.5, f"Plot error: {e}", ha='center', va='center', color='red')
3071
+ ax.set_xticks([])
3072
+ ax.set_yticks([])
3073
+
3074
+ # --- 15. Bilinmeyen tip
1443
3075
  else:
1444
3076
  ax = fig.add_subplot(1, 1, 1)
1445
- ax.text(0.5, 0.5, f"Plotting for '{type(first_elem).__name__}' not implemented.", ha='center')
1446
-
1447
- plt.tight_layout(rect=[0, 0, 1, 0.96])
3077
+ type_name = type(first_elem).__name__
3078
+ ax.text(0.5, 0.5, f"Plotting not implemented\nfor '{type_name}'",
3079
+ ha='center', va='center', fontsize=14, fontweight='bold', color='red')
3080
+ ax.set_xticks([])
3081
+ ax.set_yticks([])
3082
+
3083
+ plt.show()
3084
+
1448
3085
 
1449
3086
  # ==============================================================================
1450
3087
  # --- MAIN EXECUTION BLOCK ---
@@ -1463,9 +3100,9 @@ if __name__ == "__main__":
1463
3100
  # plt.show()
1464
3101
 
1465
3102
  # --- Example 2: Programmatic Generation and Plotting ---
1466
- print("\nRunning programmatic tests for all 11 number types...")
3103
+ print("\nRunning programmatic tests for all 16 number types...")
1467
3104
 
1468
- STEPS = 30
3105
+ STEPS = 40
1469
3106
  START_VAL = "2.5"
1470
3107
  ADD_VAL = 3.0
1471
3108
 
@@ -1474,11 +3111,13 @@ if __name__ == "__main__":
1474
3111
  "Complex": TYPE_COMPLEX, "Float": TYPE_FLOAT, "Rational": TYPE_RATIONAL,
1475
3112
  "Quaternion": TYPE_QUATERNION, "Neutrosophic": TYPE_NEUTROSOPHIC,
1476
3113
  "Neutrosophic Complex": TYPE_NEUTROSOPHIC_COMPLEX, "Hyperreal": TYPE_HYPERREAL,
1477
- "Bicomplex": TYPE_BICOMPLEX, "Neutrosophic Bicomplex": TYPE_NEUTROSOPHIC_BICOMPLEX
3114
+ "Bicomplex": TYPE_BICOMPLEX, "Neutrosophic Bicomplex": TYPE_NEUTROSOPHIC_BICOMPLEX,
3115
+ "Octonion": TYPE_OCTONION, "Sedenion": TYPE_SEDENION, "Clifford": TYPE_CLIFFORD,
3116
+ "Dual": TYPE_DUAL, "Splitcomplex": TYPE_SPLIT_COMPLEX,
1478
3117
  }
1479
3118
 
1480
3119
  types_to_plot = [
1481
- "Complex", "Quaternion", "Bicomplex", "Neutrosophic Complex", "Hyperreal"
3120
+ "Complex", "Quaternion", "Bicomplex", "Neutrosophic Complex", "Hyperreal", "Octonion", "Sedenion", "Clifford", "Dual", "Splitcompllex",
1482
3121
  ]
1483
3122
 
1484
3123
  for name, type_id in all_types.items():