Python client for OAT (Optimization and Analysis Tooling) database
Project description
OatClient - Python Client for OAT Database
A Python client library for interacting with the OAT (Optimization and Analysis Tooling) database backend.
Features
- ✅ Full support for logical operations (AND, OR, XOR, NOT, IMPLY, EQUIV)
- ✅ Cardinality constraints (AtLeast, AtMost, Equal)
- ✅ Linear inequality constraints (GeLineq)
- ✅ Property management with filtering
- ✅ Advanced query system with Filter helpers
- ✅ Optimization solver integration
- ✅ Buffered compilation modes (Instant/OnDemand)
- ✅ Type hints for better IDE support
Installation
pip install oat
Quick Start
from OatClient import OatClient, CompilationSetting
# Initialize client
client = OatClient(
base_url="http://localhost:7062",
compilation_settings=CompilationSetting.INSTANT
)
# Create primitives
x = client.set_primitive("x", bound=complex(0, 1))
y = client.set_primitive("y", bound=complex(0, 1))
z = client.set_primitive("z", bound=complex(0, 1))
# Add properties
client.set_property(x, "name", "Variable X")
# Create constraints
at_least_2 = client.set_atleast([x, y, z], 2)
# Solve
solutions = client.solve(
roots=[at_least_2],
objectives=[{x: -1, y: -2}],
assume={at_least_2: complex(1, 1)},
maximize=True
)
if solutions:
solution = solutions[0]
print(f"x = {solution[x]}") # complex(lower, upper)
Available Methods
Primitive Operations
set_primitive(id: str, bound: complex = complex(0, 1)) -> str- Create a single primitiveset_primitives(ids: List[str], bound: complex = complex(0, 1)) -> List[str]- Create multiple primitivesset_property(id: str, property: str, value: Any) -> None- Set node property
Logical Operations
set_and(references: List[str]) -> str- AND operationset_or(references: List[str]) -> str- OR operationset_xor(references: List[str]) -> str- XOR operationset_not(references: List[str]) -> str- NOT operationset_imply(lhs: str, rhs: str) -> str- Implication (lhs → rhs)set_equiv(lhs: str, rhs: str) -> str- Equivalence (lhs ↔ rhs)
Cardinality Constraints
set_atleast(references: List[str], value: int) -> str- At least N must be trueset_atmost(references: List[str], value: int) -> str- At most N must be trueset_equal(references: List[str], value: Union[int, str]) -> str- Exactly N must be true
Linear Constraints
set_gelineq(coefficients: Dict[str, int], bias: int) -> str- Greater-or-equal linear inequality
Query Operations
get_node_ids(filter: Optional[dict] = None) -> List[str]- Get node IDs with optional filteringget_properties(id: str) -> Dict[str, Any]- Get all properties for a nodeget_many_properties(ids: List[str]) -> Dict[str, Dict[str, Any]]- Get properties for multiple nodes
Solver
solve(roots: List[str], objectives: List[Dict[str, int]], assume: Dict[str, complex] = {}, maximize: bool = True) -> List[dict]- Solve optimization problem
Utility
health_check() -> bool- Check server healthcompile() -> None- Manually compile buffered operationsdelete_node(id: str) -> None- Delete a node
Bounds
In OatClient, bounds are represented as complex numbers where:
realpart = lower boundimagpart = upper bound
# Bound representing [0, 1]
bound = complex(0, 1)
# Bound representing [5, 10]
bound = complex(5, 10)
# Access bounds
lower = bound.real # 5
upper = bound.imag # 10
Filter Helpers
Use the Filter class to build complex queries:
from OatClient import Filter
# Simple property filter
nodes = client.get_node_ids(Filter.property_equals("type", "constraint"))
# Property exists
nodes = client.get_node_ids(Filter.property_exists("name"))
# Numeric comparisons
nodes = client.get_node_ids(Filter.property_gt("priority", 5))
# Complex filters
nodes = client.get_node_ids(Filter.and_(
Filter.property_exists("name"),
Filter.property_gt("priority", 5),
Filter.node_id_starts_with("task_")
))
# OR and NOT
nodes = client.get_node_ids(Filter.or_(
Filter.property_equals("status", "active"),
Filter.not_(Filter.property_exists("archived"))
))
Available Filter Methods
Filter.property_equals(key: str, value: Any)- Property equals valueFilter.property_exists(key: str)- Property existsFilter.property_contains(key: str, substring: str)- Property contains substringFilter.property_gt(key: str, value: float)- Property greater thanFilter.property_gte(key: str, value: float)- Property greater than or equalFilter.property_lt(key: str, value: float)- Property less thanFilter.property_lte(key: str, value: float)- Property less than or equalFilter.node_id_equals(node_id: str)- Node ID equalsFilter.node_id_starts_with(prefix: str)- Node ID starts with prefixFilter.and_(*expressions)- Combine with ANDFilter.or_(*expressions)- Combine with ORFilter.not_(expression)- Negate expression
Compilation Modes
Instant Compilation (Default)
Operations are compiled immediately:
client = OatClient(base_url, CompilationSetting.INSTANT)
x = client.set_primitive("x") # Compiled immediately
On-Demand Compilation
Operations are buffered and compiled in batch:
client = OatClient(base_url, CompilationSetting.ON_DEMAND)
x = client.set_primitive("x") # Buffered
y = client.set_primitive("y") # Buffered
client.compile() # Compile all buffered operations
Complete Example
from OatClient import OatClient, CompilationSetting, Filter
# Initialize
client = OatClient("http://localhost:7062", CompilationSetting.INSTANT)
# Create primitives
a = client.set_primitive("a")
b = client.set_primitive("b")
c = client.set_primitive("c")
# Add metadata
client.set_property(a, "type", "task")
client.set_property(b, "type", "task")
client.set_property(c, "type", "resource")
client.set_property(a, "priority", 10)
# Create logical constraints
and_constraint = client.set_and([a, b])
or_constraint = client.set_or([b, c])
imply_constraint = client.set_imply(a, b) # a → b
# Create cardinality constraint
atleast_2 = client.set_atleast([a, b, c], 2)
# Query nodes
tasks = client.get_node_ids(Filter.property_equals("type", "task"))
print(f"Tasks: {tasks}")
high_priority = client.get_node_ids(Filter.property_gt("priority", 5))
print(f"High priority: {high_priority}")
# Solve with objectives
solutions = client.solve(
roots=[atleast_2],
objectives=[{a: -1, b: -2}], # Minimize weighted sum
assume={atleast_2: complex(1, 1)}, # Force constraint to be true
maximize=True
)
if solutions:
for i, sol in enumerate(solutions):
print(f"\nSolution {i + 1}:")
for var, bound in sol.items():
print(f" {var}: [{int(bound.real)}, {int(bound.imag)}]")
Requirements
- Python >= 3.10
- requests
License
[Your License Here]
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 oat_python_sdk-0.1.3.tar.gz.
File metadata
- Download URL: oat_python_sdk-0.1.3.tar.gz
- Upload date:
- Size: 6.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.4 CPython/3.11.5 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
006ebc01155b5cd963bec0f921cf02e25aa57416f5da9ba51aaef3800b24bcaf
|
|
| MD5 |
69aede85822ea49ecbf5f05cd51b47ad
|
|
| BLAKE2b-256 |
c61d32573414fe3efb64266155143a87ecaf96d68d7363f52ffb3e625e237471
|
File details
Details for the file oat_python_sdk-0.1.3-py3-none-any.whl.
File metadata
- Download URL: oat_python_sdk-0.1.3-py3-none-any.whl
- Upload date:
- Size: 7.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.4 CPython/3.11.5 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0302bd9459487a2f83b0bb6f11d8881d65ac09e634fc68679503114c47c2e151
|
|
| MD5 |
be650140984b3bdf2b9b4631da2b9681
|
|
| BLAKE2b-256 |
20bf71518ab41103dc91d6ab9f6fc5e206661c691b1f181d37929364df0519ab
|