code: def test_raf_evaluate(data):
      """Tests ReconcileAdditiveForecasts evaluate, transform_evaluate, fit_transform_evaluate"""
      forecasts = data["forecasts"]
      actuals = data["actuals"]
      levels = data["levels"]
      order_dict = data["order_dict"]
      raf = ReconcileAdditiveForecasts()
      raf.fit_transform(
          forecasts=forecasts,
          actuals=actuals,
          levels=levels,
          order_dict=order_dict,
          method="mint_sample",
      )
  
      # Tests `evaluate` on training set
      raf.evaluate(is_train=True)
      assert len(raf.figures) == 3
      assert raf.constraint_violation["actual"] < 1e-5
      assert raf.constraint_violation["adjusted"] < 1e-5
      assert raf.constraint_violation["forecast"] > 1e-5
      assert list(raf.evaluation_df.columns) == [
          "MAPE pp change",
          "MedAPE pp change",
          "RMSE % change",
          "Base MAPE",
          "Adjusted MAPE",
          "Base MedAPE",
          "Adjusted MedAPE",
          "Base RMSE",
          "Adjusted RMSE",
      ]
      assert_equal(
          raf.evaluation_df["RMSE % change"],
          100
          * (
              raf.evaluation_df["Adjusted RMSE"]
              / raf.evaluation_df["Base RMSE"]
              - 1.0
          ),
          check_names=False,
      )
      assert_equal(
          raf.evaluation_df["MAPE pp change"],
          raf.evaluation_df["Adjusted MAPE"]
          - raf.evaluation_df["Base MAPE"],
          check_names=False,
      )
      assert_equal(
          raf.evaluation_df["MedAPE pp change"],
          raf.evaluation_df["Adjusted MedAPE"]
          - raf.evaluation_df["Base MedAPE"],
          check_names=False,
      )
      assert list(raf.evaluation_df["RMSE % change"] > 0) == [
          False,
          False,
          False,
          False,
      ]
      assert list(raf.evaluation_df["MAPE pp change"] > 0) == [
          False,
          False,
          False,
          False,
      ]
      assert list(raf.evaluation_df["MedAPE pp change"] > 0) == [
          False,
          False,
          False,
          False,
      ]
      assert_equal(
          mean_absolute_percent_error(
              raf.actuals["root"], raf.adjusted_forecasts["root"]
          ),
          raf.evaluation_df.loc["root", "Adjusted MAPE"],
      )
      assert_equal(
          mean_absolute_percent_error(
              raf.actuals["c1"], raf.forecasts["c1"]
          ),
          raf.evaluation_df.loc["c1", "Base MAPE"],
      )
      assert_equal(
          median_absolute_percent_error(
              raf.actuals["c2"], raf.adjusted_forecasts["c2"]
          ),
          raf.evaluation_df.loc["c2", "Adjusted MedAPE"],
      )
      assert_equal(
          median_absolute_percent_error(
              raf.actuals["c3"], raf.forecasts["c3"]
          ),
          raf.evaluation_df.loc["c3", "Base MedAPE"],
      )
      assert_equal(
          root_mean_squared_error(
              raf.actuals["root"], raf.adjusted_forecasts["root"]
          ),
          raf.evaluation_df.loc["root", "Adjusted RMSE"],
      )
      assert_equal(
          root_mean_squared_error(
              raf.actuals["c1"], raf.forecasts["c1"]
          ),
          raf.evaluation_df.loc["c1", "Base RMSE"],
      )
      evaluation_df = raf.evaluation_df
  
      # Changing the parameters affects the evaluation results
      raf = ReconcileAdditiveForecasts()
      raf.fit_transform(
          forecasts=forecasts,
          actuals=actuals,
          levels=levels,
          order_dict=order_dict,
          lower_bound=None,
          upper_bound=None,
          unbiased=True,
          lam_adj=0.0,
          lam_bias=0.0,
          lam_train=1.0,
          lam_var=0.0,
          covariance=None,
          weight_bias=None,
          weight_train=[2, 1, 1, 1],
          weight_var=None,
      )
      # Tests `evaluate` on training set
      raf.evaluate(is_train=True, plot=False, plot_num_cols=2)
      assert list(raf.evaluation_df["RMSE % change"] > 0) == [
          False,
          False,
          False,
          False,
      ]
      assert list(raf.evaluation_df["MAPE pp change"] > 0) == [
          False,
          False,
          False,
          False,
      ]
      assert list(raf.evaluation_df["MedAPE pp change"] > 0) == [
          False,
          False,
          False,
          False,
      ]
      assert not evaluation_df.equals(raf.evaluation_df)
      assert len(raf.figures) == 3
      fig = raf.figures["base_adj"]
      assert len(fig.data) == 8
      assert (
          fig.data[0].name == "root-base"
      )  # plots use reordered columns
      assert fig.data[1].name == "root-adjusted"
      assert fig.data[2].name == "c1-base"
      assert fig.data[1].legendgroup == "adjusted"
      assert fig.data[1].line.color == "#ff893a"
      assert fig.layout.title.text == "Base vs Adjusted Forecast"
      assert fig.layout.title.x == 0.5
      assert fig.layout.yaxis.title.text == "value"
      fig = raf.figures["adj_size"]
      assert len(fig.data) == 8
      assert fig.data[0].name == "zero"
      assert fig.layout.title.text == "Adjustment Size (%)"
      assert fig.layout.title.x == 0.5
      assert fig.layout.yaxis.title.text == "% adj."
      fig = raf.figures["error"]
      assert len(fig.data) == 12
      assert fig.data[0].name == "zero"
      assert fig.layout.title.text == "Forecast Error (%)"
      assert fig.layout.title.x == 0.5
      assert fig.layout.yaxis.title.text == "% error"
      # Checks layout with plot_num_cols=2
      assert fig.layout.xaxis.domain != fig.layout.xaxis2.domain
      assert fig.layout.xaxis.domain == fig.layout.xaxis3.domain
      assert fig.layout.xaxis2.domain == fig.layout.xaxis4.domain
  
      # Tests `evaluate` on test set
      actuals_test = actuals + 2.0
      actuals_test.iloc[
          0, :
      ] = 0.0  # forces divide by 0.0 in MAPE/MedAPE calculations
      forecasts_test = forecasts + np.random.randn(*actuals_test.shape)
      raf.transform(forecasts_test=forecasts_test)
      with pytest.raises(
          ValueError,
          match="`actuals_test` must be provided to evaluate on test set",
      ):
          raf.evaluate(is_train=False)
      with np.errstate(divide="ignore"):
          raf.evaluate(is_train=False, actuals_test=actuals_test)
      assert_equal(raf.actuals_test, actuals_test)
      assert raf.evaluation_df_test is not None
      assert raf.constraint_violation_test is not None
      assert_equal(
          root_mean_squared_error(
              raf.actuals_test["c1"], raf.forecasts_test["c1"]
          ),
          raf.evaluation_df_test.loc["c1", "Base RMSE"],
      )
  
      # Tests `fit_transform_evaluate`
      # (and that plot/ipython_display run without error)
      raf = ReconcileAdditiveForecasts()
      raf.fit_transform(
          forecasts=forecasts,
          actuals=actuals,
          levels=levels,
          order_dict=order_dict,
          method="bottom_up",
      )
      raf.evaluate(is_train=True)
  
      raf2 = ReconcileAdditiveForecasts()
      raf2.fit_transform_evaluate(
          forecasts=forecasts,
          actuals=actuals,
          fit_kwargs=dict(
              levels=levels, order_dict=order_dict, method="bottom_up"
          ),
          evaluate_kwargs=dict(
              ipython_display=True, plot=False, plot_num_cols=2
          ),
      )
      assert_equal(raf.evaluation_df, raf2.evaluation_df)
      assert_equal(raf.adjusted_forecasts, raf2.adjusted_forecasts)
      assert raf2.evaluation_df_test is None
  
      # Tests `transform_evaluate`
      with np.errstate(divide="ignore"):
          raf2.transform_evaluate(
              forecasts_test=forecasts_test,
              actuals_test=actuals_test,
              plot=False,
              plot_num_cols=2,
              ipython_display=True,
          )
          assert len(raf2.figures_test) == 3
          assert raf2.figures != raf2.figures_test
  
      assert_equal(
          root_mean_squared_error(
              raf2.actuals_test["c1"], raf2.forecasts_test["c1"]
          ),
          raf2.evaluation_df_test.loc["c1", "Base RMSE"],
      )
  
imports: import math
  import os
  import warnings
  import cvxpy
  import numpy
  import pandas
  import pytest
  from scipy.linalg import sqrtm
  from sklearn.exceptions import NotFittedError
  from greykite.algo.reconcile.convex.reconcile_forecasts import ReconcileAdditiveForecasts
  from greykite.algo.reconcile.convex.reconcile_forecasts import TraceInfo
  from greykite.algo.reconcile.convex.reconcile_forecasts import apply_method_defaults
  from greykite.algo.reconcile.convex.reconcile_forecasts import evaluation_plot
  from greykite.algo.reconcile.convex.reconcile_forecasts import get_fit_params
  from greykite.algo.reconcile.convex.reconcile_forecasts import get_weight_matrix
  from greykite.algo.reconcile.hierarchical_relationship import HierarchicalRelationship
  from greykite.common.constants import TIME_COL
  from greykite.common.data_loader import DataLoader
  from greykite.common.evaluation import mean_absolute_percent_error
  from greykite.common.evaluation import median_absolute_percent_error
  from greykite.common.evaluation import root_mean_squared_error
  from greykite.common.python_utils import assert_equal
  from greykite.common.python_utils import reorder_columns
label_desc: Use image node_id 12 for calling a global function with example usage: test_raf_evaluate(data) without return types