def children(self, ctype=_no_ctype): """Iterate over the children of this block. Args: ctype: Indicates the category of children to include. The default value indicates that all categories should be included. Returns: iterator of child objects """ self_byctype = self.__byctype if self_byctype is None: # empty return # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) if ctype is _no_ctype: for child in self.__order.values(): yield child elif self_byctype.__class__ is _ordered_dict_: # large-block storage if ctype in self_byctype: for child in self_byctype[ctype].values(): yield child elif self_byctype.__class__ is int: # small-block storage # (self_byctype is a union of hash bytes) h_ = hash(ctype) if (self_byctype & h_) == h_: for child in self.__order.values(): if child.ctype is ctype: yield child elif self_byctype is ctype: # storing a single ctype for child in self.__order.values(): yield child
def children(self, ctype=_no_ctype): """Iterate over the children of this block. Args: ctype: Indicates the category of children to include. The default value indicates that all categories should be included. Returns: iterator of child objects """ self_byctype = self.__byctype if self_byctype is None: # empty return # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) if ctype is _no_ctype: for child in self.__order.values(): yield child elif self_byctype.__class__ is _ordered_dict_: # large-block storage if ctype in self_byctype: for child in self_byctype[ctype].values(): yield child elif self_byctype.__class__ is int: # small-block storage # (self_byctype is a union of hash bytes) h_ = hash(ctype) if (self_byctype & h_) == h_: for child in self.__order.values(): if child.ctype is ctype: yield child elif self_byctype is ctype: # storing a single ctype for child in self.__order.values(): yield child
def preorder_traversal(node, ctype=_no_ctype, active=True, descend=True): """ A generator that yields each object in the storage tree (including the root object) using a preorder traversal. Args: node: The root object. ctype: Indicates the category of components to include. The default value indicates that all categories should be included. active (:const:`True`/:const:`None`): Controls whether or not to filter the iteration to include only the active part of the storage tree. The default is :const:`True`. Setting this keyword to :const:`None` causes the active status of objects to be ignored. descend (bool, function): Controls if a container object should be descended into during the traversal. When a function is supplied, each container object will be passed into it and the return value will indicate if the traversal continues into children of the container. Default is True, which is equivalent to `lambda x: True`. Returns: iterator of objects in the storage tree, including the root object """ assert active in (None, True) # if not active, then nothing below is active if (active is not None) and \ (not node.active): return # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) # convert descend to a function descend = _convert_descend_into(descend) if (ctype is _no_ctype) or \ (node.ctype is ctype) or \ (node.ctype._is_heterogeneous_container): yield node if (not node._is_container) or \ (not descend(node)): return for child in node.children(): child_ctype = child.ctype if not child._is_container: # not a container if (active is None) or \ child.active: if (ctype is _no_ctype) or \ (child_ctype is ctype): yield child elif child._is_heterogeneous_container: # a heterogeneous container, so use # its traversal method for obj in preorder_traversal( child, ctype=ctype, active=active, descend=descend): yield obj else: # a homogeneous container if child_ctype._is_heterogeneous_container: # this function ensures that the user provided # descend function is not called twice # on heterogeneous containers def descend_(obj_): if obj_._is_heterogeneous_container: return False else: return descend(obj_) for obj in preorder_traversal( child, active=active, descend=descend_): if not obj._is_heterogeneous_container: yield obj else: # a heterogeneous container, so use # its traversal method and reapply the # ctype filter for item in preorder_traversal( obj, ctype=ctype, active=active, descend=descend): yield item elif (ctype is _no_ctype) or \ (child_ctype is ctype): for obj in preorder_traversal( child, active=active, descend=descend): yield obj
def components(self, ctype=_no_ctype, active=True, descend_into=True): """ Generates an efficient traversal of all components stored under this container. Components are categorized objects that are either (1) not containers, or (2) are heterogeneous containers. Args: ctype: Indicates the category of components to include. The default value indicates that all categories should be included. active (:const:`True`/:const:`None`): Controls whether or not to filter the iteration to include only the active part of the storage tree. The default is :const:`True`. Setting this keyword to :const:`None` causes the active status of objects to be ignored. descend_into (bool, function): Indicates whether or not to descend into a heterogeneous container. Default is True, which is equivalent to `lambda x: True`, meaning all heterogeneous containers will be descended into. Returns: iterator of components in the storage tree """ assert active in (None, True) # if not active, then nothing below is active if (active is not None) and \ (not self.active): return # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) # convert descend_into to a function if # it is not already one descend_into = _convert_descend_into(descend_into) if ctype is _no_ctype: for child in self.children(): if (active is not None) and \ (not child.active): continue if not child._is_container: yield child elif child._is_heterogeneous_container: yield child if descend_into(child): for obj in child.components( active=active, descend_into=descend_into): yield obj elif (descend_into is _convert_descend_into._false) or \ (not child.ctype._is_heterogeneous_container): assert child._is_container for obj in child.components(active=active): yield obj else: assert child._is_container for obj in child.components( active=active): assert obj._is_heterogeneous_container yield obj if descend_into(obj): for item in obj.components( active=active, descend_into=descend_into): yield item else: for item in heterogeneous_containers(self, active=active, descend_into=descend_into): for child in item.children(ctype=ctype): if (not child._is_container) or \ child._is_heterogeneous_container: if (active is None) or \ child.active: yield child else: assert child._is_container for obj in child.components(active=active): yield obj
def heterogeneous_containers(node, ctype=_no_ctype, active=True, descend_into=True): """ A generator that yields all heterogeneous containers included in an object storage tree, including the root object. Heterogeneous containers are categorized objects with a category type different from their children. Args: node: The root object. ctype: Indicates the category of objects to include. The default value indicates that all categories should be included. active (:const:`True`/:const:`None`): Controls whether or not to filter the iteration to include only the active part of the storage tree. The default is :const:`True`. Setting this keyword to :const:`None` causes the active status of objects to be ignored. descend_into (bool, function): Indicates whether or not to descend into a heterogeneous container. Default is True, which is equivalent to `lambda x: True`, meaning all heterogeneous containers will be descended into. Returns: iterator of heterogeneous containers in the storage tree, include the root object. """ assert active in (None, True) # if not active, then nothing below is active if (active is not None) and \ (not node.active): return if not node.ctype._is_heterogeneous_container: return if not node._is_heterogeneous_container: assert node._is_container # a homogeneous container that stores # heterogeneous objects for obj in node.components(active=active): assert obj._is_heterogeneous_container for item in heterogeneous_containers( obj, ctype=ctype, active=active, descend_into=descend_into): yield item return # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) assert (ctype is _no_ctype) or \ ctype._is_heterogeneous_container # convert descend_into to a function if # it is not already one descend_into = _convert_descend_into(descend_into) # a heterogeneous container if (ctype is _no_ctype) or \ (node.ctype is ctype): yield node if not descend_into(node): return for child_ctype in node.child_ctypes(): if not child_ctype._is_heterogeneous_container: continue for child in node.children(ctype=child_ctype): assert child._is_container if (active is not None) and \ (not child.active): continue for obj in heterogeneous_containers( child, ctype=ctype, active=active, descend_into=descend_into): yield obj
def components(self, ctype=_no_ctype, active=None, descend_into=True): """ Generates an efficient traversal of all components stored under this container. Components are categorized objects that are either not containers, or are heterogeneous containers having a category type different from their children. Args: ctype: Indicates the category of components to include. The default value indicates that all categories should be included. active (:const:`True`/:const:`None`): Set to :const:`True` to indicate that only active objects should be included. The default value of :const:`None` indicates that all components (including those that have been deactivated) should be included. descend_into (bool): Indicates whether or not to descend into heterogeneous containers. Default is True. Returns: iterator of objects in the storage tree """ assert active in (None, True) # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) if ctype is _no_ctype: # if not active, then nothing below is active if (active is not None) and \ (not self.active): return for child in self.children(): if not child._is_container: if (active is None) or \ child.active: yield child elif child._is_heterogeneous_container: if (active is None) or \ child.active: yield child if descend_into: for obj in child.components(active=active, descend_into=True): yield obj elif descend_into and \ child.ctype._is_heterogeneous_container: assert child._is_container for obj in child.components(active=active): assert obj._is_container and \ obj._is_heterogeneous_container yield obj for item in obj.components(active=active, descend_into=True): yield item else: assert child._is_container for obj in child.components(active=active): yield obj else: if not descend_into: # if not active, then nothing below is active if (active is not None) and \ (not self.active): return items = (self, ) else: items = self.heterogeneous_containers(active=active, descend_into=True) for item in items: for child in item.children(ctype=ctype): if (not child._is_container) or \ child._is_heterogeneous_container: if (active is None) or \ child.active: yield child else: assert child._is_container for obj in child.components(active=active): yield obj
def heterogeneous_containers(self, ctype=_no_ctype, active=None, descend_into=True): """ A generator that visits each heterogeneous container in the storage tree. Heterogeneous containers are categorized objects, such as blocks, with a category type different from their children. Args: ctype: Indicates the category of objects to include. The default value indicates that all categories should be included. active (:const:`True`/:const:`None`): Set to :const:`True` to indicate that only active objects should be included. The default value of :const:`None` indicates that all components (including those that have been deactivated) should be included. descend_into (bool): Indicates whether or not to descend into heterogeneous containers. Default is True. Returns: iterator of objects in the storage tree """ assert active in (None, True) # if not active, then nothing below is active if (active is not None) and \ (not self.active): return # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) if (ctype is _no_ctype) or \ (self.ctype is ctype): yield self for child_ctype in self.child_ctypes(): if not child_ctype._is_heterogeneous_container: continue for child in self.children(ctype=child_ctype): assert child._is_container if child._is_heterogeneous_container: if not descend_into: if (active is None) or \ child.active: if (ctype is _no_ctype) or \ (child_ctype is ctype): yield child else: for obj in child.heterogeneous_containers( ctype=ctype, active=active, descend_into=True): yield obj else: # a homogeneous container for obj in child.components(active=active): assert obj._is_heterogeneous_container if not descend_into: if (ctype is _no_ctype) or \ (child_ctype is ctype): yield obj else: for item in obj.heterogeneous_containers( ctype=ctype, active=active, descend_into=True): yield item
def preorder_traversal(self, ctype=_no_ctype, active=None, descend=None): """ A generator that visits each node in the storage tree using a preorder traversal. This includes all components and all component containers (optionally) matching the requested type. Args: ctype: Indicates the category of components to include. The default value indicates that all categories should be included. active (:const:`True`/:const:`None`): Set to :const:`True` to indicate that only active objects should be included. The default value of :const:`None` indicates that all components (including those that have been deactivated) should be included. descend: A function that can be used to control if a container object should be descended into. When the return value is False, the traversal will not continue into children of the container. Returns: iterator of objects in the storage tree """ assert active in (None, True) # if not active, then nothing below is active if (active is not None) and \ (not self.active): return # convert AML types into Kernel types (hack for the # solver interfaces) ctype = _convert_ctype.get(ctype, ctype) if (descend is not None) and \ (not descend(self)): yield self return else: yield self for child in self.children(): child_ctype = child.ctype if not child._is_container: # not a container if (active is None) or \ child.active: if (ctype is _no_ctype) or \ (child_ctype is ctype): yield child elif child._is_heterogeneous_container: # a heterogeneous container, so use # its traversal method for obj in child.preorder_traversal(ctype=ctype, active=active, descend=descend): yield obj else: # a homogeneous container if child_ctype._is_heterogeneous_container: def descend_(obj): if obj._is_heterogeneous_container or \ (descend is None): return True else: return descend(obj) for obj in child.preorder_traversal(active=active, descend=descend_): if not obj._is_heterogeneous_container: yield obj else: # a heterogeneous container, so use # its traversal method for item in obj.preorder_traversal( ctype=ctype, active=active, descend=descend): yield item elif (ctype is _no_ctype) or \ (child_ctype is ctype): for obj in child.preorder_traversal(active=active, descend=descend): yield obj