cimod : C++ header-only library for a binary quadratic model#
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) |
|
test |
Testing tools (pytest, coverage) |
|
docs |
Documentation generation |
|
format |
Code formatting (ruff only) |
|
all |
Complete environment (dev + docs) |
|
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
oruv 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#
Result#
Notes#
As explained in Jij-Inc/cimod#48, specifying self-loop index (e.g.
{(2, 2): 5}
) in thequadratic
argument inBinaryQuadraticModel
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.