diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a38a470
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,483 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from `dotnet new gitignore`
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+tools/
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+#*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Vim temporary swap files
+*.swp
+.azure
+/.idea
\ No newline at end of file
diff --git a/POC.pyproj b/POC.pyproj
new file mode 100644
index 0000000..b3a18ef
--- /dev/null
+++ b/POC.pyproj
@@ -0,0 +1,25 @@
+
+
+
+ Debug
+ 2.0
+ {e10619c7-7881-4ab5-ba2a-0968e3e2e09e}
+
+ poc.py
+
+ .
+ .
+ {888888a0-9f3d-457c-b088-3a5042f75d52}
+ Standard Python launcher
+
+
+
+
+
+ 10.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/POC.sln b/POC.sln
new file mode 100644
index 0000000..21a7acd
--- /dev/null
+++ b/POC.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35728.132
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "POC", "POC.pyproj", "{E10619C7-7881-4AB5-BA2A-0968E3E2E09E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "POCDotnet", "POCDotnet\POCDotnet.csproj", "{177848A3-D46D-4302-9C2E-03E2E15A573B}"
+EndProject
+Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "POCNodeTypescript", "POCNodeTypescript\POCNodeTypescript.esproj", "{B84BF435-A0BA-4A96-BBDD-74F66733F96F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E10619C7-7881-4AB5-BA2A-0968E3E2E09E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E10619C7-7881-4AB5-BA2A-0968E3E2E09E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {177848A3-D46D-4302-9C2E-03E2E15A573B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {177848A3-D46D-4302-9C2E-03E2E15A573B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {177848A3-D46D-4302-9C2E-03E2E15A573B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {177848A3-D46D-4302-9C2E-03E2E15A573B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B84BF435-A0BA-4A96-BBDD-74F66733F96F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B84BF435-A0BA-4A96-BBDD-74F66733F96F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B84BF435-A0BA-4A96-BBDD-74F66733F96F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {B84BF435-A0BA-4A96-BBDD-74F66733F96F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B84BF435-A0BA-4A96-BBDD-74F66733F96F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B84BF435-A0BA-4A96-BBDD-74F66733F96F}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/POCCPlus/CMakeLists.txt b/POCCPlus/CMakeLists.txt
new file mode 100644
index 0000000..85e2b04
--- /dev/null
+++ b/POCCPlus/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 3.16)
+project(BMSSP LANGUAGES CXX)
+
+# Require C++17 (needed for structured bindings, etc.)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Enable warnings
+if (MSVC)
+ add_compile_options(/W4 /permissive-)
+else()
+ add_compile_options(-Wall -Wextra -pedantic)
+endif()
+
+# Main executable
+add_executable(bmssp
+ bmssp.cpp
+)
+
+# If you want timing/benchmark builds, enable optimization flags
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Release)
+endif()
diff --git a/POCCPlus/bmssp.cpp b/POCCPlus/bmssp.cpp
new file mode 100644
index 0000000..39aa3c9
--- /dev/null
+++ b/POCCPlus/bmssp.cpp
@@ -0,0 +1,550 @@
+// bmssp_full_impl.cpp
+// C++17 single-file port of the Python BMSSP practical implementation.
+// Includes: graph generator, Dijkstra, DataStructureD, FIND_PIVOTS, BASECASE, BMSSP recursion, instrumentation, and test harness.
+
+#include
+using namespace std;
+
+using Node = int;
+using Weight = double;
+using Edge = tuple;
+using AdjList = vector>>;
+
+static inline double INF_D() { return numeric_limits::infinity(); }
+
+// ---------------------------
+// Instrumentation
+// ---------------------------
+struct Instrument {
+ uint64_t relaxations = 0;
+ uint64_t heap_ops = 0;
+ void reset() { relaxations = heap_ops = 0; }
+};
+
+// ---------------------------
+// Utilities & Graph generator
+// ---------------------------
+pair> generate_sparse_directed_graph(int n, int m, double max_w = 100.0, optional seed = nullopt) {
+ std::mt19937_64 rng;
+ if (seed.has_value()) rng.seed(seed.value());
+ else rng.seed(std::random_device{}());
+
+ uniform_real_distribution wdist(1.0, max_w);
+ uniform_real_distribution unit(0.0, 1.0);
+
+ AdjList graph(n);
+ vector edges;
+ // weak backbone
+ for (int i = 1; i < n; ++i) {
+ uniform_int_distribution r(0, i - 1);
+ int u = r(rng);
+ double w = wdist(rng);
+ graph[u].emplace_back(i, w);
+ edges.emplace_back(u, i, w);
+ }
+ int remaining = max(0, m - (n - 1));
+ uniform_int_distribution rn(0, max(0, n - 1));
+ for (int i = 0; i < remaining; ++i) {
+ int u = rn(rng);
+ int v = rn(rng);
+ double w = wdist(rng);
+ graph[u].emplace_back(v, w);
+ edges.emplace_back(u, v, w);
+ }
+ return {graph, edges};
+}
+
+// ---------------------------
+// Dijkstra (standard)
+// ---------------------------
+unordered_map dijkstra(const AdjList &graph, Node source, Instrument *instr = nullptr) {
+ if (!instr) instr = new Instrument(); // if nullptr, avoid using but create temp to keep code simple
+ unordered_map dist;
+ int n = (int)graph.size();
+ dist.reserve(n * 2);
+ for (int i = 0; i < n; ++i) dist[i] = INF_D();
+ dist[source] = 0.0;
+
+ // min-heap: pair
+ priority_queue, vector>, greater>> pq;
+ pq.emplace(0.0, source);
+ instr->heap_ops += 1;
+
+ while (!pq.empty()) {
+ auto [d_u, u] = pq.top(); pq.pop();
+ instr->heap_ops += 1;
+ if (d_u > dist[u]) continue;
+ for (auto &e : graph[u]) {
+ Node v = e.first;
+ Weight w = e.second;
+ instr->relaxations += 1;
+ double alt = d_u + w;
+ auto it = dist.find(v);
+ double cur = (it != dist.end() ? it->second : INF_D());
+ if (alt < cur) {
+ dist[v] = alt;
+ pq.emplace(alt, v);
+ instr->heap_ops += 1;
+ }
+ }
+ }
+ return dist;
+}
+
+// ---------------------------
+// DataStructure D (practical)
+// ---------------------------
+class DataStructureD {
+public:
+ DataStructureD(int M, double B_upper, optional block_size = nullopt)
+ : M_(max(1, M)), B_upper_(B_upper) {
+ block_size_ = block_size.has_value() ? block_size.value() : max(1, M_ / 8);
+ }
+
+ void insert(Node v, Weight key) {
+ auto it = best_.find(v);
+ if (it == best_.end() || key < it->second) {
+ best_[v] = key;
+ heap_.emplace(key, v);
+ }
+ }
+
+ // iterable of (v, key)
+ void batch_prepend(const vector>& items) {
+ for (const auto &p : items) insert(p.first, p.second);
+ }
+
+ bool empty() {
+ cleanup();
+ return heap_.empty();
+ }
+
+ // pull -> (Bi, Si)
+ pair> pull() {
+ cleanup();
+ if (heap_.empty()) throw out_of_range("pull from empty D");
+ Weight Bi = heap_.top().first;
+ unordered_set Si;
+ while (!heap_.empty() && (int)Si.size() < block_size_) {
+ auto pr = heap_.top(); heap_.pop();
+ Weight key = pr.first;
+ Node v = pr.second;
+ auto it = best_.find(v);
+ if (it != best_.end() && it->second == key) {
+ Si.insert(v);
+ best_.erase(it);
+ }
+ }
+ return {Bi, Si};
+ }
+
+private:
+ void cleanup() {
+ while (!heap_.empty()) {
+ auto pr = heap_.top();
+ Node v = pr.second; Weight key = pr.first;
+ auto it = best_.find(v);
+ if (it == best_.end() || it->second != key) {
+ heap_.pop();
+ } else break;
+ }
+ }
+
+ // min-heap (pair) using greater comparator
+ priority_queue, vector>, greater>> heap_;
+ unordered_map best_;
+ int M_;
+ double B_upper_;
+ int block_size_;
+};
+
+// ---------------------------
+// FIND_PIVOTS (bounded BF-like)
+// ---------------------------
+pair, unordered_set> find_pivots(
+ const AdjList &graph,
+ const unordered_map &dist,
+ const unordered_set &S,
+ double B,
+ int n,
+ int k_steps,
+ int p_limit,
+ Instrument *instr = nullptr
+) {
+ if (!instr) instr = new Instrument();
+
+ // S_filtered = nodes in S with dist < B
+ vector s_filtered;
+ s_filtered.reserve(S.size());
+ for (Node v : S) {
+ auto it = dist.find(v);
+ if (it != dist.end() && it->second < B) s_filtered.push_back(v);
+ }
+
+ unordered_set P;
+ if (s_filtered.empty()) {
+ // fallback: up to p_limit arbitrary samples from S
+ if (!S.empty()) {
+ int take = max(1, min((int)S.size(), p_limit));
+ int count = 0;
+ for (Node v : S) {
+ P.insert(v);
+ if (++count >= take) break;
+ }
+ }
+ } else {
+ sort(s_filtered.begin(), s_filtered.end(), [&](Node a, Node b) {
+ double da = dist.at(a), db = dist.at(b);
+ return da < db;
+ });
+ int take = max(1, min((int)s_filtered.size(), p_limit));
+ for (int i = 0; i < take; ++i) P.insert(s_filtered[i]);
+ }
+
+ unordered_set source_frontier = (!P.empty() ? P : S);
+ unordered_set discovered = source_frontier;
+ unordered_set frontier = source_frontier;
+
+ int steps = max(1, k_steps);
+ for (int it_step = 0; it_step < steps; ++it_step) {
+ if (frontier.empty()) break;
+ unordered_set next_front;
+ for (Node u : frontier) {
+ double du = INF_D();
+ auto itdu = dist.find(u);
+ if (itdu != dist.end()) du = itdu->second;
+ if (du >= B) continue;
+ if ((size_t)u >= graph.size()) continue;
+ for (const auto &pr : graph[u]) {
+ Node v = pr.first; Weight w = pr.second;
+ instr->relaxations += 1;
+ double nd = du + w;
+ if (nd < B && discovered.find(v) == discovered.end()) {
+ discovered.insert(v);
+ next_front.insert(v);
+ }
+ }
+ }
+ frontier.swap(next_front);
+ }
+
+ unordered_set W = discovered;
+ if (P.empty() && !S.empty()) {
+ P.insert(*S.begin());
+ }
+ return {P, W};
+}
+
+// ---------------------------
+// BASECASE (limited Dijkstra)
+ // ---------------------------
+pair> basecase(
+ const AdjList &graph,
+ unordered_map &dist,
+ double B,
+ const unordered_set &S,
+ int k,
+ Instrument *instr = nullptr
+) {
+ if (!instr) instr = new Instrument();
+
+ if (S.empty()) return {B, {}};
+
+ // choose source x in S with smallest dist
+ Node x = -1;
+ double bestd = INF_D();
+ for (Node v : S) {
+ auto it = dist.find(v);
+ double dv = (it != dist.end() ? it->second : INF_D());
+ if (dv < bestd) { bestd = dv; x = v; }
+ }
+ if (x == -1) return {B, {}};
+
+ priority_queue, vector>, greater>> pq;
+ double start_d = (dist.find(x) != dist.end()) ? dist[x] : INF_D();
+ pq.emplace(start_d, x);
+ instr->heap_ops += 1;
+
+ unordered_set Uo;
+ unordered_set visited;
+
+ while (!pq.empty() && (int)Uo.size() < (k + 1)) {
+ auto [d_u, u] = pq.top(); pq.pop();
+ instr->heap_ops += 1;
+ auto itu = dist.find(u);
+ double currentDu = (itu != dist.end() ? itu->second : INF_D());
+ if (d_u > currentDu) continue;
+ if (Uo.find(u) == Uo.end()) Uo.insert(u);
+ if ((size_t)u >= graph.size()) continue;
+ for (auto &pr : graph[u]) {
+ Node v = pr.first; Weight w = pr.second;
+ instr->relaxations += 1;
+ double newd = dist[u] + w;
+ double dv = dist.find(v) != dist.end() ? dist[v] : INF_D();
+ if (newd < dv && newd < B) {
+ dist[v] = newd;
+ pq.emplace(newd, v);
+ instr->heap_ops += 1;
+ }
+ }
+ }
+
+ if ((int)Uo.size() <= k) {
+ return {B, Uo};
+ } else {
+ vector finite_dists;
+ finite_dists.reserve(Uo.size());
+ for (Node v : Uo) {
+ auto it = dist.find(v);
+ if (it != dist.end() && isfinite(it->second)) finite_dists.push_back(it->second);
+ }
+ if (finite_dists.empty()) return {B, {}};
+ double maxd = *max_element(finite_dists.begin(), finite_dists.end());
+ unordered_set U_filtered;
+ for (Node v : Uo) {
+ auto it = dist.find(v);
+ if (it != dist.end() && it->second < maxd) U_filtered.insert(v);
+ }
+ return {maxd, U_filtered};
+ }
+}
+
+// ---------------------------
+// BMSSP (practical recursive)
+// ---------------------------
+pair> bmssp(
+ const AdjList &graph,
+ unordered_map &dist,
+ const vector &edges,
+ int l,
+ double B,
+ const unordered_set &S,
+ int n,
+ Instrument *instr = nullptr
+) {
+ if (!instr) instr = new Instrument();
+
+ int t_param, k_param;
+ if (n <= 2) { t_param = 1; k_param = 2; }
+ else {
+ double ln = log(max(3, n));
+ t_param = max(1, (int)round(pow(ln, 2.0 / 3.0)));
+ k_param = max(2, (int)round(pow(ln, 1.0 / 3.0)));
+ }
+
+ if (l <= 0) {
+ if (S.empty()) return {B, {}};
+ return basecase(graph, dist, B, S, k_param, instr);
+ }
+
+ int p_limit = max(1, 1 << min(10, t_param));
+ int k_steps = max(1, k_param);
+
+ auto piv = find_pivots(graph, dist, S, B, n, k_steps, p_limit, instr);
+ unordered_set P = move(piv.first);
+ unordered_set W = move(piv.second);
+
+ int M = 1 << max(0, (l - 1) * t_param);
+ DataStructureD D(M, B, max(1, (int)min((int)max(1, (int)P.size()), 64)));
+ for (Node x : P) {
+ double dx = INF_D();
+ auto it = dist.find(x);
+ if (it != dist.end()) dx = it->second;
+ D.insert(x, dx);
+ }
+
+ double B_prime_initial = B;
+ if (!P.empty()) {
+ double minp = INF_D();
+ for (Node x : P) {
+ auto it = dist.find(x);
+ double dx = (it != dist.end() ? it->second : INF_D());
+ if (dx < minp) minp = dx;
+ }
+ if (isfinite(minp)) B_prime_initial = minp;
+ }
+
+ unordered_set U;
+ vector B_prime_sub_values;
+
+ int loop_guard = 0;
+ int limit = k_param * (1 << (l * max(1, t_param)));
+
+ while ((int)U.size() < limit && !D.empty()) {
+ loop_guard++;
+ if (loop_guard > 20000) break;
+ Weight Bi;
+ unordered_set Si;
+ try {
+ tie(Bi, Si) = D.pull();
+ } catch (...) {
+ break;
+ }
+
+ auto subres = bmssp(graph, dist, edges, l - 1, Bi, Si, n, instr);
+ double B_prime_sub = subres.first;
+ unordered_set Ui = move(subres.second);
+ B_prime_sub_values.push_back(B_prime_sub);
+ for (auto u : Ui) U.insert(u);
+
+ // Prepare batch set
+ vector> K_for_batch;
+ K_for_batch.reserve(64);
+
+ for (Node u : Ui) {
+ auto itu = dist.find(u);
+ if (itu == dist.end()) continue;
+ double du = itu->second;
+ if (!isfinite(du)) continue;
+ if ((size_t)u >= graph.size()) continue;
+ for (auto &pr : graph[u]) {
+ Node v = pr.first; Weight w_uv = pr.second;
+ instr->relaxations += 1;
+ double newd = du + w_uv;
+ double dv = dist.find(v) != dist.end() ? dist[v] : INF_D();
+ if (newd <= dv) {
+ dist[v] = newd;
+ if (Bi <= newd && newd < B) {
+ D.insert(v, newd);
+ } else if (B_prime_sub <= newd && newd < Bi) {
+ K_for_batch.emplace_back(v, newd);
+ }
+ }
+ }
+ }
+
+ for (Node x : Si) {
+ auto itx = dist.find(x);
+ double dx = (itx != dist.end() ? itx->second : INF_D());
+ if (B_prime_sub <= dx && dx < Bi) {
+ K_for_batch.emplace_back(x, dx);
+ }
+ }
+
+ if (!K_for_batch.empty()) D.batch_prepend(K_for_batch);
+ }
+
+ double B_prime_final = B_prime_initial;
+ if (!B_prime_sub_values.empty()) {
+ double minsub = *min_element(B_prime_sub_values.begin(), B_prime_sub_values.end());
+ B_prime_final = min(B_prime_initial, minsub);
+ }
+
+ unordered_set U_final = U;
+ for (Node x : W) {
+ auto it = dist.find(x);
+ double dx = (it != dist.end() ? it->second : INF_D());
+ if (dx < B_prime_final) U_final.insert(x);
+ }
+
+ return {B_prime_final, U_final};
+}
+
+// ---------------------------
+// Test harness
+// ---------------------------
+struct TestResult {
+ int n; int m; unsigned int seed;
+ double dijkstra_time;
+ uint64_t dijkstra_relax;
+ double bmssp_time;
+ uint64_t bmssp_relax;
+ int dijkstra_reachable;
+ int bmssp_reachable;
+ double max_diff;
+};
+
+TestResult run_single_test(int n, int m, unsigned int seed = 0, Node source = 0) {
+ cout << "Generating graph: n=" << n << ", m=" << m << ", seed=" << seed << "\n";
+ auto gen = generate_sparse_directed_graph(n, m, 100.0, seed);
+ AdjList graph = move(gen.first);
+ vector edges = move(gen.second);
+ double avg_deg = 0.0;
+ for (auto &adj : graph) avg_deg += (double)adj.size();
+ avg_deg /= (double)max(1, n);
+ cout << "Graph generated. avg out-degree ≈ " << fixed << setprecision(3) << avg_deg << "\n";
+
+ // Dijkstra
+ Instrument instr_dij;
+ auto t0 = chrono::high_resolution_clock::now();
+ auto dist_dij_map = dijkstra(graph, source, &instr_dij);
+ auto t1 = chrono::high_resolution_clock::now();
+ double dij_time = chrono::duration(t1 - t0).count();
+ int reachable_dij = 0;
+ for (auto &kv : dist_dij_map) if (isfinite(kv.second)) ++reachable_dij;
+ cout << "Dijkstra: time=" << dij_time << "s, relaxations=" << instr_dij.relaxations << ", heap_ops=" << instr_dij.heap_ops << ", reachable=" << reachable_dij << "\n";
+
+ // BMSSP
+ unordered_map dist_bm;
+ dist_bm.reserve(n * 2);
+ for (int i = 0; i < n; ++i) dist_bm[i] = INF_D();
+ dist_bm[source] = 0.0;
+
+ Instrument instr_bm;
+ int l;
+ if (n <= 2) l = 1;
+ else {
+ double ln = log(max(3, n));
+ int t_guess = max(1, (int)round(pow(ln, 2.0 / 3.0)));
+ l = max(1, (int)max(1.0, round(ln / (double)t_guess)));
+ }
+ cout << "BMSSP params: top-level l=" << l << "\n";
+
+ auto t2 = chrono::high_resolution_clock::now();
+ auto res = bmssp(graph, dist_bm, edges, l, INF_D(), unordered_set{source}, n, &instr_bm);
+ auto t3 = chrono::high_resolution_clock::now();
+ double bm_time = chrono::duration(t3 - t2).count();
+ int reachable_bm = 0;
+ for (auto &kv : dist_bm) if (isfinite(kv.second)) ++reachable_bm;
+ cout << "BMSSP: time=" << bm_time << "s, relaxations=" << instr_bm.relaxations << ", reachable=" << reachable_bm << ", B'=" << res.first << ", |U_final|=" << res.second.size() << "\n";
+
+ // Compare distances on commonly reachable nodes
+ vector diffs;
+ for (int v = 0; v < n; ++v) {
+ double dv = INF_D();
+ double db = INF_D();
+ auto it1 = dist_dij_map.find(v);
+ if (it1 != dist_dij_map.end()) dv = it1->second;
+ auto it2 = dist_bm.find(v);
+ if (it2 != dist_bm.end()) db = it2->second;
+ if (isfinite(dv) && isfinite(db)) diffs.push_back(fabs(dv - db));
+ }
+ double max_diff = 0.0;
+ if (!diffs.empty()) max_diff = *max_element(diffs.begin(), diffs.end());
+ cout << "Distance agreement (max abs diff on commonly reachable nodes): " << scientific << setprecision(6) << max_diff << "\n";
+
+ TestResult tr;
+ tr.n = n; tr.m = m; tr.seed = seed;
+ tr.dijkstra_time = dij_time; tr.dijkstra_relax = instr_dij.relaxations;
+ tr.bmssp_time = bm_time; tr.bmssp_relax = instr_bm.relaxations;
+ tr.dijkstra_reachable = reachable_dij; tr.bmssp_reachable = reachable_bm;
+ tr.max_diff = max_diff;
+ return tr;
+}
+
+// ---------------------------
+// CLI main
+// ---------------------------
+int main(int argc, char** argv) {
+ int n = 200000;
+ int m = 800000;
+ unsigned int seed = 0;
+ for (int i = 1; i < argc; ++i) {
+ string a = argv[i];
+ if ((a == "-n" || a == "--nodes") && i + 1 < argc) { n = stoi(argv[++i]); }
+ else if ((a == "-m" || a == "--edges") && i + 1 < argc) { m = stoi(argv[++i]); }
+ else if ((a == "-s" || a == "--seed") && i + 1 < argc) { seed = (unsigned int)stoul(argv[++i]); }
+ }
+
+ // To keep runtime reasonable by default for C++ demo, clamp default n/m if user doesn't want huge run:
+ if (n > 5000000) n = 5000000;
+ if (m > 50000000) m = 50000000;
+
+ try {
+ run_single_test(n, m, seed, 0);
+ } catch (const exception &ex) {
+ cerr << "Error: " << ex.what() << endl;
+ return 2;
+ }
+ return 0;
+}
diff --git a/POCDart/bmssp_full_impl.dart b/POCDart/bmssp_full_impl.dart
new file mode 100644
index 0000000..e03a84c
--- /dev/null
+++ b/POCDart/bmssp_full_impl.dart
@@ -0,0 +1,623 @@
+// bmssp_full_impl.dart
+// Dart 2.12+ (null-safety) single-file port of the Python BMSSP practical implementation.
+//
+// Provides: graph generator, Dijkstra, DataStructureD, FIND_PIVOTS, BASECASE, BMSSP recursion,
+// instrumentation, and a simple test harness / CLI.
+
+import 'dart:collection';
+import 'dart:io';
+import 'dart:math';
+
+// Type aliases
+typedef Node = int;
+typedef Weight = double;
+typedef Edge = List; // [u, v, w]
+// Graph: Map> -- We'll use List> pairs
+// But better typed: Map>
+
+class _Neighbor {
+ final int v;
+ final double w;
+ _Neighbor(this.v, this.w);
+}
+
+// ---------------------------
+// Utilities & Graph generator
+// ---------------------------
+class GraphAndEdges {
+ final Map> graph;
+ final List edges;
+ GraphAndEdges(this.graph, this.edges);
+}
+
+GraphAndEdges generateSparseDirectedGraph(int n, int m, {double maxW = 100.0, int? seed}) {
+ final rng = (seed != null) ? Random(seed) : Random();
+ final graph = >{};
+ for (var i = 0; i < n; ++i) graph[i] = <_Neighbor>[];
+ final edges = [];
+
+ // weak backbone to avoid isolated nodes
+ for (var i = 1; i < n; ++i) {
+ var u = rng.nextInt(i);
+ var w = rng.nextDouble() * (maxW - 1.0) + 1.0;
+ graph[u]!.add(_Neighbor(i, w));
+ edges.add([u, i, w]);
+ }
+ var remaining = max(0, m - (n - 1));
+ for (var i = 0; i < remaining; ++i) {
+ var u = rng.nextInt(n);
+ var v = rng.nextInt(n);
+ var w = rng.nextDouble() * (maxW - 1.0) + 1.0;
+ graph[u]!.add(_Neighbor(v, w));
+ edges.add([u, v, w]);
+ }
+ return GraphAndEdges(graph, edges);
+}
+
+// ---------------------------
+// Instrumentation
+// ---------------------------
+class Instrument {
+ int relaxations = 0;
+ int heapOps = 0;
+ void reset() {
+ relaxations = 0;
+ heapOps = 0;
+ }
+}
+
+// ---------------------------
+// Simple generic min-heap / priority queue
+// ---------------------------
+// We'll implement a simple binary heap keyed by double (priority).
+class PriorityQueue {
+ final List<_PQEntry> _data = [];
+ int get length => _data.length;
+ bool get isEmpty => _data.isEmpty;
+
+ void add(T value, double priority) {
+ _data.add(_PQEntry(value, priority));
+ _siftUp(_data.length - 1);
+ }
+
+ // returns (value, priority)
+ _PQEntry pop() {
+ if (_data.isEmpty) throw StateError('pop from empty priority queue');
+ final top = _data.first;
+ final last = _data.removeLast();
+ if (_data.isNotEmpty) {
+ _data[0] = last;
+ _siftDown(0);
+ }
+ return top;
+ }
+
+ _PQEntry peek() {
+ if (_data.isEmpty) throw StateError('peek from empty priority queue');
+ return _data.first;
+ }
+
+ void _siftUp(int idx) {
+ while (idx > 0) {
+ final parent = (idx - 1) >> 1;
+ if (_data[idx].priority < _data[parent].priority) {
+ final tmp = _data[idx];
+ _data[idx] = _data[parent];
+ _data[parent] = tmp;
+ idx = parent;
+ } else {
+ break;
+ }
+ }
+ }
+
+ void _siftDown(int idx) {
+ final n = _data.length;
+ while (true) {
+ final left = idx * 2 + 1;
+ final right = left + 1;
+ var smallest = idx;
+ if (left < n && _data[left].priority < _data[smallest].priority) smallest = left;
+ if (right < n && _data[right].priority < _data[smallest].priority) smallest = right;
+ if (smallest == idx) break;
+ final tmp = _data[idx];
+ _data[idx] = _data[smallest];
+ _data[smallest] = tmp;
+ idx = smallest;
+ }
+ }
+}
+
+class _PQEntry {
+ final T value;
+ final double priority;
+ _PQEntry(this.value, this.priority);
+}
+
+// ---------------------------
+// Dijkstra
+// ---------------------------
+Map dijkstra(Map> graph, int source, [Instrument? instr]) {
+ instr ??= Instrument();
+ final dist = {};
+ for (final k in graph.keys) dist[k] = double.infinity;
+ dist[source] = 0.0;
+ final pq = PriorityQueue();
+ pq.add(source, 0.0);
+ instr.heapOps++;
+
+ while (!pq.isEmpty) {
+ final entry = pq.pop();
+ instr.heapOps++;
+ final dU = entry.priority;
+ final u = entry.value;
+ final cur = dist[u] ?? double.infinity;
+ if (dU > cur) continue;
+ final adj = graph[u]!;
+ for (final nb in adj) {
+ instr.relaxations++;
+ final v = nb.v;
+ final w = nb.w;
+ final alt = dU + w;
+ final dv = dist[v] ?? double.infinity;
+ if (alt < dv) {
+ dist[v] = alt;
+ pq.add(v, alt);
+ instr.heapOps++;
+ }
+ }
+ }
+ return dist;
+}
+
+// ---------------------------
+// DataStructure D (practical)
+// ---------------------------
+class DataStructureD {
+ final PriorityQueue _heap = PriorityQueue();
+ final Map _best = {};
+ final int M;
+ final double BUpper;
+ final int blockSize;
+
+ DataStructureD(int M, double BUpper, {int? blockSize})
+ : M = M < 1 ? 1 : M,
+ BUpper = BUpper,
+ blockSize = blockSize ?? max(1, (M < 1 ? 1 : M) ~/ 8);
+
+ void insert(int v, double key) {
+ final prev = _best[v];
+ if (prev == null || key < prev) {
+ _best[v] = key;
+ _heap.add(v, key);
+ }
+ }
+
+ void batchPrepend(Iterable> iterablePairs) {
+ for (final p in iterablePairs) {
+ final v = p[0] as int;
+ final key = p[1] as double;
+ insert(v, key);
+ }
+ }
+
+ void _cleanup() {
+ // We can't directly inspect heap internals, so emulate lazy drain:
+ // Pop until top matches _best (this requires peeking).
+ // Our PQ exposes peek via peek; catch error if empty.
+ try {
+ while (_heap.length > 0) {
+ final top = _heap.peek();
+ final v = top.value;
+ final key = top.priority;
+ final bestVal = _best[v];
+ if (bestVal == null || bestVal != key) {
+ _heap.pop();
+ } else {
+ break;
+ }
+ }
+ } catch (e) {
+ // empty, ignore
+ }
+ }
+
+ bool isEmpty() {
+ _cleanup();
+ return _heap.isEmpty;
+ }
+
+ // pull returns Bi and Si set of up to blockSize nodes
+ Map pull() {
+ _cleanup();
+ if (_heap.isEmpty) throw StateError('pull from empty D');
+ final Bi = _heap.peek().priority;
+ final Si = {};
+ while (!_heap.isEmpty && Si.length < blockSize) {
+ final entry = _heap.pop();
+ final key = entry.priority;
+ final v = entry.value;
+ final bestVal = _best[v];
+ if (bestVal != null && bestVal == key) {
+ Si.add(v);
+ _best.remove(v);
+ }
+ }
+ return {'Bi': Bi, 'Si': Si};
+ }
+}
+
+// ---------------------------
+// FIND_PIVOTS (bounded Bellman-Ford-like)
+// ---------------------------
+Map> findPivots(
+ Map> graph,
+ Map dist,
+ Set S,
+ double B,
+ int n,
+ int kSteps,
+ int pLimit,
+ [Instrument? instr]) {
+ instr ??= Instrument();
+ final sFiltered = S.where((v) => (dist[v] ?? double.infinity) < B).toList();
+
+ Set P;
+ if (sFiltered.isEmpty) {
+ if (S.isEmpty) {
+ P = {};
+ } else {
+ final take = max(1, min(S.length, pLimit));
+ P = S.take(take).toSet();
+ }
+ } else {
+ sFiltered.sort((a, b) => (dist[a] ?? double.infinity).compareTo(dist[b] ?? double.infinity));
+ final take = max(1, min(sFiltered.length, pLimit));
+ P = sFiltered.take(take).toSet();
+ }
+
+ final sourceFrontier = P.isNotEmpty ? P.toSet() : S.toSet();
+ final discovered = sourceFrontier.toSet();
+ var frontier = sourceFrontier.toSet();
+
+ for (var step = 0; step < max(1, kSteps); ++step) {
+ if (frontier.isEmpty) break;
+ final nextFront = {};
+ for (final u in frontier) {
+ final du = dist[u] ?? double.infinity;
+ if (du >= B) continue;
+ for (final nb in graph[u] ?? []) {
+ instr.relaxations++;
+ final nd = du + nb.w;
+ if (nd < B && !discovered.contains(nb.v)) {
+ discovered.add(nb.v);
+ nextFront.add(nb.v);
+ }
+ }
+ }
+ frontier = nextFront;
+ }
+
+ final W = discovered.toSet();
+ if (P.isEmpty && S.isNotEmpty) {
+ P = {S.first};
+ }
+ return {'P': P, 'W': W};
+}
+
+// ---------------------------
+// BASECASE (Dijkstra-like limited)
+// ---------------------------
+Map basecase(
+ Map> graph, Map dist, double B, Set S, int k, [Instrument? instr]) {
+ instr ??= Instrument();
+ if (S.isEmpty) return {'Bprime': B, 'Uo': {}};
+
+ // choose x in S with smallest dist
+ int x = S.first;
+ double bestd = dist[x] ?? double.infinity;
+ for (final v in S) {
+ final dv = dist[v] ?? double.infinity;
+ if (dv < bestd) {
+ bestd = dv;
+ x = v;
+ }
+ }
+
+ final heap = PriorityQueue();
+ final startD = dist[x] ?? double.infinity;
+ heap.add(x, startD);
+ instr.heapOps++;
+
+ final Uo = {};
+
+ while (!heap.isEmpty && Uo.length < (k + 1)) {
+ final entry = heap.pop();
+ instr.heapOps++;
+ final dU = entry.priority;
+ final u = entry.value;
+ final cur = dist[u] ?? double.infinity;
+ if (dU > cur) continue;
+ if (!Uo.contains(u)) Uo.add(u);
+ for (final nb in graph[u] ?? []) {
+ instr.relaxations++;
+ final newd = (dist[u] ?? double.infinity) + nb.w;
+ final dv = dist[nb.v] ?? double.infinity;
+ if (newd < dv && newd < B) {
+ dist[nb.v] = newd;
+ heap.add(nb.v, newd);
+ instr.heapOps++;
+ }
+ }
+ }
+
+ if (Uo.length <= k) {
+ return {'Bprime': B, 'Uo': Uo};
+ } else {
+ final finiteDists = Uo.where((v) => (dist[v] ?? double.infinity).isFinite).map((v) => dist[v]!).toList();
+ if (finiteDists.isEmpty) return {'Bprime': B, 'Uo': {}};
+ final maxd = finiteDists.reduce(max);
+ final uFiltered = Uo.where((v) => (dist[v] ?? double.infinity) < maxd).toSet();
+ return {'Bprime': maxd, 'Uo': uFiltered};
+ }
+}
+
+// ---------------------------
+// BMSSP (practical recursive)
+// ---------------------------
+Map bmssp(
+ Map> graph,
+ Map dist,
+ List edges,
+ int l,
+ double B,
+ Set S,
+ int n,
+ [Instrument? instr]) {
+ instr ??= Instrument();
+
+ int tParam, kParam;
+ if (n <= 2) {
+ tParam = 1;
+ kParam = 2;
+ } else {
+ final ln = log(max(3, n));
+ tParam = max(1, (ln.pow(2.0 / 3.0)).round());
+ kParam = max(2, (ln.pow(1.0 / 3.0)).round());
+ }
+
+ if (l <= 0) {
+ if (S.isEmpty) return {'Bprime': B, 'Ufinal': {}};
+ final bc = basecase(graph, dist, B, S, kParam, instr);
+ return {'Bprime': bc['Bprime'] as double, 'Ufinal': bc['Uo'] as Set};
+ }
+
+ final pLimit = max(1, 1 << min(10, tParam));
+ final kSteps = max(1, kParam);
+
+ final piv = findPivots(graph, dist, S, B, n, kSteps, pLimit, instr);
+ var P = (piv['P'] as Set).toSet();
+ final W = (piv['W'] as Set).toSet();
+
+ final M = 1 << max(0, (l - 1) * tParam);
+ final D = DataStructureD(M, B, blockSize: max(1, min(P.isEmpty ? 1 : P.length, 64)));
+
+ for (final x in P) {
+ final dx = dist[x] ?? double.infinity;
+ D.insert(x, dx);
+ }
+
+ double bPrimeInitial = B;
+ if (P.isNotEmpty) {
+ double minv = double.infinity;
+ for (final x in P) {
+ final dx = dist[x] ?? double.infinity;
+ if (dx < minv) minv = dx;
+ }
+ if (minv.isFinite) bPrimeInitial = minv;
+ }
+
+ final U = {};
+ final bPrimeSubs = [];
+
+ var loopGuard = 0;
+ final limit = kParam * (1 << (l * max(1, tParam)));
+
+ while (U.length < limit && !D.isEmpty()) {
+ loopGuard++;
+ if (loopGuard > 20000) break;
+ Map pulled;
+ try {
+ pulled = D.pull();
+ } catch (e) {
+ break;
+ }
+ final Bi = pulled['Bi'] as double;
+ final Si = pulled['Si'] as Set;
+
+ final sub = bmssp(graph, dist, edges, l - 1, Bi, Si, n, instr);
+ final bPrimeSub = sub['Bprime'] as double;
+ final Ui = (sub['Ufinal'] as Set).toSet();
+ bPrimeSubs.add(bPrimeSub);
+ U.addAll(Ui);
+
+ final batch = >[];
+
+ for (final u in Ui) {
+ final du = dist[u] ?? double.infinity;
+ if (!du.isFinite) continue;
+ for (final nb in graph[u] ?? []) {
+ instr.relaxations++;
+ final newd = du + nb.w;
+ final dv = dist[nb.v] ?? double.infinity;
+ if (newd <= dv) {
+ dist[nb.v] = newd;
+ if (Bi <= newd && newd < B) {
+ D.insert(nb.v, newd);
+ } else if (bPrimeSub <= newd && newd < Bi) {
+ batch.add([nb.v, newd]);
+ }
+ }
+ }
+ }
+
+ for (final x in Si) {
+ final dx = dist[x] ?? double.infinity;
+ if (bPrimeSub <= dx && dx < Bi) {
+ batch.add([x, dx]);
+ }
+ }
+
+ if (batch.isNotEmpty) D.batchPrepend(batch);
+ }
+
+ double bPrimeFinal = bPrimeInitial;
+ if (bPrimeSubs.isNotEmpty) {
+ final minSub = bPrimeSubs.reduce(min);
+ bPrimeFinal = min(bPrimeInitial, minSub);
+ }
+
+ final uFinal = U.toSet();
+ for (final x in W) {
+ final dx = dist[x] ?? double.infinity;
+ if (dx < bPrimeFinal) uFinal.add(x);
+ }
+
+ return {'Bprime': bPrimeFinal, 'Ufinal': uFinal};
+}
+
+// ---------------------------
+// Test harness
+// ---------------------------
+class TestResult {
+ int n = 0;
+ int m = 0;
+ int seed = 0;
+ double dijkstraTime = 0.0;
+ int dijkstraRelax = 0;
+ double bmsspTime = 0.0;
+ int bmsspRelax = 0;
+ int dijkstraReachable = 0;
+ int bmsspReachable = 0;
+ double maxDiff = 0.0;
+}
+
+TestResult runSingleTest(int n, int m, {int seed = 0, int source = 0}) {
+ print('Generating graph: n=$n, m=$m, seed=$seed');
+ final ge = generateSparseDirectedGraph(n, m, seed: seed);
+ final graph = ge.graph;
+ final edges = ge.edges;
+ final avgDeg = graph.values.fold(0, (p, e) => p + e.length) / n;
+ print('Graph generated. avg out-degree ≈ ${avgDeg.toStringAsFixed(3)}');
+
+ // Dijkstra timing
+ final instrDij = Instrument();
+ final t0 = DateTime.now().millisecondsSinceEpoch;
+ final distDij = dijkstra(graph, source, instrDij);
+ final t1 = DateTime.now().millisecondsSinceEpoch;
+ final dijTime = (t1 - t0) / 1000.0;
+ final dijReachable = distDij.values.where((v) => v.isFinite).length;
+ print('Dijkstra: time=${dijTime.toStringAsFixed(6)}s, relaxations=${instrDij.relaxations}, heap_ops=${instrDij.heapOps}, reachable=$dijReachable');
+
+ // BMSSP practical
+ final distBm = {};
+ for (final k in graph.keys) distBm[k] = double.infinity;
+ distBm[source] = 0.0;
+ final instrBm = Instrument();
+
+ int l;
+ if (n <= 2) l = 1;
+ else {
+ final ln = log(max(3, n));
+ final tGuess = max(1, (ln.pow(2.0 / 3.0)).round());
+ l = max(1, max(1, (ln / tGuess).round()));
+ }
+ print('BMSSP params: top-level l=$l');
+
+ final t2 = DateTime.now().millisecondsSinceEpoch;
+ final res = bmssp(graph, distBm, edges, l, double.infinity, {source}, n, instrBm);
+ final t3 = DateTime.now().millisecondsSinceEpoch;
+ final bmTime = (t3 - t2) / 1000.0;
+ final bmReachable = distBm.values.where((v) => v.isFinite).length;
+ final Bp = res['Bprime'] as double;
+ final Ufinal = res['Ufinal'] as Set;
+ print('BMSSP: time=${bmTime.toStringAsFixed(6)}s, relaxations=${instrBm.relaxations}, reachable=$bmReachable, B\'=$Bp, |U_final|=${Ufinal.length}');
+
+ final diffs = [];
+ for (final v in graph.keys) {
+ final dv = distDij[v] ?? double.infinity;
+ final db = distBm[v] ?? double.infinity;
+ if (dv.isFinite && db.isFinite) diffs.add((dv - db).abs());
+ }
+ final maxDiff = diffs.isEmpty ? 0.0 : diffs.reduce(max);
+ print('Distance agreement (max abs diff on commonly reachable nodes): ${maxDiff.toStringAsExponential(6)}');
+
+ final tr = TestResult()
+ ..n = n
+ ..m = m
+ ..seed = seed
+ ..dijkstraTime = dijTime
+ ..dijkstraRelax = instrDij.relaxations
+ ..bmsspTime = bmTime
+ ..bmsspRelax = instrBm.relaxations
+ ..dijkstraReachable = dijReachable
+ ..bmsspReachable = bmReachable
+ ..maxDiff = maxDiff;
+ return tr;
+}
+
+// ---------------------------
+// CLI main
+// ---------------------------
+void printUsage() {
+ print('Usage: dart bmssp_full_impl.dart [-n nodes] [-m edges] [-s seed]');
+}
+
+void main(List args) {
+ int n = 200000;
+ int m = 800000;
+ int seed = 0;
+
+ for (var i = 0; i < args.length; ++i) {
+ final a = args[i];
+ if ((a == '-n' || a == '--nodes') && i + 1 < args.length) {
+ n = int.tryParse(args[++i]) ?? n;
+ } else if ((a == '-m' || a == '--edges') && i + 1 < args.length) {
+ m = int.tryParse(args[++i]) ?? m;
+ } else if ((a == '-s' || a == '--seed') && i + 1 < args.length) {
+ seed = int.tryParse(args[++i]) ?? seed;
+ } else if (a == '-h' || a == '--help') {
+ printUsage();
+ return;
+ }
+ }
+
+ // For interactive testing on small machines you may want to set smaller defaults:
+ if (Platform.environment.containsKey('BMSSP_SMALL')) {
+ n = 2000;
+ m = 8000;
+ }
+
+ // run test
+ try {
+ runSingleTest(n, m, seed: seed, source: 0);
+ } catch (e, st) {
+ stderr.writeln('Error: $e\n$st');
+ exit(2);
+ }
+}
+
+// ---------------------------
+// Extensions for math helpers
+// ---------------------------
+extension DoublePow on double {
+ double pow(double p) => mathPow(this, p);
+}
+double mathPow(double a, double b) => powDouble(a, b);
+
+double powDouble(double a, double b) {
+ return math_pow(a, b).toDouble();
+}
+
+// Because dart:math.pow returns num and may be slow to cast, we use a wrapper
+num math_pow(num a, num b) => pow(a, b);
diff --git a/POCDart/run.bat b/POCDart/run.bat
new file mode 100644
index 0000000..10e4a5f
--- /dev/null
+++ b/POCDart/run.bat
@@ -0,0 +1 @@
+dart bmssp_full_impl.dart -n 2000 -m 8000 -s 42
\ No newline at end of file
diff --git a/POCDotnet/BaseCaseRunner.cs b/POCDotnet/BaseCaseRunner.cs
new file mode 100644
index 0000000..04d71a6
--- /dev/null
+++ b/POCDotnet/BaseCaseRunner.cs
@@ -0,0 +1,67 @@
+using Graph = System.Collections.Generic.Dictionary>;
+using Node = System.Int32;
+
+namespace POCDotnet
+{
+ ///
+ /// BASECASE (Dijkstra-like limited)
+ ///
+ public static class BaseCaseRunner
+ {
+ public static (double BPrime, HashSet Uo) Run(
+ Graph graph,
+ Dictionary dist,
+ double B,
+ HashSet S,
+ int k,
+ Instrument? instr = null)
+ {
+ instr ??= new Instrument();
+
+ if (S.Count == 0) return (B, new HashSet());
+
+ var x = S.MinBy(v => dist.TryGetValue(v, out var dv) ? dv : double.PositiveInfinity);
+ var heap = new PriorityQueue();
+
+ var startD = dist.TryGetValue(x, out var sd) ? sd : double.PositiveInfinity;
+ heap.Enqueue(x, startD);
+ instr.HeapOps++;
+
+ var Uo = new HashSet();
+
+ while (heap.Count > 0 && Uo.Count < (k + 1))
+ {
+ heap.TryDequeue(out var u, out var dU);
+ instr.HeapOps++;
+ if (dU > (dist.TryGetValue(u, out var du) ? du : double.PositiveInfinity)) continue;
+
+ if (!Uo.Contains(u)) Uo.Add(u);
+
+ foreach (var (v, w) in graph[u])
+ {
+ instr.Relaxations++;
+ var newd = dist[u] + w;
+ if (newd < (dist.TryGetValue(v, out var dv) ? dv : double.PositiveInfinity) && newd < B)
+ {
+ dist[v] = newd;
+ heap.Enqueue(v, newd);
+ instr.HeapOps++;
+ }
+ }
+ }
+
+ if (Uo.Count <= k)
+ {
+ return (B, Uo);
+ }
+ else
+ {
+ var finite = Uo.Where(v => !double.IsPositiveInfinity(dist[v])).Select(v => dist[v]).ToList();
+ if (finite.Count == 0) return (B, new HashSet());
+ var maxd = finite.Max();
+ var Ufiltered = new HashSet(Uo.Where(v => dist[v] < maxd));
+ return (maxd, Ufiltered);
+ }
+ }
+ }
+}
diff --git a/POCDotnet/BmsspRunner.cs b/POCDotnet/BmsspRunner.cs
new file mode 100644
index 0000000..af0b466
--- /dev/null
+++ b/POCDotnet/BmsspRunner.cs
@@ -0,0 +1,131 @@
+using Edge = System.ValueTuple;
+using Graph = System.Collections.Generic.Dictionary>;
+using Node = System.Int32;
+
+namespace POCDotnet
+{
+ ///
+ /// BMSSP (practical recursive)
+ ///
+ public static class BmsspRunner
+ {
+ private static (int tParam, int kParam) GetParams(int n)
+ {
+ if (n <= 2) return (1, 2);
+ double ln = Math.Log(Math.Max(3, n));
+ int t = Math.Max(1, (int)Math.Round(Math.Pow(ln, 2.0 / 3.0)));
+ int k = Math.Max(2, (int)Math.Round(Math.Pow(ln, 1.0 / 3.0)));
+ return (t, k);
+ }
+
+ public static (double BPrime, HashSet UFinal) Run(
+ Graph graph,
+ Dictionary dist,
+ List edges,
+ int l,
+ double B,
+ HashSet S,
+ int n,
+ Instrument? instr = null)
+ {
+ instr ??= new Instrument();
+
+ var (tParam, kParam) = GetParams(n);
+
+ if (l <= 0)
+ {
+ if (S.Count == 0) return (B, new HashSet());
+ return BaseCaseRunner.Run(graph, dist, B, S, kParam, instr);
+ }
+
+ int pLimit = Math.Max(1, 1 << Math.Min(10, tParam));
+ int kSteps = Math.Max(1, kParam);
+
+ var (P, W) = PivotFinder.FindPivots(graph, dist, S, B, n, kSteps, pLimit, instr);
+
+ int M = 1 << Math.Max(0, (l - 1) * tParam);
+ var D = new DataStructureD(M, B, blockSize: Math.Max(1, Math.Min(Math.Max(P.Count, 1), 64)));
+
+ foreach (var x in P)
+ {
+ dist.TryGetValue(x, out var dx);
+ D.Insert(x, dx);
+ }
+
+ double bPrimeInitial = P.Count > 0 ? P.Min(x => dist.TryGetValue(x, out var dx) ? dx : double.PositiveInfinity) : B;
+ var U = new HashSet();
+ var bPrimeSubs = new List();
+
+ int loopGuard = 0;
+ int limit = kParam * (1 << (l * Math.Max(1, tParam)));
+
+ while (U.Count < limit && !D.Empty())
+ {
+ loopGuard++;
+ if (loopGuard > 20000) break;
+
+ double Bi;
+ HashSet Si;
+ try
+ {
+ (Bi, Si) = D.Pull();
+ }
+ catch
+ {
+ break;
+ }
+
+ var (bPrimeSub, Ui) = Run(graph, dist, edges, l - 1, Bi, Si, n, instr);
+ bPrimeSubs.Add(bPrimeSub);
+ U.UnionWith(Ui);
+
+ var batch = new HashSet<(Node v, double key)>();
+
+ foreach (var u in Ui)
+ {
+ if (!dist.TryGetValue(u, out var du) || double.IsPositiveInfinity(du)) continue;
+
+ foreach (var (v, wuv) in graph[u])
+ {
+ instr.Relaxations++;
+ var newd = du + wuv;
+
+ if (newd <= (dist.TryGetValue(v, out var dv) ? dv : double.PositiveInfinity))
+ {
+ dist[v] = newd;
+ if (Bi <= newd && newd < B)
+ {
+ D.Insert(v, newd);
+ }
+ else if (bPrimeSub <= newd && newd < Bi)
+ {
+ batch.Add((v, newd));
+ }
+ }
+ }
+ }
+
+ foreach (var x in Si)
+ {
+ var dx = dist.TryGetValue(x, out var dxx) ? dxx : double.PositiveInfinity;
+ if (bPrimeSub <= dx && dx < Bi)
+ {
+ batch.Add((x, dx));
+ }
+ }
+
+ if (batch.Count > 0) D.BatchPrepend(batch);
+ }
+
+ double bPrimeFinal = bPrimeSubs.Count > 0 ? Math.Min(bPrimeSubs.Prepend(bPrimeInitial).Min(), bPrimeInitial) : bPrimeInitial;
+
+ var UFinal = new HashSet(U);
+ foreach (var x in W)
+ {
+ if (dist.TryGetValue(x, out var dx) && dx < bPrimeFinal) UFinal.Add(x);
+ }
+
+ return (bPrimeFinal, UFinal);
+ }
+ }
+}
diff --git a/POCDotnet/DataStructureD.cs b/POCDotnet/DataStructureD.cs
new file mode 100644
index 0000000..28e9033
--- /dev/null
+++ b/POCDotnet/DataStructureD.cs
@@ -0,0 +1,76 @@
+using Node = System.Int32;
+
+namespace POCDotnet
+{
+ ///
+ /// DataStructure D (practical)
+ ///
+ public class DataStructureD
+ {
+ private readonly PriorityQueue _heap = new();
+ private readonly Dictionary _best = new();
+ private readonly int _blockSize;
+ private readonly int _M;
+ private readonly double _BUpper;
+
+ public DataStructureD(int M, double BUpper, int? blockSize = null)
+ {
+ _M = Math.Max(1, M);
+ _BUpper = BUpper;
+ _blockSize = blockSize ?? Math.Max(1, _M / 8);
+ }
+
+ public void Insert(Node v, double key)
+ {
+ if (!_best.TryGetValue(v, out var prev) || key < prev)
+ {
+ _best[v] = key;
+ _heap.Enqueue(v, key);
+ }
+ }
+
+ public void BatchPrepend(IEnumerable<(Node v, double key)> items)
+ {
+ foreach (var (v, key) in items) Insert(v, key);
+ }
+
+ private void Cleanup()
+ {
+ // remove stale heap entries
+ while (_heap.Count > 0)
+ {
+ if (_heap.TryPeek(out var v, out var key))
+ {
+ if (_best.TryGetValue(v, out var val) && val == key) break;
+ _heap.Dequeue(); // stale
+ }
+ }
+ }
+
+ public bool Empty()
+ {
+ Cleanup();
+ return _heap.Count == 0;
+ }
+
+ public (double Bi, HashSet Si) Pull()
+ {
+ Cleanup();
+ if (_heap.Count == 0) throw new InvalidOperationException("pull from empty D");
+ _heap.TryPeek(out _, out var Bi);
+ var Si = new HashSet();
+ while (_heap.Count > 0 && Si.Count < _blockSize)
+ {
+ if (_heap.TryDequeue(out var v, out var key))
+ {
+ if (_best.TryGetValue(v, out var val) && val == key)
+ {
+ Si.Add(v);
+ _best.Remove(v);
+ }
+ }
+ }
+ return (Bi, Si);
+ }
+ }
+}
diff --git a/POCDotnet/GraphGenerator.cs b/POCDotnet/GraphGenerator.cs
new file mode 100644
index 0000000..2769d80
--- /dev/null
+++ b/POCDotnet/GraphGenerator.cs
@@ -0,0 +1,39 @@
+using Edge = System.ValueTuple;
+using Graph = System.Collections.Generic.Dictionary>;
+
+namespace POCDotnet
+{
+ ///
+ /// Utilities & Graph generator
+ ///
+ public static class GraphGenerator
+ {
+ public static (Graph, List) GenerateSparseDirectedGraph(int n, int m, double maxW = 100.0, int? seed = null)
+ {
+ var rand = seed.HasValue ? new Random(seed.Value) : new Random();
+ var graph = new Graph();
+ for (int i = 0; i < n; i++) graph[i] = new List<(int, double)>();
+ var edges = new List();
+
+ // weak backbone to avoid isolated nodes
+ for (int i = 1; i < n; i++)
+ {
+ int u = rand.Next(i);
+ double w = rand.NextDouble() * maxW + 1.0;
+ graph[u].Add((i, w));
+ edges.Add((u, i, w));
+ }
+
+ int remaining = Math.Max(0, m - (n - 1));
+ for (int i = 0; i < remaining; i++)
+ {
+ int u = rand.Next(n);
+ int v = rand.Next(n);
+ double w = rand.NextDouble() * maxW + 1.0;
+ graph[u].Add((v, w));
+ edges.Add((u, v, w));
+ }
+ return (graph, edges);
+ }
+ }
+}
diff --git a/POCDotnet/Harness.cs b/POCDotnet/Harness.cs
new file mode 100644
index 0000000..98e48dc
--- /dev/null
+++ b/POCDotnet/Harness.cs
@@ -0,0 +1,59 @@
+using System.Diagnostics;
+
+namespace POCDotnet
+{
+ ///
+ /// Test harness (similar to run_single_test)
+ ///
+ public static class Harness
+ {
+ public static void RunSingleTest(int n, int m, int seed = 0, int source = 0)
+ {
+ Console.WriteLine($"Generating graph: n={n}, m={m}, seed={seed}");
+ var (graph, edges) = GraphGenerator.GenerateSparseDirectedGraph(n, m, seed: seed);
+ double avgDeg = graph.Values.Sum(adj => adj.Count) / (double)n;
+ Console.WriteLine($"Graph generated. avg out-degree ≈ {avgDeg:F3}");
+
+ var distDij = graph.Keys.ToDictionary(v => v, _ => double.PositiveInfinity);
+ distDij[source] = 0.0;
+
+ var instrDij = new Instrument();
+ var sw = Stopwatch.StartNew();
+ distDij = ShortestPath.Dijkstra(graph, source, instrDij);
+ sw.Stop();
+ Console.WriteLine($"Dijkstra: time={sw.Elapsed.TotalSeconds:F6}s, relaxations={instrDij.Relaxations}, heap_ops={instrDij.HeapOps}, reachable={distDij.Values.Count(v => !double.IsInfinity(v))}");
+
+ var distBm = graph.Keys.ToDictionary(v => v, _ => double.PositiveInfinity);
+ distBm[source] = 0.0;
+
+ var instrBm = new Instrument();
+ int l;
+ if (n <= 2) l = 1;
+ else
+ {
+ double ln = Math.Log(Math.Max(3, n));
+ int tGuess = Math.Max(1, (int)Math.Round(Math.Pow(ln, 2.0 / 3.0)));
+ l = Math.Max(1, (int)Math.Max(1, Math.Round(ln / tGuess)));
+ }
+ Console.WriteLine($"BMSSP params: top-level l={l}");
+
+ sw.Restart();
+ var (Bp, Ufinal) = BmsspRunner.Run(graph, distBm, edges, l, double.PositiveInfinity, new HashSet { source }, n, instrBm);
+ sw.Stop();
+ Console.WriteLine($"BMSSP: time={sw.Elapsed.TotalSeconds:F6}s, relaxations={instrBm.Relaxations}, reachable={distBm.Values.Count(v => !double.IsInfinity(v))}, B'={Bp}, |U_final|={Ufinal.Count}");
+
+ var diffs = new List();
+ foreach (var v in graph.Keys)
+ {
+ var dv = distDij[v];
+ var db = distBm[v];
+ if (!double.IsInfinity(dv) && !double.IsInfinity(db))
+ {
+ diffs.Add(Math.Abs(dv - db));
+ }
+ }
+ double maxDiff = diffs.Count > 0 ? diffs.Max() : 0.0;
+ Console.WriteLine($"Distance agreement (max abs diff on commonly reachable nodes): {maxDiff:E6}");
+ }
+ }
+}
diff --git a/POCDotnet/Instrument.cs b/POCDotnet/Instrument.cs
new file mode 100644
index 0000000..ea0ac94
--- /dev/null
+++ b/POCDotnet/Instrument.cs
@@ -0,0 +1,12 @@
+namespace POCDotnet
+{
+ ///
+ /// Instrumentation
+ ///
+ public class Instrument
+ {
+ public long Relaxations { get; set; }
+ public long HeapOps { get; set; }
+ public void Reset() { Relaxations = 0; HeapOps = 0; }
+ }
+}
diff --git a/POCDotnet/POCDotnet.csproj b/POCDotnet/POCDotnet.csproj
new file mode 100644
index 0000000..fd4bd08
--- /dev/null
+++ b/POCDotnet/POCDotnet.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+
+
+
diff --git a/POCDotnet/PivotFinder.cs b/POCDotnet/PivotFinder.cs
new file mode 100644
index 0000000..a0aa8db
--- /dev/null
+++ b/POCDotnet/PivotFinder.cs
@@ -0,0 +1,71 @@
+using Graph = System.Collections.Generic.Dictionary>;
+using Node = System.Int32;
+
+namespace POCDotnet
+{
+ ///
+ /// FIND_PIVOTS (practical bounded BF)
+ ///
+ public static class PivotFinder
+ {
+ public static (HashSet P, HashSet W) FindPivots(
+ Graph graph,
+ Dictionary dist,
+ HashSet S,
+ double B,
+ int n,
+ int kSteps,
+ int pLimit,
+ Instrument? instr = null)
+ {
+ instr ??= new Instrument();
+
+ var sFiltered = S.Where(v => dist.TryGetValue(v, out var dv) && dv < B).ToList();
+
+ HashSet P;
+ if (sFiltered.Count == 0)
+ {
+ var take = Math.Max(1, Math.Min(S.Count, pLimit));
+ P = new HashSet(S.Take(take));
+ }
+ else
+ {
+ sFiltered.Sort((a, b) => dist[a].CompareTo(dist[b]));
+ P = new HashSet(sFiltered.Take(Math.Max(1, Math.Min(sFiltered.Count, pLimit))));
+ }
+
+ var sourceFrontier = P.Count > 0 ? new HashSet(P) : new HashSet(S);
+ var discovered = new HashSet(sourceFrontier);
+ var frontier = new HashSet(sourceFrontier);
+
+ for (int step = 0; step < Math.Max(1, kSteps); step++)
+ {
+ if (frontier.Count == 0) break;
+ var nextFront = new HashSet();
+ foreach (var u in frontier)
+ {
+ var du = dist.TryGetValue(u, out var vdu) ? vdu : double.PositiveInfinity;
+ if (du >= B) continue;
+ foreach (var (v, w) in graph[u])
+ {
+ instr.Relaxations++;
+ var nd = du + w;
+ if (nd < B && !discovered.Contains(v))
+ {
+ discovered.Add(v);
+ nextFront.Add(v);
+ }
+ }
+ }
+ frontier = nextFront;
+ }
+
+ var W = new HashSet(discovered);
+ if (P.Count == 0 && S.Count > 0)
+ {
+ P.Add(S.First());
+ }
+ return (P, W);
+ }
+ }
+}
diff --git a/POCDotnet/Program.cs b/POCDotnet/Program.cs
new file mode 100644
index 0000000..51bfce9
--- /dev/null
+++ b/POCDotnet/Program.cs
@@ -0,0 +1,18 @@
+namespace POCDotnet
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ int n = 200_000, m = 800_000, seed = 0;
+ for (int i = 0; i < args.Length - 1; i++)
+ {
+ if (args[i] == "-n" || args[i] == "--nodes") int.TryParse(args[++i], out n);
+ else if (args[i] == "-m" || args[i] == "--edges") int.TryParse(args[++i], out m);
+ else if (args[i] == "-s" || args[i] == "--seed") int.TryParse(args[++i], out seed);
+ }
+
+ Harness.RunSingleTest(n, m, seed, source: 0);
+ }
+ }
+}
diff --git a/POCDotnet/ShortestPath.cs b/POCDotnet/ShortestPath.cs
new file mode 100644
index 0000000..5d1a8a3
--- /dev/null
+++ b/POCDotnet/ShortestPath.cs
@@ -0,0 +1,43 @@
+using Graph = System.Collections.Generic.Dictionary>;
+using Node = System.Int32;
+using Weight = System.Double;
+
+namespace POCDotnet
+{
+ ///
+ /// Dijkstra
+ ///
+ public static class ShortestPath
+ {
+ public static Dictionary Dijkstra(Graph graph, Node source, Instrument? instr = null)
+ {
+ instr ??= new Instrument();
+ var dist = graph.Keys.ToDictionary(v => v, _ => double.PositiveInfinity);
+ dist[source] = 0.0;
+
+ var pq = new PriorityQueue();
+ pq.Enqueue(source, 0.0);
+ instr.HeapOps++;
+
+ while (pq.Count > 0)
+ {
+ pq.TryDequeue(out var u, out var dU);
+ instr.HeapOps++;
+ if (dU > dist[u]) continue;
+
+ foreach (var (v, w) in graph[u])
+ {
+ instr.Relaxations++;
+ double alt = dU + w;
+ if (alt < dist[v])
+ {
+ dist[v] = alt;
+ pq.Enqueue(v, alt);
+ instr.HeapOps++;
+ }
+ }
+ }
+ return dist;
+ }
+ }
+}
diff --git a/POCNodeTypescript/.vscode/launch.json b/POCNodeTypescript/.vscode/launch.json
new file mode 100644
index 0000000..9a761b1
--- /dev/null
+++ b/POCNodeTypescript/.vscode/launch.json
@@ -0,0 +1,14 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Launch Program",
+ "skipFiles": [ "/**" ],
+ "program": "${workspaceFolder}/app.js",
+ "cwd": "${workspaceFolder}",
+ "console": "externalTerminal"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/POCNodeTypescript/CHANGELOG.md b/POCNodeTypescript/CHANGELOG.md
new file mode 100644
index 0000000..96f0f3b
--- /dev/null
+++ b/POCNodeTypescript/CHANGELOG.md
@@ -0,0 +1,15 @@
+This file explains how Visual Studio created the project.
+
+The following tools were used to generate this project:
+- TypeScript Compiler (tsc)
+
+The following steps were used to generate this project:
+- Create project file (`POCNodeTypescript.esproj`).
+- Create `launch.json` to enable debugging.
+- Install npm packages and create `tsconfig.json`: `npm init && npm i --save-dev eslint typescript @types/node && npx tsc --init --sourceMap true`.
+- Create `app.ts`.
+- Update `package.json` entry point.
+- Update TypeScript build scripts in `package.json`.
+- Create `eslint.config.js` to enable linting.
+- Add project to solution.
+- Write this file.
diff --git a/POCNodeTypescript/POCNodeTypescript.esproj b/POCNodeTypescript/POCNodeTypescript.esproj
new file mode 100644
index 0000000..a25c7c1
--- /dev/null
+++ b/POCNodeTypescript/POCNodeTypescript.esproj
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/POCNodeTypescript/app.d.ts b/POCNodeTypescript/app.d.ts
new file mode 100644
index 0000000..1ab2332
--- /dev/null
+++ b/POCNodeTypescript/app.d.ts
@@ -0,0 +1,21 @@
+#!/usr/bin/env ts-node
+/**
+ * app.ts
+ *
+ * Full TypeScript port of the Python BMSSP practical implementation.
+ * - Graph generator
+ * - Instrumentation
+ * - Dijkstra
+ * - DataStructureD (heap + map, lazy deletion)
+ * - findPivots (bounded BF-like)
+ * - basecase (Dijkstra-like limited)
+ * - Recursive bmssp
+ * - Test harness + minimal CLI
+ *
+ * Usage:
+ * ts-node bmssp.ts -n 2000 -m 8000 -s 42
+ *
+ * Note: For big graphs, increase node memory/stack or use Node with --stack-size if needed.
+ */
+export {};
+//# sourceMappingURL=app.d.ts.map
\ No newline at end of file
diff --git a/POCNodeTypescript/app.d.ts.map b/POCNodeTypescript/app.d.ts.map
new file mode 100644
index 0000000..6e2c391
--- /dev/null
+++ b/POCNodeTypescript/app.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
\ No newline at end of file
diff --git a/POCNodeTypescript/app.js b/POCNodeTypescript/app.js
new file mode 100644
index 0000000..aa99a24
--- /dev/null
+++ b/POCNodeTypescript/app.js
@@ -0,0 +1,502 @@
+#!/usr/bin/env ts-node
+/**
+ * app.ts
+ *
+ * Full TypeScript port of the Python BMSSP practical implementation.
+ * - Graph generator
+ * - Instrumentation
+ * - Dijkstra
+ * - DataStructureD (heap + map, lazy deletion)
+ * - findPivots (bounded BF-like)
+ * - basecase (Dijkstra-like limited)
+ * - Recursive bmssp
+ * - Test harness + minimal CLI
+ *
+ * Usage:
+ * ts-node bmssp.ts -n 2000 -m 8000 -s 42
+ *
+ * Note: For big graphs, increase node memory/stack or use Node with --stack-size if needed.
+ */
+const INF = Number.POSITIVE_INFINITY;
+/* ----------------------------
+ Simple min-heap for (key,node) pairs
+ ---------------------------- */
+class MinHeap {
+ data = [];
+ size() {
+ return this.data.length;
+ }
+ isEmpty() {
+ return this.data.length === 0;
+ }
+ peek() {
+ return this.data.length ? this.data[0] ?? null : null;
+ }
+ push(key, node) {
+ this.data.push({ key, node });
+ this.siftUp(this.data.length - 1);
+ }
+ pop() {
+ if (!this.data.length)
+ return null;
+ const top = this.data[0];
+ const last = this.data.pop();
+ if (this.data.length) {
+ this.data[0] = last;
+ this.siftDown(0);
+ }
+ return top ?? null;
+ }
+ siftUp(i) {
+ while (i > 0) {
+ const p = (i - 1) >> 1;
+ if (this.data[i]?.key ?? 0 < (this.data[p] ? this.data[p].key : 0)) {
+ const temp = this.data[i];
+ this.data[i] = this.data[p];
+ this.data[p] = temp;
+ i = p;
+ }
+ else
+ break;
+ }
+ }
+ siftDown(i) {
+ const n = this.data.length;
+ while (true) {
+ const l = i * 2 + 1;
+ const r = l + 1;
+ let smallest = i;
+ if (l < n && (this.data[l]?.key ?? 0) < (this.data[smallest]?.key ?? 0))
+ smallest = l;
+ if (r < n && (this.data[r]?.key ?? 0) < (this.data[smallest]?.key ?? 0))
+ smallest = r;
+ if (smallest === i)
+ break;
+ const temp = this.data[i];
+ this.data[i] = this.data[smallest];
+ this.data[smallest] = temp;
+ i = smallest;
+ }
+ }
+}
+/* ----------------------------
+ RNG (seedable) - mulberry32
+ ---------------------------- */
+function mulberry32(seed) {
+ let t = seed >>> 0;
+ return function () {
+ t += 0x6D2B79F5;
+ let r = Math.imul(t ^ (t >>> 15), t | 1);
+ r ^= r + Math.imul(r ^ (r >>> 7), r | 61);
+ return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
+ };
+}
+/* ----------------------------
+ Graph generator
+ ---------------------------- */
+function generateSparseDirectedGraph(n, m, maxW = 100.0, seed) {
+ const rand = seed !== undefined ? mulberry32(seed) : Math.random;
+ const graph = new Map();
+ for (let i = 0; i < n; i++)
+ graph.set(i, []);
+ const edges = [];
+ // backbone to avoid isolated nodes
+ for (let i = 1; i < n; i++) {
+ const u = Math.floor(rand() * i);
+ const w = rand() * (maxW - 1.0) + 1.0;
+ graph.get(u).push([i, w]);
+ edges.push([u, i, w]);
+ }
+ const remaining = Math.max(0, m - (n - 1));
+ for (let i = 0; i < remaining; i++) {
+ const u = Math.floor(rand() * n);
+ const v = Math.floor(rand() * n);
+ const w = rand() * (maxW - 1.0) + 1.0;
+ graph.get(u).push([v, w]);
+ edges.push([u, v, w]);
+ }
+ return [graph, edges];
+}
+/* ----------------------------
+ Instrumentation
+ ---------------------------- */
+class Instrument {
+ relaxations = 0;
+ heapOps = 0;
+ reset() {
+ this.relaxations = 0;
+ this.heapOps = 0;
+ }
+}
+/* ----------------------------
+ Dijkstra (standard)
+ ---------------------------- */
+function dijkstra(graph, source, instr) {
+ instr = instr ?? new Instrument();
+ const dist = new Map();
+ for (const k of graph.keys())
+ dist.set(k, INF);
+ dist.set(source, 0);
+ const heap = new MinHeap();
+ heap.push(0, source);
+ instr.heapOps++;
+ while (!heap.isEmpty()) {
+ const top = heap.pop();
+ const d_u = top.key;
+ const u = top.node;
+ instr.heapOps++;
+ const cur = dist.get(u) ?? INF;
+ if (d_u > cur)
+ continue;
+ for (const [v, w] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const alt = d_u + w;
+ const dv = dist.get(v) ?? INF;
+ if (alt < dv) {
+ dist.set(v, alt);
+ heap.push(alt, v);
+ instr.heapOps++;
+ }
+ }
+ }
+ return dist;
+}
+/* ----------------------------
+ DataStructureD (heap + map)
+ ---------------------------- */
+class DataStructureD {
+ heap = new MinHeap();
+ best = new Map();
+ M;
+ BUpper;
+ blockSize;
+ constructor(M, BUpper, blockSize) {
+ this.M = Math.max(1, M);
+ this.BUpper = BUpper;
+ this.blockSize = blockSize ?? Math.max(1, Math.floor(this.M / 8));
+ }
+ insert(v, key) {
+ const prev = this.best.get(v);
+ if (prev === undefined || key < prev) {
+ this.best.set(v, key);
+ this.heap.push(key, v);
+ }
+ }
+ batchPrepend(iterablePairs) {
+ for (const [v, key] of iterablePairs)
+ this.insert(v, key);
+ }
+ cleanup() {
+ while (!this.heap.isEmpty()) {
+ const top = this.heap.peek();
+ const node = top.node;
+ const key = top.key;
+ const cur = this.best.get(node);
+ if (cur === undefined || cur !== key) {
+ this.heap.pop(); // stale
+ }
+ else
+ break;
+ }
+ }
+ empty() {
+ this.cleanup();
+ return this.heap.isEmpty();
+ }
+ pull() {
+ this.cleanup();
+ if (this.heap.isEmpty())
+ throw new Error("pull from empty D");
+ const Bi = this.heap.peek().key;
+ const Si = new Set();
+ while (!this.heap.isEmpty() && Si.size < this.blockSize) {
+ const top = this.heap.pop();
+ const key = top.key;
+ const v = top.node;
+ const cur = this.best.get(v);
+ if (cur !== undefined && cur === key) {
+ Si.add(v);
+ this.best.delete(v);
+ }
+ }
+ return [Bi, Si];
+ }
+}
+/* ----------------------------
+ findPivots (bounded BF-like)
+ ---------------------------- */
+function findPivots(graph, dist, S, B, n, k_steps, p_limit, instr) {
+ instr = instr ?? new Instrument();
+ const S_filtered = [];
+ for (const v of S) {
+ const dv = dist.get(v) ?? INF;
+ if (dv < B)
+ S_filtered.push(v);
+ }
+ let P;
+ if (S_filtered.length === 0) {
+ // fallback: choose up to p_limit arbitrary from S
+ P = new Set();
+ if (S.size) {
+ let count = 0;
+ for (const v of S) {
+ P.add(v);
+ if (++count >= Math.max(1, Math.min(S.size, p_limit)))
+ break;
+ }
+ }
+ }
+ else {
+ S_filtered.sort((a, b) => (dist.get(a) ?? INF) - (dist.get(b) ?? INF));
+ const take = Math.max(1, Math.min(S_filtered.length, p_limit));
+ P = new Set(S_filtered.slice(0, take));
+ }
+ const source_frontier = P.size ? new Set(P) : new Set(S);
+ const discovered = new Set(source_frontier);
+ let frontier = new Set(source_frontier);
+ for (let step = 0; step < Math.max(1, k_steps); step++) {
+ if (!frontier.size)
+ break;
+ const nextFront = new Set();
+ for (const u of frontier) {
+ const du = dist.get(u) ?? INF;
+ if (du >= B)
+ continue;
+ for (const [v, w] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const nd = du + w;
+ if (nd < B && !discovered.has(v)) {
+ discovered.add(v);
+ nextFront.add(v);
+ }
+ }
+ }
+ frontier = nextFront;
+ }
+ const W = new Set(discovered);
+ if (!P.size && S.size)
+ P.add(S.values().next().value ?? 0);
+ return [P, W];
+}
+/* ----------------------------
+ basecase (Dijkstra-like limited)
+ ---------------------------- */
+function basecase(graph, dist, B, S, k, instr) {
+ instr = instr ?? new Instrument();
+ if (!S.size)
+ return [B, new Set()];
+ // choose x with smallest dist
+ let x = null;
+ let bestd = INF;
+ for (const v of S) {
+ const dv = dist.get(v) ?? INF;
+ if (dv < bestd) {
+ bestd = dv;
+ x = v;
+ }
+ }
+ if (x === null)
+ return [B, new Set()];
+ const heap = new MinHeap();
+ const start_d = dist.get(x) ?? INF;
+ heap.push(start_d, x);
+ instr.heapOps++;
+ const Uo = new Set();
+ while (!heap.isEmpty() && Uo.size < (k + 1)) {
+ const top = heap.pop();
+ instr.heapOps++;
+ const d_u = top.key;
+ const u = top.node;
+ const cur = dist.get(u) ?? INF;
+ if (d_u > cur)
+ continue;
+ if (!Uo.has(u))
+ Uo.add(u);
+ for (const [v, w] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const newd = (dist.get(u) ?? INF) + w;
+ const dv = dist.get(v) ?? INF;
+ if (newd < dv && newd < B) {
+ dist.set(v, newd);
+ heap.push(newd, v);
+ instr.heapOps++;
+ }
+ }
+ }
+ if (Uo.size <= k)
+ return [B, Uo];
+ const finiteDists = [];
+ for (const v of Uo) {
+ const dv = dist.get(v) ?? INF;
+ if (Number.isFinite(dv))
+ finiteDists.push(dv);
+ }
+ if (!finiteDists.length)
+ return [B, new Set()];
+ const maxd = Math.max(...finiteDists);
+ const Ufiltered = new Set(Array.from(Uo).filter(v => (dist.get(v) ?? INF) < maxd));
+ return [maxd, Ufiltered];
+}
+/* ----------------------------
+ bmssp (recursive)
+ ---------------------------- */
+function bmssp(graph, dist, edges, l, B, S, n, instr) {
+ instr = instr ?? new Instrument();
+ // parameter heuristics
+ let t_param, k_param;
+ if (n <= 2) {
+ t_param = 1;
+ k_param = 2;
+ }
+ else {
+ const ln = Math.log(Math.max(3, n));
+ t_param = Math.max(1, Math.round(Math.pow(ln, 2.0 / 3.0)));
+ k_param = Math.max(2, Math.round(Math.pow(ln, 1.0 / 3.0)));
+ }
+ if (l <= 0) {
+ if (!S.size)
+ return [B, new Set()];
+ return basecase(graph, dist, B, S, k_param, instr);
+ }
+ const p_limit = Math.max(1, 1 << Math.min(10, t_param));
+ const k_steps = Math.max(1, k_param);
+ const [P, W] = findPivots(graph, dist, S, B, n, k_steps, p_limit, instr);
+ const M = 1 << Math.max(0, (l - 1) * t_param);
+ const D = new DataStructureD(M, B, Math.max(1, Math.min(P.size || 1, 64)));
+ for (const x of P) {
+ D.insert(x, dist.get(x) ?? INF);
+ }
+ const B_prime_initial = (P.size ? Math.min(...Array.from(P).map(x => dist.get(x) ?? INF)) : B);
+ const U = new Set();
+ const B_prime_sub_values = [];
+ let loop_guard = 0;
+ const limit = k_param * (1 << (l * Math.max(1, t_param)));
+ while (U.size < limit && !D.empty()) {
+ loop_guard++;
+ if (loop_guard > 20000)
+ break;
+ let Bi, Si;
+ try {
+ [Bi, Si] = D.pull();
+ }
+ catch (e) {
+ break;
+ }
+ const [B_prime_sub, Ui] = bmssp(graph, dist, edges, l - 1, Bi, Si, n, instr);
+ B_prime_sub_values.push(B_prime_sub);
+ for (const u of Ui)
+ U.add(u);
+ // K_for_batch as Set of tuples -> represent as Map to avoid duplicates
+ const K_for_batchArr = [];
+ for (const u of Ui) {
+ const du = dist.get(u) ?? INF;
+ if (!Number.isFinite(du))
+ continue;
+ for (const [v, w_uv] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const newd = du + w_uv;
+ const dv = dist.get(v) ?? INF;
+ if (newd <= dv) {
+ dist.set(v, newd);
+ if (Bi <= newd && newd < B) {
+ D.insert(v, newd);
+ }
+ else if (B_prime_sub <= newd && newd < Bi) {
+ K_for_batchArr.push([v, newd]);
+ }
+ }
+ }
+ }
+ for (const x of Si) {
+ const dx = dist.get(x) ?? INF;
+ if (B_prime_sub <= dx && dx < Bi)
+ K_for_batchArr.push([x, dx]);
+ }
+ if (K_for_batchArr.length)
+ D.batchPrepend(K_for_batchArr);
+ }
+ const B_prime_final = (B_prime_sub_values.length ? Math.min(B_prime_initial, ...B_prime_sub_values) : B_prime_initial);
+ const U_final = new Set(U);
+ for (const x of W) {
+ if ((dist.get(x) ?? INF) < B_prime_final)
+ U_final.add(x);
+ }
+ return [B_prime_final, U_final];
+}
+/* ----------------------------
+ Test harness (runSingleTest)
+ ---------------------------- */
+function runSingleTest(n, m, seed = 0, source = 0) {
+ console.log(`Generating graph: n=${n}, m=${m}, seed=${seed}`);
+ const [graph, edges] = generateSparseDirectedGraph(n, m, 100.0, seed);
+ const avgDeg = Array.from(graph.values()).reduce((s, arr) => s + arr.length, 0) / n;
+ console.log(`Graph generated. avg out-degree ≈ ${avgDeg.toFixed(3)}`);
+ // Dijkstra
+ const instr_dij = new Instrument();
+ const t0 = Date.now();
+ const dist_dij = dijkstra(graph, source, instr_dij);
+ const t1 = Date.now();
+ console.log(`Dijkstra: time=${((t1 - t0) / 1000).toFixed(6)}s, relaxations=${instr_dij.relaxations}, heap_ops=${instr_dij.heapOps}, reachable=${Array.from(dist_dij.values()).filter(v => Number.isFinite(v)).length}`);
+ // BMSSP
+ const dist_bm = new Map();
+ for (const k of graph.keys())
+ dist_bm.set(k, INF);
+ dist_bm.set(source, 0);
+ const instr_bm = new Instrument();
+ let l;
+ if (n <= 2)
+ l = 1;
+ else {
+ const t_guess = Math.max(1, Math.round(Math.pow(Math.log(Math.max(3, n)), 2.0 / 3.0)));
+ l = Math.max(1, Math.max(1, Math.round(Math.log(Math.max(3, n)) / t_guess)));
+ }
+ console.log(`BMSSP params: top-level l=${l}`);
+ const t2 = Date.now();
+ const [Bp, U_final] = bmssp(graph, dist_bm, edges, l, INF, new Set([source]), n, instr_bm);
+ const t3 = Date.now();
+ console.log(`BMSSP: time=${((t3 - t2) / 1000).toFixed(6)}s, relaxations=${instr_bm.relaxations}, reachable=${Array.from(dist_bm.values()).filter(v => Number.isFinite(v)).length}, B'=${Bp}, |U_final|=${U_final.size}`);
+ const diffs = [];
+ for (const v of graph.keys()) {
+ const dv = dist_dij.get(v) ?? INF;
+ const db = dist_bm.get(v) ?? INF;
+ if (Number.isFinite(dv) && Number.isFinite(db))
+ diffs.push(Math.abs(dv - db));
+ }
+ const maxDiff = diffs.length ? Math.max(...diffs) : 0;
+ console.log(`Distance agreement (max abs diff on commonly reachable nodes): ${maxDiff.toExponential(6)}`);
+ return {
+ n, m, seed,
+ dijkstra_time: (t1 - t0) / 1000,
+ dijkstra_relax: instr_dij.relaxations,
+ bmssp_time: (t3 - t2) / 1000,
+ bmssp_relax: instr_bm.relaxations,
+ dijkstra_reachable: Array.from(dist_dij.values()).filter(v => Number.isFinite(v)).length,
+ bmssp_reachable: Array.from(dist_bm.values()).filter(v => Number.isFinite(v)).length,
+ max_diff: maxDiff
+ };
+}
+/* ----------------------------
+ CLI parsing
+ ---------------------------- */
+function parseArgs(argv) {
+ let n = 200000, m = 800000, seed = 0;
+ for (let i = 2; i < argv.length; i++) {
+ const a = argv[i];
+ if ((a === '-n' || a === '--nodes') && i + 1 < argv.length) {
+ n = parseInt(argv[++i] ?? '', 10);
+ }
+ else if ((a === '-m' || a === '--edges') && i + 1 < argv.length) {
+ m = parseInt(argv[++i] ?? '', 10);
+ }
+ else if ((a === '-s' || a === '--seed') && i + 1 < argv.length) {
+ seed = parseInt(argv[++i] ?? '', 10);
+ }
+ }
+ return { n, m, seed };
+}
+const { n, m, seed } = parseArgs(process.argv);
+// For quicker local test, you may want to reduce defaults:
+// const testDefaults = { n: 2000, m: 8000, seed: 42 };
+runSingleTest(n, m, seed, 0);
+export {};
+//# sourceMappingURL=app.js.map
\ No newline at end of file
diff --git a/POCNodeTypescript/app.js.map b/POCNodeTypescript/app.js.map
new file mode 100644
index 0000000..12e4d9e
--- /dev/null
+++ b/POCNodeTypescript/app.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"app.js","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/POCNodeTypescript/app.ts b/POCNodeTypescript/app.ts
new file mode 100644
index 0000000..41c6e73
--- /dev/null
+++ b/POCNodeTypescript/app.ts
@@ -0,0 +1,539 @@
+#!/usr/bin/env ts-node
+/**
+ * app.ts
+ *
+ * Full TypeScript port of the Python BMSSP practical implementation.
+ * - Graph generator
+ * - Instrumentation
+ * - Dijkstra
+ * - DataStructureD (heap + map, lazy deletion)
+ * - findPivots (bounded BF-like)
+ * - basecase (Dijkstra-like limited)
+ * - Recursive bmssp
+ * - Test harness + minimal CLI
+ *
+ * Usage:
+ * ts-node bmssp.ts -n 2000 -m 8000 -s 42
+ *
+ * Note: For big graphs, increase node memory/stack or use Node with --stack-size if needed.
+ */
+
+type NodeId = number;
+type Weight = number;
+type Edge = [NodeId, NodeId, Weight];
+type Graph = Map>;
+
+const INF = Number.POSITIVE_INFINITY;
+
+/* ----------------------------
+ Simple min-heap for (key,node) pairs
+ ---------------------------- */
+class MinHeap {
+ private data: Array<{ key: number; node: number }> = [];
+
+ size(): number {
+ return this.data.length;
+ }
+ isEmpty(): boolean {
+ return this.data.length === 0;
+ }
+ peek(): { key: number; node: number } | null {
+ return this.data.length ? this.data[0] ?? null : null;
+ }
+ push(key: number, node: number) {
+ this.data.push({ key, node });
+ this.siftUp(this.data.length - 1);
+ }
+ pop(): { key: number; node: number } | null {
+ if (!this.data.length) return null;
+ const top = this.data[0];
+ const last = this.data.pop()!;
+ if (this.data.length) {
+ this.data[0] = last;
+ this.siftDown(0);
+ }
+ return top ?? null;
+ }
+ private siftUp(i: number) {
+ while (i > 0) {
+ const p = (i - 1) >> 1;
+ if (this.data[i]?.key ?? 0 < (this.data[p] ? this.data[p].key : 0)) {
+ const temp = this.data[i]!;
+ this.data[i] = this.data[p]!;
+ this.data[p] = temp;
+ i = p;
+ } else break;
+ }
+ }
+ private siftDown(i: number) {
+ const n = this.data.length;
+ while (true) {
+ const l = i * 2 + 1;
+ const r = l + 1;
+ let smallest = i;
+ if (l < n && (this.data[l]?.key ?? 0) < (this.data[smallest]?.key ?? 0)) smallest = l;
+ if (r < n && (this.data[r]?.key ?? 0) < (this.data[smallest]?.key ?? 0)) smallest = r;
+ if (smallest === i) break;
+ const temp = this.data[i]!;
+ this.data[i] = this.data[smallest]!;
+ this.data[smallest] = temp;
+ i = smallest;
+ }
+ }
+}
+
+/* ----------------------------
+ RNG (seedable) - mulberry32
+ ---------------------------- */
+function mulberry32(seed: number) {
+ let t = seed >>> 0;
+ return function () {
+ t += 0x6D2B79F5;
+ let r = Math.imul(t ^ (t >>> 15), t | 1);
+ r ^= r + Math.imul(r ^ (r >>> 7), r | 61);
+ return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
+ };
+}
+
+/* ----------------------------
+ Graph generator
+ ---------------------------- */
+function generateSparseDirectedGraph(n: number, m: number, maxW = 100.0, seed?: number): [Graph, Edge[]] {
+ const rand = seed !== undefined ? mulberry32(seed) : Math.random;
+ const graph: Graph = new Map();
+ for (let i = 0; i < n; i++) graph.set(i, []);
+ const edges: Edge[] = [];
+
+ // backbone to avoid isolated nodes
+ for (let i = 1; i < n; i++) {
+ const u = Math.floor(rand() * i);
+ const w = rand() * (maxW - 1.0) + 1.0;
+ graph.get(u)!.push([i, w]);
+ edges.push([u, i, w]);
+ }
+
+ const remaining = Math.max(0, m - (n - 1));
+ for (let i = 0; i < remaining; i++) {
+ const u = Math.floor(rand() * n);
+ const v = Math.floor(rand() * n);
+ const w = rand() * (maxW - 1.0) + 1.0;
+ graph.get(u)!.push([v, w]);
+ edges.push([u, v, w]);
+ }
+ return [graph, edges];
+}
+
+/* ----------------------------
+ Instrumentation
+ ---------------------------- */
+class Instrument {
+ relaxations = 0;
+ heapOps = 0;
+ reset() {
+ this.relaxations = 0;
+ this.heapOps = 0;
+ }
+}
+
+/* ----------------------------
+ Dijkstra (standard)
+ ---------------------------- */
+function dijkstra(graph: Graph, source: NodeId, instr?: Instrument): Map {
+ instr = instr ?? new Instrument();
+ const dist: Map = new Map();
+ for (const k of graph.keys()) dist.set(k, INF);
+ dist.set(source, 0);
+
+ const heap = new MinHeap();
+ heap.push(0, source);
+ instr.heapOps++;
+
+ while (!heap.isEmpty()) {
+ const top = heap.pop()!;
+ const d_u = top.key;
+ const u = top.node;
+ instr.heapOps++;
+ const cur = dist.get(u) ?? INF;
+ if (d_u > cur) continue;
+
+ for (const [v, w] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const alt = d_u + w;
+ const dv = dist.get(v) ?? INF;
+ if (alt < dv) {
+ dist.set(v, alt);
+ heap.push(alt, v);
+ instr.heapOps++;
+ }
+ }
+ }
+ return dist;
+}
+
+/* ----------------------------
+ DataStructureD (heap + map)
+ ---------------------------- */
+class DataStructureD {
+ private heap = new MinHeap();
+ private best: Map = new Map();
+ private M: number;
+ private BUpper: number;
+ private blockSize: number;
+
+ constructor(M: number, BUpper: number, blockSize?: number) {
+ this.M = Math.max(1, M);
+ this.BUpper = BUpper;
+ this.blockSize = blockSize ?? Math.max(1, Math.floor(this.M / 8));
+ }
+
+ insert(v: NodeId, key: number) {
+ const prev = this.best.get(v);
+ if (prev === undefined || key < prev) {
+ this.best.set(v, key);
+ this.heap.push(key, v);
+ }
+ }
+
+ batchPrepend(iterablePairs: Iterable<[NodeId, number]>) {
+ for (const [v, key] of iterablePairs) this.insert(v, key);
+ }
+
+ private cleanup() {
+ while (!this.heap.isEmpty()) {
+ const top = this.heap.peek()!;
+ const node = top.node;
+ const key = top.key;
+ const cur = this.best.get(node);
+ if (cur === undefined || cur !== key) {
+ this.heap.pop(); // stale
+ } else break;
+ }
+ }
+
+ empty(): boolean {
+ this.cleanup();
+ return this.heap.isEmpty();
+ }
+
+ pull(): [number, Set] {
+ this.cleanup();
+ if (this.heap.isEmpty()) throw new Error("pull from empty D");
+ const Bi = this.heap.peek()!.key;
+ const Si = new Set();
+ while (!this.heap.isEmpty() && Si.size < this.blockSize) {
+ const top = this.heap.pop()!;
+ const key = top.key;
+ const v = top.node;
+ const cur = this.best.get(v);
+ if (cur !== undefined && cur === key) {
+ Si.add(v);
+ this.best.delete(v);
+ }
+ }
+ return [Bi, Si];
+ }
+}
+
+/* ----------------------------
+ findPivots (bounded BF-like)
+ ---------------------------- */
+function findPivots(
+ graph: Graph,
+ dist: Map,
+ S: Set,
+ B: number,
+ n: number,
+ k_steps: number,
+ p_limit: number,
+ instr?: Instrument
+): [Set, Set] {
+ instr = instr ?? new Instrument();
+
+ const S_filtered: NodeId[] = [];
+ for (const v of S) {
+ const dv = dist.get(v) ?? INF;
+ if (dv < B) S_filtered.push(v);
+ }
+
+ let P: Set;
+ if (S_filtered.length === 0) {
+ // fallback: choose up to p_limit arbitrary from S
+ P = new Set();
+ if (S.size) {
+ let count = 0;
+ for (const v of S) {
+ P.add(v);
+ if (++count >= Math.max(1, Math.min(S.size, p_limit))) break;
+ }
+ }
+ } else {
+ S_filtered.sort((a, b) => (dist.get(a) ?? INF) - (dist.get(b) ?? INF));
+ const take = Math.max(1, Math.min(S_filtered.length, p_limit));
+ P = new Set(S_filtered.slice(0, take));
+ }
+
+ const source_frontier = P.size ? new Set(P) : new Set(S);
+ const discovered = new Set(source_frontier);
+ let frontier = new Set(source_frontier);
+
+ for (let step = 0; step < Math.max(1, k_steps); step++) {
+ if (!frontier.size) break;
+ const nextFront = new Set();
+ for (const u of frontier) {
+ const du = dist.get(u) ?? INF;
+ if (du >= B) continue;
+ for (const [v, w] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const nd = du + w;
+ if (nd < B && !discovered.has(v)) {
+ discovered.add(v);
+ nextFront.add(v);
+ }
+ }
+ }
+ frontier = nextFront;
+ }
+
+ const W = new Set(discovered);
+ if (!P.size && S.size) P.add(S.values().next().value ?? 0);
+ return [P, W];
+}
+
+/* ----------------------------
+ basecase (Dijkstra-like limited)
+ ---------------------------- */
+function basecase(
+ graph: Graph,
+ dist: Map,
+ B: number,
+ S: Set,
+ k: number,
+ instr?: Instrument
+): [number, Set] {
+ instr = instr ?? new Instrument();
+ if (!S.size) return [B, new Set()];
+
+ // choose x with smallest dist
+ let x: NodeId | null = null;
+ let bestd = INF;
+ for (const v of S) {
+ const dv = dist.get(v) ?? INF;
+ if (dv < bestd) { bestd = dv; x = v; }
+ }
+ if (x === null) return [B, new Set()];
+
+ const heap = new MinHeap();
+ const start_d = dist.get(x) ?? INF;
+ heap.push(start_d, x);
+ instr.heapOps++;
+
+ const Uo = new Set();
+
+ while (!heap.isEmpty() && Uo.size < (k + 1)) {
+ const top = heap.pop()!;
+ instr.heapOps++;
+ const d_u = top.key;
+ const u = top.node;
+ const cur = dist.get(u) ?? INF;
+ if (d_u > cur) continue;
+ if (!Uo.has(u)) Uo.add(u);
+
+ for (const [v, w] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const newd = (dist.get(u) ?? INF) + w;
+ const dv = dist.get(v) ?? INF;
+ if (newd < dv && newd < B) {
+ dist.set(v, newd);
+ heap.push(newd, v);
+ instr.heapOps++;
+ }
+ }
+ }
+
+ if (Uo.size <= k) return [B, Uo];
+
+ const finiteDists: number[] = [];
+ for (const v of Uo) {
+ const dv = dist.get(v) ?? INF;
+ if (Number.isFinite(dv)) finiteDists.push(dv);
+ }
+ if (!finiteDists.length) return [B, new Set()];
+ const maxd = Math.max(...finiteDists);
+ const Ufiltered = new Set(Array.from(Uo).filter(v => (dist.get(v) ?? INF) < maxd));
+ return [maxd, Ufiltered];
+}
+
+/* ----------------------------
+ bmssp (recursive)
+ ---------------------------- */
+function bmssp(
+ graph: Graph,
+ dist: Map,
+ edges: Edge[],
+ l: number,
+ B: number,
+ S: Set,
+ n: number,
+ instr?: Instrument
+): [number, Set] {
+ instr = instr ?? new Instrument();
+
+ // parameter heuristics
+ let t_param: number, k_param: number;
+ if (n <= 2) { t_param = 1; k_param = 2; }
+ else {
+ const ln = Math.log(Math.max(3, n));
+ t_param = Math.max(1, Math.round(Math.pow(ln, 2.0 / 3.0)));
+ k_param = Math.max(2, Math.round(Math.pow(ln, 1.0 / 3.0)));
+ }
+
+ if (l <= 0) {
+ if (!S.size) return [B, new Set()];
+ return basecase(graph, dist, B, S, k_param, instr);
+ }
+
+ const p_limit = Math.max(1, 1 << Math.min(10, t_param));
+ const k_steps = Math.max(1, k_param);
+
+ const [P, W] = findPivots(graph, dist, S, B, n, k_steps, p_limit, instr);
+
+ const M = 1 << Math.max(0, (l - 1) * t_param);
+ const D = new DataStructureD(M, B, Math.max(1, Math.min(P.size || 1, 64)));
+
+ for (const x of P) {
+ D.insert(x, dist.get(x) ?? INF);
+ }
+
+ const B_prime_initial = (P.size ? Math.min(...Array.from(P).map(x => dist.get(x) ?? INF)) : B);
+
+ const U = new Set();
+ const B_prime_sub_values: number[] = [];
+
+ let loop_guard = 0;
+ const limit = k_param * (1 << (l * Math.max(1, t_param)));
+
+ while (U.size < limit && !D.empty()) {
+ loop_guard++;
+ if (loop_guard > 20000) break;
+
+ let Bi: number, Si: Set;
+ try {
+ [Bi, Si] = D.pull();
+ } catch (e) {
+ break;
+ }
+
+ const [B_prime_sub, Ui] = bmssp(graph, dist, edges, l - 1, Bi, Si, n, instr);
+ B_prime_sub_values.push(B_prime_sub);
+ for (const u of Ui) U.add(u);
+
+ // K_for_batch as Set of tuples -> represent as Map to avoid duplicates
+ const K_for_batchArr: Array<[NodeId, number]> = [];
+
+ for (const u of Ui) {
+ const du = dist.get(u) ?? INF;
+ if (!Number.isFinite(du)) continue;
+ for (const [v, w_uv] of graph.get(u) ?? []) {
+ instr.relaxations++;
+ const newd = du + w_uv;
+ const dv = dist.get(v) ?? INF;
+ if (newd <= dv) {
+ dist.set(v, newd);
+ if (Bi <= newd && newd < B) {
+ D.insert(v, newd);
+ } else if (B_prime_sub <= newd && newd < Bi) {
+ K_for_batchArr.push([v, newd]);
+ }
+ }
+ }
+ }
+
+ for (const x of Si) {
+ const dx = dist.get(x) ?? INF;
+ if (B_prime_sub <= dx && dx < Bi) K_for_batchArr.push([x, dx]);
+ }
+
+ if (K_for_batchArr.length) D.batchPrepend(K_for_batchArr);
+ }
+
+ const B_prime_final = (B_prime_sub_values.length ? Math.min(B_prime_initial, ...B_prime_sub_values) : B_prime_initial);
+
+ const U_final = new Set(U);
+ for (const x of W) {
+ if ((dist.get(x) ?? INF) < B_prime_final) U_final.add(x);
+ }
+ return [B_prime_final, U_final];
+}
+
+/* ----------------------------
+ Test harness (runSingleTest)
+ ---------------------------- */
+function runSingleTest(n: number, m: number, seed = 0, source = 0) {
+ console.log(`Generating graph: n=${n}, m=${m}, seed=${seed}`);
+ const [graph, edges] = generateSparseDirectedGraph(n, m, 100.0, seed);
+ const avgDeg = Array.from(graph.values()).reduce((s, arr) => s + arr.length, 0) / n;
+ console.log(`Graph generated. avg out-degree ≈ ${avgDeg.toFixed(3)}`);
+
+ // Dijkstra
+ const instr_dij = new Instrument();
+ const t0 = Date.now();
+ const dist_dij = dijkstra(graph, source, instr_dij);
+ const t1 = Date.now();
+ console.log(`Dijkstra: time=${((t1 - t0) / 1000).toFixed(6)}s, relaxations=${instr_dij.relaxations}, heap_ops=${instr_dij.heapOps}, reachable=${Array.from(dist_dij.values()).filter(v => Number.isFinite(v)).length}`);
+
+ // BMSSP
+ const dist_bm: Map = new Map();
+ for (const k of graph.keys()) dist_bm.set(k, INF);
+ dist_bm.set(source, 0);
+ const instr_bm = new Instrument();
+ let l: number;
+ if (n <= 2) l = 1;
+ else {
+ const t_guess = Math.max(1, Math.round(Math.pow(Math.log(Math.max(3, n)), 2.0 / 3.0)));
+ l = Math.max(1, Math.max(1, Math.round(Math.log(Math.max(3, n)) / t_guess)));
+ }
+ console.log(`BMSSP params: top-level l=${l}`);
+
+ const t2 = Date.now();
+ const [Bp, U_final] = bmssp(graph, dist_bm, edges, l, INF, new Set([source]), n, instr_bm);
+ const t3 = Date.now();
+ console.log(`BMSSP: time=${((t3 - t2) / 1000).toFixed(6)}s, relaxations=${instr_bm.relaxations}, reachable=${Array.from(dist_bm.values()).filter(v => Number.isFinite(v)).length}, B'=${Bp}, |U_final|=${U_final.size}`);
+
+ const diffs: number[] = [];
+ for (const v of graph.keys()) {
+ const dv = dist_dij.get(v) ?? INF;
+ const db = dist_bm.get(v) ?? INF;
+ if (Number.isFinite(dv) && Number.isFinite(db)) diffs.push(Math.abs(dv - db));
+ }
+ const maxDiff = diffs.length ? Math.max(...diffs) : 0;
+ console.log(`Distance agreement (max abs diff on commonly reachable nodes): ${maxDiff.toExponential(6)}`);
+ return {
+ n, m, seed,
+ dijkstra_time: (t1 - t0) / 1000,
+ dijkstra_relax: instr_dij.relaxations,
+ bmssp_time: (t3 - t2) / 1000,
+ bmssp_relax: instr_bm.relaxations,
+ dijkstra_reachable: Array.from(dist_dij.values()).filter(v => Number.isFinite(v)).length,
+ bmssp_reachable: Array.from(dist_bm.values()).filter(v => Number.isFinite(v)).length,
+ max_diff: maxDiff
+ };
+}
+
+/* ----------------------------
+ CLI parsing
+ ---------------------------- */
+function parseArgs(argv: string[]) {
+ let n = 200000, m = 800000, seed = 0;
+ for (let i = 2; i < argv.length; i++) {
+ const a = argv[i];
+ if ((a === '-n' || a === '--nodes') && i + 1 < argv.length) { n = parseInt(argv[++i] ?? '', 10); }
+ else if ((a === '-m' || a === '--edges') && i + 1 < argv.length) { m = parseInt(argv[++i] ?? '', 10); }
+ else if ((a === '-s' || a === '--seed') && i + 1 < argv.length) { seed = parseInt(argv[++i] ?? '', 10); }
+ }
+ return { n, m, seed };
+}
+
+const { n, m, seed } = parseArgs(process.argv);
+// For quicker local test, you may want to reduce defaults:
+// const testDefaults = { n: 2000, m: 8000, seed: 42 };
+runSingleTest(n, m, seed, 0);
diff --git a/POCNodeTypescript/eslint.config.js b/POCNodeTypescript/eslint.config.js
new file mode 100644
index 0000000..c91642f
--- /dev/null
+++ b/POCNodeTypescript/eslint.config.js
@@ -0,0 +1,7 @@
+module.exports = [
+ {
+ rules: {
+ // Add rules here.
+ }
+ }
+];
\ No newline at end of file
diff --git a/POCNodeTypescript/package-lock.json b/POCNodeTypescript/package-lock.json
new file mode 100644
index 0000000..4c5dc71
--- /dev/null
+++ b/POCNodeTypescript/package-lock.json
@@ -0,0 +1,1124 @@
+{
+ "name": "pocnodetypescript",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "pocnodetypescript",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "@datastructures-js/priority-queue": "^6.3.4"
+ },
+ "devDependencies": {
+ "@types/node": "^24.3.1",
+ "eslint": "^9.35.0",
+ "typescript": "^5.9.2"
+ }
+ },
+ "node_modules/@datastructures-js/heap": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/@datastructures-js/heap/-/heap-4.3.5.tgz",
+ "integrity": "sha512-zgO8KO26WnZdCxe72Ck+55mhUYmw/1CL/TueKSIIU6aqoOcXAqeaL2kRldJcXtCdJ43rqgIKYdEkiL07sQ+2VQ==",
+ "license": "MIT"
+ },
+ "node_modules/@datastructures-js/priority-queue": {
+ "version": "6.3.4",
+ "resolved": "https://registry.npmjs.org/@datastructures-js/priority-queue/-/priority-queue-6.3.4.tgz",
+ "integrity": "sha512-m8Jt1OkwyHsKRz6L1FWerz3Hw8iU5vqCdBI6khC8YNssF1kXKX6cs8Xc9Zt9ocPCxO/vZhAu/KnQ+uQ4Btw6AA==",
+ "license": "MIT",
+ "dependencies": {
+ "@datastructures-js/heap": "^4.3.3"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
+ "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.6",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
+ "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
+ "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.35.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz",
+ "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
+ "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.15.2",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "24.3.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz",
+ "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.10.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.35.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz",
+ "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.0",
+ "@eslint/config-helpers": "^0.3.1",
+ "@eslint/core": "^0.15.2",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.35.0",
+ "@eslint/plugin-kit": "^0.3.5",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
+ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.10.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
+ "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/POCNodeTypescript/package.json b/POCNodeTypescript/package.json
new file mode 100644
index 0000000..916b040
--- /dev/null
+++ b/POCNodeTypescript/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "pocnodetypescript",
+ "version": "1.0.0",
+ "main": "app.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "tsc --build",
+ "clean": "tsc --build --clean"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "description": "",
+ "devDependencies": {
+ "@types/node": "^24.3.1",
+ "eslint": "^9.35.0",
+ "typescript": "^5.9.2"
+ },
+ "dependencies": {
+ "@datastructures-js/priority-queue": "^6.3.4"
+ },
+ "type": "module"
+}
diff --git a/POCNodeTypescript/tsconfig.json b/POCNodeTypescript/tsconfig.json
new file mode 100644
index 0000000..9b4737f
--- /dev/null
+++ b/POCNodeTypescript/tsconfig.json
@@ -0,0 +1,36 @@
+{
+ // Visit https://aka.ms/tsconfig to read more about this file
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "exactOptionalPropertyTypes": true,
+ "isolatedModules": true,
+ // For nodejs:
+ "lib": [ "esnext" ],
+ // File Layout
+ // "rootDir": "./src",
+ // "outDir": "./dist",
+ // Environment Settings
+ // See also https://aka.ms/tsconfig/module
+ "module": "nodenext",
+ "moduleDetection": "force",
+ // Stricter Typechecking Options
+ "noUncheckedIndexedAccess": true,
+ "noUncheckedSideEffectImports": true,
+ "skipLibCheck": true,
+ // Other Outputs
+ "sourceMap": true,
+ // Style Options
+ // "noImplicitReturns": true,
+ // "noImplicitOverride": true,
+ // "noUnusedLocals": true,
+ // "noUnusedParameters": true,
+ // "noFallthroughCasesInSwitch": true,
+ // "noPropertyAccessFromIndexSignature": true,
+ // Recommended Options
+ "strict": true,
+ "target": "esnext",
+ "types": [ "node" ],
+ "verbatimModuleSyntax": true
+ }
+}
diff --git a/POCNodeTypescript/tsconfig.tsbuildinfo b/POCNodeTypescript/tsconfig.tsbuildinfo
new file mode 100644
index 0000000..81c6866
--- /dev/null
+++ b/POCNodeTypescript/tsconfig.tsbuildinfo
@@ -0,0 +1 @@
+{"root":["./app.ts"],"version":"5.9.2"}
\ No newline at end of file
diff --git a/README.md b/README.md
index 5fea3c4..96e93da 100644
--- a/README.md
+++ b/README.md
@@ -30,3 +30,42 @@ Distance agreement (max abs diff on commonly reachable nodes): 8.540939e+01
[alphaxiv](https://papers-pdfs.assets.alphaxiv.org/2504.17033v2.pdf)
+
+# POC Dotnet Project
+
+## Overview
+This project demonstrates a .NET-based implementation of a graph processing application. It includes a CLI interface for configuring the number of nodes, edges, and a random seed for generating graph data.
+
+## Features
+- Command-line interface for input configuration.
+- Efficient graph processing using .NET 9 features.
+- Supports large-scale graph data with customizable parameters.
+
+## Requirements
+- .NET 9 SDK
+- C# 13.0
+
+## Usage
+
+### Build the Project
+1. Clone the repository.
+2. Open the project in Visual Studio.
+3. Build the solution.
+
+### Run the Application
+Use the following command to run the application:
+### Example
+### Parameters
+- `-n` or `--nodes`: Number of nodes in the graph (default: 200,000).
+- `-m` or `--edges`: Number of edges in the graph (default: 800,000).
+- `-s` or `--seed`: Random seed for graph generation (default: 0).
+
+### C# Output => running faster than python
+```shell
+Generating graph: n=200000, m=800000, seed=0
+Graph generated. avg out-degree ≈ 4.000
+Dijkstra: time=0.356301s, relaxations=800000, heap_ops=533202, reachable=200000
+BMSSP params: top-level l=2
+BMSSP: time=0.054503s, relaxations=26910, reachable=8788, B'=0, |U_final|=2048
+Distance agreement (max abs diff on commonly reachable nodes): 8.073533E+001
+```