Skip to main content

Qaekwy, a modern, open-source Python framework for declarative constraint programming and combinatorial optimization

Project description

Qaekwy Python

A modern, open-source Python framework for declarative constraint programming and combinatorial optimization.

GitHub License PyPI - Version

Overview

Qaekwy is a Python library designed for modeling and solving combinatorial optimization and constraint satisfaction problems.

It provides a clean, Pythonic interface for defining variables, constraints, and objectives, enabling a natural define-and-solve workflow. Qaekwy manages the interaction with the solver engine, allowing users to focus entirely on expressing the structure of their problems.

Perfect for:

  • 🎓 Learning: Students can quickly model and solve problems.
  • 👩‍🏫 Teaching: Instructors can demo core CSP concepts with minimal setup.
  • 🌟 Discovering: Researchers can explore strategies, heuristics, and models.

🚀 Quick Start

Prerequisites

  • Python 3.9+
  • pip

Installation

Install the production-ready client via PyPI:

pip install qaekwy

Your First Model

import qaekwy as qw

m = qw.Model()

x = m.integer_variable("x", (-10, 10))
y = m.integer_variable("y", (-10, 10))
z = m.integer_variable("z", (-10, 10))

m.constraint(x + 2*y + 3*z <= 15)
m.constraint(x + y >= 5)

m.minimize(z)

solution = m.solve_one()
solution.pretty_print()

Output:

----------------------------------------
Solution:
----------------------------------------
x: 6
y: 8
z: -3
----------------------------------------

That's it.

Capabilities

  • Declarative Modeling Define integer, float, and boolean variables, as well as arrays and matrices, to represent problems at a high semantic level.
  • Expressive Constraints Formulate arithmetic, logical, and conditional constraints using readable and maintainable Python expressions.
  • Optimization Objectives Specify minimization and maximization goals to guide the solver toward optimal solutions.
  • Search Configuration Configure solver behavior using explicit search strategies such as Depth-First Search and Branch-and-Bound, along with branching heuristics and cutoffs.
  • Cloud-Native Execution Transparent handling of model serialization and execution on the Qaekwy Cloud Solver instance.

📚 Documentation

Visit the Qaekwy Documentation for guides, teaching resources, and detailed examples.


🧩 Constraint Programming Example: Sudoku

Here is a complete example solving a Sudoku grid:

import qaekwy as qw

# Initial Sudoku grid; 0 represents empty cells to be assigned by Qaekwy
my_problem = [
    [0, 7, 0,  0, 0, 0,  6, 9, 0],
    [0, 0, 0,  6, 1, 0,  0, 0, 0],
    [0, 9, 2,  0, 0, 0,  0, 5, 0],

    [0, 0, 0,  0, 8, 1,  7, 0, 9],
    [4, 0, 0,  0, 0, 3,  0, 0, 0],
    [0, 0, 0,  0, 5, 6,  1, 0, 8],

    [0, 5, 9,  0, 0, 0,  0, 1, 0],
    [0, 0, 0,  5, 6, 0,  0, 0, 0],
    [0, 2, 0,  0, 0, 0,  5, 7, 0]
]

# Initialize the model container
m = qw.Model()

# Create a 9x9 matrix of integer variables
# Each variable can take a value between 1 and 9 (inclusive)
grid = m.integer_matrix("grid", rows=9, cols=9, domain=(1, 9))

for i in range(9):
    # Ensure all variables in row 'i' are unique
    m.constraint_distinct(grid.row(i))
    
    # Ensure all variables in column 'i' are unique
    m.constraint_distinct(grid.col(i))

# Iterate in steps of 3 (0, 3, 6) to find the top-left corner of each block
for i in range(0, 9, 3):
    for j in range(0, 9, 3):
        # Extract the 3x3 block and enforce uniqueness
        m.constraint_distinct(grid.slice(i, j, i + 3, j + 3))

for i in range(9):
    for j in range(9):
        # If the cell is not empty (0 represents empty in our data)
        if my_problem[i][j] != 0:
            # Constrain the model variable at [i][j] to equal the input value
            m.constraint(grid[i][j] == my_problem[i][j])

# Solve the model and retrieve the first valid solution found
s = m.solve_one()

# Display the result
s.pretty_print()

Output:

----------------------------------------
Solution:
----------------------------------------
grid: (9 x 9 matrix)
    1 7 8 3 2 5 6 9 4
    5 4 3 6 1 9 8 2 7
    6 9 2 7 4 8 3 5 1
    2 6 5 4 8 1 7 3 9
    4 8 1 9 7 3 2 6 5
    9 3 7 2 5 6 1 4 8
    7 5 9 8 3 2 4 1 6
    3 1 4 5 6 7 9 8 2
    8 2 6 1 9 4 5 7 3
----------------------------------------

🎒 Optimization Example: Knapsack Problem

Here is a complete example solving a basic resource allocation problem (The Knapsack Problem):

Given a set of items, each with a weight and a value, determine which items to include in the collection so that the total weight is less than or equal to a given limit and the total value is as large as possible.

import qaekwy as qw

# 1. Setup the Model
m = qw.Model()

weights = [2, 3, 4, 5]
values  = [3, 4, 5, 6]
limit   = 7
n_items = len(weights)

# 2. Define Decision Variables (0 = exclude, 1 = include)
selected = [
    m.integer_variable(f"item_{i}", domain=(0, 1))
    for i in range(n_items)
]

# 3. Apply Constraints
# Total weight must not exceed the limit
current_weight = sum(weights[i] * selected[i] for i in range(n_items))
m.constraint(current_weight <= limit)

# 4. Define Objective
# Maximize total value
total_value = m.integer_variable(
    name="total_value",
    expression=sum(values[i] * selected[i] for i in range(n_items)),
    branch_val=qw.BranchIntegerVal.VAL_MAX # Forces the solver to try higher values first
)
m.maximize(total_value)

# 5. Solve
solution = m.solve_one(searcher="bab") # Branch-and-Bound

print(f"Max Value: {solution.total_value}")
# Output: Max Value: 9

💡 Core Concepts

Qaekwy core concept

The Model

The qw.Model acts as the container for your variables and constraints. It also manages the interaction with the underlying solver engine.

The Variables

Here are examples of variable creation in the model:

# A single integer between 0 and 100
capacity = m.integer_variable("capacity", domain=(0, 100))

# A 9x9 Grid (Matrix) for Sudoku-like problems
grid = m.integer_matrix("grid", rows=9, cols=9, domain=(1, 9))
The Constraints

Constraints are logical assertions that must be true in any valid solution.

# Arithmetic
m.constraint(x * 2 < qw.math.power(y, 2) + 5)

Modeling Capabilities

Qaekwy supports:

  • Conditional constraints
m.constraint_if_then_else(
    condition=x + y <= 7,
    then_constraint=z >= 2,
    else_constraint=z <= 2
)
  • Logical expressions
m.constraint(
    (qw.math.absolute(z) == qw.math.power(x-(y+1),2)) | (z >= 4)
)
  • Arrays and Matrices
arr = m.integer_array("arr", 3, (0,100))
m.constraint(arr[1] < x + 1)

mat = m.integer_matrix("mat", rows=2, cols=3, domain=(0,50))
m.constraint(sum(mat.col(0)) > arr[2])

...and more, visit the Qaekwy Documentation

Solving & Execution

  • solve_one() — find one feasible or optimal solution
  • solve() — returns a list of solutions
  • minimize(...) / maximize(...) — Set one or more objectives on variables
  • Searchers such as DFS, Branch-and-Bound, etc.
  • Cloud-based Solver instance (please, refer to Terms & Conditions)

Integration

The model is then sent to the Qaekwy Cloud Engine through REST API.

Qaekwy Integration


License

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

qaekwy-0.3.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qaekwy-0.3.0-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file qaekwy-0.3.0.tar.gz.

File metadata

  • Download URL: qaekwy-0.3.0.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for qaekwy-0.3.0.tar.gz
Algorithm Hash digest
SHA256 02e56f098bbf2697b8f9458d8f93f86477ade1f93159e1c97ba87292f07a55df
MD5 2578cc21b57391c3fe17993c8c48b52a
BLAKE2b-256 30052fb6c77eb78f9c08ac880243f5195f822cefa2159a2a8bbb3c0cc631c26c

See more details on using hashes here.

File details

Details for the file qaekwy-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: qaekwy-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for qaekwy-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e617814951e73704080e29c03ab108e510cd5dcf3dfacb9687ed92560e273a41
MD5 6a8bbc4e14f0d7d5442f1dca2e3929e1
BLAKE2b-256 43f19df779f2e60888452532481f3195ed726e0371eae0701af5c834fb07b7ad

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page