Esempio n. 1
0
def test_frozendict_api():
    # all the read-only methods that are fine
    through_methods = [
        '__class__', '__cmp__', '__contains__', '__delattr__', '__dir__',
        '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__',
        '__gt__', '__init__', '__iter__', '__le__', '__len__', '__lt__',
        '__ne__', '__new__', '__or__', '__reduce__', '__reversed__', '__ror__',
        '__setattr__', '__sizeof__', '__str__', 'copy', 'get', 'has_key',
        'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'values',
        'viewitems', 'viewkeys', 'viewvalues'
    ]

    fd = FrozenDict()
    ret = []
    for attrname in dir(fd):
        if attrname == '_hash':  # in the dir, even before it's set
            continue
        attr = getattr(fd, attrname)
        if not callable(attr):
            continue

        if getattr(FrozenDict, attrname) == getattr(
                dict, attrname, None) and attrname not in through_methods:
            assert attrname == False
            ret.append(attrname)

    import copy
    assert copy.copy(fd) is fd
Esempio n. 2
0
def extract_deps(conn, sent, use_conllu_feats=False):
    for idx, tok in enumerate(sent):
        assert tok["id"] == idx + 1
    tree = sent.to_tree()
    if use_conllu_feats:
        # XXX: Might be good add an option to combine both?
        lemma_map, all_lemma_feats = conllu_to_indexed(sent)
    else:
        lemma_map, all_lemma_feats = index_sentence(
            (token["form"] for token in sent))
    tree_index = {}
    make_tree_index(tree, tree_index)
    for lemma_idx, key_lemma, word in iter_match_cands(conn, lemma_map,
                                                       all_lemma_feats):
        lemma_id = lemma_idx + 1
        used_cands = frozenset((lemma_id, ))
        if word["key_is_head"]:
            node = tree_index[lemma_idx]
            head_idx = node.token["head"]
            if head_idx != 0:
                used_cands |= frozenset((head_idx, ))
        matches = select_dep_step(
            all_lemma_feats,
            tree_index,
            word["subwords"],
            expand_node(tree_index, lemma_id),
            frozenset((lemma_id, )),
            frozenset((word["key_idx"], )),
            FrozenDict(((word["key_idx"], frozenset((lemma_idx, ))), )),
        )
        if matches:
            yield matches, word
Esempio n. 3
0
 def step(dir):
     return select_tok_step(
         lambda n: n + dir,
         extend_wildcards,
         all_lemma_feats,
         subwords,
         lemma_idx + dir,
         word["key_idx"] + dir,
         FrozenDict(),
     )
Esempio n. 4
0
def extract_toks_indexed(
    conn,
    lemma_map: Dict[str, int],
    all_lemma_feats: List[Dict[str, str]],
    extend_wildcards=True,
):
    key_lemmas, words = get_matchers(conn, lemma_map)
    for lemma_idx, key_lemma, word in iter_match_cands(conn, lemma_map,
                                                       all_lemma_feats):
        # Check lemma and feats for other lemmas
        subwords = list(enumerate(word["subwords"]))

        def step(dir):
            return select_tok_step(
                lambda n: n + dir,
                extend_wildcards,
                all_lemma_feats,
                subwords,
                lemma_idx + dir,
                word["key_idx"] + dir,
                FrozenDict(),
            )

        left_matches = step(-1)
        if not left_matches:
            continue
        right_matches = step(1)
        if not right_matches:
            continue
        key_matching = FrozenDict(((word["key_idx"], frozenset(
            (lemma_idx, ))), ))
        all_matches = {
            FrozenDict({
                **left_matching,
                **key_matching,
                **right_matching
            })
            for left_matching in left_matches
            for right_matching in right_matches
        }
        yield all_matches, word
Esempio n. 5
0
def frozendict_order_insert(fd, new_key, new_value):
    new = []
    inserted = False
    for existing_key, existing_value in fd.items():
        if not inserted and existing_key == new_key:
            inserted = True
            new.append((existing_key, existing_value | frozenset(
                (new_value, ))))
            continue
        if not inserted and existing_key > new_key:
            inserted = True
            new.append((new_key, frozenset((new_value, ))))
        new.append((existing_key, existing_value))
    if not inserted:
        new.append((new_key, frozenset((new_value, ))))
    return FrozenDict(new)
Esempio n. 6
0
    def parameters(self) -> FrozenDict[str, List]:
        """
        FrozenDict[str, List]: Solver parameters in the form of a dict, where keys are
        keyword parameters in D-Wave format and values are lists of properties in
        :attr:`.BraketSampler.properties` for each key.

        `D-Wave System Documentation <https://docs.dwavesys.com/docs/latest/doc_solver_ref.html>`_
        describes the parameters and properties supported on the D-Wave system.

        Solver parameters are dependent on the selected solver and subject to change;
        for example, new released features may add parameters.
        """
        return FrozenDict({
            param: ["parameters"]
            for param in BraketSolverMetadata.get_metadata_by_arn(
                self._device_arn)["parameters"]
        })
Esempio n. 7
0
    def properties(self) -> FrozenDict[str, Any]:
        """
        FrozenDict[str, Any]: Solver properties in D-Wave format.

        `D-Wave System Documentation <https://docs.dwavesys.com/docs/latest/doc_solver_ref.html>`_
        describes the parameters and properties supported on the D-Wave system.

        Solver properties are dependent on the selected solver and subject to change;
        for example, new released features may add properties.
        """
        mapping_dict = BraketSolverMetadata.get_metadata_by_arn(
            self._device_arn)["properties"]
        return_dict = {}
        for top_level_key in mapping_dict:
            solver_dict = getattr(self.solver.properties, top_level_key).dict()
            for key in mapping_dict[top_level_key]:
                return_dict[mapping_dict[top_level_key][key]] = copy.deepcopy(
                    solver_dict[key])
        return FrozenDict(return_dict)
Esempio n. 8
0
def test_frozendict_ior():
    data = {'a': 'A', 'b': 'B'}
    fd = FrozenDict(data)

    with pytest.raises(TypeError, match=".*FrozenDicts are immutable.*"):
        fd |= fd
Esempio n. 9
0
def test_frozendict():
    efd = FrozenDict()
    assert isinstance(efd, dict)
    assert len(efd) == 0
    assert not efd
    assert repr(efd) == "FrozenDict({})"

    data = {'a': 'A', 'b': 'B'}
    fd = FrozenDict(data)

    assert bool(fd)
    assert len(fd) == 2
    assert fd['a'] == 'A'
    assert fd['b'] == 'B'
    assert sorted(fd.keys()) == ['a', 'b']
    assert sorted(fd.values()) == ['A', 'B']
    assert sorted(fd.items()) == [('a', 'A'), ('b', 'B')]
    assert 'a' in fd
    assert 'c' not in fd

    assert hash(fd)
    fd_map = {'fd': fd}
    assert fd_map['fd'] is fd

    with pytest.raises(TypeError):
        fd['c'] = 'C'
    with pytest.raises(TypeError):
        del fd['a']
    with pytest.raises(TypeError):
        fd.update(x='X')
    with pytest.raises(TypeError):
        fd.setdefault('x', [])
    with pytest.raises(TypeError):
        fd.pop('c')
    with pytest.raises(TypeError):
        fd.popitem()
    with pytest.raises(TypeError):
        fd.clear()


    import pickle
    fkfd = FrozenDict.fromkeys([2, 4, 6], value=0)
    assert pickle.loads(pickle.dumps(fkfd)) == fkfd

    assert sorted(fkfd.updated({8: 0}).keys()) == [2, 4, 6, 8]

    # try something with an unhashable value
    unfd = FrozenDict({'a': ['A']})
    with pytest.raises(TypeError) as excinfo:
        {unfd: 'val'}
    assert excinfo.type is FrozenHashError
    with pytest.raises(TypeError) as excinfo2:
        {unfd: 'val'}
    assert excinfo.value is excinfo2.value  # test cached exception

    return
Esempio n. 10
0
def delete_selected(dedup):
    """Remove all mails selected in-place, from their original boxes."""
    for mail in dedup.selection:
        logger.debug(f"Deleting {mail!r} in-place...")
        dedup.stats["mail_deleted"] += 1
        if dedup.conf.dry_run:
            logger.warning("DRY RUN: Skip action.")
        else:
            dedup.sources[mail.source_path].remove(mail.mail_id)
            logger.info(f"{mail!r} deleted.")


ACTIONS = FrozenDict({
    COPY_SELECTED: copy_selected,
    COPY_DISCARDED: None,
    MOVE_SELECTED: move_selected,
    MOVE_DISCARDED: None,
    DELETE_SELECTED: delete_selected,
    DELETE_DISCARDED: None,
})


def perform_action(dedup):
    """Performs the action on selected mail candidates."""
    logger.info(f"Perform {choice_style(dedup.conf.action)} action...")

    selection_count = len(dedup.selection)
    if selection_count == 0:
        logger.warning("No mail selected to perform action on.")
        return
    logger.info(f"{selection_count} mails selected for action.")
Esempio n. 11
0
    """Precompute the mapping of all strategy IDs to their prefered method name,
    including aliases as fallbacks.
    """
    methods = dict()
    for strategies in STRATEGY_ALIASES:
        fallback_method = None
        for strat_id in strategies:
            mid = get_method_id(strat_id)
            method = globals().get(mid)
            if method:
                fallback_method = method
            if not fallback_method:
                raise NotImplementedError(f"Can't find {mid}() method.")
            methods[strat_id] = fallback_method
    return methods


STRATEGY_METHODS = FrozenDict(build_method_mapping())


def apply_strategy(strat_id, duplicates):
    """Perform the selection strategy on the provided duplicate set.

    Returns a set of selected mails objects.
    """
    if strat_id not in STRATEGY_METHODS:
        raise ValueError(f"Unknown {strat_id} strategy.")
    method = STRATEGY_METHODS[strat_id]
    logger.debug(f"Apply {method!r}...")
    return set(method(duplicates))
Esempio n. 12
0

def is_macos():
    """ Return `True` only if current platform is of the macOS family. """
    return sys.platform == 'darwin'


def is_windows():
    """ Return `True` only if current platform is of the Windows family. """
    return sys.platform in ['win32', 'cygwin']


# Map OS IDs to evaluation function and OS labels.
OS_DEFINITIONS = FrozenDict({
    LINUX: ('Linux', is_linux()),
    MACOS: ('macOS', is_macos()),
    WINDOWS: ('Windows', is_windows())
})

# Generare sets of recognized IDs and labels.
ALL_OS_LABELS = frozenset([label for label, _ in OS_DEFINITIONS.values()])


def os_label(os_id):
    """ Return platform label for user-friendly output. """
    return OS_DEFINITIONS[os_id][0]


logger.debug(f"Raw platform ID: {sys.platform}.")

Esempio n. 13
0
class AwsDevice(Device):
    """
    Amazon Braket implementation of a device.
    Use this class to retrieve the latest metadata about the device and to run a quantum task on the
    device.
    """

    SIMULATOR_ARNS = frozenset({
        "arn:aws:braket:::device/quantum-simulator/amazon/sv1",
        "arn:aws:braket:::device/quantum-simulator/amazon/tn1",
    })
    QPU_REGIONS = FrozenDict({
        "arn:aws:braket:::device/qpu/rigetti/Aspen-8":
        "us-west-1",
        "arn:aws:braket:::device/qpu/ionq/ionQdevice":
        "us-east-1",
        "arn:aws:braket:::device/qpu/d-wave/DW_2000Q_6":
        "us-west-2",
        "arn:aws:braket:::device/qpu/d-wave/Advantage_system1":
        "us-west-2",
    })
    REGIONS = frozenset(QPU_REGIONS.values())

    DEFAULT_SHOTS_QPU = 1000
    DEFAULT_SHOTS_SIMULATOR = 0
    DEFAULT_MAX_PARALLEL = 10

    _GET_DEVICES_ORDER_BY_KEYS = frozenset(
        {"arn", "name", "type", "provider_name", "status"})

    def __init__(self, arn: str, aws_session: Optional[AwsSession] = None):
        """
        Args:
            arn (str): The ARN of the device
            aws_session (AwsSession, optional): An AWS session object. Default is `None`.

        Note:
            Some devices (QPUs) are physically located in specific AWS Regions. In some cases,
            the current `aws_session` connects to a Region other than the Region in which the QPU is
            physically located. When this occurs, a cloned `aws_session` is created for the Region
            the QPU is located in.

            See `braket.aws.aws_device.AwsDevice.DEVICE_REGIONS` for the AWS Regions provider
            devices are located in.
        """
        super().__init__(name=None, status=None)
        self._arn = arn
        self._aws_session = AwsDevice._aws_session_for_device(arn, aws_session)
        self._properties = None
        self._provider_name = None
        self._topology_graph = None
        self._type = None
        self.refresh_metadata()

    def run(
        self,
        task_specification: Union[Circuit, Problem],
        s3_destination_folder: AwsSession.S3DestinationFolder,
        shots: Optional[int] = None,
        poll_timeout_seconds: float = AwsQuantumTask.
        DEFAULT_RESULTS_POLL_TIMEOUT,
        poll_interval_seconds: float = AwsQuantumTask.
        DEFAULT_RESULTS_POLL_INTERVAL,
        *aws_quantum_task_args,
        **aws_quantum_task_kwargs,
    ) -> AwsQuantumTask:
        """
        Run a quantum task specification on this device. A task can be a circuit or an
        annealing problem.

        Args:
            task_specification (Union[Circuit, Problem]): Specification of task
                (circuit or annealing problem) to run on device.
            s3_destination_folder: The S3 location to save the task's results to.
            shots (int, optional): The number of times to run the circuit or annealing problem.
                Default is 1000 for QPUs and 0 for simulators.
            poll_timeout_seconds (float): The polling timeout for `AwsQuantumTask.result()`,
                in seconds. Default: 5 days.
            poll_interval_seconds (float): The polling interval for `AwsQuantumTask.result()`,
                in seconds. Default: 1 second.
            *aws_quantum_task_args: Variable length positional arguments for
                `braket.aws.aws_quantum_task.AwsQuantumTask.create()`.
            **aws_quantum_task_kwargs: Variable length keyword arguments for
                `braket.aws.aws_quantum_task.AwsQuantumTask.create()`.

        Returns:
            AwsQuantumTask: An AwsQuantumTask that tracks the execution on the device.

        Examples:
            >>> circuit = Circuit().h(0).cnot(0, 1)
            >>> device = AwsDevice("arn1")
            >>> device.run(circuit, ("bucket-foo", "key-bar"))

            >>> circuit = Circuit().h(0).cnot(0, 1)
            >>> device = AwsDevice("arn2")
            >>> device.run(task_specification=circuit,
            >>>     s3_destination_folder=("bucket-foo", "key-bar"))

            >>> circuit = Circuit().h(0).cnot(0, 1)
            >>> device = AwsDevice("arn3")
            >>> device.run(task_specification=circuit,
            >>>     s3_destination_folder=("bucket-foo", "key-bar"), disable_qubit_rewiring=True)

            >>> problem = Problem(
            >>>     ProblemType.ISING,
            >>>     linear={1: 3.14},
            >>>     quadratic={(1, 2): 10.08},
            >>> )
            >>> device = AwsDevice("arn4")
            >>> device.run(problem, ("bucket-foo", "key-bar"),
            >>>     device_parameters={
            >>>         "providerLevelParameters": {"postprocessingType": "SAMPLING"}}
            >>> )

        See Also:
            `braket.aws.aws_quantum_task.AwsQuantumTask.create()`
        """
        return AwsQuantumTask.create(
            self._aws_session,
            self._arn,
            task_specification,
            s3_destination_folder,
            shots if shots is not None else self._default_shots,
            poll_timeout_seconds=poll_timeout_seconds,
            poll_interval_seconds=poll_interval_seconds,
            *aws_quantum_task_args,
            **aws_quantum_task_kwargs,
        )

    def run_batch(
        self,
        task_specifications: List[Union[Circuit, Problem]],
        s3_destination_folder: AwsSession.S3DestinationFolder,
        shots: Optional[int] = None,
        max_parallel: Optional[int] = None,
        max_connections: int = AwsQuantumTaskBatch.MAX_CONNECTIONS_DEFAULT,
        poll_timeout_seconds: float = AwsQuantumTask.
        DEFAULT_RESULTS_POLL_TIMEOUT,
        poll_interval_seconds: float = AwsQuantumTask.
        DEFAULT_RESULTS_POLL_INTERVAL,
        *aws_quantum_task_args,
        **aws_quantum_task_kwargs,
    ) -> AwsQuantumTaskBatch:
        """Executes a batch of tasks in parallel

        Args:
            task_specifications (List[Union[Circuit, Problem]]): List of  circuits
                or annealing problems to run on device.
            s3_destination_folder: The S3 location to save the tasks' results to.
            shots (int, optional): The number of times to run the circuit or annealing problem.
                Default is 1000 for QPUs and 0 for simulators.
            max_parallel (int, optional): The maximum number of tasks to run on AWS in parallel.
                Batch creation will fail if this value is greater than the maximum allowed
                concurrent tasks on the device. Default: 10
            max_connections (int): The maximum number of connections in the Boto3 connection pool.
                Also the maximum number of thread pool workers for the batch. Default: 100
            poll_timeout_seconds (float): The polling timeout for `AwsQuantumTask.result()`,
                in seconds. Default: 5 days.
            poll_interval_seconds (float): The polling interval for results in seconds.
                Default: 1 second.
            *aws_quantum_task_args: Variable length positional arguments for
                `braket.aws.aws_quantum_task.AwsQuantumTask.create()`.
            **aws_quantum_task_kwargs: Variable length keyword arguments for
                `braket.aws.aws_quantum_task.AwsQuantumTask.create()`.

        Returns:
            AwsQuantumTaskBatch: A batch containing all of the tasks run

        See Also:
            `braket.aws.aws_quantum_task_batch.AwsQuantumTaskBatch`
        """
        return AwsQuantumTaskBatch(
            AwsDevice._copy_aws_session(self._aws_session,
                                        max_connections=max_connections),
            self._arn,
            task_specifications,
            s3_destination_folder,
            shots if shots is not None else self._default_shots,
            max_parallel=max_parallel
            if max_parallel is not None else self._default_max_parallel,
            max_workers=max_connections,
            poll_timeout_seconds=poll_timeout_seconds,
            poll_interval_seconds=poll_interval_seconds,
            *aws_quantum_task_args,
            **aws_quantum_task_kwargs,
        )

    def refresh_metadata(self) -> None:
        """
        Refresh the `AwsDevice` object with the most recent Device metadata.
        """
        metadata = self._aws_session.get_device(self._arn)
        self._name = metadata.get("deviceName")
        self._status = metadata.get("deviceStatus")
        self._type = AwsDeviceType(metadata.get("deviceType"))
        self._provider_name = metadata.get("providerName")
        qpu_properties = metadata.get("deviceCapabilities")
        self._properties = BraketSchemaBase.parse_raw_schema(qpu_properties)
        self._topology_graph = self._construct_topology_graph()

    @property
    def type(self) -> str:
        """str: Return the device type"""
        return self._type

    @property
    def provider_name(self) -> str:
        """str: Return the provider name"""
        return self._provider_name

    @property
    def arn(self) -> str:
        """str: Return the ARN of the device"""
        return self._arn

    @property
    # TODO: Add a link to the boto3 docs
    def properties(self) -> DeviceCapabilities:
        """DeviceCapabilities: Return the device properties

        Please see `braket.device_schema` in amazon-braket-schemas-python_

        .. _amazon-braket-schemas-python: https://github.com/aws/amazon-braket-schemas-python"""
        return self._properties

    @property
    def topology_graph(self) -> Graph:
        """Graph: topology of device as a networkx `Graph` object.
        Returns `None` if the topology is not available for the device.

        Examples:
            >>> import networkx as nx
            >>> device = AwsDevice("arn1")
            >>> nx.draw_kamada_kawai(device.topology_graph, with_labels=True, font_weight="bold")

            >>> topology_subgraph = device.topology_graph.subgraph(range(8))
            >>> nx.draw_kamada_kawai(topology_subgraph, with_labels=True, font_weight="bold")

            >>> print(device.topology_graph.edges)
        """
        return self._topology_graph

    def _construct_topology_graph(self) -> Graph:
        """
        Construct topology graph. If no such metadata is available, return `None`.

        Returns:
            Graph: topology of QPU as a networkx `Graph` object.
        """
        if hasattr(self.properties, "paradigm") and isinstance(
                self.properties.paradigm, GateModelQpuParadigmProperties):
            if self.properties.paradigm.connectivity.fullyConnected:
                return complete_graph(int(self.properties.paradigm.qubitCount))
            adjacency_lists = self.properties.paradigm.connectivity.connectivityGraph
            edges = []
            for item in adjacency_lists.items():
                i = item[0]
                edges.extend([(int(i), int(j)) for j in item[1]])
            return from_edgelist(edges)
        elif hasattr(self.properties, "provider") and isinstance(
                self.properties.provider, DwaveProviderProperties):
            edges = self.properties.provider.couplers
            return from_edgelist(edges)
        else:
            return None

    @property
    def _default_shots(self):
        return (AwsDevice.DEFAULT_SHOTS_QPU
                if "qpu" in self.arn else AwsDevice.DEFAULT_SHOTS_SIMULATOR)

    @property
    def _default_max_parallel(self):
        return AwsDevice.DEFAULT_MAX_PARALLEL

    @staticmethod
    def _aws_session_for_device(
            device_arn: str, aws_session: Optional[AwsSession]) -> AwsSession:
        """AwsSession: Returns an AwsSession for the device ARN."""
        if "qpu" in device_arn:
            return AwsDevice._aws_session_for_qpu(device_arn, aws_session)
        else:
            return aws_session or AwsSession()

    @staticmethod
    def _aws_session_for_qpu(device_arn: str,
                             aws_session: Optional[AwsSession]) -> AwsSession:
        """
        Get an AwsSession for the device ARN. QPUs are physically located in specific AWS Regions.
        The AWS sessions should connect to the Region that the QPU is located in.

        See `braket.aws.aws_qpu.AwsDevice.DEVICE_REGIONS` for the
        AWS Regions the devices are located in.
        """
        if device_arn in AwsDevice.QPU_REGIONS:
            return AwsDevice._copy_aws_session(
                aws_session, AwsDevice.QPU_REGIONS.get(device_arn), None)
        # If the QPU is unknown, search until it is found.
        device_sessions = AwsDevice._get_arn_sessions([device_arn], None,
                                                      {AwsDeviceType.QPU},
                                                      None, None, aws_session)
        if device_sessions:
            return device_sessions[device_arn]
        raise ValueError(f"QPU {device_arn} not found")

    @staticmethod
    def _copy_aws_session(
        aws_session: Optional[AwsSession],
        region: Optional[str] = None,
        max_connections: Optional[int] = None,
    ) -> AwsSession:
        config = Config(
            max_pool_connections=max_connections) if max_connections else None
        if aws_session:
            session_region = aws_session.boto_session.region_name
            new_region = region or session_region
            if session_region == new_region and not config:
                return aws_session
            else:
                creds = aws_session.boto_session.get_credentials()
                boto_session = boto3.Session(
                    aws_access_key_id=creds.access_key,
                    aws_secret_access_key=creds.secret_key,
                    aws_session_token=creds.token,
                    region_name=new_region,
                )
                return AwsSession(boto_session=boto_session, config=config)
        else:
            boto_session = boto3.Session(
                region_name=region) if region else None
            return AwsSession(boto_session=boto_session, config=config)

    def __repr__(self):
        return "Device('name': {}, 'arn': {})".format(self.name, self.arn)

    def __eq__(self, other):
        if isinstance(other, AwsDevice):
            return self.arn == other.arn
        return NotImplemented

    @staticmethod
    def get_devices(
        arns: Optional[List[str]] = None,
        names: Optional[List[str]] = None,
        types: Optional[List[AwsDeviceType]] = None,
        statuses: Optional[List[str]] = None,
        provider_names: Optional[List[str]] = None,
        order_by: str = "name",
        aws_session: Optional[AwsSession] = None,
    ) -> List[AwsDevice]:
        """
        Get devices based on filters and desired ordering. The result is the AND of
        all the filters `arns`, `names`, `types`, `statuses`, `provider_names`.

        Examples:
            >>> AwsDevice.get_devices(provider_names=['Rigetti'], statuses=['ONLINE'])
            >>> AwsDevice.get_devices(order_by='provider_name')
            >>> AwsDevice.get_devices(types=['SIMULATOR'])

        Args:
            arns (List[str], optional): device ARN list, default is `None`
            names (List[str], optional): device name list, default is `None`
            types (List[AwsDeviceType], optional): device type list, default is `None`
                QPUs will be searched for all regions and simulators will only be
                searched for the region of the current session.
            statuses (List[str], optional): device status list, default is `None`
            provider_names (List[str], optional): provider name list, default is `None`
            order_by (str, optional): field to order result by, default is `name`.
                Accepted values are ['arn', 'name', 'type', 'provider_name', 'status']
            aws_session (AwsSession, optional) aws_session: An AWS session object.
                Default is `None`.

        Returns:
            List[AwsDevice]: list of AWS devices
        """

        if order_by not in AwsDevice._GET_DEVICES_ORDER_BY_KEYS:
            raise ValueError(
                f"order_by '{order_by}' must be in {AwsDevice._GET_DEVICES_ORDER_BY_KEYS}"
            )
        types = (frozenset(types) if types else frozenset(
            {device_type
             for device_type in AwsDeviceType}))
        arn_sessions = AwsDevice._get_arn_sessions(arns, names, types,
                                                   statuses, provider_names,
                                                   aws_session)
        devices = [AwsDevice(arn, arn_sessions[arn]) for arn in arn_sessions]
        devices.sort(key=lambda x: getattr(x, order_by))
        return devices

    @staticmethod
    def _get_arn_sessions(arns, names, types, statuses, provider_names,
                          aws_session):
        aws_session = aws_session if aws_session else AwsSession()
        sessions_for_arns = {}
        session_region = aws_session.boto_session.region_name
        device_regions_set = AwsDevice._get_devices_regions_set(
            types, arns, session_region)
        for region in device_regions_set:
            session_for_region = AwsDevice._copy_aws_session(
                aws_session, region)
            # Simulators are only instantiated in the same region as the AWS session
            types_for_region = sorted(types if region ==
                                      session_region else types -
                                      {AwsDeviceType.SIMULATOR})
            region_device_arns = [
                result["deviceArn"]
                for result in session_for_region.search_devices(
                    arns=arns,
                    names=names,
                    types=types_for_region,
                    statuses=statuses,
                    provider_names=provider_names,
                )
            ]
            sessions_for_arns.update({
                arn: session_for_region
                for arn in region_device_arns if arn not in sessions_for_arns
            })
        return sessions_for_arns

    @staticmethod
    def _get_devices_regions_set(types: Optional[Set[AwsDeviceType]],
                                 arns: Optional[List[str]],
                                 current_region: str) -> FrozenSet[str]:
        """Get the set of regions to call `SearchDevices` API given filters"""
        device_regions_set = ({current_region} if types == {
            AwsDeviceType.SIMULATOR
        } else set(AwsDevice.REGIONS))
        if arns:
            arns_region_set = set()
            for arn in arns:
                if arn in AwsDevice.QPU_REGIONS:
                    arns_region_set.add(AwsDevice.QPU_REGIONS[arn])
                elif arn in AwsDevice.SIMULATOR_ARNS:
                    arns_region_set.add(current_region)
                else:
                    arns_region_set.update(AwsDevice.REGIONS)
            device_regions_set &= arns_region_set
        return frozenset(device_regions_set)
Esempio n. 14
0
class AwsDevice(Device):
    """
    Amazon Braket implementation of a device.
    Use this class to retrieve the latest metadata about the device and to run a quantum task on the
    device.
    """

    DEVICE_REGIONS = FrozenDict({
        "rigetti": ["us-west-1"],
        "ionq": ["us-east-1"],
        "d-wave": ["us-west-2"],
        "amazon": ["us-west-2", "us-west-1", "us-east-1"],
    })

    DEFAULT_SHOTS_QPU = 1000
    DEFAULT_SHOTS_SIMULATOR = 0
    DEFAULT_RESULTS_POLL_TIMEOUT = 432000
    DEFAULT_RESULTS_POLL_INTERVAL = 1

    def __init__(self, arn: str, aws_session: Optional[AwsSession] = None):
        """
        Args:
            arn (str): The ARN of the device
            aws_session (AwsSession, optional) aws_session: An AWS session object. Default = None.

        Note:
            Some devices (QPUs) are physically located in specific AWS Regions. In some cases,
            the current `aws_session` connects to a Region other than the Region in which the QPU is
            physically located. When this occurs, a cloned `aws_session` is created for the Region
            the QPU is located in.

            See `braket.aws.aws_device.AwsDevice.DEVICE_REGIONS` for the AWS Regions provider
            devices are located in.
        """
        super().__init__(name=None, status=None)
        self._arn = arn
        self._aws_session = AwsDevice._aws_session_for_device(arn, aws_session)
        self._properties = None
        self._provider_name = None
        self._type = None
        self.refresh_metadata()

    def run(
        self,
        task_specification: Union[Circuit, Problem],
        s3_destination_folder: AwsSession.S3DestinationFolder,
        shots: Optional[int] = None,
        poll_timeout_seconds: Optional[int] = DEFAULT_RESULTS_POLL_TIMEOUT,
        poll_interval_seconds: Optional[int] = DEFAULT_RESULTS_POLL_INTERVAL,
        *aws_quantum_task_args,
        **aws_quantum_task_kwargs,
    ) -> AwsQuantumTask:
        """
        Run a quantum task specification on this device. A task can be a circuit or an
        annealing problem.

        Args:
            task_specification (Union[Circuit, Problem]):  Specification of task
                (circuit or annealing problem) to run on device.
            s3_destination_folder: The S3 location to save the task's results
            shots (int, optional): The number of times to run the circuit or annealing problem.
                Default is 1000 for QPUs and 0 for simulators.
            poll_timeout_seconds (int): The polling timeout for AwsQuantumTask.result(), in seconds.
                Default: 5 days.
            poll_interval_seconds (int): The polling interval for AwsQuantumTask.result(),
                in seconds. Default: 1 second.
            *aws_quantum_task_args: Variable length positional arguments for
                `braket.aws.aws_quantum_task.AwsQuantumTask.create()`.
            **aws_quantum_task_kwargs: Variable length keyword arguments for
                `braket.aws.aws_quantum_task.AwsQuantumTask.create()`.

        Returns:
            AwsQuantumTask: An AwsQuantumTask that tracks the execution on the device.

        Examples:
            >>> circuit = Circuit().h(0).cnot(0, 1)
            >>> device = AwsDevice("arn1")
            >>> device.run(circuit, ("bucket-foo", "key-bar"))

            >>> circuit = Circuit().h(0).cnot(0, 1)
            >>> device = AwsDevice("arn2")
            >>> device.run(task_specification=circuit,
            >>>     s3_destination_folder=("bucket-foo", "key-bar"))

            >>> problem = Problem(
            >>>     ProblemType.ISING,
            >>>     linear={1: 3.14},
            >>>     quadratic={(1, 2): 10.08},
            >>> )
            >>> device = AwsDevice("arn3")
            >>> device.run(problem, ("bucket-foo", "key-bar"),
            >>>     device_parameters={
            >>>         "providerLevelParameters": {"postprocessingType": "SAMPLING"}}
            >>> )

        See Also:
            `braket.aws.aws_quantum_task.AwsQuantumTask.create()`
        """
        if shots is None:
            if "qpu" in self.arn:
                shots = AwsDevice.DEFAULT_SHOTS_QPU
            else:
                shots = AwsDevice.DEFAULT_SHOTS_SIMULATOR
        return AwsQuantumTask.create(
            self._aws_session,
            self._arn,
            task_specification,
            s3_destination_folder,
            shots,
            poll_timeout_seconds=poll_timeout_seconds,
            poll_interval_seconds=poll_interval_seconds,
            *aws_quantum_task_args,
            **aws_quantum_task_kwargs,
        )

    def refresh_metadata(self) -> None:
        """
        Refresh the `AwsDevice` object with the most recent Device metadata.
        """
        metadata = self._aws_session.get_device(self._arn)
        self._name = metadata.get("deviceName")
        self._status = metadata.get("deviceStatus")
        self._type = AwsDeviceType(metadata.get("deviceType"))
        self._provider_name = metadata.get("providerName")
        qpu_properties = metadata.get("deviceCapabilities")
        self._properties = BraketSchemaBase.parse_raw_schema(qpu_properties)
        self._topology_graph = self._construct_topology_graph()

    @property
    def type(self) -> str:
        """str: Return the device type"""
        return self._type

    @property
    def provider_name(self) -> str:
        """str: Return the provider name"""
        return self._provider_name

    @property
    def arn(self) -> str:
        """str: Return the ARN of the device"""
        return self._arn

    @property
    # TODO: Add a link to the boto3 docs
    def properties(self) -> DeviceCapabilities:
        """DeviceCapabilities: Return the device properties

        Please see `braket.device_schema` in amazon-braket-schemas-python_

        .. _amazon-braket-schemas-python: https://github.com/aws/amazon-braket-schemas-python"""
        return self._properties

    @property
    def topology_graph(self) -> Graph:
        """Graph: topology of device as a networkx Graph object.
        Returns None if the topology is not available for the device.

        Examples:
            >>> import networkx as nx
            >>> device = AwsDevice("arn1")
            >>> nx.draw_kamada_kawai(device.topology_graph, with_labels=True, font_weight="bold")

            >>> topology_subgraph = device.topology_graph.subgraph(range(8))
            >>> nx.draw_kamada_kawai(topology_subgraph, with_labels=True, font_weight="bold")

            >>> print(device.topology_graph.edges)
        """
        return self._topology_graph

    def _construct_topology_graph(self) -> Graph:
        """
        Construct topology graph. If no such metadata is available, return None.

        Returns:
            Graph: topology of QPU as a networkx Graph object
        """
        if hasattr(self.properties, "paradigm") and isinstance(
                self.properties.paradigm, GateModelQpuParadigmProperties):
            if self.properties.paradigm.connectivity.fullyConnected:
                return complete_graph(int(self.properties.paradigm.qubitCount))
            adjacency_lists = self.properties.paradigm.connectivity.connectivityGraph
            edges = []
            for item in adjacency_lists.items():
                i = item[0]
                edges.extend([(int(i), int(j)) for j in item[1]])
            return from_edgelist(edges)
        elif hasattr(self.properties, "provider") and isinstance(
                self.properties.provider, DwaveProviderProperties):
            edges = self.properties.provider.couplers
            return from_edgelist(edges)
        else:
            return None

    @staticmethod
    def _aws_session_for_device(
            device_arn: str, aws_session: Optional[AwsSession]) -> AwsSession:
        """AwsSession: Returns an AwsSession for the device ARN. """
        if "qpu" in device_arn:
            return AwsDevice._aws_session_for_qpu(device_arn, aws_session)
        else:
            return aws_session or AwsSession()

    @staticmethod
    def _aws_session_for_qpu(device_arn: str,
                             aws_session: Optional[AwsSession]) -> AwsSession:
        """
        Get an AwsSession for the device ARN. QPUs are physically located in specific AWS Regions.
        The AWS sessions should connect to the Region that the QPU is located in.

        See `braket.aws.aws_qpu.AwsDevice.DEVICE_REGIONS` for the
        AWS Regions the devices are located in.
        """
        region_key = device_arn.split("/")[-2]
        qpu_regions = AwsDevice.DEVICE_REGIONS.get(region_key, [])
        return AwsDevice._copy_aws_session(aws_session, qpu_regions)

    @staticmethod
    def _copy_aws_session(aws_session: Optional[AwsSession],
                          regions: List[str]) -> AwsSession:
        if aws_session:
            if aws_session.boto_session.region_name in regions:
                return aws_session
            else:
                creds = aws_session.boto_session.get_credentials()
                boto_session = boto3.Session(
                    aws_access_key_id=creds.access_key,
                    aws_secret_access_key=creds.secret_key,
                    aws_session_token=creds.token,
                    region_name=regions[0],
                )
                return AwsSession(boto_session=boto_session)
        else:
            boto_session = boto3.Session(region_name=regions[0])
            return AwsSession(boto_session=boto_session)

    def __repr__(self):
        return "Device('name': {}, 'arn': {})".format(self.name, self.arn)

    def __eq__(self, other):
        if isinstance(other, AwsDevice):
            return self.arn == other.arn
        return NotImplemented

    @staticmethod
    def get_devices(
        arns: Optional[List[str]] = None,
        names: Optional[List[str]] = None,
        types: Optional[List[AwsDeviceType]] = None,
        statuses: Optional[List[str]] = None,
        provider_names: Optional[List[str]] = None,
        order_by: str = "name",
        aws_session: Optional[AwsSession] = None,
    ) -> List[AwsDevice]:
        """
        Get devices based on filters and desired ordering. The result is the AND of
        all the filters `arns`, `names`, `types`, `statuses`, `provider_names`.

        Examples:
            >>> AwsDevice.get_devices(provider_names=['Rigetti'], statuses=['ONLINE'])
            >>> AwsDevice.get_devices(order_by='provider_name')
            >>> AwsDevice.get_devices(types=['SIMULATOR'])

        Args:
            arns (List[str], optional): device ARN list, default is `None`
            names (List[str], optional): device name list, default is `None`
            types (List[AwsDeviceType], optional): device type list, default is `None`
            statuses (List[str], optional): device status list, default is `None`
            provider_names (List[str], optional): provider name list, default is `None`
            order_by (str, optional): field to order result by, default is `name`.
                Accepted values are ['arn', 'name', 'type', 'provider_name', 'status']
            aws_session (AwsSession, optional) aws_session: An AWS session object. Default = None.

        Returns:
            List[AwsDevice]: list of AWS devices
        """
        order_by_list = ["arn", "name", "type", "provider_name", "status"]
        if order_by not in order_by_list:
            raise ValueError(
                f"order_by '{order_by}' must be in {order_by_list}")
        device_regions_set = AwsDevice._get_devices_regions_set(
            arns, provider_names, types)
        results = []
        for region in device_regions_set:
            aws_session = AwsDevice._copy_aws_session(aws_session, [region])
            results.extend(
                aws_session.search_devices(
                    arns=arns,
                    names=names,
                    types=types,
                    statuses=statuses,
                    provider_names=provider_names,
                ))
        arns = set([result["deviceArn"] for result in results])
        devices = [AwsDevice(arn, aws_session) for arn in arns]
        devices.sort(key=lambda x: getattr(x, order_by))
        return devices

    @staticmethod
    def _get_devices_regions_set(
        arns: Optional[List[str]],
        provider_names: Optional[List[str]],
        types: Optional[List[AwsDeviceType]],
    ) -> Set[str]:
        """Get the set of regions to call `SearchDevices` API given filters"""
        device_regions_set = set(AwsDevice.DEVICE_REGIONS[key][0]
                                 for key in AwsDevice.DEVICE_REGIONS)
        if provider_names:
            provider_region_set = set()
            for provider in provider_names:
                for key in AwsDevice.DEVICE_REGIONS:
                    if key in provider.lower():
                        provider_region_set.add(
                            AwsDevice.DEVICE_REGIONS[key][0])
                        break
            device_regions_set = device_regions_set.intersection(
                provider_region_set)
        if arns:
            arns_region_set = set([
                AwsDevice.DEVICE_REGIONS[arn.split("/")[-2]][0] for arn in arns
            ])
            device_regions_set = device_regions_set.intersection(
                arns_region_set)
        if types and types == [AwsDeviceType.SIMULATOR]:
            device_regions_set = device_regions_set.intersection(
                [AwsDevice.DEVICE_REGIONS["amazon"][0]])
        return device_regions_set
Esempio n. 15
0
                    f"Extend the default message factory for {klass} with "
                    "our own ``DedupMail`` class to add deduplication utilities."
                },
            )

            # Set our own custom factory and safety options to default constructor.
            constructor = partial(klass, factory=factory_klass, create=False)

            # Generates our own box_type_id for use in CLI parameters.
            box_type_id = klass.__name__.lower()

            yield box_type_id, constructor


# Mapping between supported box type IDs and their constructors.
BOX_TYPES = FrozenDict(build_box_constructors())

# Categorize each box type into its structure type.
BOX_STRUCTURES = FrozenDict({
    "file": {"mbox", "mmdf", "babyl"},
    "folder": {"maildir", "mh"},
})
# Check we did not forgot any box type.
assert set(flatten(BOX_STRUCTURES.values())) == set(BOX_TYPES)

# List of required sub-folders defining a properly structured maildir.
MAILDIR_SUBDIRS = frozenset(("cur", "new", "tmp"))


def autodetect_box_type(path):
    """Auto-detect the format of the mailbox located at the provided path.
Esempio n. 16
0
def test_frozendict():
    efd = FrozenDict()
    assert isinstance(efd, dict)
    assert len(efd) == 0
    assert not efd
    assert repr(efd) == "FrozenDict({})"

    data = {'a': 'A', 'b': 'B'}
    fd = FrozenDict(data)

    assert bool(fd)
    assert len(fd) == 2
    assert fd['a'] == 'A'
    assert fd['b'] == 'B'
    assert sorted(fd.keys()) == ['a', 'b']
    assert sorted(fd.values()) == ['A', 'B']
    assert sorted(fd.items()) == [('a', 'A'), ('b', 'B')]
    assert 'a' in fd
    assert 'c' not in fd

    assert hash(fd)
    fd_map = {'fd': fd}
    assert fd_map['fd'] is fd

    with pytest.raises(TypeError):
        fd['c'] = 'C'
    with pytest.raises(TypeError):
        del fd['a']
    with pytest.raises(TypeError):
        fd.update(x='X')
    with pytest.raises(TypeError):
        fd.setdefault('x', [])
    with pytest.raises(TypeError):
        fd.pop('c')
    with pytest.raises(TypeError):
        fd.popitem()
    with pytest.raises(TypeError):
        fd.clear()


    import pickle
    fkfd = FrozenDict.fromkeys([2, 4, 6], value=0)
    assert pickle.loads(pickle.dumps(fkfd)) == fkfd

    assert sorted(fkfd.updated({8: 0}).keys()) == [2, 4, 6, 8]

    # try something with an unhashable value
    unfd = FrozenDict({'a': ['A']})
    with pytest.raises(TypeError) as excinfo:
        {unfd: 'val'}
    assert excinfo.type is FrozenHashError
    with pytest.raises(TypeError) as excinfo2:
        {unfd: 'val'}
    assert excinfo.value is excinfo2.value  # test cached exception

    return