Skip to main content

ZeroFolio

Algorithm selection with zero domain knowledge via text embeddings.

ZeroFolio selects the best algorithm for a problem instance using a three-step pipeline:

  1. Serialize — read the raw instance file as plain text (zf.serialize)
  2. Embed — pass the text through any pretrained embedding model (user-provided)
  3. Select — pick the best algorithm via weighted k-nearest neighbors (zf.KNNSelector)

No feature engineering, no domain expertise, no training required. ZeroFolio handles serialization and selection; you bring your own embedding API.

Paper: arXiv:2604.19753 (AutoML 2026). Supplementary material (data, embeddings, experiment tool): doi:10.5281/zenodo.21296904. From version 0.1.1 on, zf.serialize with line_shuffle produces the same text as the paper's experiments for a given seed (0.1.0 shuffled differently).

Installation

pip install zerofolio

Verify Installation

A quick smoke test with synthetic data (no API key needed):

import numpy as np
import zerofolio as zf

# Synthetic embeddings and runtimes for 50 instances, 4 algorithms
X_train = np.random.rand(50, 128)
rt_train = np.random.rand(50, 4) * 100

selector = zf.KNNSelector(k=5)
selector.fit(X_train, rt_train)

X_test = np.random.rand(3, 128)
print(selector.predict(X_test))  # e.g. array([2, 0, 3])

Quick Start (with Gemini Embeddings)

A full example using Google's Gemini embedding model. Requires: pip install google-genai

import os
import numpy as np
import zerofolio as zf
from google import genai

# --- Step 1: Serialize instance files ---
# Reads the file as plain text, shuffles lines, truncates to budget.
text = zf.serialize("instance.cnf", strategy="line_shuffle", max_chars=10000, seed=42)

# --- Step 2: Embed (user-provided) ---
# ZeroFolio does not call any API itself. You provide an embedding function.
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

def embed(text):
    result = client.models.embed_content(
        model="gemini-embedding-2-preview",  # Gemini Embedding 2, as in the paper
        contents=text,
    )
    return result.embeddings[0].values

# Embed all your training instances into numpy arrays:
# For each instance file, call zf.serialize() then embed().
# train_embeddings: np.array of shape (n_train, 3072)
# train_runtimes:   np.array of shape (n_train, n_algorithms)
#     Each row gives the runtime (seconds) of each algorithm on that instance.
#     Use PAR10 values (10× cutoff for unsolved) for best results.
train_embeddings = np.array([embed(zf.serialize(f)) for f in train_files])

# --- Step 3: Select via k-NN ---
selector = zf.KNNSelector(k=10, metric="manhattan")
selector.fit(train_embeddings, train_runtimes)

test_embedding = np.array([embed(text)])
best_algo_idx = selector.predict(test_embedding)
print(f"Selected algorithm index: {best_algo_idx[0]}")

Using Algorithm Names

Pass algorithm names to get predictions as strings instead of indices:

algos = ["minisat", "glucose", "cadical", "kissat"]
selector = zf.KNNSelector(k=10, algorithm_names=algos)
selector.fit(train_embeddings, train_runtimes)

print(selector.predict(test_embedding))  # e.g. ["glucose"]

Multi-Seed Voting

Different random seeds expose different parts of the instance file to the embedding model. Averaging the scores over several seeds (soft voting) is optional; in the paper, two-seed voting lowered the mean PAR10 on SAT12-ALL from 1077 to 1030 (k=5). (Assumes embed and selector are set up as in the Quick Start above.)

scores = []
for seed in [42, 100, 500]:
    text = zf.serialize("instance.cnf", seed=seed)
    emb = np.array([embed(text)])
    scores.append(selector.predict_scores(emb))  # shape (1, n_algorithms)

avg_scores = np.mean(scores, axis=0)  # shape (1, n_algorithms)
best_algo_idx = int(np.argmin(avg_scores[0]))

API Reference

zf.serialize(path, strategy, max_chars, seed) Serialize an instance file to text. Works with any text-based format (CNF, WCNF, QDIMACS, MiniZinc, ASP, MPS, etc.). Gzipped files (.gz) are handled automatically.

  • strategy: "line_shuffle" (default, recommended) or "raw". Use zf.list_strategies() to see all options.
  • max_chars: Character budget for truncation (default 10,000, as in the paper). The embedding model may truncate further at its own input limit (8,192 tokens for Gemini Embedding 2, 2,048 for gemini-embedding-001).
  • seed: Random seed for line shuffling (default 42). Different seeds yield different views of the same instance. Ignored by the "raw" strategy.

zf.KNNSelector(k, metric, algorithm_names) Weighted k-NN algorithm selector using inverse-distance weighting.

  • k: Number of neighbors (default 10). Must not exceed the number of training instances.
  • metric: "manhattan" (default, as in the paper) or "cosine" (similar results in the paper).
  • algorithm_names: Optional list of algorithm name strings. When provided, predict() returns a list of name strings; otherwise it returns a numpy array of column indices.

Methods:

  • .fit(embeddings, runtimes) — fit on training embeddings and runtime matrix. Raises ValueError if k exceeds the number of training instances.
  • .predict(embeddings) — return best algorithm per instance (names or indices)
  • .predict_scores(embeddings) — return per-algorithm weighted-average scores, shape (n_test, n_algorithms)

zf.list_strategies() Return the list of available serialization strategy names.

Persistence

ZeroFolio selectors can be saved and loaded with pickle:

import pickle

with open("selector.pkl", "wb") as f:
    pickle.dump(selector, f)

with open("selector.pkl", "rb") as f:
    selector = pickle.load(f)

Citation

@inproceedings{szeider2026zerofolio,
  title={Algorithm Selection with Zero Domain Knowledge via Text Embeddings},
  author={Szeider, Stefan},
  booktitle={International Conference on Automated Machine Learning (AutoML 2026)},
  year={2026},
  note={arXiv:2604.19753}
}

License

Apache 2.0

Metadata

Release files for zerofolio 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zerofolio 0.1.1
File Size Uploaded Provenance
zerofolio-0.1.1.tar.gz 27.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for zerofolio 0.1.1
File Interpreter ABI Platform
zerofolio-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 38.1 kB

Release files / zerofolio-0.1.1.tar.gz

Download URL zerofolio-0.1.1.tar.gz
Size 27.6 kB
Tags Source
SHA-256 checksum
How to use checksums
7f6f45dc84efd6fb27b6844788c262bc617a9854187841c4362010629a83f10e
BLAKE2b-256 checksum
How to use checksums
e349e9564dfd18fc1afd778203e1a2d92b42ccf0cfff0722cdf1a0175dc98e94
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.2

Release files / zerofolio-0.1.1-py3-none-any.whl

Download URL zerofolio-0.1.1-py3-none-any.whl
Size 10.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5f9b203cb1377665791091c3d67730cddc0395f2babf3049ccd3a6080fded39
BLAKE2b-256 checksum
How to use checksums
6f178c87cc70619ef07ef6c4f0bc8b59d01addff145e813525e47202eacbdf8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.2

Security for zerofolio 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page