Solving
Once your variables are defined and constraints are applied, the final step is to solve the model. In the new Qaekwy API, this process is streamlined: the Model class itself handles the interaction with the solver engine. You simply invoke the solve methods directly on your model instance.
There are two primary methods for solving:
solve_one(): Ideal for standard usage where finding the first valid solution is sufficient.solve(): Used when you need to explore multiple solutions or exhaustively enumerate the search space.
Basic Solving
Finding a Single Solution
For most Constraint Satisfaction Problems (CSPs), you are interested in a valid assignment of variables. The solve_one()
method is the most efficient way to achieve this. It returns a single Solution object if successful, or None if no solution
satisfies the constraints.
import qaekwy as qw
m = Model()
# ...
# Returns the first found solution or None
solution = m.solve_one()
if solution:
solution.pretty_print()
else:
print("No solution found.")
Finding Multiple Solutions
To find more than one solution, use the solve() method. You can control the maximum number of results using
the solution_limit parameter.
# Returns a list of up to 5 solutions
solutions = m.solve(solution_limit=5)
if solutions:
for s in solutions:
s.pretty_print()
Search Strategies (Searchers)
The Searcher is the algorithm the solver uses to navigate the solution space. While Qaekwy defaults to Depth-First Search (dfs), choosing the right strategy can significantly impact performance depending on your problem type (e.g., optimization vs. satisfaction).
The different searcher strategies available are:
"dfs": Depth-First Search (default strategy)"bab": Branch-and-Bound"lds": Limited Discrepancy Search algorithm."pbs": Portfolio-Based Search algorithm."rbs": Restart-based Search algorithm.
# Use Branch and Bound for an optimization problem
best_solution = m.solve_one(searcher="bab")
Cutoffs: Knowing When to Stop
For really hard problems, a full search could take days or even weeks. A cutoff is like setting an actions counter for your search.
Qaekwy has a bunch of different ways to set a time limit on your search:
CutoffConstant: Stop after a fixed number of steps.CutoffFibonacci: The step limit increases like the Fibonacci sequence.CutoffGeometric: The step limit grows exponentially.CutoffLuby: A special sequence that’s good for some problems.CutoffLinear: The step limit increases in a straight line.CutoffRandom: A random step limit.
You can also combine cutoffs using Meta Cutoffs like MetaCutoffAppender, MetaCutoffMerger, and MetaCutoffRepeater.
To set a cutoff, proceed like following:
import qaekwy as qw
m = qw.Model()
# ...
# Stop searching after 1000 steps
solution = m.solve_one(cutoff=qw.CutoffConstant(1000))
Error Handling
The solve() methods abstract away the raw engine response, but they will raise a SolverError if the engine
encounters a critical failure (e.g., malformed constraints or server-side issues).
import qaekwy as qw
m = qw.Model()
# ...
try:
solutions = m.solve()
# ...
except qw.SolverError as e:
print(f"Solver failed with status {e.status}: {e.message}")