https://github.com/d-krupke/cpsat-logutils
Utils for parsing the logs of OR-Tools' CP-SAT solver.
Science Score: 26.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
○Academic publication links
-
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (9.5%) to scientific vocabulary
Repository
Utils for parsing the logs of OR-Tools' CP-SAT solver.
Basic Info
- Host: GitHub
- Owner: d-krupke
- License: mit
- Language: Python
- Default Branch: main
- Size: 138 KB
Statistics
- Stars: 2
- Watchers: 1
- Forks: 1
- Open Issues: 0
- Releases: 2
Metadata Files
README.md
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
bash
pip install cpsat-logutils
Quickstart
1) Enable CP‑SAT logging in your solver
Enable detailed CP‑SAT log output and capture it programmatically.
```python from ortools.sat.python import cp_model
model = cp_model.CpModel()
... build your model ...
solver = cpmodel.CpSolver() solver.parameters.logsearch_progress = True # Show detailed search log
loglines: list[str] = [] solver.logcallback = log_lines.append # Capture logs in a list
status = solver.Solve(model) rawlog = "\n".join(loglines) ```
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.
```python 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.
```python from cpsat_logutils.blocks import SolverBlock
if solverblock := parser.getblockoftypeornone(SolverBlock): print("CP-SAT version:", solverblock.getversion()) print("Workers:", solverblock.getnumberofworkers()) print("Parameters:", solverblock.getparameters()) ```
c) Inspect model statistics
Display the number of variables and constraints before and after presolve.
```python from cpsat_logutils.blocks import InitialModelBlock, PresolvedModelBlock
if initial := parser.getblockoftypeornone(InitialModelBlock): print( "Initial model:", initial.getnumvariables(), "vars,", initial.getnum_constraints(), "constraints", )
if presolved := parser.getblockoftypeornone(PresolvedModelBlock): print( "Presolved model:", presolved.getnumvariables(), "vars,", presolved.getnum_constraints(), "constraints", ) ```
d) Check presolve outcome
Determine whether the problem was solved during presolve.
```python from cpsat_logutils.blocks import PresolveSummaryBlock
solvedbypresolve = False if ps := parser.getblockoftypeornone(PresolveSummaryBlock): solvedbypresolve = ps.issolvedbypresolve() print("Solved by presolve:", solvedbypresolve) ```
e) Explore search progress and stats
If presolve did not solve the problem, inspect search progress events, task timing, search statistics, and objective bounds.
```python from cpsat_logutils.blocks import ( SearchProgressBlock, SearchStatsBlock, TaskTimingBlock, ObjectiveBoundsBlock, )
if not solvedbypresolve: if sp := parser.getblockoftypeornone(SearchProgressBlock): print("Presolve time (s):", sp.getpresolvetime()) print(sp.getevents()) # 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.
```python from cpsat_logutils.blocks import ResponseBlock
if resp := parser.getblockoftypeornone(ResponseBlock): print(resp.todict()) ```
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
Owner
- Name: Dominik Krupke
- Login: d-krupke
- Kind: user
- Location: Germany
- Company: TU Braunschweig
- Website: https://krupke.cc
- Repositories: 8
- Profile: https://github.com/d-krupke
Postdoc at TU Braunschweig, IBR, Algorithms Group.
GitHub Events
Total
- Create event: 1
- Issues event: 3
- Release event: 1
- Watch event: 2
- Issue comment event: 7
- Push event: 6
- Pull request event: 1
Last Year
- Create event: 1
- Issues event: 3
- Release event: 1
- Watch event: 2
- Issue comment event: 7
- Push event: 6
- Pull request event: 1
Issues and Pull Requests
Last synced: 10 months ago
All Time
- Total issues: 1
- Total pull requests: 0
- Average time to close issues: 9 minutes
- Average time to close pull requests: N/A
- Total issue authors: 1
- Total pull request authors: 0
- Average comments per issue: 2.0
- Average comments per pull request: 0
- Merged pull requests: 0
- Bot issues: 0
- Bot pull requests: 0
Past Year
- Issues: 1
- Pull requests: 0
- Average time to close issues: 9 minutes
- Average time to close pull requests: N/A
- Issue authors: 1
- Pull request authors: 0
- Average comments per issue: 2.0
- Average comments per pull request: 0
- Merged pull requests: 0
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
- rungeard (2)
- pchtsp (1)
Pull Request Authors
- rungeard (1)
Top Labels
Issue Labels
Pull Request Labels
Packages
- Total packages: 1
-
Total downloads:
- pypi 3,088 last-month
- Total dependent packages: 0
- Total dependent repositories: 0
- Total versions: 3
- Total maintainers: 1
pypi.org: cpsat-logutils
Utils for parsing the logs of OR-Tools' CP-SAT solver.
- Documentation: https://cpsat-logutils.readthedocs.io/
- License: MIT License
-
Latest release: 0.0.3
published 10 months ago
Rankings
Maintainers (1)
Dependencies
- actions/checkout v3 composite
- actions/setup-python v4 composite
- actions/checkout master composite
- actions/setup-python v4 composite
- pypa/gh-action-pypi-publish release/v1 composite