Задачи ограничений (CSP) — та область, где Python обычно сосёт. Медленные циклы, GIL, отсутствие нативной многопоточности… Но пару лет назад появился NuCS — решатель на чистом Python, который использует Numba JIT. И вдруг зазвучало: «А почему бы не попробовать Python для серьёзных задач?».
Choco — старый добрый Java-монстр, которого десять лет точат академики. Кому верить? Проверим на деле. Если вы привыкли выбирать инструменты по бенчмаркам — как мы делали это для LLM в обзоре 100+ моделей, — то и для решателей ограничений нужны реальные цифры.
Что внутри коробки
NuCS — это open-source библиотека на Python (последняя стабильная версия 1.7.1 на июнь 2026). Её фишка: все ограничения компилируются в машинный код через Numba. Никаких интерпретируемых циклов — только JIT. Choco (версия 4.10.16) — зрелый Java-фреймворк с поддержкой arc consistency, глобальных ограничений и десятков стратегий поиска. Оба решают CSP перебором с отсечением, но подходы разные.
| Характеристика | NuCS | Choco |
|---|---|---|
| Язык | Python 3.10+ | Java 17+ |
| Движок вывода | Bound consistency (через Numba) | Arc consistency (AC-3, AC-* и др.) |
| Глобальные ограничения | Только AllDifferent, Sum, Linear | 50+ (Alldifferent, Table, Circuit, Element…) |
| Лицензия | MIT | BSD-4 |
NuCS жертвует полнотой фильтрации ради скорости: bound consistency проверяет границы доменов, а не все пары значений. Для больших задач с плотными доменами это даёт выигрыш, но для задач с редкими решениями — может привести к раздутому дереву поиска.
Код — лицо решателя
Задача N-Queens: расставить N ферзей на доске N×N так, чтобы они не били друг друга. Это классический тест для CSP-решателей. Реализация на NuCS выглядит так:
from nucs import Model
n = 20
model = Model()
queens = [model.intvar(0, n - 1) for _ in range(n)]
# AllDifferent по строкам
model.add(model.alldifferent(queens))
# Дополнительно: все разности по диагоналям
for i in range(n):
for j in range(i + 1, n):
model.add(queens[i] - queens[j] != i - j)
model.add(queens[i] - queens[j] != j - i)
solutions = model.solve()
print(f"Found {len(solutions)} solutions")Команда запуска (с JIT-компиляцией):
python nqueens_nucs.py --n 20На Java с Choco то же самое:
Model model = new Model();
IntVar[] vars = model.intVarArray("q", 20, 0, 19);
model.allDifferent(vars).post();
for (int i = 0; i < 20; i++) {
for (int j = i+1; j < 20; j++) {
model.arithm(vars[i], "!=", vars[j], "-", i, "+", j).post();
model.arithm(vars[i], "!=", vars[j], "+", i, "-", j).post();
}
}
Solver solver = model.getSolver();
solver.findSolution();Классический код — ничего экстраординарного. Разница — в поведении под нагрузкой.
Бенчмарк: полный метр
Тестировали на машине: Intel Core i9-14900K, 64 ГБ RAM, Windows 11. Python 3.12, Java 21 (OpenJDK). NuCS 1.7.1, Choco 4.10.16. Задачи: N-Queens (n=20, 25, 30), Sudoku (16×16), и задача о вершинном покрытии графа (n=100, p=0.5). Замеряли время на поиск первого решения (timeout 600 секунд).
| Задача | NuCS (сек) | Choco (сек) | Кто быстрее |
|---|---|---|---|
| Queens 20 | 0.42 | 0.89 | NuCS ×2 |
| Queens 25 | 2.15 | 8.34 | NuCS ×3.9 |
| Queens 30 | 19.7 | 144.6 | NuCS ×7.3 |
| Sudoku 16×16 | 3.84 | 1.22 | Choco ×3.1 |
| Vertex Cover 100 | — (timeout) | 287 | Choco |
Кому это вообще нужно
Если вы пишете прототип на Python и не хотите городить мост с Java — NuCS ваш выбор. Особенно для исследовательских задач, где нужно быстро перебирать модели. Пример: планирование производства или маршрутизация с сотнями переменных. NuCS справится, а код будет читаемым.
Но если задача уходит в продакшен с тысячами ограничений и сложными таблицами — Choco отрабатывает каждый цент. Кроме того, Java-экосистема даёт готовые коннекторы к базам, веб-сервисам и системам мониторинга. В NuCS таких вещей нет — только голый решатель.
Обратите внимание: в наших тестах NuCS вылетел в таймаут на задаче вершинного покрытия — графы с бинарными ограничениями сложнее фильтруются через bound consistency. Если ваш типичный сценарий — графовые задачи, не надейтесь на Python.
Резюме? Не существует универсального «лучшего» решателя. NuCS — для быстрых экспериментов, где важны отзывчивость и Python-экосистема. Choco — для тяжёлого артиллерийского продакшена. Но имейте в виду: к 2026 году альтернативы вроде OR-Tools от Google и даже собранная на коленке GPU-машина могут дать фору обоим, если задачу удаётся распараллелить. В мире CSP железо всё ещё рулит.