kececinumbers 0.6.9__py3-none-any.whl → 0.7.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/__init__.py +3 -1
- kececinumbers/_version.py +1 -1
- kececinumbers/kececinumbers.py +714 -48
- {kececinumbers-0.6.9.dist-info → kececinumbers-0.7.1.dist-info}/METADATA +5 -4
- kececinumbers-0.7.1.dist-info/RECORD +10 -0
- kececinumbers-0.6.9.dist-info/RECORD +0 -10
- {kececinumbers-0.6.9.dist-info → kececinumbers-0.7.1.dist-info}/WHEEL +0 -0
- {kececinumbers-0.6.9.dist-info → kececinumbers-0.7.1.dist-info}/licenses/LICENSE +0 -0
- {kececinumbers-0.6.9.dist-info → kececinumbers-0.7.1.dist-info}/top_level.txt +0 -0
kececinumbers/__init__.py
CHANGED
@@ -22,7 +22,7 @@ import warnings
|
|
22
22
|
# importlib.reload(kececinumbers) # F821 undefined name 'kececinumbers'
|
23
23
|
|
24
24
|
# Paket sürüm numarası
|
25
|
-
__version__ = "0.
|
25
|
+
__version__ = "0.7.1"
|
26
26
|
__author__ = "Mehmet Keçeci"
|
27
27
|
__email__ = "mkececi@yaani.com"
|
28
28
|
|
@@ -82,6 +82,7 @@ __all__ = [
|
|
82
82
|
'_is_complex_like',
|
83
83
|
'is_prime_like',
|
84
84
|
'is_near_integer',
|
85
|
+
'_plot_component_distribution',
|
85
86
|
|
86
87
|
|
87
88
|
# --- Core Generation and Analysis ---
|
@@ -180,6 +181,7 @@ try:
|
|
180
181
|
_is_complex_like,
|
181
182
|
is_prime_like,
|
182
183
|
is_near_integer,
|
184
|
+
_plot_component_distribution,
|
183
185
|
|
184
186
|
|
185
187
|
# Constants
|
kececinumbers/_version.py
CHANGED
kececinumbers/kececinumbers.py
CHANGED
@@ -33,7 +33,7 @@ import collections
|
|
33
33
|
from dataclasses import dataclass
|
34
34
|
from fractions import Fraction
|
35
35
|
import math
|
36
|
-
from matplotlib.gridspec import GridSpec
|
36
|
+
#from matplotlib.gridspec import GridSpec
|
37
37
|
import matplotlib.pyplot as plt
|
38
38
|
import numbers
|
39
39
|
#from numbers import Real
|
@@ -49,6 +49,13 @@ from typing import Any, Dict, List, Optional, Tuple
|
|
49
49
|
|
50
50
|
# numpy ve diğer Keçeci tipleri için gerekli importlar
|
51
51
|
# Eğer bu kütüphaneler yüklü değilse, pip install numpy gibi komutlarla yüklemeniz gerekebilir.
|
52
|
+
try:
|
53
|
+
from matplotlib.gridspec import GridSpec
|
54
|
+
except ModuleNotFoundError:
|
55
|
+
import matplotlib
|
56
|
+
print(f"Matplotlib path: {matplotlib.__file__}")
|
57
|
+
from matplotlib.gridspec import GridSpec
|
58
|
+
|
52
59
|
try:
|
53
60
|
import numpy as np
|
54
61
|
# numpy.quaternion'ın eski adı np.quaternion. Yeni versiyonlarda quaternion modülü ayrı olabilir.
|
@@ -634,18 +641,124 @@ class SedenionNumber:
|
|
634
641
|
return f"({', '.join(map(str, self.coeffs))})"
|
635
642
|
|
636
643
|
@dataclass
|
644
|
+
class CliffordNumber:
|
645
|
+
def __init__(self, basis_dict: Dict[str, float]):
|
646
|
+
"""CliffordNumber constructor."""
|
647
|
+
# Sadece sıfır olmayan değerleri sakla
|
648
|
+
self.basis = {k: float(v) for k, v in basis_dict.items() if abs(float(v)) > 1e-10}
|
649
|
+
|
650
|
+
@property
|
651
|
+
def dimension(self) -> int:
|
652
|
+
"""Vector space dimension'ını otomatik hesaplar."""
|
653
|
+
max_index = 0
|
654
|
+
for key in self.basis.keys():
|
655
|
+
if key: # scalar değilse
|
656
|
+
# '12', '123' gibi string'lerden maksimum rakamı bul
|
657
|
+
if key.isdigit():
|
658
|
+
max_index = max(max_index, max(int(c) for c in key))
|
659
|
+
return max_index
|
660
|
+
|
661
|
+
def __add__(self, other):
|
662
|
+
if isinstance(other, CliffordNumber):
|
663
|
+
new_basis = self.basis.copy()
|
664
|
+
for k, v in other.basis.items():
|
665
|
+
new_basis[k] = new_basis.get(k, 0.0) + v
|
666
|
+
# Sıfıra yakın değerleri temizle
|
667
|
+
if abs(new_basis[k]) < 1e-10:
|
668
|
+
del new_basis[k]
|
669
|
+
return CliffordNumber(new_basis)
|
670
|
+
elif isinstance(other, (int, float)):
|
671
|
+
new_basis = self.basis.copy()
|
672
|
+
new_basis[''] = new_basis.get('', 0.0) + other
|
673
|
+
return CliffordNumber(new_basis)
|
674
|
+
return NotImplemented
|
675
|
+
|
676
|
+
def __sub__(self, other):
|
677
|
+
if isinstance(other, CliffordNumber):
|
678
|
+
new_basis = self.basis.copy()
|
679
|
+
for k, v in other.basis.items():
|
680
|
+
new_basis[k] = new_basis.get(k, 0.0) - v
|
681
|
+
if abs(new_basis[k]) < 1e-10:
|
682
|
+
del new_basis[k]
|
683
|
+
return CliffordNumber(new_basis)
|
684
|
+
elif isinstance(other, (int, float)):
|
685
|
+
new_basis = self.basis.copy()
|
686
|
+
new_basis[''] = new_basis.get('', 0.0) - other
|
687
|
+
return CliffordNumber(new_basis)
|
688
|
+
return NotImplemented
|
689
|
+
|
690
|
+
def __mul__(self, other):
|
691
|
+
if isinstance(other, (int, float)):
|
692
|
+
return CliffordNumber({k: v * other for k, v in self.basis.items()})
|
693
|
+
elif isinstance(other, CliffordNumber):
|
694
|
+
# Basit Clifford çarpımı (e_i^2 = +1 varsayımıyla)
|
695
|
+
new_basis = {}
|
696
|
+
|
697
|
+
for k1, v1 in self.basis.items():
|
698
|
+
for k2, v2 in other.basis.items():
|
699
|
+
# Skaler çarpım
|
700
|
+
if k1 == '':
|
701
|
+
product_key = k2
|
702
|
+
sign = 1.0
|
703
|
+
elif k2 == '':
|
704
|
+
product_key = k1
|
705
|
+
sign = 1.0
|
706
|
+
else:
|
707
|
+
# Vektör çarpımı: e_i * e_j
|
708
|
+
combined = sorted(k1 + k2)
|
709
|
+
product_key = ''.join(combined)
|
710
|
+
|
711
|
+
# Basitleştirilmiş: e_i^2 = +1, anti-commutative
|
712
|
+
sign = 1.0
|
713
|
+
# Burada gerçek Clifford cebir kuralları uygulanmalı
|
714
|
+
|
715
|
+
new_basis[product_key] = new_basis.get(product_key, 0.0) + sign * v1 * v2
|
716
|
+
|
717
|
+
return CliffordNumber(new_basis)
|
718
|
+
return NotImplemented
|
719
|
+
|
720
|
+
def __truediv__(self, other):
|
721
|
+
if isinstance(other, (int, float)):
|
722
|
+
if other == 0:
|
723
|
+
raise ZeroDivisionError("Division by zero")
|
724
|
+
return CliffordNumber({k: v / other for k, v in self.basis.items()})
|
725
|
+
return NotImplemented
|
726
|
+
|
727
|
+
def __str__(self):
|
728
|
+
parts = []
|
729
|
+
if '' in self.basis and abs(self.basis['']) > 1e-10:
|
730
|
+
parts.append(f"{self.basis['']:.2f}")
|
731
|
+
|
732
|
+
sorted_keys = sorted([k for k in self.basis if k != ''], key=lambda x: (len(x), x))
|
733
|
+
for k in sorted_keys:
|
734
|
+
v = self.basis[k]
|
735
|
+
if abs(v) > 1e-10:
|
736
|
+
sign = '+' if v > 0 and parts else ''
|
737
|
+
parts.append(f"{sign}{v:.2f}e{k}")
|
738
|
+
|
739
|
+
result = "".join(parts).replace("+-", "-")
|
740
|
+
return result if result else "0.0"
|
741
|
+
|
742
|
+
@classmethod
|
743
|
+
def parse(cls, s) -> 'CliffordNumber':
|
744
|
+
"""Class method olarak parse metodu"""
|
745
|
+
return _parse_clifford(s)
|
746
|
+
|
747
|
+
def __repr__(self):
|
748
|
+
return self.__str__()
|
749
|
+
"""
|
637
750
|
class CliffordNumber:
|
638
751
|
|
639
752
|
def __init__(self, basis_dict):
|
640
|
-
|
641
|
-
CliffordNumber constructor - sadece basis_dict alır.
|
642
|
-
Dimension property olarak hesaplanabilir.
|
643
|
-
|
753
|
+
|
754
|
+
#CliffordNumber constructor - sadece basis_dict alır.
|
755
|
+
#Dimension property olarak hesaplanabilir.
|
756
|
+
|
644
757
|
self.basis = {k: float(v) for k, v in basis_dict.items()}
|
645
758
|
|
646
759
|
@property
|
647
760
|
def dimension(self):
|
648
|
-
|
761
|
+
#Vector space dimension'ını otomatik hesaplar.
|
649
762
|
if not self.basis:
|
650
763
|
return 0
|
651
764
|
max_index = 0
|
@@ -727,6 +840,7 @@ class CliffordNumber:
|
|
727
840
|
if not parts:
|
728
841
|
return "0.0"
|
729
842
|
return "".join(parts).replace("+-", "-")
|
843
|
+
"""
|
730
844
|
|
731
845
|
|
732
846
|
@dataclass
|
@@ -863,10 +977,56 @@ def _extract_numeric_part(s: str) -> str:
|
|
863
977
|
# Hiç sayı bulunamazsa orijinal string'i döndür
|
864
978
|
return s
|
865
979
|
|
866
|
-
def _parse_complex(s
|
867
|
-
"""Bir string'i complex sayıya dönüştürür.
|
980
|
+
def _parse_complex(s) -> complex:
|
981
|
+
"""Bir string'i veya sayıyı complex sayıya dönüştürür.
|
868
982
|
"real,imag", "real+imag(i/j)", "real", "imag(i/j)" formatlarını destekler.
|
983
|
+
Float ve int tiplerini de doğrudan kabul eder.
|
869
984
|
"""
|
985
|
+
# Eğer zaten complex sayıysa doğrudan döndür
|
986
|
+
if isinstance(s, complex):
|
987
|
+
return s
|
988
|
+
|
989
|
+
# Eğer float veya int ise doğrudan complex'e dönüştür
|
990
|
+
if isinstance(s, (float, int)):
|
991
|
+
return complex(s)
|
992
|
+
|
993
|
+
# String işlemleri için önce string'e dönüştür
|
994
|
+
if isinstance(s, str):
|
995
|
+
s = s.strip().replace('J', 'j').replace('i', 'j') # Hem J hem i yerine j kullan
|
996
|
+
else:
|
997
|
+
s = str(s).strip().replace('J', 'j').replace('i', 'j')
|
998
|
+
|
999
|
+
# 1. Eğer "real,imag" formatındaysa
|
1000
|
+
if ',' in s:
|
1001
|
+
parts = s.split(',')
|
1002
|
+
if len(parts) == 2:
|
1003
|
+
try:
|
1004
|
+
return complex(float(parts[0]), float(parts[1]))
|
1005
|
+
except ValueError:
|
1006
|
+
pass # Devam et
|
1007
|
+
|
1008
|
+
# 2. Python'ın kendi complex() dönüştürücüsünü kullanmayı dene (örn: "1+2j", "3j", "-5")
|
1009
|
+
try:
|
1010
|
+
return complex(s)
|
1011
|
+
except ValueError:
|
1012
|
+
# 3. Sadece real kısmı varsa (örn: "5")
|
1013
|
+
try:
|
1014
|
+
return complex(float(s), 0)
|
1015
|
+
except ValueError:
|
1016
|
+
# 4. Sadece sanal kısmı varsa (örn: "2j", "j")
|
1017
|
+
if s.endswith('j'):
|
1018
|
+
try:
|
1019
|
+
imag_val = float(s[:-1]) if s[:-1] else 1.0 # "j" -> 1.0j
|
1020
|
+
return complex(0, imag_val)
|
1021
|
+
except ValueError:
|
1022
|
+
pass
|
1023
|
+
|
1024
|
+
raise ValueError(f"Geçersiz kompleks sayı formatı: '{s}'")
|
1025
|
+
"""
|
1026
|
+
def _parse_complex(s: str) -> complex:
|
1027
|
+
#Bir string'i complex sayıya dönüştürür.
|
1028
|
+
# "real,imag", "real+imag(i/j)", "real", "imag(i/j)" formatlarını destekler.
|
1029
|
+
|
870
1030
|
s = s.strip().replace('J', 'j').replace('i', 'j') # Hem J hem i yerine j kullan
|
871
1031
|
|
872
1032
|
# 1. Eğer "real,imag" formatındaysa
|
@@ -895,6 +1055,7 @@ def _parse_complex(s: str) -> complex:
|
|
895
1055
|
pass
|
896
1056
|
|
897
1057
|
raise ValueError(f"Geçersiz kompleks sayı formatı: '{s}'")
|
1058
|
+
"""
|
898
1059
|
|
899
1060
|
def convert_to_float(value):
|
900
1061
|
"""Convert various Keçeci number types to a float or raise an error if not possible."""
|
@@ -959,8 +1120,20 @@ def safe_add(added_value, ask_unit, direction):
|
|
959
1120
|
raise TypeError(f"{msg} → {type(e).__name__}: {e}") from e
|
960
1121
|
|
961
1122
|
|
962
|
-
def _parse_neutrosophic(s
|
1123
|
+
def _parse_neutrosophic(s) -> Tuple[float, float, float]:
|
963
1124
|
"""Parses neutrosophic string into (t, i, f) tuple."""
|
1125
|
+
# Eğer zaten tuple ise doğrudan döndür
|
1126
|
+
if isinstance(s, (tuple, list)) and len(s) >= 3:
|
1127
|
+
return float(s[0]), float(s[1]), float(s[2])
|
1128
|
+
|
1129
|
+
# Sayısal tipse sadece t değeri olarak işle
|
1130
|
+
if isinstance(s, (float, int, complex)):
|
1131
|
+
return float(s), 0.0, 0.0
|
1132
|
+
|
1133
|
+
# String işlemleri için önce string'e dönüştür
|
1134
|
+
if not isinstance(s, str):
|
1135
|
+
s = str(s)
|
1136
|
+
|
964
1137
|
s_clean = s.strip().replace(" ", "").upper()
|
965
1138
|
|
966
1139
|
# VİRGÜL formatı: t,i,f (3 parametre)
|
@@ -1002,8 +1175,20 @@ def _parse_neutrosophic(s: str) -> Tuple[float, float, float]:
|
|
1002
1175
|
except ValueError:
|
1003
1176
|
return 0.0, 0.0, 0.0 # Default
|
1004
1177
|
|
1005
|
-
def _parse_hyperreal(s
|
1178
|
+
def _parse_hyperreal(s) -> Tuple[float, float]:
|
1006
1179
|
"""Parses hyperreal string into (finite, infinitesimal) tuple."""
|
1180
|
+
# Eğer zaten tuple ise doğrudan döndür
|
1181
|
+
if isinstance(s, (tuple, list)) and len(s) >= 2:
|
1182
|
+
return float(s[0]), float(s[1])
|
1183
|
+
|
1184
|
+
# Sayısal tipse sadece finite değeri olarak işle
|
1185
|
+
if isinstance(s, (float, int, complex)):
|
1186
|
+
return float(s), 0.0
|
1187
|
+
|
1188
|
+
# String işlemleri için önce string'e dönüştür
|
1189
|
+
if not isinstance(s, str):
|
1190
|
+
s = str(s)
|
1191
|
+
|
1007
1192
|
s_clean = s.strip().replace(" ", "")
|
1008
1193
|
|
1009
1194
|
# VİRGÜL formatı: finite,infinitesimal
|
@@ -1036,10 +1221,20 @@ def _parse_hyperreal(s: str) -> Tuple[float, float]:
|
|
1036
1221
|
except ValueError:
|
1037
1222
|
return 0.0, 0.0 # Default
|
1038
1223
|
|
1039
|
-
def _parse_quaternion_from_csv(s
|
1040
|
-
"""Virgülle ayrılmış string'i Quaternion'a dönüştürür.
|
1041
|
-
|
1042
|
-
|
1224
|
+
def _parse_quaternion_from_csv(s) -> np.quaternion:
|
1225
|
+
"""Virgülle ayrılmış string'i veya sayıyı Quaternion'a dönüştürür."""
|
1226
|
+
# Eğer zaten quaternion ise doğrudan döndür
|
1227
|
+
if isinstance(s, np.quaternion):
|
1228
|
+
return s
|
1229
|
+
|
1230
|
+
# Sayısal tipse skaler quaternion olarak işle
|
1231
|
+
if isinstance(s, (float, int, complex)):
|
1232
|
+
return np.quaternion(float(s), 0, 0, 0)
|
1233
|
+
|
1234
|
+
# String işlemleri için önce string'e dönüştür
|
1235
|
+
if not isinstance(s, str):
|
1236
|
+
s = str(s)
|
1237
|
+
|
1043
1238
|
s = s.strip()
|
1044
1239
|
parts_str = s.split(',')
|
1045
1240
|
|
@@ -1056,15 +1251,29 @@ def _parse_quaternion_from_csv(s: str) -> np.quaternion:
|
|
1056
1251
|
else:
|
1057
1252
|
raise ValueError(f"Geçersiz quaternion formatı. 1 veya 4 bileşen bekleniyor: '{s}'")
|
1058
1253
|
|
1059
|
-
|
1060
|
-
def _has_comma_format(s: str) -> bool:
|
1254
|
+
def _has_comma_format(s) -> bool:
|
1061
1255
|
"""String'in virgül içerip içermediğini kontrol eder."""
|
1256
|
+
if not isinstance(s, str):
|
1257
|
+
s = str(s)
|
1062
1258
|
return ',' in s
|
1063
1259
|
|
1064
|
-
def _parse_neutrosophic_bicomplex(s
|
1260
|
+
def _parse_neutrosophic_bicomplex(s) -> NeutrosophicBicomplexNumber:
|
1065
1261
|
"""
|
1066
|
-
Parses string
|
1262
|
+
Parses string or numbers into NeutrosophicBicomplexNumber.
|
1067
1263
|
"""
|
1264
|
+
# Eğer zaten NeutrosophicBicomplexNumber ise doğrudan döndür
|
1265
|
+
if isinstance(s, NeutrosophicBicomplexNumber):
|
1266
|
+
return s
|
1267
|
+
|
1268
|
+
# Sayısal tipse tüm bileşenler 0, sadece ilk bileşen değerli
|
1269
|
+
if isinstance(s, (float, int, complex)):
|
1270
|
+
values = [float(s)] + [0.0] * 7
|
1271
|
+
return NeutrosophicBicomplexNumber(*values)
|
1272
|
+
|
1273
|
+
# String işlemleri için önce string'e dönüştür
|
1274
|
+
if not isinstance(s, str):
|
1275
|
+
s = str(s)
|
1276
|
+
|
1068
1277
|
try:
|
1069
1278
|
parts = s.split(',')
|
1070
1279
|
if len(parts) != 8:
|
@@ -1073,9 +1282,167 @@ def _parse_neutrosophic_bicomplex(s: str) -> NeutrosophicBicomplexNumber:
|
|
1073
1282
|
return NeutrosophicBicomplexNumber(*values)
|
1074
1283
|
except Exception as e:
|
1075
1284
|
raise ValueError(f"Invalid NeutrosophicBicomplex format: '{s}' → {e}")
|
1285
|
+
"""
|
1286
|
+
def _parse_neutrosophic(s: str) -> Tuple[float, float, float]:
|
1287
|
+
#Parses neutrosophic string into (t, i, f) tuple.
|
1288
|
+
s_clean = s.strip().replace(" ", "").upper()
|
1289
|
+
|
1290
|
+
# VİRGÜL formatı: t,i,f (3 parametre)
|
1291
|
+
if ',' in s_clean:
|
1292
|
+
parts = s_clean.split(',')
|
1293
|
+
try:
|
1294
|
+
if len(parts) >= 3:
|
1295
|
+
return float(parts[0]), float(parts[1]), float(parts[2])
|
1296
|
+
elif len(parts) == 2:
|
1297
|
+
return float(parts[0]), float(parts[1]), 0.0
|
1298
|
+
elif len(parts) == 1:
|
1299
|
+
return float(parts[0]), 0.0, 0.0
|
1300
|
+
except ValueError:
|
1301
|
+
pass
|
1076
1302
|
|
1303
|
+
# Eski formatları destekle
|
1304
|
+
try:
|
1305
|
+
if 'I' in s_clean or 'F' in s_clean:
|
1306
|
+
# Basit parsing
|
1307
|
+
t_part = s_clean
|
1308
|
+
i_val, f_val = 0.0, 0.0
|
1309
|
+
|
1310
|
+
if 'I' in s_clean:
|
1311
|
+
parts = s_clean.split('I')
|
1312
|
+
t_part = parts[0]
|
1313
|
+
i_val = float(parts[1]) if parts[1] and parts[1] not in ['', '+', '-'] else 1.0
|
1314
|
+
|
1315
|
+
if 'F' in t_part:
|
1316
|
+
parts = t_part.split('F')
|
1317
|
+
t_val = float(parts[0]) if parts[0] and parts[0] not in ['', '+', '-'] else 0.0
|
1318
|
+
f_val = float(parts[1]) if len(parts) > 1 and parts[1] not in ['', '+', '-'] else 1.0
|
1319
|
+
else:
|
1320
|
+
t_val = float(t_part) if t_part not in ['', '+', '-'] else 0.0
|
1321
|
+
|
1322
|
+
return t_val, i_val, f_val
|
1323
|
+
else:
|
1324
|
+
# Sadece sayısal değer
|
1325
|
+
return float(s_clean), 0.0, 0.0
|
1326
|
+
except ValueError:
|
1327
|
+
return 0.0, 0.0, 0.0 # Default
|
1328
|
+
"""
|
1329
|
+
"""
|
1330
|
+
def _parse_hyperreal(s: str) -> Tuple[float, float]:
|
1331
|
+
#Parses hyperreal string into (finite, infinitesimal) tuple.
|
1332
|
+
s_clean = s.strip().replace(" ", "")
|
1333
|
+
|
1334
|
+
# VİRGÜL formatı: finite,infinitesimal
|
1335
|
+
if ',' in s_clean:
|
1336
|
+
parts = s_clean.split(',')
|
1337
|
+
if len(parts) >= 2:
|
1338
|
+
try:
|
1339
|
+
return float(parts[0]), float(parts[1])
|
1340
|
+
except ValueError:
|
1341
|
+
pass
|
1342
|
+
elif len(parts) == 1:
|
1343
|
+
try:
|
1344
|
+
return float(parts[0]), 0.0
|
1345
|
+
except ValueError:
|
1346
|
+
pass
|
1347
|
+
|
1348
|
+
# Eski 'a+be' formatını destekle
|
1349
|
+
if 'e' in s_clean:
|
1350
|
+
try:
|
1351
|
+
parts = s_clean.split('e')
|
1352
|
+
finite = float(parts[0]) if parts[0] not in ['', '+', '-'] else 0.0
|
1353
|
+
infinitesimal = float(parts[1]) if len(parts) > 1 and parts[1] not in ['', '+', '-'] else 1.0
|
1354
|
+
return finite, infinitesimal
|
1355
|
+
except ValueError:
|
1356
|
+
pass
|
1357
|
+
|
1358
|
+
# Sadece sayısal değer
|
1359
|
+
try:
|
1360
|
+
return float(s_clean), 0.0
|
1361
|
+
except ValueError:
|
1362
|
+
return 0.0, 0.0 # Default
|
1363
|
+
"""
|
1364
|
+
"""
|
1365
|
+
def _parse_quaternion_from_csv(s: str) -> np.quaternion:
|
1366
|
+
#Virgülle ayrılmış string'i Quaternion'a dönüştürür.
|
1367
|
+
#"w,x,y,z" veya sadece "w" (skaler) formatlarını destekler.
|
1368
|
+
|
1369
|
+
s = s.strip()
|
1370
|
+
parts_str = s.split(',')
|
1371
|
+
|
1372
|
+
# Tüm parçaları float'a dönüştürmeyi dene
|
1373
|
+
try:
|
1374
|
+
parts_float = [float(p.strip()) for p in parts_str]
|
1375
|
+
except ValueError:
|
1376
|
+
raise ValueError(f"Quaternion bileşenleri sayı olmalı: '{s}'")
|
1377
|
+
|
1378
|
+
if len(parts_float) == 4:
|
1379
|
+
return np.quaternion(*parts_float)
|
1380
|
+
elif len(parts_float) == 1: # Sadece skaler değer
|
1381
|
+
return np.quaternion(parts_float[0], 0, 0, 0)
|
1382
|
+
else:
|
1383
|
+
raise ValueError(f"Geçersiz quaternion formatı. 1 veya 4 bileşen bekleniyor: '{s}'")
|
1384
|
+
"""
|
1385
|
+
"""
|
1386
|
+
def _has_comma_format(s: str) -> bool:
|
1387
|
+
#String'in virgül içerip içermediğini kontrol eder.
|
1388
|
+
return ',' in s
|
1389
|
+
"""
|
1390
|
+
"""
|
1391
|
+
def _parse_neutrosophic_bicomplex(s: str) -> NeutrosophicBicomplexNumber:
|
1392
|
+
|
1393
|
+
#Parses string like "a,b,c,d,e,f,g,h" into 8 components.
|
1394
|
+
|
1395
|
+
try:
|
1396
|
+
parts = s.split(',')
|
1397
|
+
if len(parts) != 8:
|
1398
|
+
raise ValueError(f"Expected 8 components, got {len(parts)}")
|
1399
|
+
values = [float(part.strip()) for part in parts]
|
1400
|
+
return NeutrosophicBicomplexNumber(*values)
|
1401
|
+
except Exception as e:
|
1402
|
+
raise ValueError(f"Invalid NeutrosophicBicomplex format: '{s}' → {e}")
|
1403
|
+
"""
|
1404
|
+
|
1405
|
+
def _parse_octonion(s) -> OctonionNumber:
|
1406
|
+
"""String'i veya sayıyı OctonionNumber'a dönüştürür.
|
1407
|
+
w,x,y,z,e,f,g,h:e0,e1,e2,e3,e4,e5,e6,e7
|
1408
|
+
"""
|
1409
|
+
# Eğer zaten OctonionNumber ise doğrudan döndür
|
1410
|
+
if isinstance(s, OctonionNumber):
|
1411
|
+
return s
|
1412
|
+
|
1413
|
+
# Eğer sayısal tipse (float, int, complex) skaler olarak işle
|
1414
|
+
if isinstance(s, (float, int, complex)):
|
1415
|
+
scalar = float(s)
|
1416
|
+
return OctonionNumber(scalar, 0, 0, 0, 0, 0, 0, 0)
|
1417
|
+
|
1418
|
+
# String işlemleri için önce string'e dönüştür
|
1419
|
+
if not isinstance(s, str):
|
1420
|
+
s = str(s)
|
1421
|
+
|
1422
|
+
s_clean = s.strip()
|
1423
|
+
|
1424
|
+
# Eğer virgül içermiyorsa, skaler olarak kabul et
|
1425
|
+
if ',' not in s_clean:
|
1426
|
+
try:
|
1427
|
+
scalar = float(s_clean)
|
1428
|
+
return OctonionNumber(scalar, 0, 0, 0, 0, 0, 0, 0)
|
1429
|
+
except ValueError:
|
1430
|
+
raise ValueError(f"Invalid octonion format: '{s}'")
|
1431
|
+
|
1432
|
+
# Virgülle ayrılmışsa
|
1433
|
+
try:
|
1434
|
+
parts = [float(p.strip()) for p in s_clean.split(',')]
|
1435
|
+
if len(parts) == 8:
|
1436
|
+
return OctonionNumber(*parts) # 8 parametre olarak gönder
|
1437
|
+
else:
|
1438
|
+
# Eksik veya fazla bileşen için default
|
1439
|
+
scalar = parts[0] if parts else 0.0
|
1440
|
+
return OctonionNumber(scalar, 0, 0, 0, 0, 0, 0, 0)
|
1441
|
+
except ValueError as e:
|
1442
|
+
raise ValueError(f"Invalid octonion format: '{s}'") from e
|
1443
|
+
"""
|
1077
1444
|
def _parse_octonion(s: str) -> OctonionNumber:
|
1078
|
-
|
1445
|
+
#'w,x,y,z,e,f,g,h' formatındaki stringi OctonionNumber'a çevirir.
|
1079
1446
|
s_clean = s.strip()
|
1080
1447
|
|
1081
1448
|
# Eğer virgül içermiyorsa, skaler olarak kabul et
|
@@ -1097,10 +1464,42 @@ def _parse_octonion(s: str) -> OctonionNumber:
|
|
1097
1464
|
return OctonionNumber(scalar, 0, 0, 0, 0, 0, 0, 0)
|
1098
1465
|
except ValueError as e:
|
1099
1466
|
raise ValueError(f"Invalid octonion format: '{s}'") from e
|
1467
|
+
"""
|
1100
1468
|
|
1469
|
+
def _parse_sedenion(s) -> SedenionNumber:
|
1470
|
+
"""String'i veya sayıyı SedenionNumber'a dönüştürür."""
|
1471
|
+
# Eğer zaten SedenionNumber ise doğrudan döndür
|
1472
|
+
if isinstance(s, SedenionNumber):
|
1473
|
+
return s
|
1474
|
+
|
1475
|
+
# Eğer sayısal tipse (float, int, complex) skaler olarak işle
|
1476
|
+
if isinstance(s, (float, int, complex)):
|
1477
|
+
scalar_val = float(s)
|
1478
|
+
return SedenionNumber([scalar_val] + [0.0] * 15)
|
1479
|
+
|
1480
|
+
# String işlemleri için önce string'e dönüştür
|
1481
|
+
if not isinstance(s, str):
|
1482
|
+
s = str(s)
|
1483
|
+
|
1484
|
+
s = s.strip()
|
1485
|
+
parts = [p.strip() for p in s.split(',')]
|
1101
1486
|
|
1487
|
+
if len(parts) == 16:
|
1488
|
+
try:
|
1489
|
+
return SedenionNumber(list(map(float, parts)))
|
1490
|
+
except ValueError as e:
|
1491
|
+
raise ValueError(f"Geçersiz sedenion bileşen değeri: '{s}' -> {e}") from e
|
1492
|
+
elif len(parts) == 1: # Sadece skaler değer girildiğinde
|
1493
|
+
try:
|
1494
|
+
scalar_val = float(parts[0])
|
1495
|
+
return SedenionNumber([scalar_val] + [0.0] * 15)
|
1496
|
+
except ValueError as e:
|
1497
|
+
raise ValueError(f"Geçersiz skaler sedenion değeri: '{s}' -> {e}") from e
|
1498
|
+
|
1499
|
+
raise ValueError(f"Sedenion için 16 bileşen veya tek skaler bileşen gerekir. Verilen: '{s}' ({len(parts)} bileşen)")
|
1500
|
+
"""
|
1102
1501
|
def _parse_sedenion(s: str) -> SedenionNumber:
|
1103
|
-
|
1502
|
+
#String'i SedenionNumber'a dönüştürür.
|
1104
1503
|
s = s.strip()
|
1105
1504
|
parts = [p.strip() for p in s.split(',')]
|
1106
1505
|
|
@@ -1117,9 +1516,109 @@ def _parse_sedenion(s: str) -> SedenionNumber:
|
|
1117
1516
|
raise ValueError(f"Geçersiz skaler sedenion değeri: '{s}' -> {e}") from e
|
1118
1517
|
|
1119
1518
|
raise ValueError(f"Sedenion için 16 bileşen veya tek skaler bileşen gerekir. Verilen: '{s}' ({len(parts)} bileşen)")
|
1519
|
+
"""
|
1120
1520
|
|
1121
|
-
def _parse_clifford(s
|
1521
|
+
def _parse_clifford(s) -> CliffordNumber:
|
1122
1522
|
"""Algebraik string'i CliffordNumber'a dönüştürür (ör: '1.0+2.0e1')."""
|
1523
|
+
if isinstance(s, CliffordNumber):
|
1524
|
+
return s
|
1525
|
+
|
1526
|
+
if isinstance(s, (float, int, complex)):
|
1527
|
+
return CliffordNumber({'': float(s)})
|
1528
|
+
|
1529
|
+
if not isinstance(s, str):
|
1530
|
+
s = str(s)
|
1531
|
+
|
1532
|
+
s = s.strip().replace(' ', '').replace('^', '') # ^ işaretini kaldır
|
1533
|
+
basis_dict = {}
|
1534
|
+
|
1535
|
+
# Daha iyi regex pattern: +-1.23e12 formatını yakala
|
1536
|
+
pattern = r'([+-]?)(\d*\.?\d+)(?:e(\d+))?|([+-]?)(?:e(\d+))'
|
1537
|
+
matches = re.findall(pattern, s)
|
1538
|
+
|
1539
|
+
for match in matches:
|
1540
|
+
sign_str, coeff_str, basis1, sign_str2, basis2 = match
|
1541
|
+
|
1542
|
+
# Hangi grup match oldu?
|
1543
|
+
if coeff_str or basis1:
|
1544
|
+
sign = -1.0 if sign_str == '-' else 1.0
|
1545
|
+
coeff = float(coeff_str) if coeff_str else 1.0
|
1546
|
+
basis_key = basis1 if basis1 else ''
|
1547
|
+
else:
|
1548
|
+
sign = -1.0 if sign_str2 == '-' else 1.0
|
1549
|
+
coeff = 1.0
|
1550
|
+
basis_key = basis2
|
1551
|
+
|
1552
|
+
value = sign * coeff
|
1553
|
+
basis_dict[basis_key] = basis_dict.get(basis_key, 0.0) + value
|
1554
|
+
|
1555
|
+
# Ayrıca +e1, -e2 gibi ifadeleri yakala
|
1556
|
+
pattern2 = r'([+-])e(\d+)'
|
1557
|
+
matches2 = re.findall(pattern2, s)
|
1558
|
+
|
1559
|
+
for sign_str, basis_key in matches2:
|
1560
|
+
sign = -1.0 if sign_str == '-' else 1.0
|
1561
|
+
basis_dict[basis_key] = basis_dict.get(basis_key, 0.0) + sign
|
1562
|
+
|
1563
|
+
return CliffordNumber(basis_dict)
|
1564
|
+
"""
|
1565
|
+
|
1566
|
+
def _parse_clifford(s) -> CliffordNumber:
|
1567
|
+
#Algebraik string'i veya sayıyı CliffordNumber'a dönüştürür (ör: '1.0+2.0e1').
|
1568
|
+
# Eğer zaten CliffordNumber ise doğrudan döndür
|
1569
|
+
if isinstance(s, CliffordNumber):
|
1570
|
+
return s
|
1571
|
+
|
1572
|
+
# Eğer sayısal tipse (float, int, complex) skaler olarak işle
|
1573
|
+
if isinstance(s, (float, int, complex)):
|
1574
|
+
return CliffordNumber({'': float(s)})
|
1575
|
+
|
1576
|
+
# String işlemleri için önce string'e dönüştür
|
1577
|
+
if not isinstance(s, str):
|
1578
|
+
s = str(s)
|
1579
|
+
|
1580
|
+
s = s.strip().replace(' ', '')
|
1581
|
+
basis_dict = {'': 0.0} # Skaler kısım
|
1582
|
+
|
1583
|
+
terms_pattern = re.compile(r"([+-]?)(\d*\.?\d+(?:[eE][+-]?\d+)?)?(e\d*)?")
|
1584
|
+
remaining_s = s
|
1585
|
+
|
1586
|
+
while remaining_s:
|
1587
|
+
match = terms_pattern.match(remaining_s)
|
1588
|
+
if not match or (match.group(2) is None and match.group(3) is None):
|
1589
|
+
if remaining_s.startswith('+') or remaining_s.startswith('-'):
|
1590
|
+
current_sign = remaining_s[0]
|
1591
|
+
remaining_s = remaining_s[1:]
|
1592
|
+
if not remaining_s:
|
1593
|
+
coeff = 1.0 if current_sign == '+' else -1.0
|
1594
|
+
basis_dict[''] = basis_dict.get('', 0.0) + coeff
|
1595
|
+
continue
|
1596
|
+
raise ValueError(f"Geçersiz Clifford terim formatı: '{remaining_s}'")
|
1597
|
+
|
1598
|
+
sign_str, coeff_str, basis_str_with_e = match.groups()
|
1599
|
+
current_sign = 1.0
|
1600
|
+
if sign_str == '-': current_sign = -1.0
|
1601
|
+
|
1602
|
+
coeff = 1.0
|
1603
|
+
if coeff_str: coeff = float(coeff_str)
|
1604
|
+
elif not sign_str: coeff = 1.0
|
1605
|
+
elif sign_str and not coeff_str: coeff = 1.0
|
1606
|
+
|
1607
|
+
coeff *= current_sign
|
1608
|
+
|
1609
|
+
if basis_str_with_e:
|
1610
|
+
basis_key = basis_str_with_e.lstrip('e')
|
1611
|
+
basis_dict[basis_key] = basis_dict.get(basis_key, 0.0) + coeff
|
1612
|
+
else:
|
1613
|
+
basis_dict[''] = basis_dict.get('', 0.0) + coeff
|
1614
|
+
|
1615
|
+
remaining_s = remaining_s[match.end():]
|
1616
|
+
|
1617
|
+
return CliffordNumber(basis_dict)
|
1618
|
+
"""
|
1619
|
+
"""
|
1620
|
+
def _parse_clifford(s: str) -> CliffordNumber:
|
1621
|
+
#Algebraik string'i CliffordNumber'a dönüştürür (ör: '1.0+2.0e1').
|
1123
1622
|
s = s.strip().replace(' ', '')
|
1124
1623
|
basis_dict = {'': 0.0} # Skaler kısım
|
1125
1624
|
|
@@ -1158,9 +1657,41 @@ def _parse_clifford(s: str) -> CliffordNumber:
|
|
1158
1657
|
remaining_s = remaining_s[match.end():]
|
1159
1658
|
|
1160
1659
|
return CliffordNumber(basis_dict)
|
1660
|
+
"""
|
1161
1661
|
|
1662
|
+
def _parse_dual(s) -> DualNumber:
|
1663
|
+
"""String'i veya sayıyı DualNumber'a dönüştürür."""
|
1664
|
+
# Eğer zaten DualNumber ise doğrudan döndür
|
1665
|
+
if isinstance(s, DualNumber):
|
1666
|
+
return s
|
1667
|
+
|
1668
|
+
# Eğer sayısal tipse (float, int, complex) real kısım olarak işle
|
1669
|
+
if isinstance(s, (float, int, complex)):
|
1670
|
+
return DualNumber(float(s), 0.0)
|
1671
|
+
|
1672
|
+
# String işlemleri için önce string'e dönüştür
|
1673
|
+
if not isinstance(s, str):
|
1674
|
+
s = str(s)
|
1675
|
+
|
1676
|
+
s = s.strip()
|
1677
|
+
parts = [p.strip() for p in s.split(',')]
|
1678
|
+
|
1679
|
+
# Sadece ilk iki bileşeni al
|
1680
|
+
if len(parts) >= 2:
|
1681
|
+
try:
|
1682
|
+
return DualNumber(float(parts[0]), float(parts[1]))
|
1683
|
+
except ValueError:
|
1684
|
+
pass
|
1685
|
+
elif len(parts) == 1: # Sadece real kısım verilmiş
|
1686
|
+
try:
|
1687
|
+
return DualNumber(float(parts[0]), 0.0)
|
1688
|
+
except ValueError:
|
1689
|
+
pass
|
1690
|
+
|
1691
|
+
raise ValueError(f"Geçersiz Dual sayı formatı: '{s}' (Real, Dual veya sadece Real bekleniyor)")
|
1692
|
+
"""
|
1162
1693
|
def _parse_dual(s: str) -> DualNumber:
|
1163
|
-
|
1694
|
+
#Virgülle ayrılmış string'i DualNumber'a dönüştürür.
|
1164
1695
|
s = s.strip()
|
1165
1696
|
parts = [p.strip() for p in s.split(',')]
|
1166
1697
|
|
@@ -1177,9 +1708,22 @@ def _parse_dual(s: str) -> DualNumber:
|
|
1177
1708
|
pass
|
1178
1709
|
|
1179
1710
|
raise ValueError(f"Geçersiz Dual sayı formatı: '{s}' (Real, Dual veya sadece Real bekleniyor)")
|
1711
|
+
"""
|
1180
1712
|
|
1181
|
-
def _parse_splitcomplex(s
|
1182
|
-
"""
|
1713
|
+
def _parse_splitcomplex(s) -> SplitcomplexNumber:
|
1714
|
+
"""String'i veya sayıyı SplitcomplexNumber'a dönüştürür."""
|
1715
|
+
# Eğer zaten SplitcomplexNumber ise doğrudan döndür
|
1716
|
+
if isinstance(s, SplitcomplexNumber):
|
1717
|
+
return s
|
1718
|
+
|
1719
|
+
# Eğer sayısal tipse (float, int, complex) real kısım olarak işle
|
1720
|
+
if isinstance(s, (float, int, complex)):
|
1721
|
+
return SplitcomplexNumber(float(s), 0.0)
|
1722
|
+
|
1723
|
+
# String işlemleri için önce string'e dönüştür
|
1724
|
+
if not isinstance(s, str):
|
1725
|
+
s = str(s)
|
1726
|
+
|
1183
1727
|
s = s.strip()
|
1184
1728
|
parts = [p.strip() for p in s.split(',')]
|
1185
1729
|
|
@@ -1195,7 +1739,25 @@ def _parse_splitcomplex(s: str) -> SplitcomplexNumber:
|
|
1195
1739
|
pass
|
1196
1740
|
|
1197
1741
|
raise ValueError(f"Geçersiz Split-Complex sayı formatı: '{s}' (Real, Split veya sadece Real bekleniyor)")
|
1742
|
+
"""
|
1743
|
+
def _parse_splitcomplex(s: str) -> SplitcomplexNumber:
|
1744
|
+
#Virgülle ayrılmış string'i SplitcomplexNumber'a dönüştürür.
|
1745
|
+
s = s.strip()
|
1746
|
+
parts = [p.strip() for p in s.split(',')]
|
1198
1747
|
|
1748
|
+
if len(parts) == 2:
|
1749
|
+
try:
|
1750
|
+
return SplitcomplexNumber(float(parts[0]), float(parts[1]))
|
1751
|
+
except ValueError:
|
1752
|
+
pass
|
1753
|
+
elif len(parts) == 1: # Sadece real kısım verilmiş
|
1754
|
+
try:
|
1755
|
+
return SplitcomplexNumber(float(parts[0]), 0.0)
|
1756
|
+
except ValueError:
|
1757
|
+
pass
|
1758
|
+
|
1759
|
+
raise ValueError(f"Geçersiz Split-Complex sayı formatı: '{s}' (Real, Split veya sadece Real bekleniyor)")
|
1760
|
+
"""
|
1199
1761
|
|
1200
1762
|
class Constants:
|
1201
1763
|
"""Oktonyon sabitleri."""
|
@@ -2485,8 +3047,8 @@ def get_interactive() -> Tuple[List[Any], Dict[str, Any]]:
|
|
2485
3047
|
9: "Enter Hyperreal start (in 'finite,infinitesimal' format, e.g., '0.0,0.0001'): ",
|
2486
3048
|
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
3049
|
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'): ",
|
3050
|
+
12: "Enter Octonion start (in 'w,x,y,z,e,f,g,h':'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'): ",
|
3051
|
+
13: "Enter Sedenion start (in 'e0,e1,...,e15' format, e.g., '1.0,2.0,3.0,0,0,0,0,0,0,0,0,0,0,0,0,0', '0.0'): ",
|
2490
3052
|
14: "Enter Clifford start (in 'scalar,e1,e2,e12,...' format, e.g., '0.1+0.2e1', '1.0+2.0e1+3.0e12'): ",
|
2491
3053
|
15: "Enter Dual start (in 'real,dual' format, e.g., '2.0,0.5'): ",
|
2492
3054
|
16: "Enter Split-Complex start (in 'real,split' format, e.g., '1.0,0.8'): ",
|
@@ -2505,8 +3067,8 @@ def get_interactive() -> Tuple[List[Any], Dict[str, Any]]:
|
|
2505
3067
|
9: "Enter Hyperreal increment (in 'finite,infinitesimal' format, e.g., '0.0,0.0001'): ",
|
2506
3068
|
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
3069
|
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.
|
2509
|
-
13: "Enter Sedenion increment (in 'e0,e1,...,e15' format, e.g., '0.
|
3070
|
+
12: "Enter Octonion increment (in 'w,x,y,z,e,f,g,h':'e0,e1,e2,e3,e4,e5,e6,e7' format, e.g., '1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0', '0.0'): ",
|
3071
|
+
13: "Enter Sedenion increment (in 'e0,e1,...,e15' format, e.g., '1.0,2.0,3.0,0,0,0,0,0,0,0,0,0,0,0,0,0', '0.0'): ",
|
2510
3072
|
14: "Enter Clifford increment (in 'scalar,e1,e2,e12,...' format, e.g., '0.1+0.2e1', '1.0+2.0e1+3.0e12'): ",
|
2511
3073
|
15: "Enter Dual increment (in 'real,dual' format, e.g., 1.0, '0.1,0.0'): ",
|
2512
3074
|
16: "Enter Split-Complex increment (in 'real,split' format, e.g., '0.1,0.0'): ",
|
@@ -2610,6 +3172,36 @@ def is_neutrosophic_like(obj):
|
|
2610
3172
|
(hasattr(obj, 'value') and hasattr(obj, 'indeterminacy')) or \
|
2611
3173
|
(hasattr(obj, 'determinate') and hasattr(obj, 'indeterminate'))
|
2612
3174
|
|
3175
|
+
# Yardımcı fonksiyon: Bileşen dağılımı grafiği
|
3176
|
+
def _plot_component_distribution(ax, elem, all_keys, seq_length=1):
|
3177
|
+
"""Bileşen dağılımını gösterir"""
|
3178
|
+
if seq_length == 1:
|
3179
|
+
# Tek veri noktası için bileşen değerleri
|
3180
|
+
components = []
|
3181
|
+
values = []
|
3182
|
+
|
3183
|
+
for key in all_keys:
|
3184
|
+
if key == '':
|
3185
|
+
components.append('Scalar')
|
3186
|
+
else:
|
3187
|
+
components.append(f'e{key}')
|
3188
|
+
values.append(elem.basis.get(key, 0.0))
|
3189
|
+
|
3190
|
+
bars = ax.bar(components, values, alpha=0.7, color='tab:blue')
|
3191
|
+
ax.set_title("Component Values")
|
3192
|
+
ax.tick_params(axis='x', rotation=45)
|
3193
|
+
|
3194
|
+
for bar in bars:
|
3195
|
+
height = bar.get_height()
|
3196
|
+
if height != 0:
|
3197
|
+
ax.text(bar.get_x() + bar.get_width()/2., height,
|
3198
|
+
f'{height:.2f}', ha='center', va='bottom')
|
3199
|
+
else:
|
3200
|
+
# Çoklu veri ama PCA yapılamıyor
|
3201
|
+
ax.text(0.5, 0.5, f"Need ≥2 data points and ≥2 features\n(Current: {seq_length} points, {len(all_keys)} features)",
|
3202
|
+
ha='center', va='center', transform=ax.transAxes, fontsize=11)
|
3203
|
+
ax.set_title("Insufficient for PCA")
|
3204
|
+
|
2613
3205
|
def plot_numbers(sequence: List[Any], title: str = "Keçeci Number Sequence Analysis"):
|
2614
3206
|
"""
|
2615
3207
|
Tüm 16 Keçeci Sayı türü için detaylı görselleştirme sağlar.
|
@@ -2618,6 +3210,13 @@ def plot_numbers(sequence: List[Any], title: str = "Keçeci Number Sequence Anal
|
|
2618
3210
|
print("Sequence is empty. Nothing to plot.")
|
2619
3211
|
return
|
2620
3212
|
|
3213
|
+
try:
|
3214
|
+
from sklearn.decomposition import PCA
|
3215
|
+
use_pca = True
|
3216
|
+
except ImportError:
|
3217
|
+
use_pca = False
|
3218
|
+
print("scikit-learn kurulu değil. PCA olmadan çizim yapılıyor...")
|
3219
|
+
|
2621
3220
|
fig = plt.figure(figsize=(18, 14), constrained_layout=True)
|
2622
3221
|
fig.suptitle(title, fontsize=18, fontweight='bold')
|
2623
3222
|
|
@@ -2790,33 +3389,100 @@ def plot_numbers(sequence: List[Any], title: str = "Keçeci Number Sequence Anal
|
|
2790
3389
|
values = {k: [elem.basis.get(k, 0.0) for elem in sequence] for k in all_keys}
|
2791
3390
|
scalar = values.get('', [0]*len(sequence))
|
2792
3391
|
vector_keys = [k for k in all_keys if len(k) == 1]
|
3392
|
+
|
3393
|
+
# numpy import et
|
3394
|
+
try:
|
3395
|
+
import numpy as np
|
3396
|
+
numpy_available = True
|
3397
|
+
except ImportError:
|
3398
|
+
numpy_available = False
|
3399
|
+
|
3400
|
+
# GERÇEK özellik sayısını hesapla (sıfır olmayan bileşenler)
|
3401
|
+
non_zero_features = 0
|
3402
|
+
for key in all_keys:
|
3403
|
+
if any(abs(elem.basis.get(key, 0.0)) > 1e-10 for elem in sequence):
|
3404
|
+
non_zero_features += 1
|
3405
|
+
|
3406
|
+
print(f"Debug: Total keys: {len(all_keys)}, Non-zero features: {non_zero_features}")
|
3407
|
+
|
3408
|
+
# Her zaman 2x2 grid kullan
|
3409
|
+
fig = plt.figure(figsize=(12, 10))
|
2793
3410
|
gs = GridSpec(2, 2, figure=fig)
|
2794
|
-
|
2795
3411
|
ax1 = fig.add_subplot(gs[0, 0])
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
3412
|
+
ax2 = fig.add_subplot(gs[0, 1])
|
3413
|
+
ax3 = fig.add_subplot(gs[1, :])
|
3414
|
+
|
3415
|
+
# 1. Grafik: Skaler ve Vektör Bileşenleri
|
3416
|
+
ax1.plot(scalar, 'o-', label='Scalar', color='black', linewidth=2)
|
3417
|
+
|
3418
|
+
# Sadece sıfır olmayan vektör bileşenlerini göster
|
3419
|
+
visible_vectors = 0
|
3420
|
+
for k in vector_keys:
|
3421
|
+
if any(abs(v) > 1e-10 for v in values[k]):
|
3422
|
+
ax1.plot(values[k], 'o-', label=f'Vec {k}', alpha=0.7, linewidth=1.5)
|
3423
|
+
visible_vectors += 1
|
3424
|
+
if visible_vectors >= 3:
|
3425
|
+
break
|
3426
|
+
|
3427
|
+
ax1.set_title("Scalar & Vector Components Over Time")
|
2800
3428
|
ax1.legend()
|
3429
|
+
ax1.grid(True, alpha=0.3)
|
2801
3430
|
|
2802
|
-
|
3431
|
+
# 2. Grafik: Bivector Magnitude
|
2803
3432
|
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")
|
3433
|
+
ax2.plot(bivector_mags, 'o-', color='tab:green', linewidth=2, label='Bivector Magnitude')
|
3434
|
+
ax2.set_title("Bivector Magnitude Over Time")
|
3435
|
+
ax2.legend()
|
3436
|
+
ax2.grid(True, alpha=0.3)
|
2806
3437
|
|
2807
|
-
|
2808
|
-
|
2809
|
-
|
2810
|
-
|
2811
|
-
|
3438
|
+
# 3. Grafik: PCA - ARTIK PCA GÖSTERİYORUZ
|
3439
|
+
if len(sequence) >= 2 and non_zero_features >= 2:
|
3440
|
+
# PCA yapılabilir durumda
|
3441
|
+
try:
|
3442
|
+
from sklearn.decomposition import PCA
|
3443
|
+
|
3444
|
+
# Tüm bileşenleri içeren matris oluştur
|
3445
|
+
matrix_data = []
|
3446
|
+
for elem in sequence:
|
3447
|
+
row = []
|
3448
|
+
for key in all_keys:
|
3449
|
+
row.append(elem.basis.get(key, 0.0))
|
3450
|
+
matrix_data.append(row)
|
3451
|
+
|
3452
|
+
if numpy_available:
|
3453
|
+
matrix = np.array(matrix_data)
|
3454
|
+
else:
|
3455
|
+
import numpy as np
|
3456
|
+
matrix = np.array(matrix_data)
|
3457
|
+
|
3458
|
+
# PCA uygula
|
3459
|
+
pca = PCA(n_components=min(2, matrix.shape[1]))
|
2812
3460
|
proj = pca.fit_transform(matrix)
|
2813
|
-
|
2814
|
-
sc = ax3.scatter(proj[:, 0], proj[:, 1], c=range(len(proj)),
|
2815
|
-
|
2816
|
-
|
2817
|
-
|
2818
|
-
|
2819
|
-
|
3461
|
+
|
3462
|
+
sc = ax3.scatter(proj[:, 0], proj[:, 1], c=range(len(proj)),
|
3463
|
+
cmap='plasma', s=50, alpha=0.8)
|
3464
|
+
ax3.set_title(f"PCA Projection ({non_zero_features} features)\nVariance: {pca.explained_variance_ratio_[0]:.3f}, {pca.explained_variance_ratio_[1]:.3f}")
|
3465
|
+
|
3466
|
+
cbar = plt.colorbar(sc, ax=ax3)
|
3467
|
+
cbar.set_label("Time Step")
|
3468
|
+
|
3469
|
+
ax3.plot(proj[:, 0], proj[:, 1], 'gray', linestyle='--', alpha=0.5)
|
3470
|
+
ax3.grid(True, alpha=0.3)
|
3471
|
+
|
3472
|
+
except ImportError:
|
3473
|
+
ax3.text(0.5, 0.5, "Install sklearn for PCA",
|
3474
|
+
ha='center', va='center', transform=ax3.transAxes)
|
3475
|
+
except Exception as e:
|
3476
|
+
ax3.text(0.5, 0.5, f"PCA Error: {str(e)[:30]}",
|
3477
|
+
ha='center', va='center', transform=ax3.transAxes)
|
3478
|
+
else:
|
3479
|
+
# PCA yapılamazsa bilgi göster
|
3480
|
+
ax3.text(0.5, 0.5, f"Need ≥2 data points and ≥2 features\n(Current: {len(sequence)} points, {non_zero_features} features)",
|
3481
|
+
ha='center', va='center', transform=ax3.transAxes)
|
3482
|
+
ax3.set_title("Insufficient for PCA")
|
3483
|
+
|
3484
|
+
#plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)
|
3485
|
+
|
2820
3486
|
|
2821
3487
|
# --- 8. DualNumber
|
2822
3488
|
elif hasattr(first_elem, 'real') and hasattr(first_elem, 'dual'):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kececinumbers
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.7.1
|
4
4
|
Summary: Keçeci Numbers: An Exploration of a Dynamic Sequence Across Diverse Number Sets
|
5
5
|
Home-page: https://github.com/WhiteSymmetry/kececinumbers
|
6
6
|
Author: Mehmet Keçeci
|
@@ -141,7 +141,7 @@ This library provides a unified algorithm that operates on 16 different number t
|
|
141
141
|
<details>
|
142
142
|
<summary>🇹🇷 Türkçe Açıklama (Click to expand)</summary>
|
143
143
|
|
144
|
-
**Keçeci Sayıları**, Collatz Varsayımı'ndan esinlenen ve farklı sayı sistemlerinde dinamik diziler üreten, analiz eden ve görselleştiren bir Python kütüphanesidir. Bu kütüphane, tamsayılardan karmaşık sayılara, kuaterniyonlardan nötrosofik sayılara kadar
|
144
|
+
**Keçeci Sayıları**, Collatz Varsayımı'ndan esinlenen ve farklı sayı sistemlerinde dinamik diziler üreten, analiz eden ve görselleştiren bir Python kütüphanesidir. Bu kütüphane, tamsayılardan karmaşık sayılara, kuaterniyonlardan nötrosofik sayılara kadar 16 farklı sayı türü üzerinde çalışan birleşik bir algoritma sunar. Akademik araştırmalar ve sayı teorisindeki keşifler için bir araç olarak tasarlanmıştır.
|
145
145
|
|
146
146
|
</details>
|
147
147
|
|
@@ -165,7 +165,7 @@ This flexible mechanism provides a rich framework for studying the behavior of n
|
|
165
165
|
* **Advanced Visualization:** Provides a multi-dimensional `plot_numbers` function tailored to the nature of each number system.
|
166
166
|
* **Keçeci Prime Number (KPN) Analysis:** Identifies the most recurring prime representation in sequences to analyze their convergence behavior.
|
167
167
|
* **Interactive and Programmatic Usage:** Supports both interactive parameter input (`get_interactive`) and direct use in scripts (`get_with_params`).
|
168
|
-
* 0.
|
168
|
+
* 0.7.1: 16 Numbers
|
169
169
|
* 0.6.7: 11 Numbers
|
170
170
|
|
171
171
|
---
|
@@ -367,7 +367,8 @@ if seq_interactive:
|
|
367
367
|
type_names = [
|
368
368
|
"Positive Real", "Negative Real", "Complex", "Float", "Rational",
|
369
369
|
"Quaternion", "Neutrosophic", "Neutro-Complex", "Hyperreal",
|
370
|
-
"Bicomplex", "Neutro-Bicomplex"
|
370
|
+
"Bicomplex", "Neutro-Bicomplex", "Octonion", "Sedenion", "Clifford",
|
371
|
+
"Dual", "Split-Complex"
|
371
372
|
]
|
372
373
|
# type_name'i params sözlüğüne ekleyerek raporu zenginleştirelim
|
373
374
|
params['type_name'] = type_names[type_choice - 1]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
docs/conf.py,sha256=jkpH_TchRJcC_EspKeY1E_rml2ODmIWhWoqvyCPu_ok,1116
|
2
|
+
kececinumbers/__init__.py,sha256=xu86m_9hyxJEAJzn0rNqD2fee1KHv68S_lH-C2tgWj4,8473
|
3
|
+
kececinumbers/_version.py,sha256=UKtHtm7N84E6BrPGq2nQkqcNcflKksJqe_V-1gJwHb0,453
|
4
|
+
kececinumbers/kececinumbers.py,sha256=eak738SZHtoO9lwHi_DbNGNhSKoIHrYdmWR7RY0E9WA,149453
|
5
|
+
kececinumbers-0.7.1.dist-info/licenses/LICENSE,sha256=NJZsJEbQuKzxn1mWPWCbRx8jRUqGS22thl8wwuRQJ9c,1071
|
6
|
+
tests/test_sample.py,sha256=vwGbEZ6gcEFq60P5Sqrnc_DVw2QFXOSU1vm3GyzQMnc,9628
|
7
|
+
kececinumbers-0.7.1.dist-info/METADATA,sha256=Us-mqQxpWZBP6CqiDL0CDXyGCeQroeELkZ9twGkT-QA,34956
|
8
|
+
kececinumbers-0.7.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
9
|
+
kececinumbers-0.7.1.dist-info/top_level.txt,sha256=ABQEKRH9iYb4sWnFdx7gIx7Hg899YktRkQpbRlSSqwU,25
|
10
|
+
kececinumbers-0.7.1.dist-info/RECORD,,
|
@@ -1,10 +0,0 @@
|
|
1
|
-
docs/conf.py,sha256=jkpH_TchRJcC_EspKeY1E_rml2ODmIWhWoqvyCPu_ok,1116
|
2
|
-
kececinumbers/__init__.py,sha256=hcp5N1niet4RTCVLHFER1Trne3N4rkr7FuTOYmW5CF8,8399
|
3
|
-
kececinumbers/_version.py,sha256=99vsIW2hk-mcMeKtSlgQTxyLR5WE8y25YIUWf5X9jjA,453
|
4
|
-
kececinumbers/kececinumbers.py,sha256=dtGfkAwjoJRC0j06XV2P2JF0F78k1bZ7UbfJ8xb5wU0,125125
|
5
|
-
kececinumbers-0.6.9.dist-info/licenses/LICENSE,sha256=NJZsJEbQuKzxn1mWPWCbRx8jRUqGS22thl8wwuRQJ9c,1071
|
6
|
-
tests/test_sample.py,sha256=vwGbEZ6gcEFq60P5Sqrnc_DVw2QFXOSU1vm3GyzQMnc,9628
|
7
|
-
kececinumbers-0.6.9.dist-info/METADATA,sha256=WTf4gVAJKivHi6eN-bRZaOxyb1JctKarq_DfaZIBSV8,34886
|
8
|
-
kececinumbers-0.6.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
9
|
-
kececinumbers-0.6.9.dist-info/top_level.txt,sha256=ABQEKRH9iYb4sWnFdx7gIx7Hg899YktRkQpbRlSSqwU,25
|
10
|
-
kececinumbers-0.6.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|