Library / SDK
chocoteam/choco-solver avatar
chocoteam/choco-solver

choco-solver: modelling constraint problems in Java and letting the solver search

An open-source Java library for Constraint Programming

781 stars160 forksJavaBSD-3-Clause

At a glance

What is it?
choco-solver is a Java library for constraint programming, with integer, boolean, set, graph and real variables, a catalogue of global constraints, pluggable search strategies and an explanation based engine. You describe the problem in Java, hand the model to the solver and read back solutions, statistics and reasons for failure.
Who is it for?
Adopt choco-solver if your problem is combinatorial and you want to state constraints and search behaviour explicitly in Java, and if the explanation engine matters to you because it can tell you why a model has no solution. Do not adopt it if your problem is a straight numeric optimisation with a smooth objective, or if your team would rather model in a declarative modelling language, since choco-parsers also exists but the Java API is where the documentation is thickest.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Constraint programming for problems where the constraints are the hard part

choco-solver is a Java library for constraint programming, and the name of the field is the clue to when it fits. In constraint programming you describe a problem as variables with domains and relations between them, and the solver's job is to search for assignments that satisfy every relation at once. That approach pays off when the constraints are numerous, heterogeneous and hard to encode as arithmetic, for example scheduling with no-overlap conditions, rostering with per-person availability, or resource assignment where each assignment consumes a capacity. The library covers a wide type surface: integer, boolean, set, graph and real variables. It ships global constraints such as alldifferent, count and nvalues, which encode a whole family of values at once instead of a long conjunction of pairwise rules. The result is that the modelling code reads closer to the domain than to a solver API. The library is BSD 3-Clause licensed, copyright IMT Atlantique, so it can be embedded in commercial software without a copyleft obligation on your own code. Support channels are a Google group and a Discord server, and the project asks for a minimal working example when you file an issue.

The model-first API: variables, constraints, solver, search, solve

The overview in the README shows the whole lifecycle in seven numbered steps, and the shape of that API is the main design decision. You build a Model, create typed variables on it, post constraints either through the model or through a variable, then take a Solver from the model, define how the search should proceed, and run it:

java
Model model = new Model("my first problem");
IntVar x = model.intVar("X", 0, 5);
IntVar y = model.intVar("Y", 0, 5);
model.element(x, new int[]{5,0,4,1,3,2}, y).post();
x.add(y).lt(5).post();
Solver solver = model.getSolver();
solver.setSearch(Search.inputOrderLBSearch(x, y));
solver.solve();
solver.printStatistics();

Two things stand out. First, constraints can be posted either through the model or directly on a variable, which lets you build a model incrementally from several places in your code without losing track of what is posted where. Second, the search strategy is a first class object rather than a solver setting. `setSearch` takes a strategy you choose, and the library offers everything from basic heuristics such as first_fail and smallest to impact-based and activity-based search. That matters in practice because the same model can be easy or intractable depending on how the search is ordered, and being able to swap strategies without rewriting the model turns performance work into a configuration change. The library also gives you facilities to interact with the search loop itself, factories that help with modelling, and a collection of samples.

Maven Central is the normal way in, and the version is 6.0.2

The requirements are modest: JDK 8 or newer and Maven 3. The artefact is on Maven Central under the groupId org.choco-solver, and adding it to a pom is the whole installation step:

xml
<dependency>
   <groupId>org.choco-solver</groupId>
   <artifactId>choco-solver</artifactId>
   <version>6.0.2</version>
</dependency>

That version, 6.0.2, is the current stable release, dated 06 Oct 2026, and it matches the recent release tags: 6.0.0 on 2026-05-05, 6.0.1 on 2026-05-21 and 6.0.2 on 2026-10-06. A CHANGES.md file is maintained for each release, which is the file to read before moving across the 6.0 major boundary, because a major version in a library like this usually signals model API changes rather than only internal refactoring. The last push was on 2026-10-22, so the project is being worked on at the time of writing. If you want to follow development instead of releases, snapshot builds are published to the Sonatype snapshot repository and you add the repository block to your pom:

xml
<repository>
    <id>sonatype</id>
    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
</repository>

Building from source is the third option, and the released sources are in the Tag section of the repository. Once you have them, the package command is:

bash
mvn clean package -DskipTests

A Makefile at the top of the repository wraps the common Maven goals, with targets such as package, install, compile, clean and tests, plus test targets that run against external solvers and checkers.

Two jar flavours, and Ibex for anything continuous

The distribution distinguishes two usages that look similar in the Maven world but behave differently in a build. As a standalone library, the jar includes all required dependencies, so you add one file to your classpath and it runs. As a library, the jar excludes all dependencies, which is what you want when your application already manages the dependency tree. The name of the jar terms the packaging, and the documented naming carries three forms: `choco-solver-4.XX.Y-jar-with-dependencies.jar` and `choco-solver-4.XX.Y.jar` for the solver itself, and `choco-parsers-4.XX.Y-jar-with-dependencies.jar`, `choco-parsers-4.XX.Y-light.jar` or `choco-parsers-4.XX.Y.jar` for the parsers module. The light tag is described as the jar-with-dependencies variant with the dependencies of this archive removed. One dependency is not bundled in any form. To declare continuous constraints you need Ibex-2.8.7 installed, with the instructions on the Ibex site, because the continuous side of the solver is delegated to that library. That is the detail most likely to surprise a first-time user: the standard artefact gives you integer, boolean, set and graph modelling out of the box, and continuous variables require an extra native component that you install separately.

The explanation engine explains why a model failed

The distinguishing feature listed in the README is the explanation based engine, which enables conflict-based back jumping, dynamic backtracking and path repair. In practice this changes what a failed solve means. Rather than returning simply unsatisfiable, the engine can produce a structured explanation that points at the constraints involved in the conflict, which is exactly what you need when a model has thousands of constraints and the failure is in one corner of the search space. Conflict-based back jumping also avoids re-exploring regions of the search tree that cannot lead to a solution, which is a search efficiency gain as well as a diagnostic one. Path repair extends the idea in the other direction: when the problem is not satisfaction but optimisation and the solver finds an improving solution, the explanation machinery can work from a violated state towards a repaired one. The README lists the interaction facilities and modelling factories alongside this engine, so the intended workflow is to reach into the search when the default behaviour is not enough. For a user evaluating the library, the explanation capability is the thing to test first on your own model, because it is the part with no equivalent in simpler solver APIs.

The parsers module lets the same engine read models from other languages

The repository is not only a solver. A separate parsers module and an etc directory sit next to the solver source, and the Makefile lists targets that compile grammars and install solver files into MiniZincIDE. The Makefile also exposes test targets named for external checkers and model formats, including ibex, checker, mzn, xcsp, mps, dimacs and expl, which tells you the model languages and verification tooling the library is exercised against. This gives you a second way to use the engine. Instead of writing the model in Java, you can describe the problem in a modelling language or a standard exchange format and solve it through the same underlying engine, which is useful when the model already exists in that format or when the team that owns the model does not write Java. The Makefile even carries a target for installing the msc file into the MiniZincIDE solver directory, and one for removing it again by version, so the integration is treated as a supported workflow rather than an accident. The README itself points at the source code and the samples in the examples directory, which includes documentation, notebooks and a Maven module of its own.

Where a constraint solver is the wrong tool

There are three cases where choco-solver is the wrong choice, and each is common enough to name. The first is smooth numeric optimisation, the kind of problem a gradient method or a dedicated continuous optimiser handles in closed form. Choco handles continuous variables by delegating to Ibex, and a continuous constraint problem is a specialised field in its own right, so a mixed problem is where the library earns its place but a purely numeric one is where it fights you. The second is a problem with no combinatorial structure. If you have a handful of continuous variables and a smooth objective, modelling it as variables and constraints adds overhead with no benefit. The third is a case where the team cannot invest in search tuning. Because the search strategy is a first class part of the model, a badly chosen strategy can make a solvable problem look intractable, and fixing that means measurement and iteration rather than configuration. Another constraint is the licence of the ecosystem around it. The BSD 3-Clause licence of the library is permissive, but the paper artefact, the parsers module and the external dependencies such as Ibex carry their own terms, and a commercial deployment should check each of them rather than assume the top level licence covers the whole stack.

Editorial conclusion

Adopt choco-solver if your problem is combinatorial and you want to state constraints and search behaviour explicitly in Java, and if the explanation engine matters to you because it can tell you why a model has no solution. Do not adopt it if your problem is a straight numeric optimisation with a smooth objective, or if your team would rather model in a declarative modelling language, since choco-parsers also exists but the Java API is where the documentation is thickest. Before committing, pin the version to 6.0.2, check whether your model needs Ibex-2.8.7 installed for continuous constraints, and read CHANGES.md for that release before upgrading from an earlier major version.

Frequently asked questions

How do I add choco-solver to a Maven project?

Add the dependency to your pom.xml with groupId org.choco-solver, artifactId choco-solver and the version you want, for example 6.0.2. The artefact is published on Maven Central and requires JDK 8 or newer and Maven 3.

What does the difference between the choco-solver jar types mean?

The jar-with-dependencies variant bundles everything needed to run, while the plain jar excludes dependencies so you can manage them in your own application. There is also a light jar for the parsers module, which is the bundled variant with this archive's dependencies removed.

Do I need Ibex to use choco-solver with real numbers?

Yes. Declaring continuous constraints requires Ibex-2.8.7 to be installed separately, with the instructions given on the Ibex website. The rest of the library works without it.

What does the explanation based engine in choco-solver give me?

It enables conflict-based back jumping, dynamic backtracking and path repair. Practically, a failed solve can come back with an explanation of which constraints were involved, instead of an undifferentiated unsatisfiable result.

How do I choose how choco-solver searches the solution space?

You set a search strategy on the solver with setSearch, for example Search.inputOrderLBSearch. The library offers basic heuristics such as first_fail and smallest, plus impact-based and activity-based strategies.

Official sources

  1. chocoteam/choco-solver on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/chocoteam-choco-solver.svg)](https://hysenlabs.com/projects/chocoteam-choco-solver)

Was this useful?