code: def generate_structure(
      num_nodes: int,
      degree: float,
      graph_type: str = "erdos-renyi",
      w_min: float = 0.5,
      w_max: float = 0.5,
  ) -> StructureModel:
      """Simulate random DAG with some expected degree.
      Notes:
          graph_type (str):
              - erdos-renyi: constructs a graph such that the probability of any given edge is degree / (num_nodes - 1)
              - barabasi-albert: constructs a scale-free graph from an initial connected graph of (degree / 2) nodes
              - full: constructs a fully-connected graph - degree has no effect
      Args:
          num_nodes: number of nodes
          degree: expected node degree, in + out
          graph_type (str):
              - erdos-renyi: constructs a graph such that the probability of any given edge is degree / (num_nodes - 1)
              - barabasi-albert: constructs a scale-free graph from an initial connected graph of (degree / 2) nodes
              - full: constructs a fully-connected graph - degree has no effect
          w_min (float): min absolute weight of an edge in the graph
          w_max (float): max absolute weight of an edge in the graph
      Raises:
          ValueError: if invalid arguments are provided
      Returns:
          weighted DAG
      """
  
      if num_nodes < 2:
          raise ValueError("DAG must have at least 2 nodes")
  
      w_min, w_max = abs(w_min), abs(w_max)
  
      if w_min > w_max:
          raise ValueError(
              "Absolute minimum weight must be less than or equal to maximum weight: "
              f"{w_min} > {w_max}"
          )
  
      if graph_type == "erdos-renyi":
          p_threshold = float(degree) / (num_nodes - 1)
          p_edge = (
              np.random.rand(num_nodes, num_nodes) < p_threshold
          ).astype(float)
          edge_flags = np.tril(p_edge, k=-1)
  
      elif graph_type == "barabasi-albert":
          m = int(round(degree / 2))
          edge_flags = np.zeros([num_nodes, num_nodes])
          bag = [0]
          for i in range(1, num_nodes):
              dest = np.random.choice(bag, size=m)
              for j in dest:
                  edge_flags[i, j] = 1
              bag.append(i)
              bag.extend(dest)
  
      elif graph_type == "full":  # ignore degree
          edge_flags = np.tril(np.ones([num_nodes, num_nodes]), k=-1)
  
      else:
          raise ValueError(
              f"Unknown graph type {graph_type}. "
              "Available types are ['erdos-renyi', 'barabasi-albert', 'full']"
          )
  
      # randomly permute edges - required because we limited ourselves to lower diagonal previously
      perms = np.random.permutation(np.eye(num_nodes, num_nodes))
      edge_flags = perms.T.dot(edge_flags).dot(perms)
  
      # random edge weights between w_min, w_max or between -w_min, -w_max
      edge_weights = np.random.uniform(
          low=w_min, high=w_max, size=[num_nodes, num_nodes]
      )
      edge_weights[np.random.rand(num_nodes, num_nodes) < 0.5] *= -1
  
      adj_matrix = (edge_flags != 0).astype(float) * edge_weights
      graph = StructureModel(adj_matrix)
      return graph
  
imports: from typing import Dict, Hashable, List, Optional, Tuple, Union
  import networkx
  import numpy
  import pandas
  from sklearn.gaussian_process.kernels import RBF, Kernel
  from causalnex.structure import StructureModel
  from causalnex.structure.categorical_variable_mapper import VariableFeatureMapper, validate_schema
label_desc: Use image node_id 1 for calling a global function with example usage: generate_structure(num_nodes, degree, graph_type, w_min, w_max) and returns: graph