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