npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

atsds

v0.0.9

Published

A deductive system

Readme

DS - A Deductive System

A deductive system for logical inference, implemented in C++. The library provides bindings for Python (via pybind11) and TypeScript/JavaScript (via Emscripten/WebAssembly).

Architecture

  • C++ Core: The core implementation in src/ and include/ds/ provides the fundamental data structures and algorithms
  • Python Bindings: Built with pybind11, wrapping the C++ core (see apyds/)
  • TypeScript/JavaScript Bindings: Built with Emscripten, compiling C++ to WebAssembly (see atsds/)

Features

  • Multi-Language Support: Use the same deductive system in C++, Python, or TypeScript/JavaScript
  • Logical Terms: Work with variables, items (constants/functors), and lists
  • Rule-Based Inference: Define rules and facts, perform logical deduction
  • Unification and Matching: Unify terms and match rules
  • Search Engine: Built-in search mechanism for iterative inference
  • WebAssembly: Run inference in the browser or Node.js environments
  • Type-Safe: Strong typing support in TypeScript and Python

Installation

TypeScript/JavaScript (npm)

The TypeScript/JavaScript package wraps the C++ core via WebAssembly.

npm install atsds

The package includes WebAssembly binaries and TypeScript type definitions.

Python (pip)

The Python package wraps the C++ core via pybind11.

pip install apyds

Requires Python 3.10-3.14.

C++ (Core Library)

The C++ library is the core implementation. Both Python and TypeScript bindings are built on top of it.

Using vcpkg

Clone the repository and use the overlay port:

git clone https://github.com/USTC-KnowledgeComputingLab/ds.git
vcpkg install ds --overlay-ports=./ds/ports

Add to your vcpkg.json:

{
  "dependencies": ["ds"]
}

In your CMakeLists.txt:

find_package(ds CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE ds::ds)

Building from Source

git clone https://github.com/USTC-KnowledgeComputingLab/ds.git
cd ds
cmake -B build
cmake --build build

Include the headers from include/ds/ in your C++ project.

Quick Start

TypeScript/JavaScript Example

import { Rule, Search } from "atsds";

// Create a search engine
const search = new Search(1000, 10000);

// Modus ponens: P -> Q, P |- Q
search.add("(`P -> `Q) `P `Q");
// Axiom schema 1: p -> (q -> p)
search.add("(`p -> (`q -> `p))");
// Axiom schema 2: (p -> (q -> r)) -> ((p -> q) -> (p -> r))
search.add("((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))");
// Axiom schema 3: (!p -> !q) -> (q -> p)
search.add("(((! `p) -> (! `q)) -> (`q -> `p))");

// Premise: !!X
search.add("(! (! X))");

// Target: X (double negation elimination)
const target = new Rule("X");

// Execute search until target is found
while (true) {
    let found = false;
    search.execute((candidate) => {
        if (candidate.key() === target.key()) {
            console.log("Found:", candidate.toString());
            found = true;
            return true; // Stop search
        }
        return false; // Continue searching
    });
    if (found) break;
}

Python Example

import apyds

# Create a search engine
search = apyds.Search(1000, 10000)

# Modus ponens: P -> Q, P |- Q
search.add("(`P -> `Q) `P `Q")
# Axiom schema 1: p -> (q -> p)
search.add("(`p -> (`q -> `p))")
# Axiom schema 2: (p -> (q -> r)) -> ((p -> q) -> (p -> r))
search.add("((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))")
# Axiom schema 3: (!p -> !q) -> (q -> p)
search.add("(((! `p) -> (! `q)) -> (`q -> `p))")

# Premise: !!X
search.add("(! (! X))")

# Target: X (double negation elimination)
target = apyds.Rule("X")

# Execute search until target is found
while True:
    found = False
    def callback(candidate):
        global found
        if candidate == target:
            print("Found:", candidate)
            found = True
            return True  # Stop search
        return False  # Continue searching
    search.execute(callback)
    if found:
        break

C++ Example

#include <cstdio>
#include <cstring>
#include <ds/ds.hh>
#include <ds/search.hh>
#include <ds/utility.hh>

int main() {
    ds::search_t search(1000, 10000);
    
    // Modus ponens: P -> Q, P |- Q
    search.add("(`P -> `Q) `P `Q");
    // Axiom schema 1: p -> (q -> p)
    search.add("(`p -> (`q -> `p))");
    // Axiom schema 2: (p -> (q -> r)) -> ((p -> q) -> (p -> r))
    search.add("((`p -> (`q -> `r)) -> ((`p -> `q) -> (`p -> `r)))");
    // Axiom schema 3: (!p -> !q) -> (q -> p)
    search.add("(((! `p) -> (! `q)) -> (`q -> `p))");
    
    // Premise: !!X
    search.add("(! (! X))");
    
    // Target: X (double negation elimination)
    auto target = ds::text_to_rule("X", 1000);
    
    // Execute search until target is found
    while (true) {
        bool found = false;
        search.execute([&](ds::rule_t* candidate) {
            if (candidate->data_size() == target->data_size() &&
                memcmp(candidate->head(), target->head(), candidate->data_size()) == 0) {
                printf("Found: %s", ds::rule_to_text(candidate, 1000).get());
                found = true;
                return true; // Stop search
            }
            return false; // Continue searching
        });
        if (found) break;
    }
    
    return 0;
}

Core Concepts

Terms

Terms are the basic building blocks of the deductive system:

  • Variables: Prefixed with backtick, e.g., `X, `P, `Q
  • Items: Constants or functors, e.g., a, father, !
  • Lists: Ordered sequences enclosed in parentheses, e.g., (a b c), (father john mary)

Rules

Rules consist of zero or more premises (above the line) and a conclusion (below the line):

premise1
premise2
----------
conclusion

A fact is a rule without premises:

----------
(parent john mary)

Grounding

Grounding substitutes variables with values using a dictionary:

const a = new Term("`a");
const dict = new Term("((`a b))"); // Substitute `a with b
const result = a.ground(dict);
console.log(result.toString()); // "b"

Matching

Matching unifies the first premise of a rule with a fact to produce a new rule. For example, applying modus ponens to double negation elimination:

// Modus ponens rule: (p -> q), p |- q
const mp = new Rule("(`p -> `q)\n`p\n`q\n");
// Double negation elimination axiom: !!x -> x
const pq = new Rule("((! (! `x)) -> `x)");
// Match produces: !!x |- x
console.log(mp.match(pq).toString()); // "(! (! `x))\n----------\n`x\n"

API Overview

TypeScript/JavaScript

  • buffer_size(size?: number): Get/set buffer size for internal operations
  • String_: String wrapper class
  • Variable: Logical variable class
  • Item: Item (constant/functor) class
  • List: List class
  • Term: General term class (variable, item, or list)
  • Rule: Logical rule class
  • Search: Search engine for inference

Python

  • buffer_size(size: int): Set buffer size
  • scoped_buffer_size(size: int): Context manager for temporary buffer size
  • String: String wrapper class
  • Variable: Logical variable class
  • Item: Item (constant/functor) class
  • List: List class
  • Term: General term class
  • Rule: Logical rule class
  • Search: Search engine for inference

C++ (Core)

All classes are in the ds namespace:

  • string_t: String handling
  • variable_t: Logical variables
  • item_t: Items (constants/functors)
  • list_t: Lists
  • term_t: General terms
  • rule_t: Logical rules
  • search_t: Search engine (in <ds/search.hh>)

See header files in include/ds/ for detailed API documentation.

Building from Source

Prerequisites

  • For TypeScript: Emscripten SDK
  • For Python: Python 3.10-3.14, C++20 compatible compiler, CMake 3.30+
  • For C++: C++20 compatible compiler, CMake 3.30+

Build All Components

# Clone repository
git clone https://github.com/USTC-KnowledgeComputingLab/ds.git
cd ds

# Build TypeScript/JavaScript (requires Emscripten)
npm install
npm run build

# Build Python package
uv sync --extra dev

# Build C++ library
cmake -B build
cmake --build build

Running Tests

# TypeScript/JavaScript tests
npm test

# Python tests
pytest

# C++ tests (if available)
cd build && ctest

Examples

Example programs are provided in the examples/ directory:

  • examples/main.mjs: TypeScript/JavaScript example
  • examples/main.py: Python example
  • examples/main.cc: C++ example

Each example demonstrates logical inference using propositional logic axioms.

Support Packages

  • BNF Conversion Library (apyds-bnf, atsds-bnf): Bidirectional conversion between DS syntax formats. See /bnf for details.

Development

Code Formatting

The project uses code formatting tools for consistency:

  • C++: clang-format (.clang-format config provided)
  • Python: ruff (configured in pyproject.toml)
  • TypeScript: Biome (configured in biome.json)

Pre-commit Hooks

Pre-commit hooks are configured in .pre-commit-config.yaml.

License

This project is licensed under the GNU General Public License v3.0 or later. See LICENSE.md for details.

Documentation

For comprehensive documentation including tutorials, API reference, and examples, visit:

Repository

Author

Hao Zhang [email protected]

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.