Metadata-Version: 2.4
Name: homlab-solver
Version: 0.1.0
Summary: 针对单个无交叉点图的 HomLab 求解算法。
License-Expression: MIT
License-File: LICENSE
Author: GGN_2015
Author-email: neko@jlulug.org
Requires-Python: >=3.10
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Description-Content-Type: text/markdown

# homlab-solver

`homlab-solver` is a small Python package for solving a single non-intersecting
HomLab diagram stored as JSON.

The package currently exposes a Python API. It does not define a command-line
entry point yet.

## Requirements

- Python 3.10 or newer
- No runtime dependencies outside the Python standard library

## Installation

After the package is published to PyPI:

```bash
python -m pip install homlab-solver
```

For local development from this repository:

```bash
python -m pip install -e .
```

## Quick Start

```python
import random

from homlab_solver import solve_single_json

rng = random.Random(42)
result = solve_single_json("test.json", rng=rng)

if result.msg:
    raise RuntimeError(result.msg)

print(result.ans)
```

You can run the same example from a shell:

```bash
python - <<'PY'
import random
from homlab_solver import solve_single_json

result = solve_single_json("test.json", rng=random.Random(42))

if result.msg:
    raise SystemExit(result.msg)

print(result.ans)
PY
```

With the sample `test.json` in this repository, the output is:

```text
(-A^2-A^(-2)) * C[-1, 1, -2]
```

## API

### `solve_single_json(filepath, rng, loop_value="(-A^2-A^(-2))", eps=1e-8)`

Solves one HomLab JSON file.

Parameters:

- `filepath`: path to a HomLab JSON file.
- `rng`: a `random.Random` instance used for small geometric perturbations and
  randomized ray tests. Pass a seeded instance when you need reproducible output.
- `loop_value`: symbolic value used for each free loop.
- `eps`: floating-point tolerance for geometric predicates.

Returns a `SolverObject` with:

- `ans`: the computed symbolic answer, or `None` if solving failed.
- `msg`: an empty string on success, or an error message on failure.

## Input JSON

The solver expects a JSON object describing a single HomLab diagram. At minimum,
the file must include:

```json
{
  "type": "homlab",
  "n": 2,
  "hs": {
    "handle_genus_0000000": {"x": 0.5, "y": 0.35},
    "handle_genus_0000001": {"x": 1.35, "y": 0.35},
    "handle_border_0000000": {"x": 0.5, "y": -0.2},
    "handle_border_0000001": {"x": 1.35, "y": -0.2}
  },
  "ns": {
    "node_0000000": {"x": 0.0, "y": 0.0}
  },
  "es": {
    "edge_0000000": {
      "id_1": "handle_genus_0000000",
      "id_2": "node_0000000"
    }
  }
}
```

Important constraints:

- `type` must be `"homlab"`.
- `n` must be `2`.
- The four handle IDs shown above are required by the current solver.
- Normal node IDs should start with `node_`.
- Handle IDs should start with `handle_`.
- Edge objects must contain `id_1` and `id_2`.
- IDs starting with `#` are treated as special metadata and ignored by the
  solving step.
- Non-handle nodes are expected to have degree `2`.
- Handle nodes are expected to have degree `0` or `1`.

## Building

This project uses `poetry-core` as its build backend. To build a source
distribution and wheel:

```bash
python -m pip install --upgrade build
python -m build
```

The generated artifacts will be written to `dist/`.

Before uploading to PyPI, check the package metadata:

```bash
python -m pip install --upgrade twine
python -m twine check dist/*
```

Upload to PyPI:

```bash
python -m twine upload dist/*
```

## License

This project is licensed under the MIT License. See `LICENSE` for details.

