kececinumbers 0.6.6__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.
- kececinumbers/__init__.py +175 -6
- kececinumbers/_version.py +1 -1
- kececinumbers/kececinumbers.py +2393 -717
- {kececinumbers-0.6.6.dist-info → kececinumbers-0.6.8.dist-info}/METADATA +1 -1
- kececinumbers-0.6.8.dist-info/RECORD +10 -0
- tests/test_sample.py +17 -18
- kececinumbers-0.6.6.dist-info/RECORD +0 -10
- {kececinumbers-0.6.6.dist-info → kececinumbers-0.6.8.dist-info}/WHEEL +0 -0
- {kececinumbers-0.6.6.dist-info → kececinumbers-0.6.8.dist-info}/licenses/LICENSE +0 -0
- {kececinumbers-0.6.6.dist-info → kececinumbers-0.6.8.dist-info}/top_level.txt +0 -0
kececinumbers/kececinumbers.py
CHANGED
@@ -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
|
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
|
71
|
-
|
72
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
92
|
-
self.
|
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.
|
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.
|
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
|
-
|
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
|
-
"""
|
111
|
-
|
112
|
-
|
113
|
-
|
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,
|
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,
|
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
|
-
|
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(
|
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:
|
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,
|
344
|
+
self.real / divisor,
|
345
|
+
self.imag / divisor,
|
346
|
+
self.indeterminacy / divisor
|
159
347
|
)
|
160
|
-
|
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(
|
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:
|
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
|
-
|
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
|
-
|
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) ->
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
234
|
-
|
473
|
+
self.z1 * other.z1 - self.z2 * other.z2,
|
474
|
+
self.z1 * other.z2 + self.z2 * other.z1
|
235
475
|
)
|
236
|
-
|
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,
|
239
|
-
if isinstance(
|
240
|
-
if
|
241
|
-
raise ZeroDivisionError("
|
242
|
-
return BicomplexNumber(self.z1 /
|
243
|
-
|
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
|
-
|
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
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
def
|
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(
|
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
|
266
|
-
|
267
|
-
|
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
|
568
|
+
def __truediv__(self, scalar):
|
271
569
|
if isinstance(scalar, (int, float)):
|
272
570
|
if scalar == 0:
|
273
|
-
raise ZeroDivisionError("
|
274
|
-
return NeutrosophicBicomplexNumber(
|
275
|
-
|
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
|
278
|
-
|
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
|
-
|
282
|
-
# ==============================================================================
|
586
|
+
def __ne__(self, other):
|
587
|
+
return not self.__eq__(other)
|
283
588
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
if
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
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
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
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
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
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
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
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
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
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
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
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
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
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
|
-
|
384
|
-
|
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
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
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
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
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
|
-
|
729
|
+
if not parts:
|
730
|
+
return "0.0"
|
731
|
+
return "".join(parts).replace("+-", "-")
|
408
732
|
|
409
733
|
|
410
|
-
|
411
|
-
|
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
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
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
|
-
|
424
|
-
|
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
|
437
|
-
|
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
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
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
|
-
|
449
|
-
|
450
|
-
|
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
|
-
|
453
|
-
|
857
|
+
if match:
|
858
|
+
return match.group(0)
|
454
859
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
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
|
-
|
482
|
-
|
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
|
489
|
-
"""
|
490
|
-
|
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
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
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
|
-
|
503
|
-
|
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
|
-
|
506
|
-
|
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
|
-
|
509
|
-
prime_events = []
|
510
|
-
current_q = q0
|
956
|
+
return result
|
511
957
|
|
512
|
-
|
513
|
-
|
514
|
-
|
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
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
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
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
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
|
-
"""
|
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
|
-
|
543
|
-
|
544
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
560
|
-
|
561
|
-
|
562
|
-
for
|
563
|
-
|
564
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
590
|
-
|
591
|
-
|
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
|
-
|
594
|
-
N = len(values)
|
595
|
-
powers = np.abs(fft(values))**2
|
596
|
-
freqs = fftfreq(N)
|
1162
|
+
return CliffordNumber(basis_dict)
|
597
1163
|
|
598
|
-
|
599
|
-
|
600
|
-
|
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
|
-
|
603
|
-
|
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
|
-
|
606
|
-
|
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
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
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
|
-
|
629
|
-
|
630
|
-
|
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
|
-
|
634
|
-
|
635
|
-
|
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
|
-
|
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
|
1506
|
+
def is_prime(n_input: Any) -> bool:
|
641
1507
|
"""
|
642
|
-
|
643
|
-
|
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
|
-
|
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
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
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
|
-
|
666
|
-
|
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
|
-
|
669
|
-
|
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
|
-
|
672
|
-
|
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
|
-
|
675
|
-
|
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
|
-
|
680
|
-
|
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
|
-
|
686
|
-
|
687
|
-
|
688
|
-
return kececi_zeta_zeros, 0.0
|
1614
|
+
trajectory = [q0]
|
1615
|
+
prime_events = []
|
1616
|
+
current_q = q0
|
689
1617
|
|
690
|
-
|
691
|
-
|
692
|
-
|
1618
|
+
for i in range(iterations):
|
1619
|
+
y = current_q + c
|
1620
|
+
processing_val = y
|
693
1621
|
|
694
|
-
|
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
|
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
|
-
|
710
|
-
|
711
|
-
|
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
|
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
|
-
|
731
|
-
('
|
732
|
-
('
|
733
|
-
('
|
734
|
-
('
|
735
|
-
|
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,
|
753
|
-
name = type_names
|
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("\
|
805
|
-
print("
|
806
|
-
|
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("\
|
813
|
-
print("
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
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
|
-
|
821
|
-
|
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
|
-
|
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,196 +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
|
-
|
1001
|
-
|
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
|
-
#
|
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))
|
2234
|
+
current_value = int(float(start_input_raw))
|
2235
|
+
add_value_typed = int(float(add_input_raw))
|
2236
|
+
ask_unit = 1
|
2237
|
+
use_integer_division = True
|
2238
|
+
|
1028
2239
|
elif kececi_type == TYPE_FLOAT:
|
1029
|
-
current_value = float(start_input_raw)
|
2240
|
+
current_value = float(start_input_raw)
|
2241
|
+
add_value_typed = float(add_input_raw)
|
2242
|
+
ask_unit = 1.0
|
2243
|
+
|
1030
2244
|
elif kececi_type == TYPE_RATIONAL:
|
1031
|
-
current_value = Fraction(start_input_raw)
|
2245
|
+
current_value = Fraction(start_input_raw)
|
2246
|
+
add_value_typed = Fraction(add_input_raw)
|
2247
|
+
ask_unit = Fraction(1)
|
2248
|
+
|
1032
2249
|
elif kececi_type == TYPE_COMPLEX:
|
1033
|
-
current_value = _parse_complex(start_input_raw)
|
2250
|
+
current_value = _parse_complex(start_input_raw)
|
2251
|
+
add_value_typed = _parse_complex(add_input_raw)
|
2252
|
+
ask_unit = 1 + 1j
|
2253
|
+
|
1034
2254
|
elif kececi_type == TYPE_QUATERNION:
|
1035
|
-
current_value = _parse_quaternion_from_csv(start_input_raw)
|
2255
|
+
current_value = _parse_quaternion_from_csv(start_input_raw)
|
2256
|
+
add_value_typed = _parse_quaternion_from_csv(add_input_raw)
|
2257
|
+
ask_unit = np.quaternion(1, 1, 1, 1)
|
2258
|
+
|
1036
2259
|
elif kececi_type == TYPE_NEUTROSOPHIC:
|
1037
|
-
|
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
|
+
|
1038
2266
|
elif kececi_type == TYPE_NEUTROSOPHIC_COMPLEX:
|
1039
|
-
s_complex = _parse_complex(start_input_raw)
|
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)
|
2271
|
+
ask_unit = NeutrosophicComplexNumber(1, 1, 1)
|
2272
|
+
|
1040
2273
|
elif kececi_type == TYPE_HYPERREAL:
|
1041
|
-
|
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
|
+
|
1042
2282
|
elif kececi_type == TYPE_BICOMPLEX:
|
1043
|
-
|
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
|
+
|
1044
2287
|
elif kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX:
|
1045
|
-
|
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
|
+
|
1046
2320
|
except (ValueError, TypeError) as e:
|
1047
2321
|
print(f"ERROR: Failed to initialize type {kececi_type} with start='{start_input_raw}' and increment='{add_input_raw}': {e}")
|
1048
2322
|
return []
|
1049
2323
|
|
1050
|
-
#
|
2324
|
+
# Log ve temizleme listelerini başlatın
|
1051
2325
|
clean_trajectory = [current_value]
|
1052
2326
|
full_log = [current_value]
|
1053
|
-
|
1054
2327
|
last_divisor_used = None
|
1055
|
-
ask_counter = 0
|
1056
|
-
|
1057
|
-
for
|
1058
|
-
#
|
2328
|
+
ask_counter = 0 # 0: +ask_unit, 1: -ask_unit
|
2329
|
+
|
2330
|
+
for step in range(iterations):
|
2331
|
+
# 1. Topla
|
1059
2332
|
added_value = current_value + add_value_typed
|
1060
|
-
|
1061
2333
|
next_q = added_value
|
1062
2334
|
divided_successfully = False
|
1063
2335
|
modified_value = None
|
1064
2336
|
|
2337
|
+
# primary_divisor ve alternative_divisor hesaplama
|
1065
2338
|
primary_divisor = 3 if last_divisor_used == 2 or last_divisor_used is None else 2
|
1066
2339
|
alternative_divisor = 2 if primary_divisor == 3 else 3
|
1067
|
-
|
2340
|
+
|
2341
|
+
# 2. Bölme dene
|
1068
2342
|
for divisor in [primary_divisor, alternative_divisor]:
|
1069
2343
|
if _is_divisible(added_value, divisor, kececi_type):
|
1070
2344
|
next_q = added_value // divisor if use_integer_division else added_value / divisor
|
1071
2345
|
last_divisor_used = divisor
|
1072
2346
|
divided_successfully = True
|
1073
2347
|
break
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
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
|
1080
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
|
1081
2363
|
for divisor in [primary_divisor, alternative_divisor]:
|
1082
2364
|
if _is_divisible(modified_value, divisor, kececi_type):
|
1083
2365
|
next_q = modified_value // divisor if use_integer_division else modified_value / divisor
|
1084
2366
|
last_divisor_used = divisor
|
1085
2367
|
break
|
1086
|
-
|
1087
|
-
#
|
2368
|
+
|
2369
|
+
# 4. Loglara ekle
|
1088
2370
|
full_log.append(added_value)
|
1089
2371
|
if modified_value is not None:
|
1090
2372
|
full_log.append(modified_value)
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
if not full_log or next_q != full_log[-1]:
|
1095
|
-
full_log.append(next_q)
|
1096
|
-
|
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
|
+
|
1097
2376
|
clean_trajectory.append(next_q)
|
1098
|
-
|
1099
|
-
# --- Durumu Güncelle ---
|
1100
2377
|
current_value = next_q
|
1101
|
-
|
1102
|
-
# --- 3. İsteğe Göre Doğru Listeyi Döndür ---
|
1103
|
-
if include_intermediate_steps:
|
1104
|
-
return full_log
|
1105
|
-
else:
|
1106
|
-
return clean_trajectory
|
1107
2378
|
|
1108
|
-
|
1109
|
-
|
1110
|
-
if not sequence:
|
1111
|
-
print("\n--- REPORT ---\nSequence could not be generated.")
|
1112
|
-
return
|
1113
|
-
|
1114
|
-
print("\n\n" + "="*50)
|
1115
|
-
print("--- DETAILED SEQUENCE REPORT ---")
|
1116
|
-
print("="*50)
|
2379
|
+
# --- SONUÇ ---
|
2380
|
+
return full_log if include_intermediate_steps else clean_trajectory
|
1117
2381
|
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
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}'")
|
1123
2396
|
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
kpn = find_kececi_prime_number(sequence)
|
1128
|
-
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!)
|
1129
2399
|
|
1130
|
-
print("\n[Sequence Preview]")
|
1131
|
-
preview_count = min(len(sequence), 30)
|
1132
|
-
print(f" --- First {preview_count} Numbers ---")
|
1133
|
-
for i in range(preview_count):
|
1134
|
-
print(f" {i}: {sequence[i]}")
|
1135
2400
|
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
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}...")
|
1140
2414
|
|
1141
|
-
|
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.")
|
1142
2423
|
|
1143
|
-
|
1144
|
-
show_all = input("Do you want to print the full sequence? (y/n): ").lower().strip()
|
1145
|
-
if show_all in ['y', 'n']:
|
1146
|
-
break
|
1147
|
-
|
1148
|
-
if show_all == 'y':
|
1149
|
-
print("\n--- FULL SEQUENCE ---")
|
1150
|
-
for i, num in enumerate(sequence):
|
1151
|
-
print(f"{i}: {num}")
|
1152
|
-
print("="*50)
|
2424
|
+
return generated_sequence
|
1153
2425
|
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
2426
|
+
except Exception as e:
|
2427
|
+
print(f"ERROR during sequence generation: {e}")
|
2428
|
+
import traceback
|
2429
|
+
traceback.print_exc()
|
2430
|
+
return []
|
1157
2431
|
|
1158
|
-
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]:
|
1159
|
-
"""Generates Keçeci Numbers with specified parameters, supporting full vectorial addition."""
|
1160
|
-
print(f"\n--- Generating Sequence: Type {kececi_type_choice}, Steps {iterations} ---")
|
1161
|
-
print(f"Start: '{start_value_raw}', Increment: '{add_value_raw}'")
|
1162
|
-
if include_intermediate_steps:
|
1163
|
-
print("Mode: Detailed (including intermediate steps)")
|
1164
|
-
|
1165
|
-
generated_sequence = unified_generator(
|
1166
|
-
kececi_type_choice,
|
1167
|
-
start_value_raw,
|
1168
|
-
add_value_raw,
|
1169
|
-
iterations,
|
1170
|
-
# Yeni parametreyi aktar
|
1171
|
-
include_intermediate_steps=include_intermediate_steps
|
1172
|
-
)
|
1173
|
-
|
1174
|
-
if generated_sequence:
|
1175
|
-
print(f"Generated {len(generated_sequence)} numbers. Preview: {generated_sequence[:30]}...")
|
1176
|
-
kpn = find_kececi_prime_number(generated_sequence)
|
1177
|
-
if kpn is not None:
|
1178
|
-
print(f"Keçeci Prime Number for this sequence: {kpn}")
|
1179
|
-
else:
|
1180
|
-
print("No repeating Keçeci Prime Number found.")
|
1181
|
-
else:
|
1182
|
-
print("Sequence generation failed.")
|
1183
|
-
|
1184
|
-
return generated_sequence
|
1185
2432
|
|
1186
2433
|
def get_interactive() -> Tuple[List[Any], Dict[str, Any]]:
|
1187
2434
|
"""
|
@@ -1189,50 +2436,99 @@ def get_interactive() -> Tuple[List[Any], Dict[str, Any]]:
|
|
1189
2436
|
This version is improved for code clarity and compatibility with the module's
|
1190
2437
|
current interface.
|
1191
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
|
+
|
1192
2459
|
print("\n--- Keçeci Numbers Interactive Generator ---")
|
1193
|
-
print(" 1: Positive Real 2: Negative Real
|
1194
|
-
print(" 4: Float 5: Rational
|
1195
|
-
print(" 7: Neutrosophic 8: Neutro-Complex
|
1196
|
-
print(" 10: 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")
|
1197
2466
|
|
1198
2467
|
# Get a valid number type from the user
|
1199
2468
|
while True:
|
1200
2469
|
try:
|
1201
|
-
type_choice = int(input("Select a Keçeci Number Type (1-
|
1202
|
-
if 1 <= type_choice <=
|
2470
|
+
type_choice = int(input("Select a Keçeci Number Type (1-16): "))
|
2471
|
+
if 1 <= type_choice <= 16:
|
1203
2472
|
break
|
1204
|
-
print("Invalid type. Please enter a number between 1 and
|
2473
|
+
print("Invalid type. Please enter a number between 1 and 16.")
|
1205
2474
|
except ValueError:
|
1206
2475
|
print("Invalid input. Please enter a number.")
|
1207
2476
|
|
1208
2477
|
# User prompts for the starting value
|
1209
2478
|
start_prompts = {
|
1210
|
-
1: "Enter
|
1211
|
-
2: "Enter
|
1212
|
-
3: "Enter
|
1213
|
-
4: "Enter
|
1214
|
-
5: "Enter
|
1215
|
-
6: "Enter
|
1216
|
-
7: "Enter
|
1217
|
-
8: "Enter
|
1218
|
-
9: "Enter
|
1219
|
-
10: "Enter
|
1220
|
-
11: "Enter
|
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'): ",
|
1221
2495
|
}
|
1222
2496
|
|
1223
2497
|
# User prompts for the increment value
|
1224
2498
|
add_prompts = {
|
1225
|
-
|
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'): ",
|
1226
2515
|
}
|
1227
|
-
default_add_prompt = "Enter increment value (e.g., '9.0'): "
|
1228
2516
|
|
1229
2517
|
# Get inputs from the user
|
1230
2518
|
start_input_val_raw = input(start_prompts.get(type_choice, "Enter starting value: "))
|
1231
|
-
add_input_val_raw = input(add_prompts.get(type_choice,
|
1232
|
-
|
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.")
|
1233
2529
|
|
1234
2530
|
show_details_input = input("Do you want to include the intermediate calculation steps? (y/n): ").lower().strip()
|
1235
|
-
show_details = (show_details_input == 'y')
|
2531
|
+
show_details = (show_details_input == 'y' or show_details_input == 'yes')
|
1236
2532
|
|
1237
2533
|
# Generate the sequence with the correct parameter names and values
|
1238
2534
|
sequence = get_with_params(
|
@@ -1268,7 +2564,7 @@ def find_period(sequence: List[Any], min_repeats: int = 3) -> Optional[List[Any]
|
|
1268
2564
|
Returns:
|
1269
2565
|
The repeating cycle as a list if found, otherwise None.
|
1270
2566
|
"""
|
1271
|
-
if len(sequence) <
|
2567
|
+
if len(sequence) < 4: # Çok kısa dizilerde periyot aramak anlamsız
|
1272
2568
|
return None
|
1273
2569
|
|
1274
2570
|
# Olası periyot uzunluklarını dizinin yarısına kadar kontrol et
|
@@ -1297,119 +2593,497 @@ def find_period(sequence: List[Any], min_repeats: int = 3) -> Optional[List[Any]
|
|
1297
2593
|
# Hiçbir periyot bulunamadı
|
1298
2594
|
return None
|
1299
2595
|
|
1300
|
-
def
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
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
|
1312
2607
|
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
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'))
|
1320
2614
|
|
1321
2615
|
def plot_numbers(sequence: List[Any], title: str = "Keçeci Number Sequence Analysis"):
|
1322
|
-
"""
|
1323
|
-
|
1324
|
-
|
2616
|
+
"""
|
2617
|
+
Tüm 16 Keçeci Sayı türü için detaylı görselleştirme sağlar.
|
2618
|
+
"""
|
1325
2619
|
if not sequence:
|
1326
|
-
print("Sequence is empty
|
2620
|
+
print("Sequence is empty. Nothing to plot.")
|
1327
2621
|
return
|
1328
2622
|
|
1329
|
-
fig = plt.figure(figsize=(
|
1330
|
-
|
2623
|
+
fig = plt.figure(figsize=(18, 14), constrained_layout=True)
|
2624
|
+
fig.suptitle(title, fontsize=18, fontweight='bold')
|
2625
|
+
|
1331
2626
|
first_elem = sequence[0]
|
1332
|
-
|
1333
|
-
|
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)):
|
1334
2660
|
ax = fig.add_subplot(1, 1, 1)
|
1335
|
-
ax.plot([float(x) for x in sequence], 'o-',
|
1336
|
-
ax.set_title("
|
1337
|
-
ax.set_xlabel("
|
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)
|
1338
2666
|
|
2667
|
+
# --- 3. Complex
|
1339
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)
|
1340
2731
|
gs = GridSpec(2, 2, figure=fig)
|
1341
|
-
|
1342
|
-
real_parts, imag_parts = [c.real for c in sequence], [c.imag for c in sequence]
|
1343
|
-
ax1.plot(real_parts, 'o-', label='Real Part'), ax1.set_title("Real Part"), ax1.legend()
|
1344
|
-
ax2.plot(imag_parts, 'o-', color='red', label='Imaginary Part'), ax2.set_title("Imaginary Part"), ax2.legend()
|
1345
|
-
ax3.plot(real_parts, imag_parts, '.-', label='Trajectory')
|
1346
|
-
ax3.scatter(real_parts[0], imag_parts[0], c='g', s=100, label='Start', zorder=5)
|
1347
|
-
ax3.scatter(real_parts[-1], imag_parts[-1], c='r', s=100, label='End', zorder=5)
|
1348
|
-
ax3.set_title("Trajectory in Complex Plane"), ax3.set_xlabel("Real"), ax3.set_ylabel("Imaginary"), ax3.legend(), ax3.axis('equal')
|
1349
|
-
|
1350
|
-
elif isinstance(first_elem, np.quaternion):
|
1351
|
-
gs = GridSpec(2, 1, figure=fig)
|
2732
|
+
|
1352
2733
|
ax1 = fig.add_subplot(gs[0, 0])
|
1353
|
-
|
1354
|
-
|
1355
|
-
ax1.
|
1356
|
-
ax1.
|
1357
|
-
|
1358
|
-
ax2
|
1359
|
-
|
1360
|
-
|
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)
|
1361
2758
|
gs = GridSpec(2, 2, figure=fig)
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
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')):
|
1398
2932
|
|
1399
|
-
|
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]
|
1400
3008
|
gs = GridSpec(2, 2, figure=fig)
|
1401
|
-
ax1, ax2 = fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[0, 1])
|
1402
|
-
ax3, ax4 = fig.add_subplot(gs[1, 0]), fig.add_subplot(gs[1, 1])
|
1403
|
-
ax1.plot([n.real for n in sequence], [n.imag for n in sequence], '.-'), ax1.set_title("Primary Deterministic")
|
1404
|
-
ax2.plot([n.neut_real for n in sequence], [n.neut_imag for n in sequence], '.-'), ax2.set_title("Primary Neutrosophic")
|
1405
|
-
ax3.plot([n.j_real for n in sequence], [n.j_imag for n in sequence], '.-'), ax3.set_title("Secondary Deterministic")
|
1406
|
-
ax4.plot([n.j_neut_real for n in sequence], [n.j_neut_imag for n in sequence], '.-'), ax4.set_title("Secondary Neutrosophic")
|
1407
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
|
1408
3077
|
else:
|
1409
3078
|
ax = fig.add_subplot(1, 1, 1)
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
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
|
+
|
1413
3087
|
|
1414
3088
|
# ==============================================================================
|
1415
3089
|
# --- MAIN EXECUTION BLOCK ---
|
@@ -1428,9 +3102,9 @@ if __name__ == "__main__":
|
|
1428
3102
|
# plt.show()
|
1429
3103
|
|
1430
3104
|
# --- Example 2: Programmatic Generation and Plotting ---
|
1431
|
-
print("\nRunning programmatic tests for all
|
3105
|
+
print("\nRunning programmatic tests for all 16 number types...")
|
1432
3106
|
|
1433
|
-
STEPS =
|
3107
|
+
STEPS = 40
|
1434
3108
|
START_VAL = "2.5"
|
1435
3109
|
ADD_VAL = 3.0
|
1436
3110
|
|
@@ -1439,11 +3113,13 @@ if __name__ == "__main__":
|
|
1439
3113
|
"Complex": TYPE_COMPLEX, "Float": TYPE_FLOAT, "Rational": TYPE_RATIONAL,
|
1440
3114
|
"Quaternion": TYPE_QUATERNION, "Neutrosophic": TYPE_NEUTROSOPHIC,
|
1441
3115
|
"Neutrosophic Complex": TYPE_NEUTROSOPHIC_COMPLEX, "Hyperreal": TYPE_HYPERREAL,
|
1442
|
-
"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,
|
1443
3119
|
}
|
1444
3120
|
|
1445
3121
|
types_to_plot = [
|
1446
|
-
"Complex", "Quaternion", "Bicomplex", "Neutrosophic Complex", "Hyperreal"
|
3122
|
+
"Complex", "Quaternion", "Bicomplex", "Neutrosophic Complex", "Hyperreal", "Octonion", "Sedenion", "Clifford", "Dual", "Splitcompllex",
|
1447
3123
|
]
|
1448
3124
|
|
1449
3125
|
for name, type_id in all_types.items():
|