code: def compare_result_with_ideal(
      em_cpds: Dict[str, pd.DataFrame],
      sm: StructureModel,
      data: pd.DataFrame,
      true_values_lv: np.array,
      node_states: Dict[AnyStr, Union[List, Set]],
  ) -> Tuple[float, float]:
      """
      Compare learned CPDs with ideal CPDs
  
      Args:
          em_cpds: Learned CPDs for different nodes
          sm: Structure model
          data: Input dataset
          true_values_lv: Ideal values of the latent variable
          node_states: Possible tates of different nodes
  
      Returns:
          Maximum absolute difference and root mean square of differences
      """
      data["z"] = true_values_lv.reshape(-1)
      bn = BayesianNetwork(sm)
      bn.fit_node_states(states_to_df(node_states))
      bn.fit_cpds(data)
  
      max_delta = -1
      avg_delta = 0
  
      for node in em_cpds:
          deltas = (em_cpds[node] - bn.cpds[node]).abs().values
          max_delta = max(max_delta, deltas.max())
          avg_delta += np.mean(deltas**2)
  
      avg_delta = np.sqrt(avg_delta / len(em_cpds))
      return max_delta, avg_delta
  
imports: from collections import Counter
  from typing import Any, AnyStr, Dict, Iterable, List, Set, Tuple, Union
  import numpy
  import pandas
  import pytest
  from causalnex.estimator.em import EMSingleLatentVariable
  from causalnex.network import BayesianNetwork
  from causalnex.structure.structuremodel import StructureModel
  from causalnex.utils.data_utils import states_to_df
label_desc: Use image node_id 2 for calling a global function with example usage: compare_result_with_ideal(em_cpds, sm, data, true_values_lv, node_states) and returns: max_delta,  avg_delta