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 CHANGED
@@ -1,37 +1,33 @@
1
1
  # RecursiveSet
2
2
 
3
- > High-performance, mutable set implementation for TypeScript – modeled after ZFC set theory.
4
-
5
- Supports recursive nesting, strict structural equality, and includes all classic set operations (union, intersection, difference, powerset, cartesian product). **Designed for Theoretical Computer Science, Graphs, and FSMs.**
3
+ > **High-Performance ZFC Set Implementation for TypeScript**
4
+ >
5
+ > Mutable, strictly typed, and optimized for cache locality.
6
6
 
7
7
  [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
8
8
  [![npm version](https://img.shields.io/npm/v/recursive-set.svg)](https://www.npmjs.com/package/recursive-set)
9
9
 
10
10
  ---
11
11
 
12
- ## Features
12
+ ## 🚀 What is this?
13
13
 
14
- * **Strict Value Equality:** Mathematical sets behave mathematically. `{a, b}` is equal to `{b, a}`.
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
- ## Implementation Details
21
+ ---
24
22
 
25
- This library enforces **Strict ZFC Semantics**, differing from native JavaScript `Set`:
23
+ ## Features
26
24
 
27
- - **Extensionality:** Two sets are equal if they contain the same elements.
28
- - `new RecursiveSet(new RecursiveSet(1)).equals(new RecursiveSet(new RecursiveSet(1)))` is `true`.
29
- - **No Hidden References:** Plain JavaScript Arrays and Objects are **rejected** to prevent reference-equality confusion.
30
- - Use `Tuple` for ordered sequences.
31
- - Use `RecursiveSet` for collections.
32
- - **Performance:** Powered by **Functional Red-Black Trees**.
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()); // {{q0, q1}}
63
- console.log(transitions.toString()); // {(q0, q1)}
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
- // T must be explicit or inferred. No default 'unknown'.
74
- new RecursiveSet<T>(...elements: Array<T | RecursiveSet<T>>)
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
- * `add(element: T | RecursiveSet<T>): this` – Add element. **Throws on NaN or plain Object/Array.**
81
- * `remove(element: T | RecursiveSet<T>): this` – Remove element.
82
- * `clear(): this` – Remove all elements.
83
-
84
- **Snapshot:**
85
- - `clone(): RecursiveSet<T>` – Creates a shallow copy in **O(1)** time (Copy-on-Write).
86
-
87
- **Set Operations:**
88
- - `union(other: RecursiveSet<T>): RecursiveSet<T>` – A B
89
- - `intersection(other: RecursiveSet<T>): RecursiveSet<T>` – A ∩ B
90
- - `difference(other: RecursiveSet<T>): RecursiveSet<T>` – A \ B
91
- - `symmetricDifference(other: RecursiveSet<T>): RecursiveSet<T>` – A △ B
92
-
93
- **Advanced Operations:**
94
- - `powerset(): RecursiveSet<RecursiveSet<T>>`𝒫(A)
95
- - `cartesianProduct<U>(other: RecursiveSet<U>): RecursiveSet<Tuple<[T, U]>>` – A × B (Returns Tuples!)
96
-
97
- **Predicates:**
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
- - `size: number` – Cardinality |A|
106
- - `toString(): string` – Pretty print with and {}
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
- ## Examples
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
- ```typescript
136
- const state = new RecursiveSet("init");
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
- // Create a checkpoint (O(1))
140
- const checkpoint = state.clone();
141
-
142
- state.add("newState");
143
- // If this path fails, simply revert:
144
- // state = checkpoint; (conceptually)
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
- ## Use Cases
122
+ ## Breaking Changes in v4.0
191
123
 
192
- * **Finite State Machine (FSM):** States as Sets, Transitions as Tuples.
193
- * **Graph Theory:** Edges as Tuples `(u, v)`, Nodes as Sets.
194
- * **Formal Languages:** Alphabets, Grammars, Power Sets.
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