| |
| |
| |
| |
|
|
| class FractalGenerator { |
| constructor(config = {}) { |
| this.maxDepth = config.maxDepth || 5; |
| this.compressionThreshold = config.compressionThreshold || 0.8; |
| this.symbolicMarkers = { |
| root: '🜏', |
| seed: '∴', |
| bidirectional: '⇌', |
| compression: '⧖', |
| anchor: '☍' |
| }; |
| this.patternRegistry = new Map(); |
| this.compressionStats = { |
| ratio: 1.0, |
| residueNodes: 0, |
| anchorReferences: 0 |
| }; |
| } |
|
|
| |
| |
| |
| generate(data, pattern = 'auto') { |
| const rootPattern = pattern === 'auto' ? this.detectPattern(data) : pattern; |
| |
| const fractalStructure = { |
| "$fractal": { |
| version: "1.0.0", |
| root_pattern: rootPattern, |
| compression: { |
| ratio: 1.0, |
| symbolic_residue: {}, |
| attention_efficiency: 1.0 |
| }, |
| interpretability_map: { |
| scale_invariance: "high", |
| pattern_visibility: "recursive" |
| } |
| }, |
| content: this._generateRecursive(data, 0, rootPattern) |
| }; |
|
|
| |
| fractalStructure.$fractal.compression.ratio = this.compressionStats.ratio; |
| fractalStructure.$fractal.compression.attention_efficiency = |
| this.calculateAttentionEfficiency(data, fractalStructure.content); |
|
|
| return fractalStructure; |
| } |
|
|
| |
| |
| |
| detectPattern(data) { |
| if (Array.isArray(data)) { |
| return this._detectListPattern(data); |
| } else if (typeof data === 'object' && data !== null) { |
| return this._detectObjectPattern(data); |
| } |
| return 'primitive'; |
| } |
|
|
| _detectObjectPattern(obj) { |
| const structure = Object.keys(obj).reduce((acc, key) => { |
| acc[key] = typeof obj[key]; |
| return acc; |
| }, {}); |
| |
| const structureHash = JSON.stringify(structure); |
| const patternId = `pattern_${this._hashCode(structureHash)}`; |
| |
| this.patternRegistry.set(patternId, { |
| structure, |
| instances: [obj] |
| }); |
| |
| return patternId; |
| } |
|
|
| _detectListPattern(arr) { |
| |
| const patterns = new Map(); |
| |
| for (let len = 1; len <= Math.floor(arr.length / 2); len++) { |
| for (let i = 0; i <= arr.length - len; i++) { |
| const pattern = JSON.stringify(arr.slice(i, i + len)); |
| const count = patterns.get(pattern) || 0; |
| patterns.set(pattern, count + 1); |
| } |
| } |
| |
| |
| let maxCount = 0; |
| let bestPattern = null; |
| |
| patterns.forEach((count, pattern) => { |
| if (count > maxCount) { |
| maxCount = count; |
| bestPattern = pattern; |
| } |
| }); |
| |
| return bestPattern ? `list_pattern_${this._hashCode(bestPattern)}` : 'list'; |
| } |
|
|
| |
| |
| |
| _generateRecursive(data, depth, patternId) { |
| if (depth >= this.maxDepth || this._isPrimitive(data)) { |
| return data; |
| } |
|
|
| const node = { |
| [`${this.symbolicMarkers.compression}depth`]: depth, |
| [`${this.symbolicMarkers.root}pattern`]: patternId |
| }; |
|
|
| |
| const existingPattern = this._findExistingPattern(data); |
| if (existingPattern && depth > 0) { |
| node[`${this.symbolicMarkers.anchor}anchor`] = `#/patterns/${existingPattern}`; |
| node[`${this.symbolicMarkers.seed}seed`] = this._extractSeed(data); |
| this.compressionStats.anchorReferences++; |
| this.compressionStats.ratio *= 0.85; |
| return node; |
| } |
|
|
| |
| if (typeof data === 'object' && data !== null && !Array.isArray(data)) { |
| const children = {}; |
| |
| for (const [key, value] of Object.entries(data)) { |
| const childPattern = this.detectPattern(value); |
| const markedKey = `${this.symbolicMarkers.bidirectional}${key}`; |
| children[markedKey] = this._generateRecursive(value, depth + 1, childPattern); |
| } |
| |
| if (Object.keys(children).length > 0) { |
| node[`${this.symbolicMarkers.bidirectional}children`] = children; |
| } |
| |
| |
| node[`${this.symbolicMarkers.seed}seed`] = this._extractSeed(data); |
| this.compressionStats.residueNodes++; |
| } |
| |
| |
| else if (Array.isArray(data)) { |
| const listPattern = this._detectListRepeats(data); |
| if (listPattern) { |
| node[`${this.symbolicMarkers.seed}seed`] = { |
| pattern: listPattern.pattern, |
| repetitions: listPattern.count |
| }; |
| node[`${this.symbolicMarkers.bidirectional}expansions`] = |
| data.map(item => this._generateRecursive(item, depth + 1, 'list_item')); |
| } else { |
| return data.map(item => |
| this._generateRecursive(item, depth + 1, 'list_item')); |
| } |
| } |
|
|
| return node; |
| } |
|
|
| |
| |
| |
| _extractSeed(data) { |
| if (typeof data !== 'object' || data === null) { |
| return data; |
| } |
|
|
| const seed = {}; |
| for (const [key, value] of Object.entries(data)) { |
| if (this._isPrimitive(value)) { |
| seed[key] = value; |
| } else { |
| seed[key] = `${this.symbolicMarkers.bidirectional}expand`; |
| } |
| } |
| return seed; |
| } |
|
|
| |
| |
| |
| _findExistingPattern(data) { |
| const dataStr = JSON.stringify(data); |
| for (const [patternId, pattern] of this.patternRegistry.entries()) { |
| if (pattern.instances.some(instance => |
| JSON.stringify(instance) === dataStr)) { |
| return patternId; |
| } |
| } |
| return null; |
| } |
|
|
| |
| |
| |
| _detectListRepeats(arr) { |
| for (let len = 1; len <= Math.floor(arr.length / 2); len++) { |
| const pattern = arr.slice(0, len); |
| let count = 0; |
| |
| for (let i = 0; i < arr.length; i += len) { |
| const slice = arr.slice(i, i + len); |
| if (JSON.stringify(slice) === JSON.stringify(pattern)) { |
| count++; |
| } else { |
| break; |
| } |
| } |
| |
| if (count > 1 && count * len === arr.length) { |
| return { pattern, count }; |
| } |
| } |
| return null; |
| } |
|
|
| |
| |
| |
| calculateAttentionEfficiency(original, fractal) { |
| const originalComplexity = this._calculateComplexity(original); |
| const fractalComplexity = this._calculateComplexity(fractal); |
| |
| return originalComplexity / fractalComplexity; |
| } |
|
|
| _calculateComplexity(data, depth = 0) { |
| if (this._isPrimitive(data)) { |
| return 1; |
| } |
| |
| if (Array.isArray(data)) { |
| return data.reduce((sum, item) => |
| sum + this._calculateComplexity(item, depth + 1), 0); |
| } |
| |
| if (typeof data === 'object' && data !== null) { |
| let complexity = 0; |
| |
| |
| if (data[`${this.symbolicMarkers.anchor}anchor`]) { |
| return 1; |
| } |
| |
| for (const value of Object.values(data)) { |
| complexity += this._calculateComplexity(value, depth + 1); |
| } |
| |
| return complexity; |
| } |
| |
| return 1; |
| } |
|
|
| _isPrimitive(value) { |
| return value === null || |
| typeof value === 'string' || |
| typeof value === 'number' || |
| typeof value === 'boolean'; |
| } |
|
|
| _hashCode(str) { |
| let hash = 0; |
| for (let i = 0; i < str.length; i++) { |
| const char = str.charCodeAt(i); |
| hash = ((hash << 5) - hash) + char; |
| hash = hash & hash; |
| } |
| return Math.abs(hash).toString(16); |
| } |
|
|
| |
| |
| |
| visualize(fractalData, config = {}) { |
| const width = config.width || 800; |
| const height = config.height || 600; |
| const nodeRadius = config.nodeRadius || 20; |
| |
| const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); |
| svg.setAttribute("width", width); |
| svg.setAttribute("height", height); |
| svg.setAttribute("viewBox", `0 0 ${width} ${height}`); |
| |
| |
| this._visualizeNode(svg, fractalData.content, width / 2, 50, width / 4, nodeRadius); |
| |
| return svg; |
| } |
|
|
| _visualizeNode(svg, node, x, y, xOffset, radius) { |
| if (!node || typeof node !== 'object') return; |
| |
| |
| const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); |
| circle.setAttribute("cx", x); |
| circle.setAttribute("cy", y); |
| circle.setAttribute("r", radius); |
| |
| |
| if (node[`${this.symbolicMarkers.anchor}anchor`]) { |
| circle.setAttribute("fill", "#ff7f7f"); |
| } else if (node[`${this.symbolicMarkers.seed}seed`]) { |
| circle.setAttribute("fill", "#7f7fff"); |
| } else { |
| circle.setAttribute("fill", "#7fff7f"); |
| } |
| |
| circle.setAttribute("stroke", "#333"); |
| circle.setAttribute("stroke-width", "2"); |
| svg.appendChild(circle); |
| |
| |
| if (node[`${this.symbolicMarkers.root}pattern`]) { |
| const text = document.createElementNS("http://www.w3.org/2000/svg", "text"); |
| text.setAttribute("x", x); |
| text.setAttribute("y", y); |
| text.setAttribute("text-anchor", "middle"); |
| text.setAttribute("dy", "0.3em"); |
| text.setAttribute("font-size", "10px"); |
| text.textContent = node[`${this.symbolicMarkers.root}pattern`].substring(0, 8); |
| svg.appendChild(text); |
| } |
| |
| |
| const children = node[`${this.symbolicMarkers.bidirectional}children`]; |
| if (children) { |
| const childKeys = Object.keys(children); |
| childKeys.forEach((key, index) => { |
| const childX = x + (index - (childKeys.length - 1) / 2) * xOffset; |
| const childY = y + 100; |
| |
| |
| const line = document.createElementNS("http://www.w3.org/2000/svg", "line"); |
| line.setAttribute("x1", x); |
| line.setAttribute("y1", y + radius); |
| line.setAttribute("x2", childX); |
| line.setAttribute("y2", childY - radius); |
| line.setAttribute("stroke", "#666"); |
| line.setAttribute("stroke-width", "1"); |
| svg.appendChild(line); |
| |
| |
| this._visualizeNode(svg, children[key], childX, childY, xOffset / 2, radius * 0.8); |
| }); |
| } |
| } |
| } |
|
|
| |
| if (typeof module !== 'undefined' && module.exports) { |
| module.exports = FractalGenerator; |
| } |
|
|