class_docstr: A circuit-cutting distribution policy for executing (large) circuits on available (comparably
  smaller) devices.
  
  .. note::
  
      This class is part of a work-in-progress feature to support automatic cut placement in the
      circuit cutting workflow. Currently only manual placement of cuts is supported,
      check out the :func:`qml.cut_circuit() <pennylane.cut_circuit>` transform for more details.
  
  Args:
      devices (Union[qml.Device, Sequence[qml.Device]]): Single, or Sequence of, device(s).
          Optional only when ``max_free_wires`` is provided.
      max_free_wires (int): Number of wires for the largest available device. Optional only when
          ``devices`` is provided where it defaults to the maximum number of wires among
          ``devices``.
      min_free_wires (int): Number of wires for the smallest available device, or, equivalently,
          the smallest max fragment-wire-size that the partitioning is allowed to explore.
          When provided, this parameter will be used to derive an upper-bound to the range of
          explored number of fragments.  Optional, defaults to 2 which corresponds to attempting
          the most granular partitioning of max 2-wire fragments.
      num_fragments_probed (Union[int, Sequence[int]]): Single, or 2-Sequence of, number(s)
          specifying the potential (range of) number of fragments for the partitioner to attempt.
          Optional, defaults to probing all valid strategies derivable from the circuit and
          devices. When provided, has precedence over all other arguments affecting partitioning
          exploration, such as ``max_free_wires``, ``min_free_wires``, or ``exhaustive``.
      max_free_gates (int): Maximum allowed circuit depth for the deepest available device.
          Optional, defaults to unlimited depth.
      min_free_gates (int): Maximum allowed circuit depth for the shallowest available device.
          Optional, defaults to ``max_free_gates``.
      imbalance_tolerance (float): The global maximum allowed imbalance for all partition trials.
          Optional, defaults to unlimited imbalance. Used only if there's a known hard balancing
          constraint on the partitioning problem.
      trials_per_probe (int): Number of repeated partitioning trials for a random automatic
          cutting method to attempt per set of partitioning parameters. For a deterministic
          cutting method, this can be set to 1. Defaults to 4.
  
  **Example**
  
  The following cut strategy specifies that a circuit should be cut into between
  ``2`` to ``5`` fragments, with each fragment having at most ``6`` wires and
  at least ``4`` wires:
  
  >>> cut_strategy = qml.transforms.CutStrategy(
  ...     max_free_wires=6,
  ...     min_free_wires=4,
  ...     num_fragments_probed=(2, 5),
  ... )
class_docstr_tok: ["A","circuit-cutting","distribution","policy","for","executing","(","large",")","circuits","on","available","(","comparably","smaller",")","devices",".","..","note",":",":","This","class","is","part","of","a","work-in-progress","feature","to","support","automatic","cut","placement","in","the","circuit","cutting","workflow",".","Currently","only","manual","placement","of","cuts","is","supported",",","check","out","the",":","func",":","`","qml.cut_circuit","(",")","<","pennylane.cut_circuit",">","`","transform","for","more","details",".","Args",":","devices","(","Union","[","qml.Device",",","Sequence","[","qml.Device","]","]",")",":","Single",",","or","Sequence","of",",","device","(","s",")",".","Optional","only","when","``","max_free_wires","``","is","provided",".","max_free_wires","(","int",")",":","Number","of","wires","for","the","largest","available","device",".","Optional","only","when","``","devices","``","is","provided","where","it","defaults","to","the","maximum","number","of","wires","among","``","devices","``",".","min_free_wires","(","int",")",":","Number","of","wires","for","the","smallest","available","device",",","or",",","equivalently",",","the","smallest","max","fragment-wire-size","that","the","partitioning","is","allowed","to","explore",".","When","provided",",","this","parameter","will","be","used","to","derive","an","upper-bound","to","the","range","of","explored","number","of","fragments",".","Optional",",","defaults","to","2","which","corresponds","to","attempting","the","most","granular","partitioning","of","max","2-wire","fragments",".","num_fragments_probed","(","Union","[","int",",","Sequence","[","int","]","]",")",":","Single",",","or","2-Sequence","of",",","number","(","s",")","specifying","the","potential","(","range","of",")","number","of","fragments","for","the","partitioner","to","attempt",".","Optional",",","defaults","to","probing","all","valid","strategies","derivable","from","the","circuit","and","devices",".","When","provided",",","has","precedence","over","all","other","arguments","affecting","partitioning","exploration",",","such","as","``","max_free_wires","``",",","``","min_free_wires","``",",","or","``","exhaustive","``",".","max_free_gates","(","int",")",":","Maximum","allowed","circuit","depth","for","the","deepest","available","device",".","Optional",",","defaults","to","unlimited","depth",".","min_free_gates","(","int",")",":","Maximum","allowed","circuit","depth","for","the","shallowest","available","device",".","Optional",",","defaults","to","``","max_free_gates","``",".","imbalance_tolerance","(","float",")",":","The","global","maximum","allowed","imbalance","for","all","partition","trials",".","Optional",",","defaults","to","unlimited","imbalance",".","Used","only","if","there","'s","a","known","hard","balancing","constraint","on","the","partitioning","problem",".","trials_per_probe","(","int",")",":","Number","of","repeated","partitioning","trials","for","a","random","automatic","cutting","method","to","attempt","per","set","of","partitioning","parameters",".","For","a","deterministic","cutting","method",",","this","can","be","set","to","1",".","Defaults","to","4",".","*","*","Example","*","*","The","following","cut","strategy","specifies","that","a","circuit","should","be","cut","into","between","``","2","``","to","``","5","``","fragments",",","with","each","fragment","having","at","most","``","6","``","wires","and","at","least","``","4","``","wires",":",">",">",">","cut_strategy","=","qml.transforms.CutStrategy","(","...","max_free_wires=6",",","...","min_free_wires=4",",","...","num_fragments_probed=","(","2",",","5",")",",","...",")"]
docstr: Helper function for determining best imbalance limit.
docstr_tok: ["Helper","function","for","determining","best","imbalance","limit","."]
code: def _infer_imbalance(
      k, wire_depths, free_wires, free_gates, imbalance_tolerance=None
  ) -> float:
      """Helper function for determining best imbalance limit."""
      num_wires = len(wire_depths)
      num_gates = sum(wire_depths.values())
  
      avg_fragment_wires = (num_wires - 1) // k + 1
      avg_fragment_gates = (num_gates - 1) // k + 1
      if free_wires < avg_fragment_wires:
          raise ValueError(
              "`free_wires` should be no less than the average number of wires per fragment. "
              f"Got {free_wires} >= {avg_fragment_wires} ."
          )
      if free_gates < avg_fragment_gates:
          raise ValueError(
              "`free_gates` should be no less than the average number of gates per fragment. "
              f"Got {free_gates} >= {avg_fragment_gates} ."
          )
      if free_gates > num_gates - k:
          # Case where gate depth not limited (`-k` since each fragments has to have >= 1 gates):
          free_gates = num_gates
          # A small adjustment is added to the imbalance factor to prevents small ks from resulting
          # in extremely unbalanced fragments. It will heuristically force the smallest fragment size
          # to be >= 3 if the average fragment size is greater than 5. In other words, tiny fragments
          # are only allowed when average fragmeng size is small in the first place.
          balancing_adjustment = 2 if avg_fragment_gates > 5 else 0
          free_gates = free_gates - (k - 1 + balancing_adjustment)
  
      depth_imbalance = (
          max(wire_depths.values()) * num_wires / num_gates - 1
      )
      max_imbalance = free_gates / avg_fragment_gates - 1
      imbalance = min(depth_imbalance, max_imbalance)
      if imbalance_tolerance is not None:
          imbalance = min(imbalance, imbalance_tolerance)
  
      return imbalance
  
file_path: pennylane/pennylane/qcut/cutstrategy.py
imports: import warnings
  from collections.abc import Sequence
  from dataclasses import InitVar, dataclass
  from typing import Any, ClassVar, Dict, List, Sequence, Union
  from networkx import MultiDiGraph
  import pennylane
  from pennylane.ops.meta import WireCut
label_desc: Use image node_id 3 for calling the CutStrategy obj's underlying member method code with example usage: obj._infer_imbalance(k, wire_depths, free_wires, free_gates, imbalance_tolerance) and returns: imbalance