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