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 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.6.9"
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
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # _version.py
3
3
 
4
- __version__ = "0.6.9"
4
+ __version__ = "0.7.1"
5
5
  __license__ = "MIT"
6
6
  __description__ = "Keçeci Numbers: An Exploration of a Dynamic Sequence Across Diverse Number Sets."
7
7
  __author__ = "Mehmet Keçeci"
@@ -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
- """Vector space dimension'ını otomatik hesaplar."""
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: str) -> complex:
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: str) -> Tuple[float, float, float]:
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: str) -> Tuple[float, float]:
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: str) -> np.quaternion:
1040
- """Virgülle ayrılmış string'i Quaternion'a dönüştürür.
1041
- "w,x,y,z" veya sadece "w" (skaler) formatlarını destekler.
1042
- """
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: str) -> NeutrosophicBicomplexNumber:
1260
+ def _parse_neutrosophic_bicomplex(s) -> NeutrosophicBicomplexNumber:
1065
1261
  """
1066
- Parses string like "a,b,c,d,e,f,g,h" into 8 components.
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
- """'w,x,y,z,e,f,g,h' formatındaki stringi OctonionNumber'a çevirir."""
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
- """String'i SedenionNumber'a dönüştürür."""
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: str) -> CliffordNumber:
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
- """Virgülle ayrılmış string'i DualNumber'a dönüştürür."""
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: str) -> SplitcomplexNumber:
1182
- """Virgülle ayrılmış string'i SplitcomplexNumber'a dönüştürür."""
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.1', '0.0'): ",
2509
- 13: "Enter Sedenion increment (in 'e0,e1,...,e15' format, e.g., '0.1', '0.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
- ax1.plot(scalar, 'o-', label='Scalar', color='black')
2797
- for k in vector_keys[:3]:
2798
- ax1.plot(values[k], label=f'Vec {k}', alpha=0.7)
2799
- ax1.set_title("Scalar & Vectors")
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
- ax2 = fig.add_subplot(gs[0, 1])
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
- try:
2808
- from sklearn.decomposition import PCA
2809
- matrix = np.array([list(v.values()) for v in values.values()]).T
2810
- pca = PCA(n_components=2)
2811
- if len(sequence) > 1:
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
- ax3 = fig.add_subplot(gs[1, :])
2814
- sc = ax3.scatter(proj[:, 0], proj[:, 1], c=range(len(proj)), cmap='plasma')
2815
- ax3.set_title("Clifford PCA")
2816
- plt.colorbar(sc, ax=ax3, label="Component")
2817
- except:
2818
- ax3 = fig.add_subplot(gs[1, :])
2819
- ax3.text(0.5, 0.5, "Install sklearn for PCA", ha='center')
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.6.9
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 11 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.
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.6.9: 16 Nubers
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,,