Utils for parsing the logs of OR-Tools' CP-SAT solver.
Project description
cpsat-logutils
Utilities to parse and work with the logs of OR‑Tools CP‑SAT.
This library extracts key information from CP‑SAT logs (solutions, bounds, presolve stats, subsolver activity, search progress, conflicts, etc.) and exposes them in structured Python objects you can analyze or visualize.
Installation
pip install cpsat-logutils
Quickstart
1) Enable CP‑SAT logging in your solver
Enable detailed CP‑SAT log output and capture it programmatically.
from ortools.sat.python import cp_model
model = cp_model.CpModel()
# ... build your model ...
solver = cp_model.CpSolver()
solver.parameters.log_search_progress = True # Show detailed search log
log_lines: list[str] = []
solver.log_callback = log_lines.append # Capture logs in a list
status = solver.Solve(model)
raw_log = "\n".join(log_lines)
2) Parse the log with cpsat-logutils
Below is a step-by-step parsing workflow. For each block, explore its block-specific methods in the blocks/ directory, and adapt the calls shown here to your needs.
a) Instantiate the parser
Create the parser instance from the raw log string.
from cpsat_logutils import LogParser
parser = LogParser(raw_log)
b) Retrieve solver-level info
Get high-level solver metadata such as version, number of workers, and parameters.
from cpsat_logutils.blocks import SolverBlock
if solver_block := parser.get_block_of_type_or_none(SolverBlock):
print("CP-SAT version:", solver_block.get_version())
print("Workers:", solver_block.get_number_of_workers())
print("Parameters:", solver_block.get_parameters())
c) Inspect model statistics
Display the number of variables and constraints before and after presolve.
from cpsat_logutils.blocks import InitialModelBlock, PresolvedModelBlock
if initial := parser.get_block_of_type_or_none(InitialModelBlock):
print(
"Initial model:",
initial.get_num_variables(),
"vars,",
initial.get_num_constraints(),
"constraints",
)
if presolved := parser.get_block_of_type_or_none(PresolvedModelBlock):
print(
"Presolved model:",
presolved.get_num_variables(),
"vars,",
presolved.get_num_constraints(),
"constraints",
)
d) Check presolve outcome
Determine whether the problem was solved during presolve.
from cpsat_logutils.blocks import PresolveSummaryBlock
solved_by_presolve = False
if ps := parser.get_block_of_type_or_none(PresolveSummaryBlock):
solved_by_presolve = ps.is_solved_by_presolve()
print("Solved by presolve:", solved_by_presolve)
e) Explore search progress and stats
If presolve did not solve the problem, inspect search progress events, task timing, search statistics, and objective bounds.
from cpsat_logutils.blocks import (
SearchProgressBlock,
SearchStatsBlock,
TaskTimingBlock,
ObjectiveBoundsBlock,
)
if not solved_by_presolve:
if sp := parser.get_block_of_type_or_none(SearchProgressBlock):
print("Presolve time (s):", sp.get_presolve_time())
print(sp.get_events()) # list of events, see BoundEvent, ObjEvent, ModelEvent
if tt := parser.get_block_of_type_or_none(TaskTimingBlock):
print(tt.to_pandas().head())
if ss := parser.get_block_of_type_or_none(SearchStatsBlock):
print(ss.to_pandas().head())
if ob := parser.get_block_of_type_or_none(ObjectiveBoundsBlock):
print(ob.to_pandas().head())
f) Get final solver response
Access the solver’s final response, including status and objective value.
from cpsat_logutils.blocks import ResponseBlock
if resp := parser.get_block_of_type_or_none(ResponseBlock):
print(resp.to_dict())
3) Save or visualize
cpsat-logutils focuses on parsing and structuring; you can:
- export DataFrames to CSV/JSON for dashboards,
- plot progress/bounds over time with matplotlib/plotly,
- feed the output into your own analyzers.
If you prefer a ready‑made GUI, see the CP‑SAT Log Analyzer below.
Examples
- Minimal example logs live in
example_logs/of this repo. - See the test suite in
tests/for end‑to‑end parsing and assertions.
FAQ
Which CP‑SAT versions are supported? The parser targets the log format used by recent OR‑Tools releases (9.8+). If a newer CP‑SAT version changes the log format and something breaks, please open an issue with a sample CP‑SAT output log.
Can I parse logs from other languages (C++/Java/C#)? Yes. As long as you
enable log_search_progress and collect the textual CP‑SAT log, the content is
the same. Save it to a text file or feed the string to the parser.
Do I need to redirect stdout? No. In Python you can capture logs via
solver.log_callback = my_fn to avoid duplicates.
Related resources
- CP‑SAT (official docs) — overview & tutorials: https://developers.google.com/optimization/cp/cp_solver
- The CP‑SAT Primer — in‑depth guide by the same author: https://d-krupke.github.io/cpsat-primer/00_intro.html
- CP‑SAT Log Analyzer (GUI) — Streamlit app to explore logs interactively: https://cpsat-log-analyzer.streamlit.app/ • source: https://github.com/d-krupke/CP-SAT-Log-Analyzer
Contributing
Issues and PRs are welcome! If you hit a parsing edge case, please attach a sample CP‑SAT output log that reproduces it.
When submitting a merge request, please ensure:
- All tests pass locally:
pytest - Code style and linting pass: use
pre-commitwith the provided configuration (.pre-commit-config.yaml). Runpre-commit run --all-filesbefore submitting.
Refer to the CI workflow for the full test and lint configuration.
Version History
- v0.0.3: Extended
__all__import
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cpsat_logutils-0.0.4.tar.gz.
File metadata
- Download URL: cpsat_logutils-0.0.4.tar.gz
- Upload date:
- Size: 114.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6997a05c247dc94558f20e7057fce34069f5e12849bf63fe65d9927cf60ed50e
|
|
| MD5 |
9156202d3ea809cd53cb2661112905bf
|
|
| BLAKE2b-256 |
2013f02ec02a7c95d7b271e7c3c0dbe76c228e2d82ca3169d7cb8c909e3ba7c2
|
Provenance
The following attestation bundles were made for cpsat_logutils-0.0.4.tar.gz:
Publisher:
release.yml on d-krupke/cpsat-logutils
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cpsat_logutils-0.0.4.tar.gz -
Subject digest:
6997a05c247dc94558f20e7057fce34069f5e12849bf63fe65d9927cf60ed50e - Sigstore transparency entry: 1271288883
- Sigstore integration time:
-
Permalink:
d-krupke/cpsat-logutils@93e64d3f80b2c3dc4e94f4ae51aba8598adeae85 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/d-krupke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@93e64d3f80b2c3dc4e94f4ae51aba8598adeae85 -
Trigger Event:
release
-
Statement type:
File details
Details for the file cpsat_logutils-0.0.4-py3-none-any.whl.
File metadata
- Download URL: cpsat_logutils-0.0.4-py3-none-any.whl
- Upload date:
- Size: 33.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9038b8df6897ad9e3abc7d6f3ec71d378b48a35afbf49a607498b7e9d10dfe4
|
|
| MD5 |
848194e3a886354dd0d0271ff6e44fe0
|
|
| BLAKE2b-256 |
689b1a824368f44b42f518aae78fe6bcbed9e0f081806871067a2ec035d7b210
|
Provenance
The following attestation bundles were made for cpsat_logutils-0.0.4-py3-none-any.whl:
Publisher:
release.yml on d-krupke/cpsat-logutils
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cpsat_logutils-0.0.4-py3-none-any.whl -
Subject digest:
b9038b8df6897ad9e3abc7d6f3ec71d378b48a35afbf49a607498b7e9d10dfe4 - Sigstore transparency entry: 1271288892
- Sigstore integration time:
-
Permalink:
d-krupke/cpsat-logutils@93e64d3f80b2c3dc4e94f4ae51aba8598adeae85 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/d-krupke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@93e64d3f80b2c3dc4e94f4ae51aba8598adeae85 -
Trigger Event:
release
-
Statement type: