Python client for OAT (Optimization and Analysis Tooling) database
Project description
OatDB Python SDK
A Python client library for interacting with the OatDB (Optimization and Analysis Tooling) database backend.
Features
- ✅ Full support for all 30 OatDB API functions
- ✅ Logical operations (AND, OR, XOR, NOT, IMPLY, EQUIV)
- ✅ Cardinality constraints (AtLeast, AtMost, Equal)
- ✅ Linear inequality constraints (GeLineq)
- ✅ Property management
- ✅ DAG operations (sub, sub_many, validate, ranks)
- ✅ Constraint propagation
- ✅ Optimization solver (solve, solve_many)
- ✅ Node deletion and management
- ✅ Alias support for named constraints
- ✅ Type hints for better IDE support
Installation
pip install oat-python-sdk
Or with Poetry:
poetry add oat-python-sdk
Quick Start
from oatdb import OatClient, set_primitive, set_property, set_and, sub, solve
# Initialize client
client = OatClient("http://localhost:7061")
# Create primitives with bounds [min, max]
x = set_primitive("x", bound=1j) # [0, 1]
y = set_primitive("y", bound=10j) # [0, 10]
# Add properties
x_name = set_property(x, "name", "Variable X")
# Create constraints
constraint = set_and([x, y], alias="my_constraint")
# Extract DAG and solve
dag = sub(constraint)
solution = solve(
dag=dag,
objective={
x: 1,
y: 2
},
assume={
# Force constraint to be true
constraint: 1+1j
},
maximize=True
)
# Execute and get results
result = client.execute(solution)
print(result)
Core Concepts
Bounds
Bounds are represented as complex numbers where:
- Real part = lower bound
- Imaginary part = upper bound
# Bound [0, 1]
bound = 1j
# Bound [5, 10]
bound = 5 + 10j
# Access bounds from solution
solution_data = result[solution.out]
x_bounds = solution_data["x"] # [lower, upper] as list
Function Calls and Execution
All operations return FunctionCall objects that you execute using the client:
from oatdb import OatClient, set_primitive, set_and, sub
client = OatClient("http://localhost:7061")
# Create function calls
x = set_primitive("x", bound=1j)
y = set_primitive("y", bound=1j)
constraint = set_and([x, y])
# Execute a single operation
result = client.execute(constraint)
# Execute multiple operations
dag = sub(constraint)
result = client.execute_many([x, y, constraint, dag])
# Access results by the function call's output key
dag_data = result[dag.out]
Available Functions
All functions return FunctionCall objects that are executed using client.execute() or client.execute_many().
Primitive Operations
set_primitive(id: str, bound: complex = 1j, alias: Optional[str] = None)- Create a single primitiveset_primitives(ids: List[str], bound: complex = 1j)- Create multiple primitivesset_property(id: Union[str, FunctionCall], property: str, value: Any)- Set node property
Logical Operations
set_and(references: List, alias: Optional[str] = None)- AND operationset_or(references: List, alias: Optional[str] = None)- OR operationset_xor(references: List, alias: Optional[str] = None)- XOR operationset_not(references: List, alias: Optional[str] = None)- NOT operationset_imply(lhs, rhs, alias: Optional[str] = None)- Implication (lhs → rhs)set_equiv(lhs, rhs, alias: Optional[str] = None)- Equivalence (lhs ↔ rhs)
Cardinality Constraints
set_atleast(references: List, value: int, alias: Optional[str] = None)- At least N must be trueset_atmost(references: List, value: int, alias: Optional[str] = None)- At most N must be trueset_equal(references: List, value: Union[int, str], alias: Optional[str] = None)- Exactly N must be true
Linear Constraints
set_gelineq(coefficients: Dict, bias: int, alias: Optional[str] = None)- Greater-or-equal linear inequality (ax + b >= 0)
DAG Operations
sub(root)- Extract sub-DAG from a root nodesub_many(roots: List)- Extract multiple sub-DAGsget_node_ids(dag)- Get all node IDs in a DAGget_ids_from_dag(dag)- Get all node IDs from a DAG (alternative)validate(dag)- Validate DAG structureranks(dag)- Compute topological ranks
Alias Operations
get_id_from_alias(alias: str)- Get node ID from aliasget_alias(id)- Get alias for a node IDget_aliases_from_id(id)- Get all aliases for a node IDget_ids_from_aliases(aliases: List[str])- Get IDs for multiple aliases
Node Operations
get_node(id)- Get a single nodeget_nodes(ids: List)- Get multiple nodesget_property_values(property: str)- Get all nodes with a specific property
Propagation
propagate(assignments: Dict)- Propagate constraints with assignmentspropagate_many(many_assignments: List[Dict])- Propagate multiple assignment sets
Solver
solve(dag, objective: Dict, assume: Optional[Dict] = None, maximize: bool = True)- Solve single optimizationsolve_many(dag, objectives: List[Dict], assume: Optional[Dict] = None, maximize: bool = True)- Solve multiple optimizations
Deletion
delete_node(id)- Delete a single nodedelete_sub(roots: List)- Delete sub-DAGs from roots
Client Methods
OatClient(url: str)- Initialize client with server URLclient.execute(call: FunctionCall)- Execute a single function callclient.execute_many(calls: List[FunctionCall])- Execute multiple function calls
Complete Example
from oatdb import (
OatClient, set_primitive, set_property, set_and, set_or,
set_imply, set_atleast, set_gelineq, sub, solve
)
# Initialize
client = OatClient("http://localhost:7061")
# Create primitives
x = set_primitive("x", bound=10j)
y = set_primitive("y", bound=10j)
z = set_primitive("z", bound=10j)
# Add metadata
x_type = set_property(x, "type", "variable")
x_priority = set_property(x, "priority", 10)
# Create constraints
and_constraint = set_and([x, y], alias="both_xy")
or_constraint = set_or([y, z])
imply_constraint = set_imply(x, y) # x → y
# Cardinality: at least 2 must be true
atleast_2 = set_atleast([x, y, z], 2)
# Linear constraint: 2x + 3y - z + 5 >= 0
linear = set_gelineq(
coefficients={x: 2, y: 3, z: -1},
bias=5
)
# Combine all constraints
root = set_and([atleast_2, linear], alias="root")
# Extract DAG
dag = sub(root)
# Solve optimization: maximize 3x + 2y + z
solution = solve(
dag=dag,
objective={
x: 3,
y: 2,
z: 1
},
assume={
root: 1+1j
},
maximize=True
)
# Execute and get results
result = client.execute(solution)
print("Solution:")
for var, bounds in result.items():
if isinstance(bounds, complex):
print(f" {var}: [{bounds.real}, {bounds.imag}]")
Working with Aliases
from oatdb import OatClient, set_primitive, set_and, get_id_from_alias, get_alias
client = OatClient("http://localhost:7061")
# Create constraint with alias
x = set_primitive("x", bound=1j)
y = set_primitive("y", bound=1j)
constraint = set_and([x, y], alias="my_constraint")
# Execute creation
client.execute_many([x, y, constraint])
# Query by alias
id_from_alias = get_id_from_alias("my_constraint")
alias_from_id = get_alias(id_from_alias)
result = client.execute_many([id_from_alias, alias_from_id])
print(f"ID: {result[id_from_alias.out]}")
print(f"Alias: {result[alias_from_id.out]}")
Propagation Example
from oatdb import OatClient, set_primitive, set_and, propagate
client = OatClient("http://localhost:7061")
# Create AND constraint
a = set_primitive("a", bound=1j)
b = set_primitive("b", bound=1j)
c = set_primitive("c", bound=1j)
and_gate = set_and([a, b, c], alias="and_gate")
# Propagate: if AND is true, what can we infer?
prop_result = propagate(
assignments={
a: 1+1j,
b: 1+1j,
c: 1+1j,
and_gate: 1j # Upper bound only
}
)
result = client.execute(prop_result)
# Result will show that a, b, and c must all be [1, 1]
print(f"Inferred bounds: {result}")
Testing
Run the comprehensive test suite:
cd clients/Python
python tests/test_client.py
Or with Poetry:
poetry run python tests/test_client.py
Note: Make sure the OatDB server is running on http://localhost:7061 before running tests.
Run examples:
python examples.py
Requirements
- Python >= 3.10
- requests >= 2.31.0
Development
# Install with Poetry
poetry install
# Run tests
poetry run pytest
# Format code
poetry run black .
# Type checking
poetry run mypy oatdb
License
MIT
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file oatdb-0.4.132.tar.gz.
File metadata
- Download URL: oatdb-0.4.132.tar.gz
- Upload date:
- Size: 11.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.4 CPython/3.10.15 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f12f5dc6b926de08475a41a2b3e1bc0a43d54ef709c0f78919b0110a2e8457a9
|
|
| MD5 |
00d5c803169d898e487b213ae1902141
|
|
| BLAKE2b-256 |
659a974a35a7084817e7b44406d71664b23bf5ae8e36ce3c066630545002e937
|
File details
Details for the file oatdb-0.4.132-py3-none-any.whl.
File metadata
- Download URL: oatdb-0.4.132-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.4 CPython/3.10.15 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7d0a7d6cd7806ca1a576cdbe853645aedd8984bdbb85c3afe701144c62dc18b
|
|
| MD5 |
f5bab67749af69a0ac41364e6db6b69b
|
|
| BLAKE2b-256 |
12c6d3a47fb09c935e4ac3ceeeb9243f77fe993ad62118751644286a7f85edf5
|