input: 
  import numpy as np
  
  def optimize_with_constraints(obj_func, constraints, x0, method='slsqp', bounds=None) -> np.ndarray:
      """ Optimize the given objective function "obj_func" with the specified constraints and initial guess x0.
      The constraints should be a list of dictionaries where each dictionary describes a constraint in the following format:
      {
          'type': 'eq' or 'ineq',
          'fun': constraint function
      }
      Bounds should be specified as a list of tuples, where each tuple corresponds to the min and max of a variable in x0.
      The method defaults to 'slsqp' and options will be used to control the behavior of the solver.
  
      >>> def obj_func(x):
      ...     return (x[0] - 1)**2 + (x[1] - 2.5)**2
      ... 
      >>> def constraint1(x):
      ...     return x[0] - 2 * x[1] + 2
      ... 
      >>> def constraint2(x):
      ...     return -x[0] - 2 * x[1] + 6
      ... 
      >>> def constraint3(x):
      ...     return -x[0] + 2 * x[1] + 2
      ... 
      >>> constraints = [{'type': 'ineq', 'fun': constraint1}, {'type': 'ineq', 'fun': constraint2}, {'type': 'ineq', 'fun': constraint3}]
      >>> x0 = np.array([0, 0])
      >>> bounds = [(-10, 10), (-10, 10)]
      >>> solution = optimize_with_constraints(obj_func, constraints, x0, bounds=bounds)
      >>> solution.round(1)
      array([1.4, 1.7])
      """
      from scipy.optimize import minimize
      res = minimize(obj_func, x0, method=method, bounds=bounds, constraints=constraints)
      return res.x
  
output:     from scipy.optimize import minimize
      res = minimize(obj_func, x0, method=method, bounds=bounds, constraints=constraints)
      return res.x