kececinumbers 0.2.0__py3-none-any.whl → 0.2.1__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/kececinumbers.py +785 -540
- {kececinumbers-0.2.0.dist-info → kececinumbers-0.2.1.dist-info}/METADATA +91 -23
- kececinumbers-0.2.1.dist-info/RECORD +8 -0
- {kececinumbers-0.2.0.dist-info → kececinumbers-0.2.1.dist-info}/WHEEL +1 -1
- kececinumbers-0.2.0.dist-info/RECORD +0 -8
- {kececinumbers-0.2.0.dist-info → kececinumbers-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {kececinumbers-0.2.0.dist-info → kececinumbers-0.2.1.dist-info}/top_level.txt +0 -0
kececinumbers/kececinumbers.py
CHANGED
@@ -1,628 +1,873 @@
|
|
1
|
-
|
1
|
+
### `kececinumbers.py`
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
# -*- coding: utf-8 -*-
|
4
|
+
"""
|
5
|
+
Keçeci Numbers Module (kececinumbers.py)
|
6
|
+
|
7
|
+
This module provides a comprehensive framework for generating, analyzing, and
|
8
|
+
visualizing Keçeci Numbers across various number systems. It supports 11
|
9
|
+
distinct types, from standard integers and complex numbers to more exotic
|
10
|
+
constructs like neutrosophic and bicomplex numbers.
|
11
|
+
|
12
|
+
The core of the module is the `unified_generator`, which implements the
|
13
|
+
specific algorithm for creating Keçeci Number sequences. High-level functions
|
14
|
+
are available for easy interaction, parameter-based generation, and plotting.
|
15
|
+
|
16
|
+
Key Features:
|
17
|
+
- Generation of 11 types of Keçeci Numbers.
|
18
|
+
- A robust, unified algorithm for all number types.
|
19
|
+
- Helper functions for mathematical properties like primality and divisibility.
|
20
|
+
- Advanced plotting capabilities tailored to each number system.
|
21
|
+
- Functions for interactive use or programmatic integration.
|
22
|
+
"""
|
23
|
+
|
24
|
+
# --- Standard Library Imports ---
|
25
|
+
import collections
|
6
26
|
import math
|
27
|
+
import random
|
28
|
+
from dataclasses import dataclass
|
7
29
|
from fractions import Fraction
|
8
|
-
import quaternion # pip install numpy numpy-quaternion
|
9
|
-
import collections
|
10
30
|
|
31
|
+
# --- Third-Party Imports ---
|
32
|
+
import matplotlib.pyplot as plt
|
33
|
+
import numpy as np
|
34
|
+
import quaternion # Requires: pip install numpy numpy-quaternion
|
35
|
+
from matplotlib.gridspec import GridSpec
|
36
|
+
|
37
|
+
# ==============================================================================
|
38
|
+
# --- MODULE CONSTANTS: KEÇECI NUMBER TYPES ---
|
39
|
+
# ==============================================================================
|
40
|
+
TYPE_POSITIVE_REAL = 1
|
41
|
+
TYPE_NEGATIVE_REAL = 2
|
42
|
+
TYPE_COMPLEX = 3
|
43
|
+
TYPE_FLOAT = 4
|
44
|
+
TYPE_RATIONAL = 5
|
45
|
+
TYPE_QUATERNION = 6
|
46
|
+
TYPE_NEUTROSOPHIC = 7
|
47
|
+
TYPE_NEUTROSOPHIC_COMPLEX = 8
|
48
|
+
TYPE_HYPERREAL = 9
|
49
|
+
TYPE_BICOMPLEX = 10
|
50
|
+
TYPE_NEUTROSOPHIC_BICOMPLEX = 11
|
51
|
+
|
52
|
+
# ==============================================================================
|
53
|
+
# --- CUSTOM NUMBER CLASS DEFINITIONS ---
|
54
|
+
# ==============================================================================
|
55
|
+
|
56
|
+
@dataclass
|
57
|
+
class NeutrosophicNumber:
|
58
|
+
"""
|
59
|
+
Represents a neutrosophic number of the form a + bI, where I is the
|
60
|
+
indeterminate part and I^2 = I.
|
61
|
+
|
62
|
+
Attributes:
|
63
|
+
a (float): The determinate part.
|
64
|
+
b (float): The indeterminate part.
|
65
|
+
"""
|
66
|
+
a: float
|
67
|
+
b: float
|
68
|
+
|
69
|
+
def __add__(self, other):
|
70
|
+
if isinstance(other, NeutrosophicNumber):
|
71
|
+
return NeutrosophicNumber(self.a + other.a, self.b + other.b)
|
72
|
+
return NeutrosophicNumber(self.a + other, self.b)
|
73
|
+
|
74
|
+
def __sub__(self, other):
|
75
|
+
if isinstance(other, NeutrosophicNumber):
|
76
|
+
return NeutrosophicNumber(self.a - other.a, self.b - other.b)
|
77
|
+
return NeutrosophicNumber(self.a - other, self.b)
|
78
|
+
|
79
|
+
def __mul__(self, other):
|
80
|
+
if isinstance(other, NeutrosophicNumber):
|
81
|
+
# (a + bI)(c + dI) = ac + (ad + bc + bd)I
|
82
|
+
return NeutrosophicNumber(
|
83
|
+
self.a * other.a,
|
84
|
+
self.a * other.b + self.b * other.a + self.b * other.b
|
85
|
+
)
|
86
|
+
return NeutrosophicNumber(self.a * other, self.b * other)
|
87
|
+
|
88
|
+
def __truediv__(self, divisor):
|
89
|
+
if isinstance(divisor, (int, float)):
|
90
|
+
return NeutrosophicNumber(self.a / divisor, self.b / divisor)
|
91
|
+
raise TypeError("Only scalar division is supported for NeutrosophicNumber.")
|
92
|
+
|
93
|
+
def __str__(self):
|
94
|
+
return f"{self.a} + {self.b}I"
|
95
|
+
|
96
|
+
@dataclass
|
97
|
+
class NeutrosophicComplexNumber:
|
98
|
+
"""
|
99
|
+
Represents a neutrosophic-complex number, combining a standard complex number
|
100
|
+
(real + imag*j) with an independent level of indeterminacy (I).
|
101
|
+
|
102
|
+
This object models systems where a value has both a complex-valued state
|
103
|
+
(like quantum amplitude) and an associated level of uncertainty or
|
104
|
+
unreliability (like quantum decoherence).
|
105
|
+
|
106
|
+
Attributes:
|
107
|
+
real (float): The real part of the deterministic component.
|
108
|
+
imag (float): The imaginary part of the deterministic component.
|
109
|
+
indeterminacy (float): The coefficient of the indeterminate part, I.
|
110
|
+
"""
|
111
|
+
|
112
|
+
def __init__(self, real: float = 0.0, imag: float = 0.0, indeterminacy: float = 0.0):
|
113
|
+
"""
|
114
|
+
Initialises a NeutrosophicComplexNumber.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
real (float): The initial real part. Defaults to 0.0.
|
118
|
+
imag (float): The initial imaginary part. Defaults to 0.0.
|
119
|
+
indeterminacy (float): The initial indeterminacy level. Defaults to 0.0.
|
120
|
+
"""
|
121
|
+
self.real = float(real)
|
122
|
+
self.imag = float(imag)
|
123
|
+
self.indeterminacy = float(indeterminacy)
|
124
|
+
|
125
|
+
def __repr__(self) -> str:
|
126
|
+
"""
|
127
|
+
Returns an unambiguous, developer-friendly representation of the object.
|
128
|
+
"""
|
129
|
+
return f"NeutrosophicComplexNumber(real={self.real}, imag={self.imag}, indeterminacy={self.indeterminacy})"
|
130
|
+
|
131
|
+
def __str__(self) -> str:
|
132
|
+
"""
|
133
|
+
Returns a user-friendly string representation of the object.
|
134
|
+
"""
|
135
|
+
# Shows a sign for the imaginary part for clarity (e.g., +1.0j, -2.0j)
|
136
|
+
return f"({self.real}{self.imag:+}j) + {self.indeterminacy}I"
|
137
|
+
|
138
|
+
# --- Mathematical Operations ---
|
139
|
+
|
140
|
+
def __add__(self, other):
|
141
|
+
"""Adds another number to this one."""
|
142
|
+
if isinstance(other, NeutrosophicComplexNumber):
|
143
|
+
return NeutrosophicComplexNumber(
|
144
|
+
self.real + other.real,
|
145
|
+
self.imag + other.imag,
|
146
|
+
self.indeterminacy + other.indeterminacy
|
147
|
+
)
|
148
|
+
# Allows adding a scalar (int/float) to the real part.
|
149
|
+
elif isinstance(other, (int, float)):
|
150
|
+
return NeutrosophicComplexNumber(self.real + other, self.imag, self.indeterminacy)
|
151
|
+
return NotImplemented
|
152
|
+
|
153
|
+
def __sub__(self, other):
|
154
|
+
"""Subtracts another number from this one."""
|
155
|
+
if isinstance(other, NeutrosophicComplexNumber):
|
156
|
+
return NeutrosophicComplexNumber(
|
157
|
+
self.real - other.real,
|
158
|
+
self.imag - other.imag,
|
159
|
+
self.indeterminacy - other.indeterminacy
|
160
|
+
)
|
161
|
+
elif isinstance(other, (int, float)):
|
162
|
+
return NeutrosophicComplexNumber(self.real - other, self.imag, self.indeterminacy)
|
163
|
+
return NotImplemented
|
164
|
+
|
165
|
+
def __mul__(self, other):
|
166
|
+
"""
|
167
|
+
Multiplies this number by another number (scalar, complex, or neutrosophic-complex).
|
168
|
+
This is the most critical operation for complex dynamics.
|
169
|
+
"""
|
170
|
+
if isinstance(other, NeutrosophicComplexNumber):
|
171
|
+
# (a+bj)*(c+dj) = (ac-bd) + (ad+bc)j
|
172
|
+
new_real = self.real * other.real - self.imag * other.imag
|
173
|
+
new_imag = self.real * other.imag + self.imag * other.real
|
174
|
+
|
175
|
+
# The indeterminacy grows based on both original indeterminacies and
|
176
|
+
# the magnitude of the deterministic part, creating rich, non-linear behaviour.
|
177
|
+
new_indeterminacy = self.indeterminacy + other.indeterminacy + (self.magnitude_sq() * other.indeterminacy)
|
178
|
+
|
179
|
+
return NeutrosophicComplexNumber(new_real, new_imag, new_indeterminacy)
|
180
|
+
|
181
|
+
elif isinstance(other, complex):
|
182
|
+
# Multiply by a standard Python complex number
|
183
|
+
new_real = self.real * other.real - self.imag * other.imag
|
184
|
+
new_imag = self.real * other.imag + self.imag * other.real
|
185
|
+
# The indeterminacy is unaffected when multiplied by a purely deterministic complex number.
|
186
|
+
return NeutrosophicComplexNumber(new_real, new_imag, self.indeterminacy)
|
187
|
+
|
188
|
+
elif isinstance(other, (int, float)):
|
189
|
+
# Multiply by a scalar
|
190
|
+
return NeutrosophicComplexNumber(
|
191
|
+
self.real * other,
|
192
|
+
self.imag * other,
|
193
|
+
self.indeterminacy * other
|
194
|
+
)
|
195
|
+
return NotImplemented
|
196
|
+
|
197
|
+
def __truediv__(self, divisor):
|
198
|
+
"""Divides this number by a scalar."""
|
199
|
+
if isinstance(divisor, (int, float)):
|
200
|
+
if divisor == 0:
|
201
|
+
raise ZeroDivisionError("Cannot divide a NeutrosophicComplexNumber by zero.")
|
202
|
+
return NeutrosophicComplexNumber(
|
203
|
+
self.real / divisor,
|
204
|
+
self.imag / divisor,
|
205
|
+
self.indeterminacy / divisor
|
206
|
+
)
|
207
|
+
raise TypeError("Only scalar division is supported for NeutrosophicComplexNumber.")
|
208
|
+
|
209
|
+
# --- Reversed Mathematical Operations ---
|
210
|
+
|
211
|
+
def __radd__(self, other):
|
212
|
+
"""Handles cases like `5 + my_number`."""
|
213
|
+
return self.__add__(other)
|
214
|
+
|
215
|
+
def __rsub__(self, other):
|
216
|
+
"""Handles cases like `5 - my_number`."""
|
217
|
+
if isinstance(other, (int, float)):
|
218
|
+
return NeutrosophicComplexNumber(other - self.real, -self.imag, -self.indeterminacy)
|
219
|
+
return NotImplemented
|
220
|
+
|
221
|
+
def __rmul__(self, other):
|
222
|
+
"""Handles cases like `5 * my_number`."""
|
223
|
+
return self.__mul__(other)
|
224
|
+
|
225
|
+
# --- Unary and Comparison Operations ---
|
226
|
+
|
227
|
+
def __neg__(self):
|
228
|
+
"""Returns the negative of the number."""
|
229
|
+
return NeutrosophicComplexNumber(-self.real, -self.imag, self.indeterminacy)
|
230
|
+
|
231
|
+
def __eq__(self, other) -> bool:
|
232
|
+
"""Checks for equality between two numbers."""
|
233
|
+
if not isinstance(other, NeutrosophicComplexNumber):
|
234
|
+
return False
|
235
|
+
return (self.real == other.real and
|
236
|
+
self.imag == other.imag and
|
237
|
+
self.indeterminacy == other.indeterminacy)
|
238
|
+
|
239
|
+
# --- Helper Methods ---
|
240
|
+
|
241
|
+
def magnitude_sq(self) -> float:
|
242
|
+
"""Returns the squared magnitude of the deterministic (complex) part."""
|
243
|
+
return self.real**2 + self.imag**2
|
244
|
+
|
245
|
+
def magnitude(self) -> float:
|
246
|
+
"""Returns the magnitude (modulus or absolute value) of the deterministic part."""
|
247
|
+
return math.sqrt(self.magnitude_sq())
|
248
|
+
|
249
|
+
def deterministic_part(self) -> complex:
|
250
|
+
"""Returns the deterministic part as a standard Python complex number."""
|
251
|
+
return complex(self.real, self.imag)
|
252
|
+
|
253
|
+
|
254
|
+
@dataclass
|
255
|
+
class HyperrealNumber:
|
256
|
+
"""
|
257
|
+
Represents a hyperreal number as a sequence of real numbers.
|
258
|
+
Operations are performed element-wise on the sequences.
|
259
|
+
|
260
|
+
Attributes:
|
261
|
+
sequence (list[float]): The sequence representing the hyperreal.
|
262
|
+
"""
|
263
|
+
sequence: list
|
264
|
+
|
265
|
+
def __add__(self, other):
|
266
|
+
if isinstance(other, HyperrealNumber):
|
267
|
+
return HyperrealNumber([a + b for a, b in zip(self.sequence, other.sequence)])
|
268
|
+
raise TypeError("Unsupported operand for +: HyperrealNumber and non-HyperrealNumber.")
|
269
|
+
|
270
|
+
def __sub__(self, other):
|
271
|
+
if isinstance(other, HyperrealNumber):
|
272
|
+
return HyperrealNumber([a - b for a, b in zip(self.sequence, other.sequence)])
|
273
|
+
raise TypeError("Unsupported operand for -: HyperrealNumber and non-HyperrealNumber.")
|
274
|
+
|
275
|
+
# --- YENİ EKLENEN DÜZELTME ---
|
276
|
+
# --- NEWLY ADDED FIX ---
|
277
|
+
def __mul__(self, scalar):
|
278
|
+
"""Handles multiplication by a scalar (int or float)."""
|
279
|
+
if isinstance(scalar, (int, float)):
|
280
|
+
return HyperrealNumber([x * scalar for x in self.sequence])
|
281
|
+
raise TypeError(f"Unsupported operand for *: HyperrealNumber and {type(scalar).__name__}")
|
282
|
+
|
283
|
+
def __rmul__(self, scalar):
|
284
|
+
"""Handles the case where the scalar is on the left (e.g., float * HyperrealNumber)."""
|
285
|
+
return self.__mul__(scalar)
|
286
|
+
# --- DÜZELTME SONU ---
|
287
|
+
# --- END OF FIX ---
|
288
|
+
|
289
|
+
def __truediv__(self, divisor):
|
290
|
+
if isinstance(divisor, (int, float)):
|
291
|
+
if divisor == 0:
|
292
|
+
raise ZeroDivisionError("Scalar division by zero.")
|
293
|
+
return HyperrealNumber([x / divisor for x in self.sequence])
|
294
|
+
raise TypeError("Only scalar division is supported.")
|
295
|
+
|
296
|
+
def __mod__(self, divisor):
|
297
|
+
if isinstance(divisor, (int, float)):
|
298
|
+
return [x % divisor for x in self.sequence]
|
299
|
+
raise TypeError("Modulo operation only supported with a scalar divisor.")
|
300
|
+
|
301
|
+
def __str__(self):
|
302
|
+
return f"Hyperreal({self.sequence[:3]}...)"
|
303
|
+
|
304
|
+
@dataclass
|
305
|
+
class BicomplexNumber:
|
306
|
+
"""
|
307
|
+
Represents a bicomplex number of the form z1 + j*z2, where z1 and z2
|
308
|
+
are standard complex numbers, i^2 = -1, and j^2 = -1.
|
309
|
+
|
310
|
+
Attributes:
|
311
|
+
z1 (complex): The first complex component.
|
312
|
+
z2 (complex): The second complex component (coefficient of j).
|
313
|
+
"""
|
314
|
+
z1: complex
|
315
|
+
z2: complex
|
316
|
+
|
317
|
+
def __add__(self, other):
|
318
|
+
if isinstance(other, BicomplexNumber):
|
319
|
+
return BicomplexNumber(self.z1 + other.z1, self.z2 + other.z2)
|
320
|
+
raise TypeError("Unsupported operand for +: BicomplexNumber and non-BicomplexNumber.")
|
321
|
+
|
322
|
+
def __sub__(self, other):
|
323
|
+
if isinstance(other, BicomplexNumber):
|
324
|
+
return BicomplexNumber(self.z1 - other.z1, self.z2 - other.z2)
|
325
|
+
raise TypeError("Unsupported operand for -: BicomplexNumber and non-BicomplexNumber.")
|
326
|
+
|
327
|
+
def __mul__(self, other):
|
328
|
+
if isinstance(other, BicomplexNumber):
|
329
|
+
# (z1 + z2j)(w1 + w2j) = (z1w1 - z2w2) + (z1w2 + z2w1)j
|
330
|
+
return BicomplexNumber(
|
331
|
+
(self.z1 * other.z1) - (self.z2 * other.z2),
|
332
|
+
(self.z1 * other.z2) + (self.z2 * other.z1)
|
333
|
+
)
|
334
|
+
raise TypeError("Unsupported operand for *: BicomplexNumber and non-BicomplexNumber.")
|
335
|
+
|
336
|
+
def __truediv__(self, scalar):
|
337
|
+
if isinstance(scalar, (int, float)):
|
338
|
+
return BicomplexNumber(self.z1 / scalar, self.z2 / scalar)
|
339
|
+
raise TypeError("Only scalar division is supported.")
|
340
|
+
|
341
|
+
def __str__(self):
|
342
|
+
return f"Bicomplex({self.z1}, {self.z2})"
|
343
|
+
|
344
|
+
@dataclass
|
345
|
+
class NeutrosophicBicomplexNumber:
|
346
|
+
"""
|
347
|
+
Represents a highly complex number with multiple components.
|
348
|
+
NOTE: The multiplication implemented here is a simplified, element-wise
|
349
|
+
operation for demonstrative purposes and is not mathematically rigorous.
|
350
|
+
The true algebraic multiplication is exceedingly complex.
|
351
|
+
"""
|
352
|
+
real: float
|
353
|
+
imag: float
|
354
|
+
neut_real: float
|
355
|
+
neut_imag: float
|
356
|
+
j_real: float
|
357
|
+
j_imag: float
|
358
|
+
j_neut_real: float
|
359
|
+
j_neut_imag: float
|
360
|
+
|
361
|
+
def __add__(self, other):
|
362
|
+
if isinstance(other, NeutrosophicBicomplexNumber):
|
363
|
+
return NeutrosophicBicomplexNumber(*(a + b for a, b in zip(self.__dict__.values(), other.__dict__.values())))
|
364
|
+
raise TypeError("Unsupported operand for +.")
|
365
|
+
|
366
|
+
def __sub__(self, other):
|
367
|
+
if isinstance(other, NeutrosophicBicomplexNumber):
|
368
|
+
return NeutrosophicBicomplexNumber(*(a - b for a, b in zip(self.__dict__.values(), other.__dict__.values())))
|
369
|
+
raise TypeError("Unsupported operand for -.")
|
370
|
+
|
371
|
+
def __truediv__(self, scalar):
|
372
|
+
if isinstance(scalar, (int, float)):
|
373
|
+
return NeutrosophicBicomplexNumber(*(val / scalar for val in self.__dict__.values()))
|
374
|
+
raise TypeError("Only scalar division supported.")
|
375
|
+
|
376
|
+
def __str__(self):
|
377
|
+
return f"NeutroBicomplex(r={self.real}, i={self.imag}, Ir={self.neut_real}, ...)"
|
378
|
+
|
379
|
+
|
380
|
+
# ==============================================================================
|
381
|
+
# --- HELPER FUNCTIONS ---
|
382
|
+
# ==============================================================================
|
11
383
|
|
12
|
-
# --- Helper Functions ---
|
13
384
|
def is_prime(n_input):
|
14
385
|
"""
|
15
|
-
Checks if a given number (or its
|
16
|
-
|
17
|
-
For Rational numbers, its integer part is used.
|
18
|
-
For Complex/Quaternion numbers, its real/scalar part is used.
|
386
|
+
Checks if a given number (or its principal component) is prime.
|
387
|
+
Extracts the relevant integer part from various number types for testing.
|
19
388
|
"""
|
20
389
|
value_to_check = 0
|
390
|
+
# Extract the integer part to check for primality based on type
|
21
391
|
if isinstance(n_input, (int, float)):
|
22
392
|
value_to_check = abs(int(n_input))
|
23
393
|
elif isinstance(n_input, Fraction):
|
24
|
-
value_to_check = abs(int(n_input))
|
394
|
+
value_to_check = abs(int(n_input))
|
25
395
|
elif isinstance(n_input, complex):
|
26
396
|
value_to_check = abs(int(n_input.real))
|
27
|
-
elif isinstance(n_input, np.quaternion):
|
28
|
-
value_to_check = abs(int(n_input.w))
|
29
|
-
|
397
|
+
elif isinstance(n_input, np.quaternion):
|
398
|
+
value_to_check = abs(int(n_input.w))
|
399
|
+
elif isinstance(n_input, NeutrosophicNumber):
|
400
|
+
value_to_check = abs(int(n_input.a))
|
401
|
+
elif isinstance(n_input, NeutrosophicComplexNumber):
|
402
|
+
value_to_check = abs(int(n_input.real))
|
403
|
+
elif isinstance(n_input, HyperrealNumber):
|
404
|
+
value_to_check = abs(int(n_input.sequence[0])) if n_input.sequence else 0
|
405
|
+
elif isinstance(n_input, BicomplexNumber):
|
406
|
+
value_to_check = abs(int(n_input.z1.real))
|
407
|
+
elif isinstance(n_input, NeutrosophicBicomplexNumber):
|
408
|
+
value_to_check = abs(int(n_input.real))
|
409
|
+
else:
|
30
410
|
try:
|
31
411
|
value_to_check = abs(int(n_input))
|
32
412
|
except (ValueError, TypeError):
|
33
|
-
return False
|
413
|
+
return False
|
34
414
|
|
415
|
+
# Standard primality test algorithm
|
35
416
|
if value_to_check < 2:
|
36
417
|
return False
|
37
|
-
# Optimize for 2 and even numbers
|
38
418
|
if value_to_check == 2:
|
39
419
|
return True
|
40
420
|
if value_to_check % 2 == 0:
|
41
421
|
return False
|
42
|
-
# Check only odd divisors up to
|
43
|
-
for i in range(3, int(value_to_check
|
422
|
+
# Check only odd divisors up to the square root
|
423
|
+
for i in range(3, int(math.sqrt(value_to_check)) + 1, 2):
|
44
424
|
if value_to_check % i == 0:
|
45
425
|
return False
|
46
426
|
return True
|
47
427
|
|
48
|
-
|
428
|
+
def _is_divisible(value, divisor, kececi_type):
|
429
|
+
"""
|
430
|
+
Helper to check divisibility for different number types.
|
431
|
+
Returns True if a number is "perfectly divisible" by an integer divisor.
|
432
|
+
"""
|
433
|
+
try:
|
434
|
+
if kececi_type in [TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL]:
|
435
|
+
return value % divisor == 0
|
436
|
+
elif kececi_type == TYPE_FLOAT:
|
437
|
+
return math.isclose(value % divisor, 0)
|
438
|
+
elif kececi_type == TYPE_RATIONAL:
|
439
|
+
return (value / divisor).denominator == 1
|
440
|
+
elif kececi_type == TYPE_COMPLEX:
|
441
|
+
return math.isclose(value.real % divisor, 0) and math.isclose(value.imag % divisor, 0)
|
442
|
+
elif kececi_type == TYPE_QUATERNION:
|
443
|
+
return all(math.isclose(c % divisor, 0) for c in [value.w, value.x, value.y, value.z])
|
444
|
+
elif kececi_type == TYPE_NEUTROSOPHIC:
|
445
|
+
return math.isclose(value.a % divisor, 0) and math.isclose(value.b % divisor, 0)
|
446
|
+
elif kececi_type == TYPE_NEUTROSOPHIC_COMPLEX:
|
447
|
+
return all(math.isclose(c % divisor, 0) for c in [value.real, value.imag, value.indeterminacy])
|
448
|
+
elif kececi_type == TYPE_HYPERREAL:
|
449
|
+
return all(math.isclose(x % divisor, 0) for x in value.sequence)
|
450
|
+
elif kececi_type == TYPE_BICOMPLEX:
|
451
|
+
return (_is_divisible(value.z1, divisor, TYPE_COMPLEX) and
|
452
|
+
_is_divisible(value.z2, divisor, TYPE_COMPLEX))
|
453
|
+
elif kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX:
|
454
|
+
return all(math.isclose(c % divisor, 0) for c in value.__dict__.values())
|
455
|
+
except (TypeError, ValueError):
|
456
|
+
return False
|
457
|
+
return False
|
458
|
+
|
459
|
+
# ==============================================================================
|
460
|
+
# --- CORE GENERATOR ---
|
461
|
+
# ==============================================================================
|
462
|
+
|
49
463
|
def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, iterations):
|
50
464
|
"""
|
51
|
-
|
52
|
-
|
53
|
-
5 (Rational), 6 (Quaternion)
|
54
|
-
start_input_raw: Starting value (as string or number, appropriate for the type)
|
55
|
-
add_input_base_scalar: Base scalar value for increment (interpreted based on type)
|
56
|
-
iterations: Number of iterations
|
465
|
+
The core engine for generating Keçeci Number sequences of any supported type.
|
466
|
+
This version includes robust type conversion to prevent initialization errors.
|
57
467
|
"""
|
58
|
-
|
468
|
+
# --- Step 1: Initialization based on Keçeci Type ---
|
59
469
|
current_value = None
|
60
|
-
|
470
|
+
add_value_typed = None
|
61
471
|
ask_unit = None
|
62
|
-
use_integer_division = False
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
except ValueError:
|
85
|
-
try:
|
86
|
-
s_scalar_from_string = float(str(start_input_raw))
|
87
|
-
start_complex_val = complex(s_scalar_from_string, s_scalar_from_string)
|
88
|
-
except ValueError:
|
89
|
-
raise ValueError(f"Cannot convert start_input_raw '{start_input_raw}' to a complex number.")
|
90
|
-
current_value = start_complex_val
|
91
|
-
a_scalar_for_add = float(add_input_base_scalar)
|
92
|
-
_add_value_typed = complex(a_scalar_for_add, a_scalar_for_add) # a+aj
|
93
|
-
ask_unit = 1 + 1j
|
94
|
-
elif kececi_type == 4: # Floating-Point Numbers
|
95
|
-
current_value = float(start_input_raw)
|
96
|
-
_add_value_typed = float(add_input_base_scalar)
|
97
|
-
ask_unit = 1.0
|
98
|
-
elif kececi_type == 5: # Rational Numbers
|
99
|
-
if isinstance(start_input_raw, Fraction):
|
100
|
-
current_value = start_input_raw
|
101
|
-
else:
|
472
|
+
use_integer_division = False
|
473
|
+
|
474
|
+
try:
|
475
|
+
# Convert the ADD value once, as it's always a scalar float.
|
476
|
+
a_float = float(add_input_base_scalar)
|
477
|
+
|
478
|
+
# Handle START value conversion properly within each type-specific block.
|
479
|
+
if kececi_type in [TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL]:
|
480
|
+
# Correctly handle float strings like "2.5" by converting to float first.
|
481
|
+
s_int = int(float(start_input_raw))
|
482
|
+
current_value = s_int
|
483
|
+
add_value_typed = int(a_float)
|
484
|
+
ask_unit = 1
|
485
|
+
use_integer_division = True
|
486
|
+
|
487
|
+
elif kececi_type == TYPE_FLOAT:
|
488
|
+
current_value = float(start_input_raw)
|
489
|
+
add_value_typed = a_float
|
490
|
+
ask_unit = 1.0
|
491
|
+
|
492
|
+
elif kececi_type == TYPE_RATIONAL:
|
493
|
+
# The Fraction constructor correctly handles strings like "2.5".
|
102
494
|
current_value = Fraction(str(start_input_raw))
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
current_value =
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
495
|
+
add_value_typed = Fraction(str(add_input_base_scalar))
|
496
|
+
ask_unit = Fraction(1, 1)
|
497
|
+
|
498
|
+
elif kececi_type == TYPE_COMPLEX:
|
499
|
+
s_complex = complex(start_input_raw)
|
500
|
+
# If input was a plain number (e.g., "2.5"), interpret it as s+sj.
|
501
|
+
if s_complex.imag == 0 and 'j' not in str(start_input_raw).lower():
|
502
|
+
s_complex = complex(s_complex.real, s_complex.real)
|
503
|
+
current_value = s_complex
|
504
|
+
add_value_typed = complex(a_float, a_float)
|
505
|
+
ask_unit = 1 + 1j
|
506
|
+
|
507
|
+
elif kececi_type == TYPE_QUATERNION:
|
508
|
+
# Explicitly convert the input string to a float before use.
|
509
|
+
s_float = float(start_input_raw)
|
510
|
+
current_value = np.quaternion(s_float, s_float, s_float, s_float)
|
511
|
+
add_value_typed = np.quaternion(a_float, a_float, a_float, a_float)
|
512
|
+
ask_unit = np.quaternion(1, 1, 1, 1)
|
513
|
+
|
514
|
+
elif kececi_type == TYPE_NEUTROSOPHIC:
|
515
|
+
s_float = float(start_input_raw)
|
516
|
+
current_value = NeutrosophicNumber(s_float, s_float / 2)
|
517
|
+
add_value_typed = NeutrosophicNumber(a_float, a_float / 2)
|
518
|
+
ask_unit = NeutrosophicNumber(1, 1)
|
519
|
+
|
520
|
+
elif kececi_type == TYPE_NEUTROSOPHIC_COMPLEX:
|
521
|
+
s_float = float(start_input_raw)
|
522
|
+
current_value = NeutrosophicComplexNumber(s_float, s_float / 2, s_float / 3)
|
523
|
+
add_value_typed = NeutrosophicComplexNumber(a_float, a_float / 2, a_float / 3)
|
524
|
+
ask_unit = NeutrosophicComplexNumber(1, 1, 1)
|
525
|
+
|
526
|
+
elif kececi_type == TYPE_HYPERREAL:
|
527
|
+
s_float = float(start_input_raw)
|
528
|
+
current_value = HyperrealNumber([s_float / n for n in range(1, 11)])
|
529
|
+
add_value_typed = HyperrealNumber([a_float / n for n in range(1, 11)])
|
530
|
+
ask_unit = HyperrealNumber([1.0] * 10)
|
531
|
+
|
532
|
+
elif kececi_type == TYPE_BICOMPLEX:
|
533
|
+
s_complex = complex(start_input_raw)
|
534
|
+
a_complex = complex(a_float)
|
535
|
+
current_value = BicomplexNumber(s_complex, s_complex / 2)
|
536
|
+
add_value_typed = BicomplexNumber(a_complex, a_complex / 2)
|
537
|
+
ask_unit = BicomplexNumber(complex(1, 1), complex(0.5, 0.5))
|
538
|
+
|
539
|
+
elif kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX:
|
540
|
+
s_float = float(start_input_raw)
|
541
|
+
parts = [s_float / (n + 1) for n in range(8)]
|
542
|
+
add_parts = [a_float / (n + 1) for n in range(8)]
|
543
|
+
ask_parts = [1.0 / (n + 1) for n in range(8)]
|
544
|
+
current_value = NeutrosophicBicomplexNumber(*parts)
|
545
|
+
add_value_typed = NeutrosophicBicomplexNumber(*add_parts)
|
546
|
+
ask_unit = NeutrosophicBicomplexNumber(*ask_parts)
|
547
|
+
|
548
|
+
else:
|
549
|
+
raise ValueError(f"Invalid Keçeci Number Type: {kececi_type}")
|
116
550
|
|
117
|
-
|
118
|
-
|
119
|
-
|
551
|
+
except (ValueError, TypeError) as e:
|
552
|
+
print(f"Error initializing generator for type {kececi_type} with input '{start_input_raw}': {e}")
|
553
|
+
return []
|
120
554
|
|
121
|
-
|
122
|
-
|
123
|
-
|
555
|
+
# --- Step 2: Iteration Loop (This part remains unchanged) ---
|
556
|
+
sequence = [current_value]
|
557
|
+
last_divisor_used = None
|
558
|
+
ask_counter = 0
|
559
|
+
|
560
|
+
for _ in range(iterations):
|
561
|
+
# Rule 1: Add the increment value
|
562
|
+
added_value = current_value + add_value_typed
|
124
563
|
sequence.append(added_value)
|
125
|
-
actual_iterations_done += 1
|
126
|
-
if actual_iterations_done >= iterations: break
|
127
|
-
|
128
|
-
|
129
|
-
value_for_primality_check = added_value
|
130
564
|
|
131
|
-
|
565
|
+
result_value = added_value
|
566
|
+
divided_successfully = False
|
567
|
+
|
568
|
+
# Rule 2: Attempt Division
|
569
|
+
primary_divisor = 3 if last_divisor_used == 2 or last_divisor_used is None else 2
|
132
570
|
alternative_divisor = 2 if primary_divisor == 3 else 3
|
133
571
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
can_divide = False
|
139
|
-
if kececi_type in [1, 2]:
|
140
|
-
can_divide = (added_value % divisor_candidate == 0)
|
141
|
-
elif kececi_type == 3:
|
142
|
-
can_divide = math.isclose(added_value.real % divisor_candidate, 0) and math.isclose(added_value.imag % divisor_candidate, 0)
|
143
|
-
elif kececi_type == 4:
|
144
|
-
can_divide = math.isclose(added_value % divisor_candidate, 0) or \
|
145
|
-
math.isclose(added_value % divisor_candidate, divisor_candidate) # handles floating point precision
|
146
|
-
elif kececi_type == 5:
|
147
|
-
if divisor_candidate != 0:
|
148
|
-
quotient_rational = added_value / divisor_candidate
|
149
|
-
can_divide = (quotient_rational.denominator == 1)
|
150
|
-
elif kececi_type == 6:
|
151
|
-
# For quaternions, typically division is by scalar. Check if all components are divisible.
|
152
|
-
# Or, as per your current `is_prime`, just check the scalar part.
|
153
|
-
# Let's stick to the scalar part for consistency with `is_prime` for now.
|
154
|
-
can_divide = math.isclose(added_value.w % divisor_candidate, 0) and \
|
155
|
-
math.isclose(added_value.x % divisor_candidate, 0) and \
|
156
|
-
math.isclose(added_value.y % divisor_candidate, 0) and \
|
157
|
-
math.isclose(added_value.z % divisor_candidate, 0)
|
158
|
-
|
159
|
-
|
160
|
-
if can_divide:
|
161
|
-
if use_integer_division:
|
162
|
-
result_value = added_value // divisor_candidate
|
163
|
-
else:
|
164
|
-
result_value = added_value / divisor_candidate # For complex, float, rational, quaternion
|
165
|
-
last_divisor_used = divisor_candidate
|
572
|
+
for divisor in [primary_divisor, alternative_divisor]:
|
573
|
+
if _is_divisible(added_value, divisor, kececi_type):
|
574
|
+
result_value = added_value // divisor if use_integer_division else added_value / divisor
|
575
|
+
last_divisor_used = divisor
|
166
576
|
divided_successfully = True
|
167
|
-
break
|
168
|
-
|
169
|
-
if
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
if
|
181
|
-
result_value = modified_value
|
577
|
+
break
|
578
|
+
|
579
|
+
# Rule 3: Apply ASK Rule if division failed and the number is prime
|
580
|
+
if not divided_successfully and is_prime(added_value):
|
581
|
+
# Augment or Shrink the value
|
582
|
+
modified_value = (added_value + ask_unit) if ask_counter == 0 else (added_value - ask_unit)
|
583
|
+
ask_counter = 1 - ask_counter # Flip between 0 and 1
|
584
|
+
sequence.append(modified_value)
|
585
|
+
|
586
|
+
result_value = modified_value # Default to modified value if re-division fails
|
587
|
+
|
588
|
+
# Re-attempt division on the modified value
|
589
|
+
for divisor in [primary_divisor, alternative_divisor]:
|
590
|
+
if _is_divisible(modified_value, divisor, kececi_type):
|
591
|
+
result_value = modified_value // divisor if use_integer_division else modified_value / divisor
|
592
|
+
last_divisor_used = divisor
|
182
593
|
break
|
183
|
-
|
184
|
-
|
185
|
-
current_target_for_division_mod = modified_value
|
186
|
-
divided_after_modification = False
|
187
|
-
for divisor_candidate_mod in [primary_divisor, alternative_divisor]: # Re-use primary/alternative logic
|
188
|
-
can_divide_mod = False
|
189
|
-
if kececi_type in [1, 2]:
|
190
|
-
can_divide_mod = (current_target_for_division_mod % divisor_candidate_mod == 0)
|
191
|
-
elif kececi_type == 3:
|
192
|
-
can_divide_mod = math.isclose(current_target_for_division_mod.real % divisor_candidate_mod, 0) and \
|
193
|
-
math.isclose(current_target_for_division_mod.imag % divisor_candidate_mod, 0)
|
194
|
-
elif kececi_type == 4:
|
195
|
-
can_divide_mod = math.isclose(current_target_for_division_mod % divisor_candidate_mod, 0) or \
|
196
|
-
math.isclose(current_target_for_division_mod % divisor_candidate_mod, divisor_candidate_mod)
|
197
|
-
elif kececi_type == 5:
|
198
|
-
if divisor_candidate_mod != 0:
|
199
|
-
quotient_rational_mod = current_target_for_division_mod / divisor_candidate_mod
|
200
|
-
can_divide_mod = (quotient_rational_mod.denominator == 1)
|
201
|
-
elif kececi_type == 6:
|
202
|
-
can_divide_mod = math.isclose(current_target_for_division_mod.w % divisor_candidate_mod, 0) and \
|
203
|
-
math.isclose(current_target_for_division_mod.x % divisor_candidate_mod, 0) and \
|
204
|
-
math.isclose(current_target_for_division_mod.y % divisor_candidate_mod, 0) and \
|
205
|
-
math.isclose(current_target_for_division_mod.z % divisor_candidate_mod, 0)
|
206
|
-
|
207
|
-
|
208
|
-
if can_divide_mod:
|
209
|
-
if use_integer_division:
|
210
|
-
result_value = current_target_for_division_mod // divisor_candidate_mod
|
211
|
-
else:
|
212
|
-
result_value = current_target_for_division_mod / divisor_candidate_mod
|
213
|
-
last_divisor_used = divisor_candidate_mod # Update last_divisor_used
|
214
|
-
divided_after_modification = True
|
215
|
-
break
|
216
|
-
if not divided_after_modification:
|
217
|
-
result_value = modified_value
|
218
|
-
else: # Not prime and not divisible
|
219
|
-
result_value = added_value
|
220
594
|
|
221
595
|
sequence.append(result_value)
|
222
|
-
actual_iterations_done += 1
|
223
|
-
if actual_iterations_done >= iterations: break
|
224
596
|
current_value = result_value
|
225
597
|
|
226
|
-
return sequence
|
598
|
+
return sequence
|
227
599
|
|
600
|
+
# ==============================================================================
|
601
|
+
# --- HIGH-LEVEL CONTROL FUNCTIONS ---
|
602
|
+
# ==============================================================================
|
228
603
|
|
229
|
-
|
230
|
-
def get_interactive():
|
604
|
+
def get_with_params(kececi_type_choice, iterations, start_value_raw="0", add_value_base_scalar=9.0):
|
231
605
|
"""
|
232
|
-
|
606
|
+
Generates Keçeci Numbers with specified parameters.
|
233
607
|
"""
|
234
|
-
print("
|
235
|
-
print("
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
608
|
+
print(f"\n--- Generating Sequence: Type {kececi_type_choice}, Steps {iterations} ---")
|
609
|
+
print(f"Start: '{start_value_raw}', Increment: {add_value_base_scalar}")
|
610
|
+
|
611
|
+
generated_sequence = unified_generator(
|
612
|
+
kececi_type_choice,
|
613
|
+
start_value_raw,
|
614
|
+
add_value_base_scalar,
|
615
|
+
iterations
|
616
|
+
)
|
241
617
|
|
242
|
-
while True:
|
243
|
-
try:
|
244
|
-
type_choice = int(input("Please select Keçeci Number Type (1-6): "))
|
245
|
-
if 1 <= type_choice <= 6: break
|
246
|
-
else: print("Invalid type.")
|
247
|
-
except ValueError: print("Please enter a numeric value.")
|
248
|
-
|
249
|
-
start_prompt = "Enter the starting number (e.g., 0 or 2.5, complex:3+4j, rational: 3/4, quaternions: 1) : "
|
250
|
-
if type_choice == 3: start_prompt = "Enter starting complex number (e.g., 3+4j or just 3 for 3+3j): "
|
251
|
-
elif type_choice == 5: start_prompt = "Enter starting rational (e.g., 7/2 or 5 for 5/1): "
|
252
|
-
|
253
|
-
start_input_val_raw = input(start_prompt)
|
254
|
-
|
255
|
-
while True:
|
256
|
-
try:
|
257
|
-
add_base_scalar_val = float(input("Enter the base scalar value for increment (e.g., 9): "))
|
258
|
-
break
|
259
|
-
except ValueError: print("Please enter a numeric value.")
|
260
|
-
|
261
|
-
while True:
|
262
|
-
try:
|
263
|
-
# Iterations'ı Keçeci adımları olarak düşünelim (her adımda 2 sayı eklenir: added_value, result_value)
|
264
|
-
num_kececi_steps = int(input("Enter the number of Keçeci steps (positive integer: e.g., 15, generates ~30 numbers): "))
|
265
|
-
if num_kececi_steps > 0: break
|
266
|
-
else: print("Number of Keçeci steps must be positive.")
|
267
|
-
except ValueError: print("Please enter an integer value.")
|
268
|
-
|
269
|
-
generated_sequence = unified_generator(type_choice, start_input_val_raw, add_base_scalar_val, num_kececi_steps)
|
270
|
-
|
271
|
-
# *** YENİ EKLENEN KISIM BAŞLANGICI ***
|
272
618
|
if generated_sequence:
|
273
|
-
print(f"
|
619
|
+
print(f"Generated {len(generated_sequence)} numbers. Preview: {generated_sequence[:3]}...")
|
274
620
|
kpn = find_kececi_prime_number(generated_sequence)
|
275
621
|
if kpn is not None:
|
276
622
|
print(f"Keçeci Prime Number for this sequence: {kpn}")
|
277
623
|
else:
|
278
|
-
print("No Keçeci Prime Number found
|
624
|
+
print("No repeating Keçeci Prime Number found.")
|
279
625
|
else:
|
280
|
-
print("
|
281
|
-
|
282
|
-
|
283
|
-
return generated_sequence # Fonksiyon yine de diziyi döndürmeli
|
626
|
+
print("Sequence generation failed.")
|
627
|
+
|
628
|
+
return generated_sequence
|
284
629
|
|
285
|
-
def
|
630
|
+
def get_interactive():
|
286
631
|
"""
|
287
|
-
|
288
|
-
If fixed_params is False, start_value_raw and add_value_base_scalar are used as bases for randomization.
|
289
|
-
random_range_factor influences the range of random values.
|
632
|
+
Interactively gets parameters from the user and generates Keçeci Numbers.
|
290
633
|
"""
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
actual_start_raw = str(random.randint(0, int(random_range_factor)))
|
297
|
-
actual_add_base = float(random.randint(1, int(random_range_factor*1.5)))
|
298
|
-
elif kececi_type_choice == 2:
|
299
|
-
actual_start_raw = str(random.randint(-int(random_range_factor), 0))
|
300
|
-
actual_add_base = float(random.randint(-int(random_range_factor*1.5), -1))
|
301
|
-
elif kececi_type_choice == 3:
|
302
|
-
re_start = random.uniform(-random_range_factor/2, random_range_factor/2)
|
303
|
-
im_start = random.uniform(-random_range_factor/2, random_range_factor/2)
|
304
|
-
actual_start_raw = f"{re_start}{im_start:+}j" # String formatında complex
|
305
|
-
actual_add_base = random.uniform(1, random_range_factor/2)
|
306
|
-
elif kececi_type_choice == 4:
|
307
|
-
actual_start_raw = str(random.uniform(-random_range_factor, random_range_factor))
|
308
|
-
actual_add_base = random.uniform(0.1, random_range_factor/2)
|
309
|
-
elif kececi_type_choice == 5:
|
310
|
-
num = random.randint(-random_range_factor, random_range_factor)
|
311
|
-
den = random.randint(1, int(random_range_factor/2) if random_range_factor/2 >=1 else 1)
|
312
|
-
actual_start_raw = f"{num}/{den}"
|
313
|
-
actual_add_base = float(random.randint(1,random_range_factor))
|
314
|
-
elif kececi_type_choice == 6:
|
315
|
-
# Quaternion için başlangıç ve ekleme skaler olsun, unified_generator q(s,s,s,s) yapsın
|
316
|
-
actual_start_raw = str(random.uniform(-random_range_factor/2, random_range_factor/2))
|
317
|
-
actual_add_base = random.uniform(1, random_range_factor/2)
|
318
|
-
else:
|
319
|
-
if kececi_type_choice == 2 and float(actual_add_base) > 0: # add_value_base_scalar float olabilir
|
320
|
-
actual_add_base = -abs(float(actual_add_base))
|
321
|
-
|
322
|
-
|
323
|
-
generated_sequence = unified_generator(kececi_type_choice, actual_start_raw, actual_add_base, iterations)
|
634
|
+
print("\n--- Keçeci Number Interactive Generator ---")
|
635
|
+
print(" 1: Positive Real 2: Negative Real 3: Complex")
|
636
|
+
print(" 4: Float 5: Rational 6: Quaternion")
|
637
|
+
print(" 7: Neutrosophic 8: Neutro-Complex 9: Hyperreal")
|
638
|
+
print(" 10: Bicomplex 11: Neutro-Bicomplex")
|
324
639
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
640
|
+
while True:
|
641
|
+
try:
|
642
|
+
type_choice = int(input(f"Select Keçeci Number Type (1-11): "))
|
643
|
+
if 1 <= type_choice <= 11: break
|
644
|
+
else: print("Invalid type. Please enter a number between 1 and 11.")
|
645
|
+
except ValueError: print("Invalid input. Please enter a number.")
|
646
|
+
|
647
|
+
start_prompt = "Enter starting value: "
|
648
|
+
if type_choice == TYPE_COMPLEX: start_prompt = "Enter complex start (e.g., '3+4j' or '3' for 3+3j): "
|
649
|
+
elif type_choice == TYPE_RATIONAL: start_prompt = "Enter rational start (e.g., '7/2' or '5'): "
|
650
|
+
elif type_choice == TYPE_BICOMPLEX: start_prompt = "Enter bicomplex start (complex, e.g., '2+1j'): "
|
651
|
+
|
652
|
+
start_input_val_raw = input(start_prompt)
|
653
|
+
add_base_scalar_val = float(input("Enter base scalar increment (e.g., 9.0): "))
|
654
|
+
num_kececi_steps = int(input("Enter number of Keçeci steps (e.g., 15): "))
|
655
|
+
|
656
|
+
sequence = get_with_params(type_choice, num_kececi_steps, start_input_val_raw, add_base_scalar_val)
|
657
|
+
plot_numbers(sequence, f"Keçeci Type {type_choice} Sequence")
|
658
|
+
plt.show()
|
338
659
|
|
660
|
+
# ==============================================================================
|
661
|
+
# --- ANALYSIS AND PLOTTING ---
|
662
|
+
# ==============================================================================
|
339
663
|
|
340
|
-
def
|
341
|
-
fixed_start_raw="0", fixed_add_base_scalar=9.0, random_factor=10):
|
664
|
+
def find_kececi_prime_number(kececi_numbers_list):
|
342
665
|
"""
|
343
|
-
|
666
|
+
Finds the Keçeci Prime Number from a generated sequence.
|
667
|
+
|
668
|
+
The Keçeci Prime is the integer representation of the most frequent number
|
669
|
+
in the sequence whose principal component is itself prime. Ties in frequency
|
670
|
+
are broken by choosing the larger prime number.
|
344
671
|
"""
|
345
|
-
|
346
|
-
|
347
|
-
|
672
|
+
if not kececi_numbers_list:
|
673
|
+
return None
|
674
|
+
|
675
|
+
# Extract integer representations of numbers that are prime
|
676
|
+
integer_prime_reps = []
|
677
|
+
for num in kececi_numbers_list:
|
678
|
+
if is_prime(num):
|
679
|
+
# This logic is duplicated from is_prime to get the value itself
|
680
|
+
value = 0
|
681
|
+
if isinstance(num, (int, float, Fraction)): value = abs(int(num))
|
682
|
+
elif isinstance(num, complex): value = abs(int(num.real))
|
683
|
+
elif isinstance(num, np.quaternion): value = abs(int(num.w))
|
684
|
+
elif isinstance(num, NeutrosophicNumber): value = abs(int(num.a))
|
685
|
+
elif isinstance(num, NeutrosophicComplexNumber): value = abs(int(num.real))
|
686
|
+
elif isinstance(num, HyperrealNumber): value = abs(int(num.sequence[0])) if num.sequence else 0
|
687
|
+
elif isinstance(num, BicomplexNumber): value = abs(int(num.z1.real))
|
688
|
+
elif isinstance(num, NeutrosophicBicomplexNumber): value = abs(int(num.real))
|
689
|
+
integer_prime_reps.append(value)
|
690
|
+
|
691
|
+
if not integer_prime_reps:
|
692
|
+
return None
|
693
|
+
|
694
|
+
# Count frequencies of these prime integers
|
695
|
+
counts = collections.Counter(integer_prime_reps)
|
696
|
+
|
697
|
+
# Find primes that repeat
|
698
|
+
repeating_primes = [(freq, prime) for prime, freq in counts.items() if freq > 1]
|
699
|
+
|
700
|
+
if not repeating_primes:
|
701
|
+
return None
|
348
702
|
|
349
|
-
#
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
fixed_params=use_fixed_params_for_selected_type,
|
355
|
-
random_range_factor=random_factor)
|
356
|
-
return generated_sequence # get_with_params zaten KPN yazdırıyor.
|
357
|
-
|
358
|
-
# --- Plotting Function (can be called from the notebook) ---
|
359
|
-
def plot_numbers(sequence, title="Keçeci Numbers"):
|
703
|
+
# Find the one with the highest frequency, using the prime value as a tie-breaker
|
704
|
+
_, best_prime = max(repeating_primes)
|
705
|
+
return best_prime
|
706
|
+
|
707
|
+
def plot_numbers(sequence, title="Keçeci Number Sequence Analysis"):
|
360
708
|
"""
|
361
|
-
Plots the generated Keçeci Number sequence
|
709
|
+
Plots the generated Keçeci Number sequence with appropriate visualizations
|
710
|
+
for each number type.
|
362
711
|
"""
|
363
|
-
plt.
|
712
|
+
plt.style.use('seaborn-v0_8-whitegrid')
|
364
713
|
|
365
714
|
if not sequence:
|
366
715
|
print("Sequence is empty, nothing to plot.")
|
367
|
-
plt.title(title + " (Empty Sequence)")
|
368
|
-
plt.text(0.5, 0.5, "Empty Sequence", ha='center', va='center', fontsize=16)
|
369
|
-
plt.show()
|
370
716
|
return
|
371
717
|
|
718
|
+
fig = plt.figure(figsize=(15, 8))
|
719
|
+
plt.suptitle(title, fontsize=16, y=0.98)
|
372
720
|
first_elem = sequence[0]
|
721
|
+
|
722
|
+
# --- Plotting logic per type ---
|
723
|
+
|
724
|
+
# CORRECTED: Check for the actual Python types.
|
725
|
+
# This correctly handles types 1, 2, and 4 (Positive/Negative Real, Float).
|
726
|
+
if isinstance(first_elem, (int, float)):
|
727
|
+
ax = fig.add_subplot(1, 1, 1)
|
728
|
+
ax.plot([float(x) for x in sequence], 'o-')
|
729
|
+
ax.set_title("Value over Iterations")
|
730
|
+
ax.set_xlabel("Index"); ax.set_ylabel("Value")
|
373
731
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
plt.title(title + " (No Quaternion Data)")
|
380
|
-
plt.text(0.5, 0.5, "No Quaternion Data", ha='center', va='center', fontsize=16)
|
381
|
-
plt.show()
|
382
|
-
return
|
383
|
-
|
384
|
-
w_parts = [q.w for q in q_sequence]
|
385
|
-
vector_norms = [np.sqrt(q.x**2 + q.y**2 + q.z**2) for q in q_sequence]
|
386
|
-
|
387
|
-
plt.subplot(2, 1, 1)
|
388
|
-
plt.plot(w_parts, marker='o', linestyle='-', label='w (Scalar Part)')
|
389
|
-
plt.title(title + " - Quaternion Scalar Part (w)")
|
390
|
-
plt.xlabel("Index"); plt.ylabel("Value"); plt.grid(True); plt.legend()
|
391
|
-
|
392
|
-
plt.subplot(2, 1, 2)
|
393
|
-
plt.plot(vector_norms, marker='x', linestyle='--', color='purple', label='Vector Part Norm (|xi+yj+zk|)')
|
394
|
-
plt.title(title + " - Quaternion Vector Part Norm")
|
395
|
-
plt.xlabel("Index"); plt.ylabel("Value"); plt.grid(True); plt.legend()
|
732
|
+
elif isinstance(first_elem, Fraction):
|
733
|
+
ax = fig.add_subplot(1, 1, 1)
|
734
|
+
ax.plot([float(x) for x in sequence], 'o-')
|
735
|
+
ax.set_title("Value over Iterations (as float)")
|
736
|
+
ax.set_xlabel("Index"); ax.set_ylabel("Value")
|
396
737
|
|
397
738
|
elif isinstance(first_elem, complex):
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
real_parts =
|
407
|
-
|
739
|
+
gs = GridSpec(2, 2, figure=fig)
|
740
|
+
ax1 = fig.add_subplot(gs[0, 0])
|
741
|
+
ax2 = fig.add_subplot(gs[0, 1])
|
742
|
+
ax3 = fig.add_subplot(gs[1, :])
|
743
|
+
|
744
|
+
real_parts = [c.real for c in sequence]
|
745
|
+
imag_parts = [c.imag for c in sequence]
|
746
|
+
|
747
|
+
ax1.plot(real_parts, 'o-', label='Real Part')
|
748
|
+
ax1.set_title("Real Part"); ax1.legend()
|
749
|
+
|
750
|
+
ax2.plot(imag_parts, 'o-', color='red', label='Imaginary Part')
|
751
|
+
ax2.set_title("Imaginary Part"); ax2.legend()
|
752
|
+
|
753
|
+
ax3.plot(real_parts, imag_parts, '.-', label='Trajectory')
|
754
|
+
ax3.scatter(real_parts[0], imag_parts[0], c='g', s=100, label='Start', zorder=5)
|
755
|
+
ax3.scatter(real_parts[-1], imag_parts[-1], c='r', s=100, label='End', zorder=5)
|
756
|
+
ax3.set_title("Trajectory in Complex Plane"); ax3.set_xlabel("Real"); ax3.set_ylabel("Imaginary"); ax3.legend(); ax3.axis('equal')
|
757
|
+
|
758
|
+
elif isinstance(first_elem, np.quaternion):
|
759
|
+
gs = GridSpec(2, 1, figure=fig)
|
760
|
+
ax1 = fig.add_subplot(gs[0, 0])
|
761
|
+
ax2 = fig.add_subplot(gs[1, 0])
|
762
|
+
|
763
|
+
ax1.plot([q.w for q in sequence], 'o-', label='w (scalar)')
|
764
|
+
ax1.plot([q.x for q in sequence], 's--', label='x')
|
765
|
+
ax1.plot([q.y for q in sequence], '^--', label='y')
|
766
|
+
ax1.plot([q.z for q in sequence], 'd--', label='z')
|
767
|
+
ax1.set_title("Quaternion Components"); ax1.legend()
|
768
|
+
|
769
|
+
magnitudes = [np.sqrt(q.w**2 + q.x**2 + q.y**2 + q.z**2) for q in sequence]
|
770
|
+
ax2.plot(magnitudes, 'o-', color='purple', label='Magnitude')
|
771
|
+
ax2.set_title("Quaternion Magnitude"); ax2.legend()
|
772
|
+
|
773
|
+
elif isinstance(first_elem, BicomplexNumber):
|
774
|
+
gs = GridSpec(2, 2, figure=fig)
|
775
|
+
ax1 = fig.add_subplot(gs[0, 0]); ax2 = fig.add_subplot(gs[0, 1])
|
776
|
+
ax3 = fig.add_subplot(gs[1, 0]); ax4 = fig.add_subplot(gs[1, 1])
|
777
|
+
|
778
|
+
z1r = [x.z1.real for x in sequence]; z1i = [x.z1.imag for x in sequence]
|
779
|
+
z2r = [x.z2.real for x in sequence]; z2i = [x.z2.imag for x in sequence]
|
780
|
+
|
781
|
+
ax1.plot(z1r, label='z1.real'); ax1.plot(z1i, label='z1.imag')
|
782
|
+
ax1.set_title("Component z1"); ax1.legend()
|
408
783
|
|
409
|
-
|
410
|
-
|
411
|
-
plt.title(title + " - Complex Real Part"); plt.xlabel("Index")
|
412
|
-
plt.ylabel("Value"); plt.grid(True); plt.legend()
|
784
|
+
ax2.plot(z2r, label='z2.real'); ax2.plot(z2i, label='z2.imag')
|
785
|
+
ax2.set_title("Component z2"); ax2.legend()
|
413
786
|
|
414
|
-
|
415
|
-
|
416
|
-
plt.title(title + " - Complex Imaginary Part"); plt.xlabel("Index")
|
417
|
-
plt.ylabel("Value"); plt.grid(True); plt.legend()
|
787
|
+
ax3.plot(z1r, z1i, '.-'); ax3.set_title("z1 in Complex Plane")
|
788
|
+
ax4.plot(z2r, z2i, '.-'); ax4.set_title("z2 in Complex Plane")
|
418
789
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
790
|
+
elif isinstance(first_elem, NeutrosophicNumber):
|
791
|
+
gs = GridSpec(1, 2, figure=fig)
|
792
|
+
ax1 = fig.add_subplot(gs[0, 0]); ax2 = fig.add_subplot(gs[0, 1])
|
793
|
+
|
794
|
+
a = [x.a for x in sequence]; b = [x.b for x in sequence]
|
795
|
+
ax1.plot(a, label='Determinate (a)'); ax1.plot(b, label='Indeterminate (b)')
|
796
|
+
ax1.set_title("Components"); ax1.legend()
|
797
|
+
|
798
|
+
sc = ax2.scatter(a, b, c=range(len(a)), cmap='viridis')
|
799
|
+
ax2.set_title("Determinate vs. Indeterminate"); fig.colorbar(sc, ax=ax2)
|
427
800
|
|
428
|
-
elif isinstance(first_elem,
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
plt.title(title + " (Rational Numbers - plotted as float)")
|
439
|
-
plt.xlabel("Index"); plt.ylabel("Value (float)"); plt.grid(True)
|
801
|
+
elif isinstance(first_elem, NeutrosophicComplexNumber):
|
802
|
+
gs = GridSpec(1, 2, figure=fig)
|
803
|
+
ax1 = fig.add_subplot(gs[0, 0]); ax2 = fig.add_subplot(gs[0, 1])
|
804
|
+
|
805
|
+
r = [x.real for x in sequence]; i = [x.imag for x in sequence]; ind = [x.indeterminacy for x in sequence]
|
806
|
+
ax1.plot(r, label='Real'); ax1.plot(i, label='Imag'); ax1.plot(ind, label='Indeterminacy', linestyle=':')
|
807
|
+
ax1.set_title("Components"); ax1.legend()
|
808
|
+
|
809
|
+
sc = ax2.scatter(r, i, c=ind, cmap='magma')
|
810
|
+
ax2.set_title("Complex Plane (colored by Indeterminacy)"); fig.colorbar(sc, ax=ax2, label='Indeterminacy')
|
440
811
|
|
441
|
-
else: #
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
if not numeric_sequence: # If all were non-numeric after filtering
|
446
|
-
raise ValueError("No numeric data to plot after filtering.")
|
447
|
-
plt.plot(numeric_sequence, marker='o', linestyle='-')
|
448
|
-
except (ValueError, TypeError):
|
449
|
-
print(f"Warning: Sequence for '{title}' contains non-standard numeric or mixed types. Attempting basic plot.")
|
450
|
-
# Fallback for truly mixed or unplottable types: plot what you can as numbers
|
451
|
-
plottable_part = []
|
452
|
-
for x in sequence:
|
453
|
-
try: plottable_part.append(float(x))
|
454
|
-
except: pass # Ignore non-convertible
|
455
|
-
if plottable_part:
|
456
|
-
plt.plot(plottable_part, marker='o', linestyle='-')
|
457
|
-
else:
|
458
|
-
print("Could not plot any part of the sequence.")
|
459
|
-
plt.title(title + " (Non-Numeric or Unplottable Data)")
|
460
|
-
plt.text(0.5, 0.5, "Non-Numeric or Unplottable Data", ha='center', va='center', fontsize=16)
|
461
|
-
|
462
|
-
plt.title(title); plt.xlabel("Index")
|
463
|
-
plt.ylabel("Value"); plt.grid(True)
|
812
|
+
else: # Fallback for Hyperreal, Neutro-Bicomplex, and others
|
813
|
+
ax = fig.add_subplot(1, 1, 1)
|
814
|
+
ax.text(0.5, 0.5, f"Plotting for type '{type(first_elem).__name__}'\nis not specifically implemented.\nShowing string representation of first 3 elements:\n\n1. {sequence[0]}\n2. {sequence[1]}\n3. {sequence[2]}",
|
815
|
+
ha='center', va='center', fontsize=12, bbox=dict(facecolor='lightyellow'))
|
464
816
|
|
465
|
-
plt.tight_layout()
|
466
|
-
# plt.show() # Genellikle notebook'ta %matplotlib inline ile otomatik gösterilir.
|
467
|
-
# .py script'te bu satırın yorumunu kaldırmak gerekebilir.
|
817
|
+
plt.tight_layout(rect=[0, 0, 1, 0.96])
|
468
818
|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
""
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
for num_original in kececi_numbers_list:
|
482
|
-
if is_prime(num_original):
|
483
|
-
value_checked = 0
|
484
|
-
if isinstance(num_original, (int, float)):
|
485
|
-
value_checked = abs(int(num_original))
|
486
|
-
elif isinstance(num_original, Fraction):
|
487
|
-
value_checked = abs(int(num_original))
|
488
|
-
elif isinstance(num_original, complex):
|
489
|
-
value_checked = abs(int(num_original.real))
|
490
|
-
elif isinstance(num_original, np.quaternion):
|
491
|
-
value_checked = abs(int(num_original.w))
|
492
|
-
else:
|
493
|
-
try:
|
494
|
-
value_checked = abs(int(num_original))
|
495
|
-
except (ValueError, TypeError):
|
496
|
-
continue
|
497
|
-
integer_prime_representations.append(value_checked)
|
498
|
-
|
499
|
-
if not integer_prime_representations:
|
500
|
-
return None
|
501
|
-
|
502
|
-
counts = collections.Counter(integer_prime_representations)
|
503
|
-
repeating_primes_info = []
|
504
|
-
for prime_int_val, freq in counts.items():
|
505
|
-
if freq > 1: # Sadece tekrarlayan asallar
|
506
|
-
repeating_primes_info.append((freq, prime_int_val))
|
819
|
+
# ==============================================================================
|
820
|
+
# --- MAIN EXECUTION BLOCK ---
|
821
|
+
# ==============================================================================
|
822
|
+
if __name__ == "__main__":
|
823
|
+
print("="*60)
|
824
|
+
print(" Keçeci Numbers Module - Demonstration")
|
825
|
+
print("="*60)
|
826
|
+
print(f"This script demonstrates the generation of various Keçeci Number types.")
|
827
|
+
|
828
|
+
# --- Example 1: Interactive Mode ---
|
829
|
+
# To run interactive mode, uncomment the following line:
|
830
|
+
# get_interactive()
|
507
831
|
|
508
|
-
|
509
|
-
|
832
|
+
# --- Example 2: Programmatic Generation and Plotting ---
|
833
|
+
# We will generate a sequence for each type to test the system.
|
834
|
+
print("\nRunning programmatic tests for all 11 number types...")
|
510
835
|
|
511
|
-
#
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
836
|
+
# Test parameters
|
837
|
+
STEPS = 15
|
838
|
+
START_VAL = "2.5"
|
839
|
+
ADD_VAL = 3.0
|
840
|
+
|
841
|
+
all_types = {
|
842
|
+
"Positive Real": TYPE_POSITIVE_REAL,
|
843
|
+
"Negative Real": TYPE_NEGATIVE_REAL,
|
844
|
+
"Complex": TYPE_COMPLEX,
|
845
|
+
"Float": TYPE_FLOAT,
|
846
|
+
"Rational": TYPE_RATIONAL,
|
847
|
+
"Quaternion": TYPE_QUATERNION,
|
848
|
+
"Neutrosophic": TYPE_NEUTROSOPHIC,
|
849
|
+
"Neutrosophic Complex": TYPE_NEUTROSOPHIC_COMPLEX,
|
850
|
+
"Hyperreal": TYPE_HYPERREAL,
|
851
|
+
"Bicomplex": TYPE_BICOMPLEX,
|
852
|
+
"Neutrosophic Bicomplex": TYPE_NEUTROSOPHIC_BICOMPLEX
|
853
|
+
}
|
854
|
+
|
855
|
+
# Generate and plot for a few selected types
|
856
|
+
types_to_plot = [
|
857
|
+
"Complex",
|
858
|
+
"Quaternion",
|
859
|
+
"Bicomplex",
|
860
|
+
"Neutrosophic Complex"
|
861
|
+
]
|
518
862
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
TYPE_QUATERNION = 6
|
528
|
-
|
529
|
-
# --- DEFINITIONS (as a multiline string, can be accessed as kececinumbers.DEFINITIONS) ---
|
530
|
-
DEFINITIONS = """
|
531
|
-
Keçeci NumberS UNIFIED DEFINITION
|
532
|
-
|
533
|
-
A Keçeci Number sequence is derived from a `start_input_raw` and an `add_input_base_scalar`.
|
534
|
-
These inputs are interpreted according to the selected Keçeci Number Type to become the `current_value` and a type-specific `_add_value_typed`.
|
535
|
-
|
536
|
-
In each "Keçeci step" (which typically adds 2 or 3 numbers to the sequence):
|
537
|
-
1. `added_value = current_value + _add_value_typed`.
|
538
|
-
2. `added_value` is recorded in the sequence.
|
539
|
-
3. A `result_value` is obtained by applying the Division Rule and, if necessary, the ASK Rule to `added_value`.
|
540
|
-
4. `result_value` is recorded in the sequence.
|
541
|
-
5. `current_value = result_value`.
|
542
|
-
This process is repeated for the specified `number_of_iterations` (Keçeci steps).
|
543
|
-
|
544
|
-
Division Rule:
|
545
|
-
* A `last_divisor_used` (2 or 3) is tracked.
|
546
|
-
* `primary_divisor`: If `last_divisor_used` is nonexistent (first step) or 2, it's 3; if it's 3, it's 2.
|
547
|
-
* `alternative_divisor`: The other of `primary_divisor` (2 or 3).
|
548
|
-
* `value_to_check_division`: This is `added_value` (or `modified_value` after ASK).
|
549
|
-
* The part of this value used for divisibility depends on the number type (e.g., real/scalar part for complex/quaternion, the fraction itself for rational).
|
550
|
-
* For Complex/Quaternion, all components should be divisible by the integer divisor for perfect division.
|
551
|
-
* First, division by `primary_divisor` is attempted:
|
552
|
-
* If `value_to_check_division` (or its relevant part) is "perfectly divisible" by `primary_divisor` (in a type-specific sense, e.g., for rationals, the result is an integer),
|
553
|
-
then `result_value = value_to_check_division / primary_divisor`. `last_divisor_used = primary_divisor`.
|
554
|
-
* If unsuccessful, division by `alternative_divisor` is attempted:
|
555
|
-
* If `value_to_check_division` (or its relevant part) is "perfectly divisible" by `alternative_divisor`,
|
556
|
-
then `result_value = value_to_check_division / alternative_divisor`. `last_divisor_used = alternative_divisor`.
|
557
|
-
|
558
|
-
Primality and ASK (Augment/Shrink then Check) Rule (if Division Fails):
|
559
|
-
* `value_for_primality_check`: The part/representation of `added_value` used for primality testing (e.g., integer part of real, real part of complex).
|
560
|
-
* If `is_prime(value_for_primality_check)` is true:
|
561
|
-
* An `ask_counter` (0 or 1) is used.
|
562
|
-
* `ask_unit`: A type-specific unit value (e.g., 1 for real, 1+1j for complex, Fraction(1,1) for rational, quaternion(1,1,1,1) for quaternion).
|
563
|
-
* If `ask_counter` is 0: `modified_value = added_value + ask_unit`, `ask_counter = 1`.
|
564
|
-
* If `ask_counter` is 1: `modified_value = added_value - ask_unit`, `ask_counter = 0`.
|
565
|
-
* `modified_value` is added to the sequence.
|
566
|
-
* The Division Rule above is re-attempted on this `modified_value`.
|
567
|
-
* If division is successful, `result_value` is the quotient.
|
568
|
-
* If unsuccessful, `result_value = modified_value`.
|
569
|
-
* If `is_prime(value_for_primality_check)` is false (and it wasn't divisible):
|
570
|
-
* `result_value = added_value`.
|
571
|
-
|
572
|
-
Number Types and Specifics:
|
573
|
-
1. Positive Real Numbers (Treated as Integer):
|
574
|
-
* Start/Increment: Positive integers.
|
575
|
-
* Division: Integer division (`//`). Perfect divisibility: `% == 0`.
|
576
|
-
* ASK unit: `1`. Primality: `abs(int(number))`.
|
577
|
-
2. Negative Real Numbers (Treated as Integer):
|
578
|
-
* Start/Increment: Generally negative integers.
|
579
|
-
* Division: Integer division (`//`). Perfect divisibility: `% == 0`.
|
580
|
-
* ASK unit: `1`. Primality: `abs(int(number))`.
|
581
|
-
3. Complex Numbers (`complex`):
|
582
|
-
* Start/Increment: Complex numbers. Scalar input `s` is interpreted as `s+sj` for start, and scalar `a` as `a+aj` for increment.
|
583
|
-
* Division: Complex division (`/`). Perfect divisibility: Both real and imaginary parts are `math.isclose(part % integer_divisor, 0)`.
|
584
|
-
* ASK unit: `1+1j`. Primality: `abs(int(number.real))`.
|
585
|
-
4. Floating-Point Numbers (Treated as Float):
|
586
|
-
* Start/Increment: Decimal numbers.
|
587
|
-
* Division: Float division (`/`). Perfect divisibility: `math.isclose(number % integer_divisor, 0)`.
|
588
|
-
* ASK unit: `1.0`. Primality: `abs(int(number))`.
|
589
|
-
5. Rational Numbers (`fractions.Fraction`):
|
590
|
-
* Start/Increment: Fractions. Scalar input `s` is interpreted as `Fraction(s,1)`.
|
591
|
-
* Division: Fraction division (`/`). Perfect divisibility: `(fraction / integer_divisor).denominator == 1`.
|
592
|
-
* ASK unit: `Fraction(1,1)`. Primality: `abs(int(fraction))`.
|
593
|
-
6. Quaternions (`numpy.quaternion`):
|
594
|
-
* Start/Increment: Quaternions. Scalar input `s` is interpreted as `q(s,s,s,s)` for start, and scalar `a` as `q(a,a,a,a)` for increment.
|
595
|
-
* Division: Quaternion division (`/`). Perfect divisibility: All w,x,y,z parts are `math.isclose(part % integer_divisor, 0)`.
|
596
|
-
* ASK unit: `quaternion(1,1,1,1)`. Primality: `abs(int(number.w))`.
|
597
|
-
"""
|
598
|
-
|
863
|
+
for name, type_id in all_types.items():
|
864
|
+
# Adjust start/add values for specific types if needed
|
865
|
+
start = "-5" if type_id == TYPE_NEGATIVE_REAL else "2+3j" if type_id in [TYPE_COMPLEX, TYPE_BICOMPLEX] else START_VAL
|
866
|
+
|
867
|
+
seq = get_with_params(type_id, STEPS, start, ADD_VAL)
|
868
|
+
|
869
|
+
if name in types_to_plot and seq:
|
870
|
+
plot_numbers(seq, title=f"Demonstration: {name} Keçeci Numbers")
|
599
871
|
|
600
|
-
|
601
|
-
|
602
|
-
print("This module provides functions to generate and plot Keçeci Numbers.")
|
603
|
-
print("Example: Use 'import kececinumbers as kn' in your script/notebook.")
|
604
|
-
print("\nAvailable functions:")
|
605
|
-
print("- kn.get_interactive()")
|
606
|
-
print("- kn.get_with_params(kececi_type, iterations, ...)")
|
607
|
-
print("- kn.get_random_type(iterations, ...)")
|
608
|
-
print("- kn.plot_numbers(sequence, title)")
|
609
|
-
print("- kn.find_kececi_prime_number(sequence)") # Explicitly list it
|
610
|
-
print("- kn.unified_generator(...) (low-level)")
|
611
|
-
print("\nAccess definitions by printing kn.DEFINITIONS") # Changed to instruction
|
612
|
-
print("\nAccess type constants like: kn.TYPE_COMPLEX")
|
613
|
-
|
614
|
-
print("\nRunning a quick test for Complex numbers (fixed params, 5 Keçeci steps):")
|
615
|
-
# `iterations` in get_with_params is number of Keçeci steps
|
616
|
-
test_seq = get_with_params(TYPE_COMPLEX, 5, start_value_raw="1+1j", add_value_base_scalar=2.0, fixed_params=True)
|
617
|
-
# KPN will be printed by get_with_params
|
618
|
-
|
619
|
-
# Example of calling find_kececi_prime_number directly if needed
|
620
|
-
# if test_seq:
|
621
|
-
# kpn_direct = find_kececi_prime_number(test_seq)
|
622
|
-
# if kpn_direct is not None:
|
623
|
-
# print(f"Direct call to find_kececi_prime_number result: {kpn_direct}")
|
624
|
-
# else:
|
625
|
-
# print("Direct call: No Keçeci Prime Number found.")
|
626
|
-
|
627
|
-
# print("\nRunning a quick test for Negative Integers (10 Keçeci steps):")
|
628
|
-
# test_seq_neg = get_random_type(num_iterations=10) # KPN will be printed
|
872
|
+
print("\n\nDemonstration finished. Plots for selected types are shown.")
|
873
|
+
plt.show()
|