recursive-set 3.0.0 → 4.0.0
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.
- package/README.md +63 -131
- package/dist/cjs/index.js +418 -205
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +30 -25
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +417 -201
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,37 +1,33 @@
|
|
|
1
1
|
# RecursiveSet
|
|
2
2
|
|
|
3
|
-
> High-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
> **High-Performance ZFC Set Implementation for TypeScript**
|
|
4
|
+
>
|
|
5
|
+
> Mutable, strictly typed, and optimized for cache locality.
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.npmjs.com/package/recursive-set)
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## 🚀 What is this?
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
* **Tuples First:** Includes a strongly typed `Tuple` class for ordered pairs (e.g., edges, transitions), solving JS Array reference pitfalls.
|
|
16
|
-
* **Homogeneous by Default:** Generic typing (`RecursiveSet<T>`) enforces clean data structures.
|
|
17
|
-
* **Recursive:** Sets can contain sets (of sets...). Ideal for Power Sets and Von Neumann Ordinals.
|
|
18
|
-
* **Copy-on-Write:** **O(1) cloning** via structural sharing (powered by persistent Red-Black Trees).
|
|
19
|
-
* **Lean \& Mean:** No implicit overhead. Cycle checking is left to the user to allow maximum performance.
|
|
14
|
+
A mathematical set implementation designed for **Theoretical Computer Science**, **SAT-Solvers**, and **Graph Theory**. Unlike native JavaScript `Set`, `RecursiveSet` enforces **Structural Equality** (ZFC semantics) and supports deep nesting.
|
|
20
15
|
|
|
21
|
-
|
|
16
|
+
**v4.0.0 Update:** Now powered by **Sorted Arrays** instead of Red-Black Trees.
|
|
17
|
+
* **5x-10x Faster** than v3.0 (cache locality vs. pointer chasing).
|
|
18
|
+
* **O(1) Equality Checks** via aggressive hash caching.
|
|
19
|
+
* **Native Array Support** included.
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
---
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
## Features
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- Insertion/Lookup: **O(log n)**.
|
|
34
|
-
- Cloning: **O(1)**.
|
|
25
|
+
* **🔢 Strict Structural Equality:** `{1, 2}` is equal to `{2, 1}`.
|
|
26
|
+
* **📦 Deeply Recursive:** Sets can contain Sets. Ideal for Power Sets.
|
|
27
|
+
* **⚡ High Performance:** Optimized for V8 (Chrome/Node) using flat memory layouts and binary search.
|
|
28
|
+
* **📐 Tuples & Arrays:** Native support for `Tuple` class or standard JS Arrays `[a, b]` as elements.
|
|
29
|
+
* **🔒 Type Safe:** Fully strict TypeScript implementation. No `any` casts.
|
|
30
|
+
* **🛡️ Deterministic:** Hashing is order-independent for Sets and order-dependent for Sequences.
|
|
35
31
|
|
|
36
32
|
---
|
|
37
33
|
|
|
@@ -51,16 +47,19 @@ const states = new RecursiveSet<string>();
|
|
|
51
47
|
states.add("q0").add("q1");
|
|
52
48
|
|
|
53
49
|
// 2. Sets of Sets (Partitioning)
|
|
50
|
+
// Recursion requires explicit typing!
|
|
54
51
|
const partition = new RecursiveSet<RecursiveSet<string>>();
|
|
55
52
|
partition.add(states); // {{q0, q1}}
|
|
56
53
|
|
|
57
54
|
// 3. Tuples (Ordered Pairs / Edges)
|
|
58
55
|
const edge = new Tuple("q0", "q1"); // (q0, q1)
|
|
56
|
+
// or simply: const edge = ["q0", "q1"];
|
|
57
|
+
|
|
59
58
|
const transitions = new RecursiveSet<Tuple<[string, string]>>();
|
|
60
59
|
transitions.add(edge);
|
|
61
60
|
|
|
62
|
-
console.log(partition.toString());
|
|
63
|
-
console.log(transitions.toString());
|
|
61
|
+
console.log(partition.toString()); // {{q0, q1}}
|
|
62
|
+
console.log(transitions.toString()); // {(q0, q1)}
|
|
64
63
|
```
|
|
65
64
|
|
|
66
65
|
---
|
|
@@ -70,128 +69,62 @@ console.log(transitions.toString()); // {(q0, q1)}
|
|
|
70
69
|
### Constructor
|
|
71
70
|
|
|
72
71
|
```typescript
|
|
73
|
-
//
|
|
74
|
-
|
|
72
|
+
// Create empty or with initial elements
|
|
73
|
+
// Elements are automatically sorted and deduplicated.
|
|
74
|
+
new RecursiveSet<T>(...elements: T[])
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
|
|
77
78
|
### Methods
|
|
78
79
|
|
|
79
80
|
**Mutation:**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
|
|
84
|
-
**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- `has(element: T | RecursiveSet<T>): boolean` – Check membership
|
|
99
|
-
- `isSubset(other: RecursiveSet<T>): boolean` – Check if ⊆
|
|
100
|
-
- `isSuperset(other: RecursiveSet<T>): boolean` – Check if ⊇
|
|
101
|
-
- `equals(other: RecursiveSet<T>): boolean` – Structural equality
|
|
102
|
-
- `isEmpty(): boolean` – Check if set is empty
|
|
81
|
+
* `add(element: T): this` – Insert element (O(N) worst case, O(1) append).
|
|
82
|
+
* `remove(element: T): this` – Remove element.
|
|
83
|
+
* `clear(): this` – Reset set.
|
|
84
|
+
|
|
85
|
+
**Set Operations (Immutable results):**
|
|
86
|
+
* `union(other: RecursiveSet<T>): RecursiveSet<T>` – $A \cup B$
|
|
87
|
+
* `intersection(other: RecursiveSet<T>): RecursiveSet<T>` – $A \cap B$
|
|
88
|
+
* `difference(other: RecursiveSet<T>): RecursiveSet<T>` – $A \setminus B$
|
|
89
|
+
* `symmetricDifference(other: RecursiveSet<T>): RecursiveSet<T>` – $A \triangle B$
|
|
90
|
+
* `powerset(): RecursiveSet<RecursiveSet<T>>` – $\mathcal{P}(A)$
|
|
91
|
+
* `cartesianProduct<U>(other: RecursiveSet<U>): RecursiveSet<Tuple<[T, U]>>` – $A \times B$
|
|
92
|
+
|
|
93
|
+
**Predicates (Fast):**
|
|
94
|
+
* `has(element: T): boolean` – **O(log N)** lookup (Binary Search).
|
|
95
|
+
* `equals(other: RecursiveSet<T>): boolean` – **O(1)** via Hash-Cache (usually).
|
|
96
|
+
* `isSubset(other: RecursiveSet<T>): boolean` – Check if $A \subseteq B$.
|
|
97
|
+
* `isSuperset(other: RecursiveSet<T>): boolean` – Check if $A \supseteq B$.
|
|
98
|
+
* `isEmpty(): boolean` – Check if $|A| = 0$.
|
|
103
99
|
|
|
104
100
|
**Properties:**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
### Tuple Class
|
|
101
|
+
* `size: number` – Cardinality.
|
|
102
|
+
* `hashCode: number` – The cached hash of the set.
|
|
109
103
|
|
|
110
|
-
Helper for structural value equality of sequences.
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
const t1 = new Tuple(1, 2);
|
|
114
|
-
const t2 = new Tuple(1, 2);
|
|
115
|
-
// In JS: [1,2] !== [1,2]
|
|
116
|
-
// In RecursiveSet: t1 equals t2 (Structural Equality)
|
|
117
|
-
```
|
|
118
104
|
---
|
|
119
105
|
|
|
120
|
-
##
|
|
121
|
-
|
|
122
|
-
### Basic Usage
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
const s1 = new RecursiveSet(1, 2, 3);
|
|
126
|
-
const s2 = new RecursiveSet(2, 3, 4);
|
|
127
|
-
|
|
128
|
-
console.log(s1.union(s2)); // {1, 2, 3, 4}
|
|
129
|
-
console.log(s1.intersection(s2)); // {2, 3}
|
|
130
|
-
console.log(s1.difference(s2)); // {1}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Backtracking with O(1) Clone
|
|
106
|
+
## Performance Notes (v4.0)
|
|
134
107
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// ... perform some operations ...
|
|
108
|
+
**Why Sorted Arrays?**
|
|
109
|
+
For sets with $N < 1000$ (common in logic puzzles, N-Queens, graphs), the overhead of allocating tree nodes (v2/v3) dominates runtime. Sorted Arrays exploit **CPU Cache Lines**.
|
|
138
110
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Power Set
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
const set = new RecursiveSet(1, 2);
|
|
151
|
-
const power = set.powerset();
|
|
152
|
-
|
|
153
|
-
console.log(power.toString()); // {∅, {1}, {2}, {1, 2}}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### Cartesian Product \& Tuples
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
const A = new RecursiveSet(1, 2);
|
|
160
|
-
const B = new RecursiveSet("x", "y");
|
|
161
|
-
|
|
162
|
-
// A × B = {(1, x), (1, y), (2, x), (2, y)}
|
|
163
|
-
const product = A.cartesianProduct(B);
|
|
164
|
-
|
|
165
|
-
// Result contains strongly typed Tuples
|
|
166
|
-
for (const tuple of product) {
|
|
167
|
-
console.log(tuple.get(0), tuple.get(1)); // 1 "x"
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
### Strictness (Breaking Changes in V3)
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
const s = new RecursiveSet<number>();
|
|
176
|
-
|
|
177
|
-
// ❌ Error: Plain Arrays not supported (Reference Ambiguity)
|
|
178
|
-
// s.add([1, 2]);
|
|
179
|
-
|
|
180
|
-
// ✅ Correct: Use Tuple
|
|
181
|
-
s.add(new Tuple(1, 2));
|
|
182
|
-
|
|
183
|
-
// ❌ Error: NaN is not supported
|
|
184
|
-
// s.add(NaN);
|
|
185
|
-
```
|
|
111
|
+
| Operation | Complexity | Real World (Small N) |
|
|
112
|
+
| :--- | :--- | :--- |
|
|
113
|
+
| **Lookup** | $O(\log N)$ | 🚀 Instant |
|
|
114
|
+
| **Equality** | $O(N)$ / $O(1)$* | ⚡ Instant (Hash Match) |
|
|
115
|
+
| **Insert** | $O(N)$ | Fast (Native `splice` / `memmove`) |
|
|
116
|
+
| **Iteration** | $O(N)$ | 🚀 Native Array Speed |
|
|
186
117
|
|
|
118
|
+
*\*Equality is O(1) if hashes differ (99% case), O(N) if hash collision occurs.*
|
|
187
119
|
|
|
188
120
|
---
|
|
189
121
|
|
|
190
|
-
##
|
|
122
|
+
## Breaking Changes in v4.0
|
|
191
123
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
124
|
+
1. **Engine Switch (Array Backend):** Iterators are now **live**. Modifying the set while iterating over it will reflect changes immediately (Standard JS Array behavior). In v3 (RBT), iterators were snapshots.
|
|
125
|
+
2. **Arrays Supported:** Adding `[1, 2]` is now natively supported and treated as a `Tuple`.
|
|
126
|
+
3. **Strict Generics (Maintained from v3):** `add()` requires explicit generic types for recursion.
|
|
127
|
+
4. **Plain Objects Rejected (Maintained from v3):** `{a: 1}` throws an Error. Use `Tuple` or `RecursiveSet`.
|
|
195
128
|
|
|
196
129
|
---
|
|
197
130
|
|
|
@@ -203,7 +136,7 @@ Contributions are welcome!
|
|
|
203
136
|
git clone https://github.com/cstrerath/recursive-set.git
|
|
204
137
|
npm install
|
|
205
138
|
npm run build
|
|
206
|
-
npx tsx test.ts
|
|
139
|
+
npx tsx test/test.ts
|
|
207
140
|
```
|
|
208
141
|
|
|
209
142
|
---
|
|
@@ -221,5 +154,4 @@ See [LICENSE](LICENSE) for details.
|
|
|
221
154
|
|
|
222
155
|
Inspired by:
|
|
223
156
|
* Zermelo-Fraenkel set theory (ZFC)
|
|
224
|
-
* Formal Language Theory requirements
|
|
225
|
-
* Powered by [functional-red-black-tree](https://github.com/mikolalysenko/functional-red-black-tree)
|
|
157
|
+
* Formal Language Theory requirements
|