#  _________________________________________________________________________
#
#  Coopr: A COmmon Optimization Python Repository
#  Copyright (c) 2008 Sandia Corporation.
#  This software is distributed under the BSD License.
#  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
#  the U.S. Government retains certain rights in this software.
#  For more information, see the Coopr README.txt file.
#  _________________________________________________________________________

__all__ = ['SolverInformation', 'SolverStatus', 'TerminationCondition']

from container import *
from pyutilib.enum import Enum


# Semantics: A coarse summary of how the solver terminated.
SolverStatus = Enum(
    'ok',                   # Normal termination
    'warning',              # Termination with unusual condition
    'error',                # Terminated internally with error
    'aborted',              # Terminated due to external conditions (e.g. interrupts)
    'unknown'               # An unitialized value 
    )

TerminationCondition = Enum(
    # OK
    'maxIterations',        # Exceeded maximum number of iterations allowed by user
    'minFunctionValue',     # Found solution smaller than specified function value
    'minStepLength',        # Step length is smaller than specified limit
    'globallyOptimal',      # Found a globally optimal solution
    'locallyOptimal',       # Found a locally optimal solution
    'optimal',              # Found an optimal solution
    'maxEvaluations',       # Exceeded maximum number of problem evaluations
    # WARNING
    'unbounded',            # Demonstrated that problem is unbounded
    'infeasible',           # Demonstrated that the problem is infeasible
    'invalidProlem',        # The problem setup or characteristics are not valide for the solver
    'other'                 # Other, uncategorized normal termination
    # ERROR
    'solverFailure',        # Solver failed to terminate correctly
    'internalSolverError',  # Internal solver error
    'error',                # Other errors
    # ABORTED
    'userInterrupt',        # Interrupt signal generated by user
    'resourceInterrupt',    # Interrupt signal in resources used by optimizer
    'licensingProblems',    # Problem accessing solver license
    # UNKNOWN
    'unknown'               # An unitialized value 
    )



class BranchAndBoundStats(MapContainer):

    def __init__(self):
        MapContainer.__init__(self)
        self.declare('number of bounded subproblems')
        self.declare('number of created subproblems')


class BlackBoxStats(MapContainer):

    def __init__(self):
        MapContainer.__init__(self)
        self.declare('number of function evaluations')
        self.declare('number of gradient evaluations')
        self.declare('number of iterations')


class SolverStatistics(MapContainer):

    def __init__(self):
        MapContainer.__init__(self)
        self.declare("branch_and_bound", value=BranchAndBoundStats(), active=False)
        self.declare("black_box", value=BlackBoxStats(), active=False)


class SolverInformation(MapContainer):

    def __init__(self):
        MapContainer.__init__(self)
        self.declare('name')
        self.declare('status', value=SolverStatus.ok)
        self.declare('return_code') # Semantics: the integer return code from the shell in which the solver is launched.
        self.declare('message')
        self.declare('user_time', type=ScalarType.time)
        self.declare('system_time', type=ScalarType.time)
        self.declare('wallclock_time', type=ScalarType.time)
        self.declare('termination_condition', value=TerminationCondition.unknown) # Semantics: The specific condition that caused the solver to terminate.
        self.declare('termination_message') # Semantics: A string pritned by the solver that summarizes the termination status.
        self.declare('statistics', value=SolverStatistics(), active=False)

