lqft-python-engine 0.1.3__tar.gz → 0.1.7__tar.gz
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.
- {lqft_python_engine-0.1.3/lqft_python_engine.egg-info → lqft_python_engine-0.1.7}/PKG-INFO +3 -2
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/lqft_engine.c +72 -55
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/lqft_engine.py +25 -4
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7/lqft_python_engine.egg-info}/PKG-INFO +3 -2
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/lqft_python_engine.egg-info/SOURCES.txt +2 -0
- lqft_python_engine-0.1.7/lqft_python_engine.egg-info/requires.txt +1 -0
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/lqft_python_engine.egg-info/top_level.txt +1 -0
- lqft_python_engine-0.1.7/pure_python_ds.py +139 -0
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/setup.py +5 -6
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/LICENSE.md +0 -0
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/lqft_python_engine.egg-info/dependency_links.txt +0 -0
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/pyproject.toml +0 -0
- {lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/setup.cfg +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lqft-python-engine
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: Log-Quantum Fractal Tree: Pattern-Aware Deduplicating Data Structure
|
|
5
5
|
Home-page: https://github.com/ParjadM/Log-Quantum-Fractal-Tree-LQFT-
|
|
6
6
|
Author: Parjad Minooei
|
|
7
7
|
License: MIT
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
12
11
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
12
|
Requires-Python: >=3.8
|
|
14
13
|
Description-Content-Type: text/markdown
|
|
15
14
|
License-File: LICENSE.md
|
|
15
|
+
Requires-Dist: psutil
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: classifier
|
|
18
18
|
Dynamic: description
|
|
@@ -20,6 +20,7 @@ Dynamic: description-content-type
|
|
|
20
20
|
Dynamic: home-page
|
|
21
21
|
Dynamic: license
|
|
22
22
|
Dynamic: license-file
|
|
23
|
+
Dynamic: requires-dist
|
|
23
24
|
Dynamic: requires-python
|
|
24
25
|
Dynamic: summary
|
|
25
26
|
|
|
@@ -11,30 +11,29 @@
|
|
|
11
11
|
#include <stdint.h>
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* LQFT C-Engine
|
|
14
|
+
* LQFT C-Engine - V4.3 (Dynamic Registry Build)
|
|
15
15
|
* Architect: Parjad Minooei
|
|
16
|
-
* *
|
|
17
|
-
* *
|
|
18
|
-
* * MAJOR FIX 3: Capped MAX_BITS to 64 to prevent Undefined Behavior bit-shifts.
|
|
16
|
+
* * BUGFIX: Added missing 'search' method to the native export table.
|
|
17
|
+
* * MEMORY: Moved Registry to HEAP (Dynamic) for zero-footprint reclamation.
|
|
19
18
|
*/
|
|
20
19
|
|
|
21
20
|
#define BIT_PARTITION 5
|
|
22
|
-
#define MAX_BITS 64
|
|
21
|
+
#define MAX_BITS 64
|
|
23
22
|
#define MASK 0x1F
|
|
24
|
-
#define REGISTRY_SIZE 8000009
|
|
23
|
+
#define REGISTRY_SIZE 8000009
|
|
25
24
|
|
|
26
25
|
typedef struct LQFTNode {
|
|
27
26
|
void* value;
|
|
28
27
|
uint64_t key_hash;
|
|
29
28
|
struct LQFTNode* children[32];
|
|
30
|
-
char struct_hash[17];
|
|
29
|
+
char struct_hash[17];
|
|
31
30
|
} LQFTNode;
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
// Registry is now a pointer allocated on the HEAP to allow full OS reclamation
|
|
33
|
+
static LQFTNode** registry = NULL;
|
|
34
|
+
static int physical_node_count = 0;
|
|
35
|
+
static LQFTNode* global_root = NULL;
|
|
36
36
|
|
|
37
|
-
// Upgraded to 64-bit FNV-1a Hash to prevent structural collisions at massive scales
|
|
38
37
|
uint64_t fnv1a_64(const char* str) {
|
|
39
38
|
uint64_t hash = 14695981039346656037ULL;
|
|
40
39
|
while (*str) {
|
|
@@ -44,8 +43,27 @@ uint64_t fnv1a_64(const char* str) {
|
|
|
44
43
|
return hash;
|
|
45
44
|
}
|
|
46
45
|
|
|
46
|
+
char* portable_strdup(const char* s) {
|
|
47
|
+
if (!s) return NULL;
|
|
48
|
+
#ifdef _WIN32
|
|
49
|
+
return _strdup(s);
|
|
50
|
+
#else
|
|
51
|
+
return strdup(s);
|
|
52
|
+
#endif
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static int init_registry() {
|
|
56
|
+
if (registry == NULL) {
|
|
57
|
+
// Use calloc to initialize all pointer slots to NULL safely
|
|
58
|
+
registry = (LQFTNode**)calloc(REGISTRY_SIZE, sizeof(LQFTNode*));
|
|
59
|
+
if (registry == NULL) return 0;
|
|
60
|
+
}
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
LQFTNode* create_node(void* value, uint64_t key_hash) {
|
|
48
65
|
LQFTNode* node = (LQFTNode*)malloc(sizeof(LQFTNode));
|
|
66
|
+
if (!node) return NULL;
|
|
49
67
|
node->value = value;
|
|
50
68
|
node->key_hash = key_hash;
|
|
51
69
|
for (int i = 0; i < 32; i++) node->children[i] = NULL;
|
|
@@ -53,6 +71,8 @@ LQFTNode* create_node(void* value, uint64_t key_hash) {
|
|
|
53
71
|
}
|
|
54
72
|
|
|
55
73
|
LQFTNode* get_canonical(void* value, uint64_t key_hash, LQFTNode** children) {
|
|
74
|
+
if (!init_registry()) return NULL;
|
|
75
|
+
|
|
56
76
|
char buffer[8192] = { 0 };
|
|
57
77
|
if (value != NULL) {
|
|
58
78
|
sprintf(buffer, "leaf:%s:%llu", (char*)value, (unsigned long long)key_hash);
|
|
@@ -61,23 +81,21 @@ LQFTNode* get_canonical(void* value, uint64_t key_hash, LQFTNode** children) {
|
|
|
61
81
|
for (int i = 0; i < 32; i++) {
|
|
62
82
|
if (children && children[i]) {
|
|
63
83
|
char seg_buf[32];
|
|
64
|
-
// FIX: Adding [%d] prevents identically hashed children in different slots from merging
|
|
65
84
|
sprintf(seg_buf, "[%d]%s", i, children[i]->struct_hash);
|
|
66
85
|
strcat(buffer, seg_buf);
|
|
67
86
|
}
|
|
68
87
|
}
|
|
69
88
|
}
|
|
70
89
|
|
|
71
|
-
// 64-bit structural hash formatting
|
|
72
90
|
uint64_t full_hash = fnv1a_64(buffer);
|
|
73
91
|
char lookup_hash[17];
|
|
74
92
|
sprintf(lookup_hash, "%016llx", (unsigned long long)full_hash);
|
|
75
93
|
uint32_t idx = full_hash % REGISTRY_SIZE;
|
|
76
94
|
|
|
77
|
-
// Linear Probing logic
|
|
78
95
|
uint32_t start_idx = idx;
|
|
79
96
|
while (registry[idx] != NULL) {
|
|
80
97
|
if (strcmp(registry[idx]->struct_hash, lookup_hash) == 0) {
|
|
98
|
+
if (value) free(value);
|
|
81
99
|
return registry[idx];
|
|
82
100
|
}
|
|
83
101
|
idx = (idx + 1) % REGISTRY_SIZE;
|
|
@@ -85,6 +103,7 @@ LQFTNode* get_canonical(void* value, uint64_t key_hash, LQFTNode** children) {
|
|
|
85
103
|
}
|
|
86
104
|
|
|
87
105
|
LQFTNode* new_node = create_node(value, key_hash);
|
|
106
|
+
if (!new_node) return NULL;
|
|
88
107
|
if (children) {
|
|
89
108
|
for (int i = 0; i < 32; i++) new_node->children[i] = children[i];
|
|
90
109
|
}
|
|
@@ -94,24 +113,33 @@ LQFTNode* get_canonical(void* value, uint64_t key_hash, LQFTNode** children) {
|
|
|
94
113
|
return new_node;
|
|
95
114
|
}
|
|
96
115
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
116
|
+
static PyObject* method_free_all(PyObject* self, PyObject* args) {
|
|
117
|
+
int freed_count = 0;
|
|
118
|
+
if (registry != NULL) {
|
|
119
|
+
for (int i = 0; i < REGISTRY_SIZE; i++) {
|
|
120
|
+
if (registry[i] != NULL) {
|
|
121
|
+
if (registry[i]->value) free(registry[i]->value);
|
|
122
|
+
free(registry[i]);
|
|
123
|
+
registry[i] = NULL;
|
|
124
|
+
freed_count++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Dynamic reclamation: Free the registry array itself
|
|
128
|
+
free(registry);
|
|
129
|
+
registry = NULL;
|
|
130
|
+
}
|
|
131
|
+
physical_node_count = 0;
|
|
132
|
+
global_root = NULL;
|
|
133
|
+
return PyLong_FromLong(freed_count);
|
|
104
134
|
}
|
|
105
135
|
|
|
106
|
-
// --- PYTHON API BRIDGE ---
|
|
107
|
-
|
|
108
136
|
static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
109
137
|
unsigned long long h;
|
|
110
138
|
char* val_str;
|
|
111
139
|
if (!PyArg_ParseTuple(args, "Ks", &h, &val_str)) return NULL;
|
|
112
140
|
|
|
113
141
|
if (!global_root) {
|
|
114
|
-
|
|
142
|
+
if (!init_registry()) return PyErr_NoMemory();
|
|
115
143
|
global_root = get_canonical(NULL, 0, NULL);
|
|
116
144
|
}
|
|
117
145
|
|
|
@@ -122,7 +150,6 @@ static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
|
122
150
|
LQFTNode* curr = global_root;
|
|
123
151
|
int bit_depth = 0;
|
|
124
152
|
|
|
125
|
-
// 1. Traversal
|
|
126
153
|
while (curr != NULL && curr->value == NULL) {
|
|
127
154
|
uint32_t segment = (h >> bit_depth) & MASK;
|
|
128
155
|
path_nodes[path_len] = curr;
|
|
@@ -137,16 +164,14 @@ static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
|
137
164
|
bit_depth += BIT_PARTITION;
|
|
138
165
|
}
|
|
139
166
|
|
|
140
|
-
// 2. Node Update / Collision Logic
|
|
141
167
|
LQFTNode* new_sub_node = NULL;
|
|
142
|
-
|
|
143
168
|
if (curr == NULL) {
|
|
144
169
|
new_sub_node = get_canonical(portable_strdup(val_str), h, NULL);
|
|
145
170
|
} else if (curr->key_hash == h) {
|
|
146
171
|
new_sub_node = get_canonical(portable_strdup(val_str), h, curr->children);
|
|
147
172
|
} else {
|
|
148
173
|
unsigned long long old_h = curr->key_hash;
|
|
149
|
-
char* old_val = (char*)curr->value;
|
|
174
|
+
char* old_val = portable_strdup((char*)curr->value);
|
|
150
175
|
int temp_depth = bit_depth;
|
|
151
176
|
|
|
152
177
|
while (temp_depth < MAX_BITS) {
|
|
@@ -154,30 +179,23 @@ static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
|
154
179
|
uint32_t s_new = (h >> temp_depth) & MASK;
|
|
155
180
|
|
|
156
181
|
if (s_old != s_new) {
|
|
157
|
-
LQFTNode* c_old = get_canonical(
|
|
182
|
+
LQFTNode* c_old = get_canonical(old_val, old_h, curr->children);
|
|
158
183
|
LQFTNode* c_new = get_canonical(portable_strdup(val_str), h, NULL);
|
|
159
|
-
|
|
160
184
|
LQFTNode* new_children[32] = {NULL};
|
|
161
185
|
new_children[s_old] = c_old;
|
|
162
186
|
new_children[s_new] = c_new;
|
|
163
|
-
|
|
164
187
|
new_sub_node = get_canonical(NULL, 0, new_children);
|
|
165
188
|
break;
|
|
166
189
|
} else {
|
|
167
|
-
path_nodes[path_len] = NULL;
|
|
190
|
+
path_nodes[path_len] = NULL;
|
|
168
191
|
path_segs[path_len] = s_old;
|
|
169
192
|
path_len++;
|
|
170
193
|
temp_depth += BIT_PARTITION;
|
|
171
194
|
}
|
|
172
195
|
}
|
|
173
|
-
|
|
174
|
-
// Absolute Hash Collision (Rare)
|
|
175
|
-
if (new_sub_node == NULL) {
|
|
176
|
-
new_sub_node = get_canonical(portable_strdup(val_str), h, curr->children);
|
|
177
|
-
}
|
|
196
|
+
if (new_sub_node == NULL) new_sub_node = get_canonical(portable_strdup(val_str), h, curr->children);
|
|
178
197
|
}
|
|
179
198
|
|
|
180
|
-
// 3. Iterative Back-Propagation
|
|
181
199
|
for (int i = path_len - 1; i >= 0; i--) {
|
|
182
200
|
if (path_nodes[i] == NULL) {
|
|
183
201
|
LQFTNode* new_children[32] = {NULL};
|
|
@@ -200,22 +218,24 @@ static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
|
200
218
|
static PyObject* method_search(PyObject* self, PyObject* args) {
|
|
201
219
|
unsigned long long h;
|
|
202
220
|
if (!PyArg_ParseTuple(args, "K", &h)) return NULL;
|
|
203
|
-
|
|
221
|
+
|
|
222
|
+
if (!global_root || registry == NULL) {
|
|
223
|
+
Py_RETURN_NONE;
|
|
224
|
+
}
|
|
204
225
|
|
|
205
226
|
LQFTNode* curr = global_root;
|
|
206
227
|
int bit_depth = 0;
|
|
207
228
|
|
|
208
|
-
while (curr != NULL) {
|
|
209
|
-
if (curr->value != NULL) {
|
|
210
|
-
if (curr->key_hash == h) return PyUnicode_FromString((char*)curr->value);
|
|
211
|
-
Py_RETURN_NONE;
|
|
212
|
-
}
|
|
229
|
+
while (curr != NULL && curr->value == NULL) {
|
|
213
230
|
uint32_t segment = (h >> bit_depth) & MASK;
|
|
214
|
-
if (curr->children[segment] == NULL) { Py_RETURN_NONE; }
|
|
215
231
|
curr = curr->children[segment];
|
|
216
232
|
bit_depth += BIT_PARTITION;
|
|
217
|
-
if (bit_depth >= MAX_BITS) break;
|
|
218
233
|
}
|
|
234
|
+
|
|
235
|
+
if (curr != NULL && curr->key_hash == h) {
|
|
236
|
+
return PyUnicode_FromString((char*)curr->value);
|
|
237
|
+
}
|
|
238
|
+
|
|
219
239
|
Py_RETURN_NONE;
|
|
220
240
|
}
|
|
221
241
|
|
|
@@ -224,16 +244,13 @@ static PyObject* method_get_metrics(PyObject* self, PyObject* args) {
|
|
|
224
244
|
}
|
|
225
245
|
|
|
226
246
|
static PyMethodDef LQFTMethods[] = {
|
|
227
|
-
{"insert", method_insert, METH_VARARGS, "Insert
|
|
228
|
-
{"search", method_search, METH_VARARGS, "Search
|
|
229
|
-
{"get_metrics", method_get_metrics, METH_VARARGS, "
|
|
247
|
+
{"insert", method_insert, METH_VARARGS, "Insert"},
|
|
248
|
+
{"search", method_search, METH_VARARGS, "Search"},
|
|
249
|
+
{"get_metrics", method_get_metrics, METH_VARARGS, "Metrics"},
|
|
250
|
+
{"free_all", method_free_all, METH_VARARGS, "Reclaim"},
|
|
230
251
|
{NULL, NULL, 0, NULL}
|
|
231
252
|
};
|
|
232
253
|
|
|
233
|
-
static struct PyModuleDef lqftmodule = {
|
|
234
|
-
PyModuleDef_HEAD_INIT, "lqft_c_engine", "LQFT Performance Engine", -1, LQFTMethods
|
|
235
|
-
};
|
|
254
|
+
static struct PyModuleDef lqftmodule = { PyModuleDef_HEAD_INIT, "lqft_c_engine", NULL, -1, LQFTMethods };
|
|
236
255
|
|
|
237
|
-
PyMODINIT_FUNC PyInit_lqft_c_engine(void) {
|
|
238
|
-
return PyModule_Create(&lqftmodule);
|
|
239
|
-
}
|
|
256
|
+
PyMODINIT_FUNC PyInit_lqft_c_engine(void) { return PyModule_Create(&lqftmodule); }
|
|
@@ -138,7 +138,6 @@ class AdaptiveLQFT:
|
|
|
138
138
|
self.threshold = float('inf') # Prevent continuous upgrade attempts
|
|
139
139
|
return
|
|
140
140
|
|
|
141
|
-
# print("\n[⚙️] AdaptiveLQFT: Threshold reached. Migrating to Native C-Engine...")
|
|
142
141
|
for key, val in self._light_store.items():
|
|
143
142
|
h = self._get_64bit_hash(key)
|
|
144
143
|
lqft_c_engine.insert(h, val)
|
|
@@ -149,16 +148,16 @@ class AdaptiveLQFT:
|
|
|
149
148
|
|
|
150
149
|
def insert(self, key, value):
|
|
151
150
|
if not self.is_native:
|
|
152
|
-
# Phase 1: Small Data Operations
|
|
151
|
+
# Phase 1: Small Data Operations
|
|
153
152
|
if key not in self._light_store:
|
|
154
153
|
self.size += 1
|
|
155
154
|
self._light_store[key] = value
|
|
156
155
|
|
|
157
|
-
# Check
|
|
156
|
+
# Check for migration threshold
|
|
158
157
|
if self.size >= self.threshold:
|
|
159
158
|
self._migrate_to_native()
|
|
160
159
|
else:
|
|
161
|
-
# Phase 2: Massive Data Operations (
|
|
160
|
+
# Phase 2: Massive Data Operations (Native C-Heap)
|
|
162
161
|
h = self._get_64bit_hash(key)
|
|
163
162
|
lqft_c_engine.insert(h, value)
|
|
164
163
|
|
|
@@ -169,6 +168,28 @@ class AdaptiveLQFT:
|
|
|
169
168
|
h = self._get_64bit_hash(key)
|
|
170
169
|
return lqft_c_engine.search(h)
|
|
171
170
|
|
|
171
|
+
def clear(self):
|
|
172
|
+
"""
|
|
173
|
+
Memory Reclamation: Manually trigger C-level heap cleanup.
|
|
174
|
+
In the Adaptive model, this handles both the Python dict and the C-Registry.
|
|
175
|
+
"""
|
|
176
|
+
self._light_store.clear()
|
|
177
|
+
self.size = 0
|
|
178
|
+
if C_ENGINE_READY:
|
|
179
|
+
return lqft_c_engine.free_all()
|
|
180
|
+
return 0
|
|
181
|
+
|
|
182
|
+
def __del__(self):
|
|
183
|
+
"""
|
|
184
|
+
Finalizer: Reclaims unmanaged C memory when the Python object is deleted.
|
|
185
|
+
Crucial for preventing memory leaks in long-running systems.
|
|
186
|
+
"""
|
|
187
|
+
try:
|
|
188
|
+
self.clear()
|
|
189
|
+
except:
|
|
190
|
+
# Silence errors during late interpreter shutdown/garbage collection
|
|
191
|
+
pass
|
|
192
|
+
|
|
172
193
|
def status(self):
|
|
173
194
|
"""Returns the current state of the engine."""
|
|
174
195
|
return {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lqft-python-engine
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: Log-Quantum Fractal Tree: Pattern-Aware Deduplicating Data Structure
|
|
5
5
|
Home-page: https://github.com/ParjadM/Log-Quantum-Fractal-Tree-LQFT-
|
|
6
6
|
Author: Parjad Minooei
|
|
7
7
|
License: MIT
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
12
11
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
12
|
Requires-Python: >=3.8
|
|
14
13
|
Description-Content-Type: text/markdown
|
|
15
14
|
License-File: LICENSE.md
|
|
15
|
+
Requires-Dist: psutil
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: classifier
|
|
18
18
|
Dynamic: description
|
|
@@ -20,6 +20,7 @@ Dynamic: description-content-type
|
|
|
20
20
|
Dynamic: home-page
|
|
21
21
|
Dynamic: license
|
|
22
22
|
Dynamic: license-file
|
|
23
|
+
Dynamic: requires-dist
|
|
23
24
|
Dynamic: requires-python
|
|
24
25
|
Dynamic: summary
|
|
25
26
|
|
{lqft_python_engine-0.1.3 → lqft_python_engine-0.1.7}/lqft_python_engine.egg-info/SOURCES.txt
RENAMED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
LICENSE.md
|
|
2
2
|
lqft_engine.c
|
|
3
3
|
lqft_engine.py
|
|
4
|
+
pure_python_ds.py
|
|
4
5
|
pyproject.toml
|
|
5
6
|
setup.py
|
|
6
7
|
lqft_python_engine.egg-info/PKG-INFO
|
|
7
8
|
lqft_python_engine.egg-info/SOURCES.txt
|
|
8
9
|
lqft_python_engine.egg-info/dependency_links.txt
|
|
10
|
+
lqft_python_engine.egg-info/requires.txt
|
|
9
11
|
lqft_python_engine.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
psutil
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import struct
|
|
2
|
+
|
|
3
|
+
# ---------------------------------------------------------
|
|
4
|
+
# 1. DETERMINISTIC HASHING (FNV-1a 64-bit)
|
|
5
|
+
# ---------------------------------------------------------
|
|
6
|
+
def fnv1a_64(key: str) -> int:
|
|
7
|
+
"""Generates a strict 64-bit deterministic hash for O(1) routing."""
|
|
8
|
+
hval = 0xcbf29ce484222325
|
|
9
|
+
fnv_prime = 0x100000001b3
|
|
10
|
+
for byte in key.encode('utf-8'):
|
|
11
|
+
hval ^= byte
|
|
12
|
+
hval = (hval * fnv_prime) & 0xFFFFFFFFFFFFFFFF
|
|
13
|
+
return hval
|
|
14
|
+
|
|
15
|
+
def combine_hashes(hashes: list) -> int:
|
|
16
|
+
"""Combines child Merkle hashes to generate a parent's structural hash."""
|
|
17
|
+
hval = 0
|
|
18
|
+
for h in hashes:
|
|
19
|
+
if h is not None:
|
|
20
|
+
hval ^= h
|
|
21
|
+
hval = (hval * 0x100000001b3) & 0xFFFFFFFFFFFFFFFF
|
|
22
|
+
return hval
|
|
23
|
+
|
|
24
|
+
# ---------------------------------------------------------
|
|
25
|
+
# 2. GLOBAL C-REGISTRY MOCK (Structural Folding)
|
|
26
|
+
# ---------------------------------------------------------
|
|
27
|
+
# Maps a Merkle Hash -> Physical Node Instance
|
|
28
|
+
NODE_REGISTRY = {}
|
|
29
|
+
|
|
30
|
+
class LQFTNode:
|
|
31
|
+
"""A fixed 32-way routing node."""
|
|
32
|
+
__slots__ = ('children', 'value', 'merkle_hash')
|
|
33
|
+
|
|
34
|
+
def __init__(self, value=None):
|
|
35
|
+
self.children = [None] * 32
|
|
36
|
+
self.value = value
|
|
37
|
+
self.merkle_hash = None
|
|
38
|
+
|
|
39
|
+
def get_deduplicated_node(node: LQFTNode) -> LQFTNode:
|
|
40
|
+
"""
|
|
41
|
+
The core of O(Σ) Space Complexity.
|
|
42
|
+
If a node with this exact structure exists, return the existing memory pointer.
|
|
43
|
+
Otherwise, register this new node.
|
|
44
|
+
"""
|
|
45
|
+
# Calculate structural Merkle Hash
|
|
46
|
+
child_hashes = [c.merkle_hash if c else None for c in node.children]
|
|
47
|
+
base_hash = fnv1a_64(str(node.value)) if node.value is not None else 0
|
|
48
|
+
node.merkle_hash = (base_hash ^ combine_hashes(child_hashes)) & 0xFFFFFFFFFFFFFFFF
|
|
49
|
+
|
|
50
|
+
# Structural Folding (Deduplication)
|
|
51
|
+
if node.merkle_hash in NODE_REGISTRY:
|
|
52
|
+
return NODE_REGISTRY[node.merkle_hash]
|
|
53
|
+
|
|
54
|
+
NODE_REGISTRY[node.merkle_hash] = node
|
|
55
|
+
return node
|
|
56
|
+
|
|
57
|
+
# ---------------------------------------------------------
|
|
58
|
+
# 3. THE LQFT ARCHITECTURE (Strictly Iterative)
|
|
59
|
+
# ---------------------------------------------------------
|
|
60
|
+
class LQFT:
|
|
61
|
+
def __init__(self):
|
|
62
|
+
self.root = get_deduplicated_node(LQFTNode())
|
|
63
|
+
|
|
64
|
+
def insert(self, key: str, value: any):
|
|
65
|
+
"""
|
|
66
|
+
O(1) Insertion. Capped at exactly 13 hops.
|
|
67
|
+
STRICTLY ITERATIVE. NO RECURSION ALLOWED.
|
|
68
|
+
"""
|
|
69
|
+
key_hash = fnv1a_64(key)
|
|
70
|
+
|
|
71
|
+
# Step 1: Iterative Traversal Down
|
|
72
|
+
# We store the path to allow bottom-up Merkle folding without recursion
|
|
73
|
+
path_stack = []
|
|
74
|
+
current = self.root
|
|
75
|
+
|
|
76
|
+
for level in range(13): # Fixed 64-bit space (13 chunks of 5 bits)
|
|
77
|
+
index = (key_hash >> (level * 5)) & 0x1F # Mask 5 bits
|
|
78
|
+
path_stack.append((current, index))
|
|
79
|
+
|
|
80
|
+
if current.children[index] is None:
|
|
81
|
+
current = LQFTNode() # Create empty node for routing
|
|
82
|
+
else:
|
|
83
|
+
current = current.children[index]
|
|
84
|
+
|
|
85
|
+
# Step 2: Create the Leaf Node
|
|
86
|
+
new_leaf = LQFTNode(value=value)
|
|
87
|
+
current = get_deduplicated_node(new_leaf)
|
|
88
|
+
|
|
89
|
+
# Step 3: Iterative Bottom-Up Folding (Copy-on-Write)
|
|
90
|
+
while path_stack:
|
|
91
|
+
parent_node, index = path_stack.pop()
|
|
92
|
+
|
|
93
|
+
# Create a copy of the parent to ensure immutability/versioning
|
|
94
|
+
new_parent = LQFTNode()
|
|
95
|
+
new_parent.children = list(parent_node.children) # Copy references
|
|
96
|
+
new_parent.children[index] = current # Attach the new folded child
|
|
97
|
+
|
|
98
|
+
# Deduplicate the new parent
|
|
99
|
+
current = get_deduplicated_node(new_parent)
|
|
100
|
+
|
|
101
|
+
# The final deduplicated node becomes the new root
|
|
102
|
+
self.root = current
|
|
103
|
+
|
|
104
|
+
def search(self, key: str) -> any:
|
|
105
|
+
"""O(1) Search. Guaranteed max 13 hops. Iterative."""
|
|
106
|
+
key_hash = fnv1a_64(key)
|
|
107
|
+
current = self.root
|
|
108
|
+
|
|
109
|
+
for level in range(13):
|
|
110
|
+
index = (key_hash >> (level * 5)) & 0x1F
|
|
111
|
+
current = current.children[index]
|
|
112
|
+
if current is None:
|
|
113
|
+
return None # Key not found
|
|
114
|
+
|
|
115
|
+
# FIXED: This return statement is now outside the loop!
|
|
116
|
+
return current.value
|
|
117
|
+
|
|
118
|
+
# Make it easy to use like standard Python Dicts
|
|
119
|
+
def __setitem__(self, key, value):
|
|
120
|
+
self.insert(key, value)
|
|
121
|
+
|
|
122
|
+
def __getitem__(self, key):
|
|
123
|
+
res = self.search(key)
|
|
124
|
+
if res is None:
|
|
125
|
+
raise KeyError(key)
|
|
126
|
+
return res
|
|
127
|
+
|
|
128
|
+
# ---------------------------------------------------------
|
|
129
|
+
# 4. EASY API (The "Heapify" Equivalent)
|
|
130
|
+
# ---------------------------------------------------------
|
|
131
|
+
def build_lqft(iterable) -> LQFT:
|
|
132
|
+
"""
|
|
133
|
+
Instantiates and builds an LQFT in O(1) interface time.
|
|
134
|
+
Usage: tree = build_lqft([("user1", "dataA"), ("user2", "dataB")])
|
|
135
|
+
"""
|
|
136
|
+
tree = LQFT()
|
|
137
|
+
for key, value in iterable:
|
|
138
|
+
tree.insert(key, value)
|
|
139
|
+
return tree
|
|
@@ -13,7 +13,7 @@ if os.name == 'nt':
|
|
|
13
13
|
else:
|
|
14
14
|
extra_compile_args = ['-O3']
|
|
15
15
|
|
|
16
|
-
# Load README for PyPI long_description
|
|
16
|
+
# Load README for PyPI long_description
|
|
17
17
|
long_description = "Log-Quantum Fractal Tree Engine"
|
|
18
18
|
if os.path.exists("readme.md"):
|
|
19
19
|
with open("readme.md", "r", encoding="utf-8") as fh:
|
|
@@ -31,7 +31,7 @@ lqft_extension = Extension(
|
|
|
31
31
|
|
|
32
32
|
setup(
|
|
33
33
|
name="lqft-python-engine",
|
|
34
|
-
version="0.1.
|
|
34
|
+
version="0.1.7",
|
|
35
35
|
description="Log-Quantum Fractal Tree: Pattern-Aware Deduplicating Data Structure",
|
|
36
36
|
long_description=long_description,
|
|
37
37
|
long_description_content_type="text/markdown",
|
|
@@ -39,13 +39,12 @@ setup(
|
|
|
39
39
|
url="https://github.com/ParjadM/Log-Quantum-Fractal-Tree-LQFT-",
|
|
40
40
|
ext_modules=[lqft_extension],
|
|
41
41
|
packages=find_packages(),
|
|
42
|
-
py_modules=["lqft_engine"],
|
|
43
|
-
install_requires=[],
|
|
44
|
-
license="MIT",
|
|
42
|
+
py_modules=["lqft_engine", "pure_python_ds"],
|
|
43
|
+
install_requires=['psutil'],
|
|
44
|
+
license="MIT",
|
|
45
45
|
classifiers=[
|
|
46
46
|
"Programming Language :: Python :: 3",
|
|
47
47
|
"Programming Language :: Python :: 3.12",
|
|
48
|
-
"License :: OSI Approved :: MIT License",
|
|
49
48
|
"Operating System :: OS Independent",
|
|
50
49
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
51
50
|
],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|