cimod : C++ header-only library for a binary quadratic model#

PyPI version shields.io PyPI pyversions PyPI implementation PyPI format PyPI license PyPI download month Downloads

Test Build&Upload CodeQL Build Documentation pages-build-deployment codecov

How to use#

You should only include a header src/binary_quadratic_model.hpp in your project.

Example#

C++#

#include "src/binary_quadratic_model.hpp"

using namespace cimod;
int main()
{
// Set linear biases and quadratic biases
Linear<uint32_t, double> linear{ {1, 1.0}, {2, 2.0}, {3, 3.0}, {4, 4.0} };
Quadratic<uint32_t, double> quadratic
{
     {std::make_pair(1, 2), 12.0}, {std::make_pair(1, 3), 13.0}, {std::make_pair(1, 4), 14.0},
     {std::make_pair(2, 3), 23.0}, {std::make_pair(2, 4), 24.0},
     {std::make_pair(3, 4), 34.0}
 };

// Set offset
double offset = 0.0;

// Set variable type
Vartype vartype = Vartype::BINARY;
// Create a BinaryQuadraticModel instance
BinaryQuadraticModel<uint32_t, double, cimod::Dense> bqm(linear, quadratic, offset, vartype);

//linear terms -> bqm.get_linear()
//quadratic terms -> bqm.get_quadratic()

return 0;
}

Python#

import cimod
import dimod

# Set linear biases and quadratic biases
linear = {1:1.0, 2:2.0, 3:3.0, 4:4.0}
quadratic = {(1,2):12.0, (1,3):13.0, (1,4):14.0, (2,3):23.0, (2,4):24.0, (3,4):34.0}

# Set offset
offset = 0.0

# Set variable type
vartype = dimod.BINARY

# Create a BinaryQuadraticModel instance
bqm = cimod.BinaryQuadraticModel(linear, quadratic, offset, vartype)

print(bqm.linear)
print(bqm.quadratic)

Install#

For Users#

# Binary package (recommended)
$ pip install jij-cimod

# From source  
$ pip install --no-binary=jij-cimod jij-cimod 

# Latest development version
$ pip install git+https://github.com/Jij-Inc/cimod.git

For Developers#

This project uses uv for dependency management.

# Clone repository
$ git clone https://github.com/Jij-Inc/cimod.git
$ cd cimod

# Install uv (choose one method)
$ curl -LsSf https://astral.sh/uv/install.sh | sh  # macOS/Linux
# or: brew install uv                              # Homebrew
# or: pip install uv                               # fallback option

# Install with development dependencies (exact versions)
$ uv sync --locked --group dev

# Verify installation
$ uv run python -c "import cimod; print('cimod installed successfully')"
$ uv run pytest tests/ -v --tb=short

Development#

Dependency Groups#

The project uses PEP 735 dependency groups in pyproject.toml:

Group

Purpose

Command

dev

Development environment (build + test + format)

uv sync --group dev

test

Testing tools (pytest, coverage)

uv sync --group test

docs

Documentation generation

uv sync --group docs

format

Code formatting (ruff only)

uv sync --group format

all

Complete environment (dev + docs)

uv sync --group all

Lock file usage:

  • For exact reproduction (CI/CD, verification): uv sync --locked --group dev

  • For development (may update dependencies): uv sync --group dev

  • To update lock file: uv lock or uv lock --upgrade

Dependencies are locked in uv.lock for reproducible builds across environments.

System Requirements#

  • Python: 3.9-3.13

  • C++: C++17 compatible compiler

  • CMake: 3.20+ (for C++ development)

Testing#

Python Tests#

# Install test dependencies (exact versions)
$ uv sync --locked --group test

# Basic test run
$ uv run pytest tests/ -v

# With coverage report
$ uv run pytest tests/ -v --cov=cimod --cov-report=html
$ uv run python -m coverage html

C++ Tests#

# Build C++ tests (independent of Python environment)
$ mkdir build 
$ cmake -DCMAKE_BUILD_TYPE=Debug -S . -B build
$ cmake --build build --parallel

# Run C++ tests
$ cd build
$ ./tests/cimod_test
# Alternatively Use CTest 
$ ctest --extra-verbose --parallel --schedule-random

Requirements: CMake > 3.22, C++17

Code Quality#

Unified Tooling with Ruff#

# Install format dependencies (exact versions)
$ uv sync --locked --group format

# Check and fix all issues
$ uv run ruff check .              # Lint check
$ uv run ruff format .             # Format code  
$ uv run ruff check . --fix        # Auto-fix issues

# All-in-one check (recommended)
$ uv run ruff check . && uv run ruff format --check .

Benchmark#

Benchmark code#

import dimod
import cimod
import time

fil = open("benchmark", "w")
fil.write("N t_dimod t_cimod\n")

def benchmark(N, test_fw):
    linear = {}
    quadratic = {}

    spin = {}

    # interactions

    for i in range(N):
        spin[i] = 1

    for elem in range(N):
        linear[elem] = 2.0*elem;

    for i in range(N):
        for j in range(i+1, N):
            if i != j:
                quadratic[(i,j)] = (i+j)/(N)

    t1 = time.time()

    # initialize
    a = test_fw.BinaryQuadraticModel(linear, quadratic, 0, test_fw.BINARY)
    a.change_vartype(test_fw.SPIN)

    # calculate energy for 50 times.
    for _ in range(50):
        print(a.energy(spin))

    t2 = time.time()

    return t2-t1

d_arr = []
c_arr = []

for N in [25, 50, 100, 200, 300, 400, 600, 800,1000, 1600, 2000, 3200, 5000]:
    print("N {}".format(N))
    d = benchmark(N, dimod)
    c = benchmark(N, cimod)
    print("{} {} {}".format(N, d, c))
    fil.write("{} {} {}\n".format(N, d, c))

Software versions#

Package

Version

cimod

1.0.3

dimod

0.9.2

Result#

benchmark

Notes#

  • As explained in Jij-Inc/cimod#48, specifying self-loop index (e.g. {(2, 2): 5}) in the quadratic argument in BinaryQuadraticModel is not allowed.

Licences#

Copyright 2020-2025 Jij Inc.

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0  

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.