@File : _base_archive.py @Time : 2024/06/07 12:17:34 @Author : Alejandro Marrero @Version : 1.0 @Contact : amarrerd@ull.edu.es @License : (C)Copyright 2024, Alejandro Marrero @Desc : None

Archive

Bases: ABC

Base Archive

Works as a foundation for all the types of archives allowed in Digneapy.

Source code in digneapy/archives/_archive.py
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
class Archive(ABC):
    """Base Archive

    Works as a foundation for all the types of archives allowed in Digneapy.
    """

    def __init__(
        self,
        initial_instances: Optional[Sequence[Instance]] = None,
    ):
        """Creates an instance of a Archive (unstructured) for QD algorithms

        Args:
            initial_instances (Sequence[Instance], optional): Instances to initialise the archive. Defaults to None.
        """
        self._storage: dict[Keys, list] = {
            Keys.instances: [],
            Keys.descriptors: [],
        }
        if initial_instances is not None and len(initial_instances) > 0:
            if check_valid_instance_batch(initial_instances):
                for instance in initial_instances:
                    self._storage[Keys.instances].append(instance)
                    self._storage[Keys.descriptors].append(instance.descriptor)
            else:
                raise TypeError(
                    "All objects of initial_instances must be of type Instance."
                )

    @property
    def instances(self) -> Sequence[Instance]:
        """Instances of the archive

        Returns:
            Sequence[Instance]: Sequence of instances stored in the archive.
        """
        return self._storage[Keys.instances]

    @property
    def descriptors(self) -> np.ndarray:
        """Descriptors of the instances

        Returns:
            np.ndarray: Returns a np.ndarray with the descriptors of
                the instances stored in the archive
        """
        return np.asarray(self._storage[Keys.descriptors])

    @abstractmethod
    def extend(
        self,
        instances: Sequence[Instance],
        *args,
        **kwargs,
    ):
        """Extends the archive with a collection of instances.

        This method must be implemented by each subclass of Archive.
        Args:
            instances (Sequence[Instance]): Collection of instances to insert in the archive.

        Raises:
            NotImplementedError
        """
        raise NotImplementedError("To be implemented in subclasses")

    def __call__(self, *args, **kwargs):
        raise NotImplementedError(f"Not implemented for {self.__class__.__name__}")

    def __iter__(self) -> Iterator[Instance]:
        """Iterator of the Archive.

        Allows users to iterate the instances of the archive

        Returns:
            Iterator: Returns an Iterator of Instances stored
        """
        return iter(self._storage[Keys.instances])

    def __str__(self):
        return f"Archive(|{len(self)}|)"

    def __repr__(self):
        return self.__str__()

    def __array__(self, dtype=object, copy: Optional[bool] = None) -> np.ndarray:
        """Cast the Archive to an array

        Args:
            dtype (optional): Data type of the resulting array. Defaults to object.
            copy (bool, optional): Whether to copy the objects or reference them. Defaults to None.

        Returns:
            np.ndarray: Array with the instances stored in the archive
        """
        return np.asarray(self._storage[Keys.instances], dtype=object, copy=copy)

    def __eq__(self, other: Self) -> bool:
        """Compares two archives

        Args:
            other (Archive): Other archive type to compare

        Returns:
            bool: Returns True if both archives have the same amount of instances
                and all of those instances are the same when compared Inst_a == Inst_b.
        """
        if not isinstance(other, Archive):
            raise TypeError(f"Archives cannot be compared with {other.__class__}.")

        self_cls = self.__class__
        other_cls = other.__class__
        if self_cls != other_cls:
            raise TypeError(
                f"Cannot compared an Archive of class {self_cls} with another of class {other_cls}. Use the same classes."
            )

        return len(self) == len(other) and all(
            a == b
            for a, b in zip(
                self._storage[Keys.instances], other._storage[Keys.instances]
            )
        )

    def __len__(self) -> int:
        """Length of the Archive

        Returns:
            int: Number of instances stored in the archive
        """
        return len(self._storage[Keys.instances])

    def to_dict(self) -> dict:
        """Converts the archive into a dictionary

        This method could be extended in the subclasses to include
        extra information. In this class, in only includes the instances.

        Returns:
            dict: Dictionary with the instances stored in the archive
        """
        return {
            "instances": {
                i: instance.to_dict()
                for i, instance in enumerate(self._storage[Keys.instances])
            }
        }

descriptors property

Descriptors of the instances

Returns:
  • ndarray

    np.ndarray: Returns a np.ndarray with the descriptors of the instances stored in the archive

instances property

Instances of the archive

Returns:
  • Sequence[Instance]

    Sequence[Instance]: Sequence of instances stored in the archive.

__array__(dtype=object, copy=None)

Cast the Archive to an array

Parameters:
  • dtype (optional, default: object ) –

    Data type of the resulting array. Defaults to object.

  • copy (bool, default: None ) –

    Whether to copy the objects or reference them. Defaults to None.

Returns:
  • ndarray

    np.ndarray: Array with the instances stored in the archive

Source code in digneapy/archives/_archive.py
117
118
119
120
121
122
123
124
125
126
127
def __array__(self, dtype=object, copy: Optional[bool] = None) -> np.ndarray:
    """Cast the Archive to an array

    Args:
        dtype (optional): Data type of the resulting array. Defaults to object.
        copy (bool, optional): Whether to copy the objects or reference them. Defaults to None.

    Returns:
        np.ndarray: Array with the instances stored in the archive
    """
    return np.asarray(self._storage[Keys.instances], dtype=object, copy=copy)

__eq__(other)

Compares two archives

Parameters:
  • other (Archive) –

    Other archive type to compare

Returns:
  • bool( bool ) –

    Returns True if both archives have the same amount of instances and all of those instances are the same when compared Inst_a == Inst_b.

Source code in digneapy/archives/_archive.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def __eq__(self, other: Self) -> bool:
    """Compares two archives

    Args:
        other (Archive): Other archive type to compare

    Returns:
        bool: Returns True if both archives have the same amount of instances
            and all of those instances are the same when compared Inst_a == Inst_b.
    """
    if not isinstance(other, Archive):
        raise TypeError(f"Archives cannot be compared with {other.__class__}.")

    self_cls = self.__class__
    other_cls = other.__class__
    if self_cls != other_cls:
        raise TypeError(
            f"Cannot compared an Archive of class {self_cls} with another of class {other_cls}. Use the same classes."
        )

    return len(self) == len(other) and all(
        a == b
        for a, b in zip(
            self._storage[Keys.instances], other._storage[Keys.instances]
        )
    )

__init__(initial_instances=None)

Creates an instance of a Archive (unstructured) for QD algorithms

Parameters:
  • initial_instances (Sequence[Instance], default: None ) –

    Instances to initialise the archive. Defaults to None.

Source code in digneapy/archives/_archive.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
def __init__(
    self,
    initial_instances: Optional[Sequence[Instance]] = None,
):
    """Creates an instance of a Archive (unstructured) for QD algorithms

    Args:
        initial_instances (Sequence[Instance], optional): Instances to initialise the archive. Defaults to None.
    """
    self._storage: dict[Keys, list] = {
        Keys.instances: [],
        Keys.descriptors: [],
    }
    if initial_instances is not None and len(initial_instances) > 0:
        if check_valid_instance_batch(initial_instances):
            for instance in initial_instances:
                self._storage[Keys.instances].append(instance)
                self._storage[Keys.descriptors].append(instance.descriptor)
        else:
            raise TypeError(
                "All objects of initial_instances must be of type Instance."
            )

__iter__()

Iterator of the Archive.

Allows users to iterate the instances of the archive

Returns:
  • Iterator( Iterator[Instance] ) –

    Returns an Iterator of Instances stored

Source code in digneapy/archives/_archive.py
101
102
103
104
105
106
107
108
109
def __iter__(self) -> Iterator[Instance]:
    """Iterator of the Archive.

    Allows users to iterate the instances of the archive

    Returns:
        Iterator: Returns an Iterator of Instances stored
    """
    return iter(self._storage[Keys.instances])

__len__()

Length of the Archive

Returns:
  • int( int ) –

    Number of instances stored in the archive

Source code in digneapy/archives/_archive.py
156
157
158
159
160
161
162
def __len__(self) -> int:
    """Length of the Archive

    Returns:
        int: Number of instances stored in the archive
    """
    return len(self._storage[Keys.instances])

extend(instances, *args, **kwargs) abstractmethod

Extends the archive with a collection of instances.

This method must be implemented by each subclass of Archive. Args: instances (Sequence[Instance]): Collection of instances to insert in the archive.

Source code in digneapy/archives/_archive.py
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@abstractmethod
def extend(
    self,
    instances: Sequence[Instance],
    *args,
    **kwargs,
):
    """Extends the archive with a collection of instances.

    This method must be implemented by each subclass of Archive.
    Args:
        instances (Sequence[Instance]): Collection of instances to insert in the archive.

    Raises:
        NotImplementedError
    """
    raise NotImplementedError("To be implemented in subclasses")

to_dict()

Converts the archive into a dictionary

This method could be extended in the subclasses to include extra information. In this class, in only includes the instances.

Returns:
  • dict( dict ) –

    Dictionary with the instances stored in the archive

Source code in digneapy/archives/_archive.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def to_dict(self) -> dict:
    """Converts the archive into a dictionary

    This method could be extended in the subclasses to include
    extra information. In this class, in only includes the instances.

    Returns:
        dict: Dictionary with the instances stored in the archive
    """
    return {
        "instances": {
            i: instance.to_dict()
            for i, instance in enumerate(self._storage[Keys.instances])
        }
    }