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