def test_core_numbers(): for c in (Catalan, Catalan(), ComplexInfinity, ComplexInfinity(), EulerGamma, EulerGamma(), Exp1, Exp1(), GoldenRatio, GoldenRatio(), Half, Half(), ImaginaryUnit, ImaginaryUnit(), Infinity, Infinity(), Integer, Integer(2), NaN, NaN(), NegativeInfinity, NegativeInfinity(), NegativeOne, NegativeOne(), Number, Number(15), NumberSymbol, NumberSymbol(), One, One(), Pi, Pi(), Rational, Rational(1,2), Real, Real("1.2"), Zero, Zero()): check(c)
def test_sympy__core__numbers__NaN(): from sympy.core.numbers import NaN assert _test_args(NaN())
def resolve_balance_sheet(x0: np.ndarray, eqs: List[Eq], plug_keys: Sequence[str], subs_dict: Dict[IndexedBase, float], forecast_dates: pd.DatetimeIndex, config: StatementsConfigManager, sympy_namespace: Dict[str, IndexedBase], bs_diff_max: float, balance_groups: List[Set[str]], timeout: float) -> Dict[IndexedBase, float]: plug_solutions = _x_arr_to_plug_solutions(x0, plug_keys, sympy_namespace) all_to_solve: Dict[IndexedBase, Expr] = {} for eq in eqs: expr = eq.rhs - eq.lhs if expr == NaN(): raise InvalidForecastEquationException(f'got NaN forecast equation. LHS: {eq.lhs}, RHS: {eq.rhs}') if eq.lhs in all_to_solve: raise InvalidForecastEquationException( f'got multiple equations to solve for {eq.lhs}. Already had {all_to_solve[eq.lhs]}, now got {expr}' ) all_to_solve[eq.lhs] = expr for sol_dict in [subs_dict, plug_solutions]: # Plug solutions second here so that they are at end of array for lhs, rhs in sol_dict.items(): expr = rhs - lhs if expr == NaN(): raise MissingDataException(f'got NaN for {lhs} but that is needed for resolving the forecast') if lhs in all_to_solve: existing_value = all_to_solve[lhs] if isinstance(existing_value, float): had_message = f'forecast/plug value of {existing_value}' else: had_message = f'equation of {existing_value}' raise InvalidForecastEquationException( f'got forecast/plug value for {lhs} but already had an existing {had_message}, now got {expr}' ) all_to_solve[lhs] = expr to_solve_for = list(all_to_solve.keys()) solve_exprs = list(all_to_solve.values()) _check_for_invalid_system_of_equations(eqs, subs_dict, plug_solutions, to_solve_for, solve_exprs) eq_arrs = _symbolic_to_matrix(solve_exprs, to_solve_for) # Get better initial x0 by adding to appropriate plug _adjust_x0_to_initial_balance_guess(x0, plug_keys, eq_arrs, forecast_dates, to_solve_for, config, balance_groups) result = PlugResult(timeout=timeout) res: Optional[OptimizeResult] = None try: res = minimize( _resolve_balance_sheet_check_diff, x0, args=(eq_arrs, forecast_dates, to_solve_for, bs_diff_max, balance_groups, result), bounds=[(0, None) for _ in range(len(x0))], # all positive method='TNC', options=dict( maxCGit=0, maxfun=1000000000, ) ) except (BalanceSheetBalancedException, BalanceSheetNotBalancedException): pass if not result.met_goal: if result.fun is None or result.res is None: # Mainly for mypy purposes raise BalanceSheetNotBalancedException( 'Unexpected balancing error. Did not evaluate the balancing function even once' ) plug_solutions = _x_arr_to_plug_solutions(result.res, plug_keys, sympy_namespace) avg_error = (result.fun ** 2 / len(result.res)) ** 0.5 message = ( f'final solution {plug_solutions} still could not meet max difference of ' f'${bs_diff_max:,.0f} within timeout of {result.timeout}s. ' f'Average difference was ${avg_error:,.0f}.\nIf the make_forecast or plug ' f'configuration for any items were changed, ensure that changes in {plug_keys} can flow through ' f'to Total Assets and Total Liabilities and Equity. For example, if make_forecast=True for Total Debt ' f'and make_forecast=False for ST Debt, then using LT debt as a plug will not work as ST debt will ' f'go down when LT debt goes up.\nOtherwise, consider ' f'passing to .forecast a timeout greater than {result.timeout}, ' f'a bs_diff_max at a value greater than {avg_error:,.0f}, or pass ' f'balance=False to skip balancing entirely.' ) raise BalanceSheetNotBalancedException(message) else: logger.info(f'Balanced in {result.time_elapsed:.1f}s') plug_solutions = _x_arr_to_plug_solutions(result.res, plug_keys, sympy_namespace) solutions_dict = _solve_eqs_with_plug_solutions( eqs, plug_solutions, subs_dict, forecast_dates, config.items ) return solutions_dict