103 lines
2.9 KiB
Python
103 lines
2.9 KiB
Python
import enum
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
from typing import Iterator
|
|
from ..common import DeviceKind, Circuit
|
|
|
|
|
|
class ResultPriority(enum.Enum):
|
|
"""
|
|
The priority of the result.
|
|
"""
|
|
|
|
LESS_DEVICES = enum.auto()
|
|
"""Less devices is the first priority."""
|
|
MORE_ACCURACY = enum.auto()
|
|
"""More accuracy is the first priority."""
|
|
|
|
|
|
@dataclass
|
|
class ResolverRequest:
|
|
"""
|
|
The request object for the resolver.
|
|
"""
|
|
|
|
device_kind: DeviceKind
|
|
"""The kind of device to resolve."""
|
|
target_value: float
|
|
"""The target value of the device."""
|
|
tolerance: float
|
|
"""The tolerance of the device."""
|
|
result_priority: ResultPriority
|
|
"""The priority of the result."""
|
|
count_limit: int
|
|
"""The limit of the count of results."""
|
|
|
|
|
|
class ResolverResult:
|
|
"""
|
|
The result of the resolver.
|
|
"""
|
|
|
|
circuit: Circuit
|
|
"""The circuit of the result."""
|
|
|
|
__value_cache: float | None
|
|
"""The cache of the circuit value."""
|
|
__difference_cache: float | None
|
|
"""The cache of the difference between the target value and the circuit value."""
|
|
__relative_difference_cache: float | None
|
|
"""The cache of the relative difference between the target value and the circuit value."""
|
|
|
|
def __init__(self, circuit: Circuit):
|
|
self.circuit = circuit
|
|
self.__value_cache = None
|
|
self.__difference_cache = None
|
|
self.__relative_difference_cache = None
|
|
|
|
def compute(self, device_kind: DeviceKind) -> float:
|
|
"""
|
|
Compute the circuit value.
|
|
"""
|
|
if self.__value_cache is None:
|
|
self.__value_cache = self.circuit.compute(device_kind)
|
|
return self.__value_cache
|
|
|
|
def difference(self, target_value: float, device_kind: DeviceKind) -> float:
|
|
"""
|
|
Get the difference between the target value and the circuit value.
|
|
"""
|
|
if self.__difference_cache is None:
|
|
self.__difference_cache = abs(
|
|
target_value - self.circuit.compute(device_kind)
|
|
)
|
|
return self.__difference_cache
|
|
|
|
def relative_difference(
|
|
self, target_value: float, device_kind: DeviceKind
|
|
) -> float:
|
|
"""
|
|
Get the relative difference between the target value and the circuit value.
|
|
"""
|
|
if self.__relative_difference_cache is None:
|
|
self.__relative_difference_cache = (
|
|
abs(target_value - self.circuit.compute(device_kind)) / target_value
|
|
)
|
|
return self.__relative_difference_cache
|
|
|
|
def len_devices(self) -> int:
|
|
"""
|
|
Get the number of devices in the circuit.
|
|
"""
|
|
return self.circuit.len_devices()
|
|
|
|
|
|
class Resolver(ABC):
|
|
"""
|
|
Abstract base class for all resolvers.
|
|
"""
|
|
|
|
@abstractmethod
|
|
def resolve(self, request: ResolverRequest) -> Iterator[ResolverResult]:
|
|
pass
|