Source code for prodigy.analysis.optimization.gf_optimizer

from typing import List, Union, get_args

import sympy
from prodigy.pgcl import Expr, OptimizationType, VarExpr
from prodigy.pgcl.parser import parse_expr

from prodigy.distribution.distribution import Distribution

from .optimizer import Optimizer


[docs] class GFOptimizer(Optimizer):
[docs] @staticmethod def optimize( condition: Union[str, Expr], dist: Distribution, *parameters: Union[str, VarExpr], method: OptimizationType = OptimizationType.MINIMIZE ) -> List[Union[str, Expr]]: if len(parameters) > 1: raise NotImplementedError( "We currently do not support multivariate optimization.") # Make sure, that the condition is a parsed expression. if not isinstance(condition, get_args(Expr)): expr = parse_expr(condition) else: expr = condition # Compute the target function that needs to be optimized: target_function = sympy.S(dist.filter(expr).get_probability_mass()) # invoke sympy to get the optimization. if method == OptimizationType.MAXIMIZE: maximum = sympy.maximum( target_function, sympy.Symbol(str(parameters[0])), sympy.sets.Interval(0, sympy.S("oo"), False, True)) param = sympy.solve(target_function - maximum, sympy.S(str(parameters[0]))) param = [ real_sol for real_sol in param if real_sol.is_real and real_sol.is_nonnegative ] elif method == OptimizationType.MINIMIZE: minimum = sympy.minimum( target_function, sympy.Symbol(str(parameters[0])), sympy.sets.Interval(0, sympy.S("oo"), False, True)) param = sympy.solve(target_function - minimum, sympy.S(str(parameters[0]))) param = [ real_sol for real_sol in param if real_sol.is_real and real_sol.is_nonnegative ] else: raise TypeError(f"Unknown optimization method. {method}") return param