docs: def minimize_ipopt(fun, x0, args=(), kwargs=None, method=None, jac=None, hess=None, hessp=None,
                     bounds=None, constraints=(), tol=None, callback=None, options=None):
      """
      Minimize a function using ipopt. The call signature is exactly like for
      `scipy.optimize.mimize`. In options, all options are directly passed to
      ipopt. Check [http://www.coin-or.org/Ipopt/documentation/node39.html] for
      details.
      The options `disp` and `maxiter` are automatically mapped to their
      ipopt-equivalents `print_level` and `max_iter`.
      """
      if not SCIPY_INSTALLED:
          raise ImportError('Install SciPy to use the `minimize_ipopt` function.')
  
      _x0 = np.atleast_1d(x0)
      problem = IpoptProblemWrapper(fun, args=args, kwargs=kwargs, jac=jac, hess=hess,
                                    hessp=hessp, constraints=constraints)
      lb, ub = get_bounds(bounds)
  
      cl, cu = get_constraint_bounds(constraints, x0)
  
      if options is None:
          options = {}
  
      nlp = cyipopt.problem(n = len(_x0),
                            m = len(cl),
                            problem_obj=problem,
                            lb=lb,
                            ub=ub,
                            cl=cl,
                            cu=cu)
  
      # python3 compatibility
      convert_to_bytes(options)
  
      # Rename some default scipy options
      replace_option(options, b'disp', b'print_level')
      replace_option(options, b'maxiter', b'max_iter')
      if b'print_level' not in options:
          options[b'print_level'] = 0
      if b'tol' not in options:
          options[b'tol'] = tol or 1e-8
      if b'mu_strategy' not in options:
          options[b'mu_strategy'] = b'adaptive'
      if b'hessian_approximation' not in options:
          if hess is None and hessp is None:
              options[b'hessian_approximation'] = b'limited-memory'
      for option, value in options.items():
          try:
              nlp.addOption(option, value)
          except TypeError as e:
              raise TypeError('Invalid option for IPOPT: {0}: {1} (Original message: "{2}")'.format(option, value, e))
  
      x, info = nlp.solve(_x0)
  
      if np.asarray(x0).shape == ():
          x = x[0]
  
      return OptimizeResult(x=x, success=info['status'] == 0, status=info['status'],
                            message=info['status_msg'],
                            fun=info['obj_val'],
                            info=info,
                            nfev=problem.nfev,
                            njev=problem.njev,
                            nit=problem.nit)