class Optimizer:
    def __init__(self, problem):
        self.problem = problem

    def solve_optimization_problem(self, initial_guesses=None, solver_options=None):
        opti = self.problem['opti']
        
        if initial_guesses:
            for param, value in initial_guesses.items():
                opti.set_initial(self.problem[param], value)

        # Set numerical backend, with options if provided
        if solver_options:
            opti.solver('ipopt', solver_options)
        else:
            opti.solver('ipopt')

        try:
            sol = opti.solve()   # actual solve
            status = 'succeeded'
        except:
            sol = None
            status = 'failed'

        results = {
            'status' : status,
            'solution' : sol,
        }

        if sol:
            for var_name, var in self.problem.items():
                if var_name != 'opti':
                    results[var_name] = sol.value(var)

        return results