Source code for flopt.solvers

from flopt.constants import VariableType, ExpressionType
from flopt.env import setup_logger

logger = setup_logger(__name__)

algo_list = [
    "Random",
    "2-Opt",
    "SteepestDescent",
    "OptunaTPE",
    "OptunaCmaEs",
    "OptunaNSGAII",
    "Hyperopt",
    "SFLA",
    "Gurobi",
    "Pulp",
    "Scipy",
    "ScipyMilp",
    "Cvxopt",
    # "Amplify",
    "auto",
]


[docs]def Solver(algo="auto"): """ Obtain Solver object. Parameters ---------- algo : str algorithm name Returns ------- Solver object return Solver """ if algo.endswith("Search"): algo = algo.replace("Search", "") logger.warning( f"It is recommended to use algorithm name {algo} instead of {algo}Search, " + f"{algo}Search will not be available in the future version" ) if algo == "CvxoptQp": algo = "Cvxopt" logger.warning( f"It is recommended to use algorithm name Cvxopt instead of CvxoptQp, " + f"CvxoptQp will not be available in the future version" ) elif algo == "HyperoptTPE": algo = "Cvxopt" logger.warning( f"It is recommended to use algorithm name Hyperopt instead of HyperoptTPE, " + f"HyperoptTPE will not be available in the future version" ) algo = algo.lower() if algo == "random": from flopt.solvers.random_search import RandomSearch return RandomSearch() elif algo == "2-opt": from flopt.solvers.two_opt import TwoOpt return TwoOpt() elif algo == "steepestdescent": from flopt.solvers.steepest_descent import SteepestDescentSearch return SteepestDescentSearch() elif algo == "optunatpe": from flopt.solvers.optuna_searches import OptunaTPESearch return OptunaTPESearch() elif algo == "optunacmaes": from flopt.solvers.optuna_searches import OptunaCmaEsSearch return OptunaCmaEsSearch() elif algo == "optunansgaii": from flopt.solvers.optuna_searches import OptunaNSGAIISearch return OptunaNSGAIISearch() elif algo == "hyperopt": from flopt.solvers.hyperopt_search import HyperoptSearch return HyperoptSearch() elif algo == "sfla": from flopt.solvers.shuffled_frog_leaping_search import ShuffledFrogLeapingSearch return ShuffledFrogLeapingSearch() elif algo == "gurobi": from flopt.solvers.gurobi_search import GurobiSearch return GurobiSearch() elif algo == "pulp": from flopt.solvers.pulp_search import PulpSearch return PulpSearch() elif algo == "scipy": from flopt.solvers.scipy_searches import ScipySearch return ScipySearch() elif algo == "scipymilp": from flopt.solvers.scipy_searches import ScipyMilpSearch return ScipyMilpSearch() elif algo == "cvxopt": from flopt.solvers.cvxopt_search import CvxoptSearch return CvxoptSearch() elif algo == "amplify": from flopt.solvers.amplify_search import AmplifySearch return AmplifySearch() elif algo == "auto": from flopt.solvers.auto_search import AutoSearch return AutoSearch() else: assert False, f"{algo} is not available, choices from {Solver_list()}"
[docs]def Solver_list(): """ Obtain useable solver list Returns ------- list return list of algorithm names """ return algo_list
[docs]def allAvailableSolvers(prob): """Obtain all available solvers to solve the problem Parameters ---------- prob : Problem problem Returns ------- list of str algorithm names that can solve the problem Examples -------- .. code-block:: python import flopt from flopt import Variable, Problem, CustomExpression # Linear problem without constraint a = Variable("a", 0, 1, "Integer") b = Variable("b", 1, 2, "Continuous") c = Variable("c", 1, 3, "Continuous") prob_linear = Problem(name="Only objective") prob_linear += a + b + c # Problem with constraint prob_with_const = Problem(name="With constraint") prob_with_const += a + b + c prob_with_const += a + b >= 2 # Non-Linear problem prob_nonlinear = Problem("Non Linear") prob_nonlinear += a*b*c prob_nonlinear += a + b >= 2 # Permutation Problem p = Variable("p", 0, 4, "Permutation") prob_perm = Problem("TestP") def obj(p): return p[-1] - p[0] prob_perm += CustomExpression(obj, [p]) # display solvers can solve prob_linear print(flopt.allAvailableSolvers(prob_linear) # display solvers can solve prob_with_const print(flopt.allAvailableSolvers(prob_with_const)) # display solvers can solve prob_nonlinear print(flopt.allAvailableSolvers(prob_nonlinear)) # display solvers can solve prob_perm print(flopt.allAvailableSolvers(prob_perm)) """ available_solvers = [ algo for algo in Solver_list() if Solver(algo=algo).available(prob) ] return available_solvers
def allAvailableSolversProblemType(problem_type): """ Parameters ---------- problem_type : dict key is "Variable", "Objective", "Constraint" Returns ------- list of str algorithm names that can solve the problem Examples -------- .. code-block:: python import flopt.constants import flopt.solvers problem_type = dict( Variable=flopt.constants.VariableType.Number, Objective=flopt.constants.ExpressionType.BlackBox, Constraint=None ) flopt.solvers.allAvailableSolversProblemType(problem_type) """ available_solvers = [ algo for algo in Solver_list() if Solver(algo=algo).availableProblemType(problem_type) ] return available_solvers def estimate_problem_type(prob): """Estimate problem types Parameters ---------- prob : Problem """ from flopt.solvers.selector import ( lp, mip, ising, qp, permutation, blackbox, blackbox_mip, nonlinear, nonlinear_mip, ) problem_classes = [ (lp, "lp"), (mip, "mip"), (ising, "ising"), (qp, "quadratic"), (permutation, "permutation"), (blackbox, "blackbox"), (blackbox_mip, "blackbox with interger variables"), (nonlinear, "nonlinear"), (nonlinear_mip, "nonlinear with integer variables"), ] def check(problem_type, problem_class): is_problem_class = ( problem_type["Variable"].expand() <= problem_class["Variable"].expand() and problem_type["Objective"].expand() <= problem_class["Objective"].expand() and problem_type["Constraint"].expand() <= problem_class["Constraint"].expand() ) return is_problem_class problem_type = prob.toProblemType() print("Problem") print(prob.__str__(prefix="\t")) print() print("Problem components") print(f"\tVariable: {problem_type['Variable']}") print(f"\tObjective: {problem_type['Objective']}") print(f"\tConstraint: {problem_type['Constraint']}") print() print("Problem classes") for problem_class, name in problem_classes: if is_problem_class := check(problem_type, problem_class): print("\t-->", name) else: print("\t ", name)