import contextlib
import numpy as np
from ..core.parameter import assign_values_jit as assign_values_jit
from ..util import ztyping as ztyping
from ..util.container import convert_to_container as convert_to_container
from ..util.exception import DerivativeCalculationError as DerivativeCalculationError, MaximumIterationReached as MaximumIterationReached
from ..z import numpy as znp
from .strategy import ZfitStrategy as ZfitStrategy
from _typeshed import Incomplete
from collections.abc import Callable as Callable, Generator
from zfit._interfaces import ZfitLoss as ZfitLoss

def assign_values_func(params, values): ...
def check_derivative_none_raise(values, params) -> None: ...

class LossEval:
    maxiter: Incomplete
    loss: Incomplete
    hesse_fn: Incomplete
    gradients_fn: Incomplete
    value_gradients_fn: Incomplete
    last_value: Incomplete
    last_gradient: Incomplete
    last_hessian: Incomplete
    nan_counter: int
    params: Incomplete
    strategy: Incomplete
    do_print: Incomplete
    full: Incomplete
    numpy_converter: Incomplete
    def __init__(self, loss: ZfitLoss, params: ztyping.ParamTypeInput, strategy: ZfitStrategy, do_print: bool, maxiter: int, grad_fn: Callable | None = None, hesse_fn: Callable | None = None, numpy_converter: Callable | None = None, full: bool | None = None) -> None: ...
    @property
    def niter(self): ...
    @property
    def maxiter_reached(self): ...
    @contextlib.contextmanager
    def ignore_maxiter(self) -> Generator[None]: ...
    @property
    def ignoring_maxiter(self): ...
    @property
    def nfunc_eval(self): ...
    @nfunc_eval.setter
    def nfunc_eval(self, value) -> None: ...
    @property
    def ngrad_eval(self): ...
    @ngrad_eval.setter
    def ngrad_eval(self, value) -> None: ...
    @property
    def nhess_eval(self): ...
    @nhess_eval.setter
    def nhess_eval(self, value) -> None: ...
    def value_gradient(self, values: np.ndarray) -> tuple[np.float64, np.ndarray]: ...
    def value(self, values: np.ndarray) -> np.float64: ...
    def gradient(self, values: np.ndarray) -> np.ndarray: ...
    def hessian(self, values) -> znp.array: ...

def print_params(params, values, loss=None) -> None: ...
def print_gradient(params, values, gradient, loss=None) -> None: ...
