Source code for sherpa_ai.output_parsers.self_consistency.abstract_objects

from collections import defaultdict
from typing import Union

from pydantic import BaseModel, ConfigDict

from sherpa_ai.output_parsers.self_consistency.abstractors import (
    AttributeAbstractor,
    CountingAttributeAbstractor,
)
from sherpa_ai.output_parsers.self_consistency.distributions import Distribution
from sherpa_ai.output_parsers.self_consistency.object_aggregator import ObjectAggregator


[docs] class AbstractObject(BaseModel): """ Abstract object that maps each attribute into a distribution """ model_config = ConfigDict(arbitrary_types_allowed=True) obj_schema: type[BaseModel] """ Schema of the object, used to validate the object. """ obj_dict: dict[str, Union[Distribution, dict]] = {}
[docs] @classmethod def from_aggregator(cls, obj_aggregator: ObjectAggregator) -> "AbstractObject": """ Create an AbstractObject from an ObjectAggregator. Args: obj_aggregator (ObjectAggregator): The ObjectAggregator to convert. Returns: AbstractObject: An instance of AbstractObject with the aggregated data. """ counting_abstractor = CountingAttributeAbstractor() # TODO: Support other types of abstractors based on the attribute type abstractor_map = defaultdict(lambda: counting_abstractor) # Recursively abstract the object dictionary using the abstractor map abstracted_dict = abstract_recursive( obj_aggregator.obj_dict, abstractor_map, obj_aggregator.value_weight_map ) return cls( obj_schema=obj_aggregator.obj_schema, obj_dict=abstracted_dict, )
def abstract_recursive( obj_dict: dict[str, Union[list, dict]], abstractor_map: dict[str, AttributeAbstractor], value_weight_map: dict[str, Union[dict, float]] = {}, ) -> dict[str, Union[list, Distribution]]: """ Recursively abstract the object dictionary using the provided abstractor. Args: obj_dict (dict[str, Union[list, dict]]): The object dictionary to abstract. abstractor_map (dict[str, AttributeAbstractor]): A mapping of attribute names to abstractors. Returns: dict[str, Union[list, Distribution]]: The abstracted object dictionary. """ # noqa: E501 abstracted_dict = {} for key, value in obj_dict.items(): if isinstance(value, list): # If the value is a list, abstract it using the corresponding abstractor abstractor = abstractor_map[key] weight_map = value_weight_map.get(key, {}) abstracted_dict[key] = abstractor.abstract(value, weight_map) elif isinstance(value, dict): # If the value is a dictionary, recursively abstract it abstracted_dict[key] = abstract_recursive( value, abstractor_map, value_weight_map.get(key, {}) ) else: raise TypeError(f"Unsupported type for key '{key}': {type(value)}") return abstracted_dict