Quanlse/ErrorMitigation/ZNE/Extrapolation.py
def extrapolate(rescalingCoes: Iterable,
                expectations: Iterable,
                type: str = 'richardson',
                order: int = None,
                a0: float = None,
                sysFunc: bool = True) -> float:
    r"""
    Return the zero-noise extrapolation result (when the rescaling coefficient is zero) using different
    extrapolation strategies.


    :math:`\left\{\lambda_j, E_j \right\}_{1}^m \rightarrow\lim_{\lambda \to 0} E(\lambda)`

    :param rescalingCoes: Iterable, shape (m,).
        a series of rescaling coefficients (:math:`\lambda`)
    :param expectations: Iterable, shape (m,).
        a series of expectations corresponding to 'rescalingCoes'
    :param type: str, default: 'linear'.
        strategy for extrapolating, options: ['linear', 'polynomial', 'richardson', 'poly-exponential', 'exponential']
        or its simplified notations: ['linear', 'poly', 'richard', 'poly-exp', 'exp']
    :param order: int, default: None.
        default is None means that when using `poly-exp`-type or `poly`-type strategy,
        result of a specific order should specify its value
    :param a0: float, default: None.
        default is None means that when using 'poly-exp'-type strategy and the first term is unknown
    :param sysFunc: bool, default: True.
        True implies using the default np.polyfit method, otherwise, use the implemented linearRegression method
    :return: value of expectation when the rescaling coefficient is zero

    References
    ----------
    .. [1] Giurgica-Tiron, T., et al. (2020). Digital zero noise extrapolation for quantum error mitigation: 306-316.
    .. [2] Temme, K., et al. (2017). "Error mitigation for short-depth quantum circuits."
            Physical Review Letters 119(18): 180509.
    .. [3] Wikipedia, "Polynomial regression",
           https://en.wikipedia.org/wiki/Polynomial_regression
    .. [4] Wikipedia, "Polynomial interpolation",
           https://en.wikipedia.org/wiki/Polynomial_interpolation
    """
    typeOptional = ['linear', 'polynomial', 'richardson', 'poly-exponential', 'exponential']
    typeOptionalSimple = ['linear', 'poly', 'richard', 'poly-exp', 'exp']
    if len(rescalingCoes) != len(expectations):
        raise Error.ArgumentError('The length of "rescalingCoes" and "expectations" should be equal!')
    if (type not in typeOptional) and (type not in typeOptionalSimple):
        raise Error.ArgumentError('Please specify the "type" argument from {}'.format(typeOptional))
    # variables definition
    lams = np.array(rescalingCoes)
    Es = np.array(expectations)

    # number of samples
    m = len(lams)
    # extrapolating procedure
    if type == 'linear':
        if m == 2:
            # simply two-point extrapolating
            slope = (Es[1] - Es[0]) / (lams[1] - lams[0])
            res = Es[0] + slope * (0 - lams[0])
        else:
            # linear fitting
            if sysFunc:
                res = np.polyfit(lams, Es, 1)[-1]
            else:
                res = linearRegression(lams, Es)[0]
    elif type == 'richardson' or type == 'richard':
        # (m-1)th-order Richardson Extrapolation
        # 1) solve linear equations
        A = np.array([lams ** i for i in range(m)])
        b = np.zeros_like(lams)
        b[0] = 1
        # 2) compute extrapolated result
        coeffs = np.linalg.solve(A, b)
        res = sum(coeffs * Es)
    elif type == 'polynomial' or type == 'poly':
        if order is not None:
            # return extrapolation result of the specific order
            if order >= m - 1:
                raise Error.ArgumentError(
                    'Please limit value of "order" lower than "m-1" (m is length of "expectations")')
            # polynomial basis function transformation
            if sysFunc:
                res = np.polyfit(lams, Es, order)[-1]
            else:
                res = polyRegression(lams, Es, order)[0]
        else:
            # return extrapolation result of polynomial
            # order: [2, 3, ..., m-2] (list including m-3 elements)
            orders = range(2, m - 1)
            if sysFunc:
                res = [np.polyfit(lams, Es, d)[-1] for d in orders]
            else:
                res = [polyRegression(lams, Es, d)[0] for d in orders]
    elif type == 'poly-exponential' or type == 'poly-exp':
        if a0 is not None:  # a0 is already known
            sign = 1 if np.alltrue(Es - a0 > 0) else -1
            EsLog = np.log(np.abs(Es - a0))
            if order is not None:
                if order >= m - 1:
                    raise Error.ArgumentError('Please limit value of "order" '
                                              'lower than "m-1" (m is length of "expectations")')
                # polynomial basis function transformation
                if sysFunc:
                    z0 = np.polyfit(lams, EsLog, order)[-1]
                else:
                    z0 = polyRegression(lams, EsLog, order)[0]
                res = a0 + sign * np.exp(z0)
            else:
                # return extrapolation result of poly-exponential
                # order: [2, 3, ..., m-2] (list including m-3 elements)
                orders = range(2, m - 1)
                res = []
                for d in orders:
                    if sysFunc:
                        z0 = np.polyfit(lams, EsLog, d)[-1]
                    else:
                        z0 = polyRegression(lams, EsLog, d)[0]
                    res.append(a0 + sign * np.exp(z0))
        else:
            raise Error.ArgumentError("The {} extrapolation method with a0 "
                                      "is unknown is under construction.".format(type))
    elif type == 'exponential' or type == 'exp':
        if a0 is not None:  # a0 is already known
            sign = 1 if np.alltrue(Es - a0 > 0) else -1
            EsLog = np.log(np.abs(Es - a0))
            if m == 2:
                # simply two-point extrapolating
                slope = (EsLog[1] - EsLog[0]) / (lams[1] - lams[0])
                z0 = slope * (0 - lams[0]) + EsLog[0]
                res = a0 + sign * np.exp(z0)
            else:
                if sysFunc:
                    z0 = np.polyfit(lams, EsLog, 1)[-1]
                else:
                    z0 = linearRegression(lams, EsLog)[0]
                res = a0 + sign * np.exp(z0)
        else:
            # numeric fitting using scipy.optimize
            paras, _ = optimize.curve_fit(expSingle, lams, Es)
            res = paras[0] + paras[1]

    return res
r"""
    Return the zero-noise extrapolation result (when the rescaling coefficient is zero) using different
    extrapolation strategies.


    :math:`\left\{\lambda_j, E_j \right\}_{1}^m \rightarrow\lim_{\lambda \to 0} E(\lambda)`

    :param rescalingCoes: Iterable, shape (m,).
        a series of rescaling coefficients (:math:`\lambda`)
    :param expectations: Iterable, shape (m,).
        a series of expectations corresponding to 'rescalingCoes'
    :param type: str, default: 'linear'.
        strategy for extrapolating, options: ['linear', 'polynomial', 'richardson', 'poly-exponential', 'exponential']
        or its simplified notations: ['linear', 'poly', 'richard', 'poly-exp', 'exp']
    :param order: int, default: None.
        default is None means that when using `poly-exp`-type or `poly`-type strategy,
        result of a specific order should specify its value
    :param a0: float, default: None.
        default is None means that when using 'poly-exp'-type strategy and the first term is unknown
    :param sysFunc: bool, default: True.
        True implies using the default np.polyfit method, otherwise, use the implemented linearRegression method
    :return: value of expectation when the rescaling coefficient is zero

    References
    ----------
    .. [1] Giurgica-Tiron, T., et al. (2020). Digital zero noise extrapolation for quantum error mitigation: 306-316.
    .. [2] Temme, K., et al. (2017). "Error mitigation for short-depth quantum circuits."
            Physical Review Letters 119(18): 180509.
    .. [3] Wikipedia, "Polynomial regression",
           https://en.wikipedia.org/wiki/Polynomial_regression
    .. [4] Wikipedia, "Polynomial interpolation",
           https://en.wikipedia.org/wiki/Polynomial_interpolation
    
r"""
Return the zero-noise extrapolation result (when the rescaling coefficient is zero) using different
extrapolation strategies.
r " " " Return the zero - noise extrapolation result ( when the rescaling coefficient is zero ) using different extrapolation strategies .
def extrapolate(rescalingCoes: Iterable,
                expectations: Iterable,
                type: str = 'richardson',
                order: int = None,
                a0: float = None,
                sysFunc: bool = True) -> float:
    typeOptional = ['linear', 'polynomial', 'richardson', 'poly-exponential', 'exponential']
    typeOptionalSimple = ['linear', 'poly', 'richard', 'poly-exp', 'exp']
    if len(rescalingCoes) != len(expectations):
        raise Error.ArgumentError('The length of "rescalingCoes" and "expectations" should be equal!')
    if (type not in typeOptional) and (type not in typeOptionalSimple):
        raise Error.ArgumentError('Please specify the "type" argument from {}'.format(typeOptional))
    lams = np.array(rescalingCoes)
    Es = np.array(expectations)
    m = len(lams)
    if type == 'linear':
        if m == 2:
            slope = (Es[1] - Es[0]) / (lams[1] - lams[0])
            res = Es[0] + slope * (0 - lams[0])
        else:
            if sysFunc:
                res = np.polyfit(lams, Es, 1)[-1]
            else:
                res = linearRegression(lams, Es)[0]
    elif type == 'richardson' or type == 'richard':
        A = np.array([lams ** i for i in range(m)])
        b = np.zeros_like(lams)
        b[0] = 1
        coeffs = np.linalg.solve(A, b)
        res = sum(coeffs * Es)
    elif type == 'polynomial' or type == 'poly':
        if order is not None:
            if order >= m - 1:
                raise Error.ArgumentError(
                    'Please limit value of "order" lower than "m-1" (m is length of "expectations")')
            if sysFunc:
                res = np.polyfit(lams, Es, order)[-1]
            else:
                res = polyRegression(lams, Es, order)[0]
        else:
            orders = range(2, m - 1)
            if sysFunc:
                res = [np.polyfit(lams, Es, d)[-1] for d in orders]
            else:
                res = [polyRegression(lams, Es, d)[0] for d in orders]
    elif type == 'poly-exponential' or type == 'poly-exp':
        if a0 is not None:  
            sign = 1 if np.alltrue(Es - a0 > 0) else -1
            EsLog = np.log(np.abs(Es - a0))
            if order is not None:
                if order >= m - 1:
                    raise Error.ArgumentError('Please limit value of "order" '
                                              'lower than "m-1" (m is length of "expectations")')
                if sysFunc:
                    z0 = np.polyfit(lams, EsLog, order)[-1]
                else:
                    z0 = polyRegression(lams, EsLog, order)[0]
                res = a0 + sign * np.exp(z0)
            else:
                orders = range(2, m - 1)
                res = []
                for d in orders:
                    if sysFunc:
                        z0 = np.polyfit(lams, EsLog, d)[-1]
                    else:
                        z0 = polyRegression(lams, EsLog, d)[0]
                    res.append(a0 + sign * np.exp(z0))
        else:
            raise Error.ArgumentError("The {} extrapolation method with a0 "
                                      "is unknown is under construction.".format(type))
    elif type == 'exponential' or type == 'exp':
        if a0 is not None:  
            sign = 1 if np.alltrue(Es - a0 > 0) else -1
            EsLog = np.log(np.abs(Es - a0))
            if m == 2:
                slope = (EsLog[1] - EsLog[0]) / (lams[1] - lams[0])
                z0 = slope * (0 - lams[0]) + EsLog[0]
                res = a0 + sign * np.exp(z0)
            else:
                if sysFunc:
                    z0 = np.polyfit(lams, EsLog, 1)[-1]
                else:
                    z0 = linearRegression(lams, EsLog)[0]
                res = a0 + sign * np.exp(z0)
        else:
            paras, _ = optimize.curve_fit(expSingle, lams, Es)
            res = paras[0] + paras[1]
    return res
def extrapolate ( rescalingCoes : Iterable , expectations : Iterable , type : str = 'richardson' , order : int = None , a0 : float = None , sysFunc : bool = True ) -> float : typeOptional = [ 'linear' , 'polynomial' , 'richardson' , 'poly-exponential' , 'exponential' ] typeOptionalSimple = [ 'linear' , 'poly' , 'richard' , 'poly-exp' , 'exp' ] if len ( rescalingCoes ) != len ( expectations ) : raise Error . ArgumentError ( 'The length of "rescalingCoes" and "expectations" should be equal!' ) if ( type not in typeOptional ) and ( type not in typeOptionalSimple ) : raise Error . ArgumentError ( 'Please specify the "type" argument from {}' . format ( typeOptional ) ) lams = np . array ( rescalingCoes ) Es = np . array ( expectations ) m = len ( lams ) if type == 'linear' : if m == 2 : slope = ( Es [ 1 ] - Es [ 0 ] ) / ( lams [ 1 ] - lams [ 0 ] ) res = Es [ 0 ] + slope * ( 0 - lams [ 0 ] ) else : if sysFunc : res = np . polyfit ( lams , Es , 1 ) [ - 1 ] else : res = linearRegression ( lams , Es ) [ 0 ] elif type == 'richardson' or type == 'richard' : A = np . array ( [ lams ** i for i in range ( m ) ] ) b = np . zeros_like ( lams ) b [ 0 ] = 1 coeffs = np . linalg . solve ( A , b ) res = sum ( coeffs * Es ) elif type == 'polynomial' or type == 'poly' : if order is not None : if order >= m - 1 : raise Error . ArgumentError ( 'Please limit value of "order" lower than "m-1" (m is length of "expectations")' ) if sysFunc : res = np . polyfit ( lams , Es , order ) [ - 1 ] else : res = polyRegression ( lams , Es , order ) [ 0 ] else : orders = range ( 2 , m - 1 ) if sysFunc : res = [ np . polyfit ( lams , Es , d ) [ - 1 ] for d in orders ] else : res = [ polyRegression ( lams , Es , d ) [ 0 ] for d in orders ] elif type == 'poly-exponential' or type == 'poly-exp' : if a0 is not None : sign = 1 if np . alltrue ( Es - a0 > 0 ) else - 1 EsLog = np . log ( np . abs ( Es - a0 ) ) if order is not None : if order >= m - 1 : raise Error . ArgumentError ( 'Please limit value of "order" ' 'lower than "m-1" (m is length of "expectations")' ) if sysFunc : z0 = np . polyfit ( lams , EsLog , order ) [ - 1 ] else : z0 = polyRegression ( lams , EsLog , order ) [ 0 ] res = a0 + sign * np . exp ( z0 ) else : orders = range ( 2 , m - 1 ) res = [ ] for d in orders : if sysFunc : z0 = np . polyfit ( lams , EsLog , d ) [ - 1 ] else : z0 = polyRegression ( lams , EsLog , d ) [ 0 ] res . append ( a0 + sign * np . exp ( z0 ) ) else : raise Error . ArgumentError ( "The {} extrapolation method with a0 " "is unknown is under construction." . format ( type ) ) elif type == 'exponential' or type == 'exp' : if a0 is not None : sign = 1 if np . alltrue ( Es - a0 > 0 ) else - 1 EsLog = np . log ( np . abs ( Es - a0 ) ) if m == 2 : slope = ( EsLog [ 1 ] - EsLog [ 0 ] ) / ( lams [ 1 ] - lams [ 0 ] ) z0 = slope * ( 0 - lams [ 0 ] ) + EsLog [ 0 ] res = a0 + sign * np . exp ( z0 ) else : if sysFunc : z0 = np . polyfit ( lams , EsLog , 1 ) [ - 1 ] else : z0 = linearRegression ( lams , EsLog ) [ 0 ] res = a0 + sign * np . exp ( z0 ) else : paras , _ = optimize . curve_fit ( expSingle , lams , Es ) res = paras [ 0 ] + paras [ 1 ] return res
r"""
Return the zero-noise extrapolation result (when the rescaling coefficient is zero) using different
extrapolation strategies.
r " " " Return the zero - noise extrapolation result ( when the rescaling coefficient is zero ) using different extrapolation strategies .
r"""
    Return the zero-noise extrapolation result (when the rescaling coefficient is zero) using different
    extrapolation strategies.


    :math:`\left\{\lambda_j, E_j \right\}_{1}^m \rightarrow\lim_{\lambda \to 0} E(\lambda)`

    :param rescalingCoes: Iterable, shape (m,).
        a series of rescaling coefficients (:math:`\lambda`)
    :param expectations: Iterable, shape (m,).
        a series of expectations corresponding to 'rescalingCoes'
    :param type: str, default: 'linear'.
        strategy for extrapolating, options: ['linear', 'polynomial', 'richardson', 'poly-exponential', 'exponential']
        or its simplified notations: ['linear', 'poly', 'richard', 'poly-exp', 'exp']
    :param order: int, default: None.
        default is None means that when using `poly-exp`-type or `poly`-type strategy,
        result of a specific order should specify its value
    :param a0: float, default: None.
        default is None means that when using 'poly-exp'-type strategy and the first term is unknown
    :param sysFunc: bool, default: True.
        True implies using the default np.polyfit method, otherwise, use the implemented linearRegression method
    :return: value of expectation when the rescaling coefficient is zero

    References
    ----------
    .. [1] Giurgica-Tiron, T., et al. (2020). Digital zero noise extrapolation for quantum error mitigation: 306-316.
    .. [2] Temme, K., et al. (2017). "Error mitigation for short-depth quantum circuits."
            Physical Review Letters 119(18): 180509.
    .. [3] Wikipedia, "Polynomial regression",
           https://en.wikipedia.org/wiki/Polynomial_regression
    .. [4] Wikipedia, "Polynomial interpolation",
           https://en.wikipedia.org/wiki/Polynomial_interpolation
    """ # variables definition # number of samples # extrapolating procedure # simply two-point extrapolating # linear fitting # (m-1)th-order Richardson Extrapolation # 1) solve linear equations # 2) compute extrapolated result # return extrapolation result of the specific order # polynomial basis function transformation # return extrapolation result of polynomial # order: [2, 3, ..., m-2] (list including m-3 elements) # a0 is already known # polynomial basis function transformation # return extrapolation result of poly-exponential # order: [2, 3, ..., m-2] (list including m-3 elements) # a0 is already known # simply two-point extrapolating # numeric fitting using scipy.optimize
value of expectation when the rescaling coefficient is zero
References

[1] Giurgica-Tiron, T., et al.
value of expectation when the rescaling coefficient is zero References [ 1 ] Giurgica - Tiron T . et al .
rescalingCoes
Iterable
Iterable, shape (m,).
a series of rescaling coefficients (:math:`\lambda`)
Iterable shape ( m ) . a series of rescaling coefficients ( : math : ` \ lambda ` )
expectations
Iterable
Iterable, shape (m,).
a series of expectations corresponding to 'rescalingCoes'
Iterable shape ( m ) . a series of expectations corresponding to ' rescalingCoes '
type
str
str, default: 'linear'.
strategy for extrapolating, options: ['linear', 'polynomial', 'richardson', 'poly-exponential', 'exponential']
or its simplified notations: ['linear', 'poly', 'richard', 'poly-exp', 'exp']
str default : ' linear ' . strategy for extrapolating options : [ ' linear ' ' polynomial ' ' richardson ' ' poly - exponential ' ' exponential ' ] or its simplified notations : [ ' linear ' ' poly ' ' richard ' ' poly - exp ' ' exp ' ]
order
int
int, default: None.
default is None means that when using `poly-exp`-type or `poly`-type strategy,
result of a specific order should specify its value
int default : None . default is None means that when using ` poly - exp ` - type or ` poly ` - type strategy result of a specific order should specify its value
a0
float
float, default: None.
default is None means that when using 'poly-exp'-type strategy and the first term is unknown
float default : None . default is None means that when using ' poly - exp ' - type strategy and the first term is unknown
sysFunc
bool
bool, default: True.
True implies using the default np.polyfit method, otherwise, use the implemented linearRegression method
bool default : True . True implies using the default np . polyfit method otherwise use the implemented linearRegression method
math
None