///|
/// A node in the finite product graph used by exact relation membership.
priv struct ProductConfiguration {
  state : Int32
  input_index : Int32
  output_index : Int32
}

///|
/// Check whether a transducer has a path matching both complete token arrays.
/// Epsilon labels consume no token on their respective side. `is_zero` lets the
/// caller exclude semiring-zero arcs and finals; all other weight operations are
/// ignored. This is a membership query, not a path-weight aggregation API.
pub fn[W] accepts_pair(
  transducer : Transducer[W],
  input : Array[String],
  output : Array[String],
  is_zero : (W) -> Bool,
) -> Result[Bool, WfstError] {
  let start = match transducer.start {
    Some(state) => state
    None => return Err(WfstError::NoStartState)
  }
  let input_length = input.length()
  let output_length = output.length()
  let visited : Array[Array[Array[Bool]]] = []
  for _ in 0.. return Ok(true)
        _ => ()
      }
    }
    for arc in transducer.outgoing[current.state] {
      if !is_zero(arc.weight) {
        let next_input : Int32? = match arc.input {
          Label::Epsilon => Some(current.input_index)
          Label::Symbol(symbol) =>
            if current.input_index < input_length &&
              input[current.input_index] == symbol {
              Some(current.input_index + 1)
            } else {
              None
            }
        }
        let next_output : Int32? = match arc.output {
          Label::Epsilon => Some(current.output_index)
          Label::Symbol(symbol) =>
            if current.output_index < output_length &&
              output[current.output_index] == symbol {
              Some(current.output_index + 1)
            } else {
              None
            }
        }
        match (next_input, next_output) {
          (Some(input_index), Some(output_index)) => {
            let destination = arc.destination
            if !visited[destination][input_index][output_index] {
              visited[destination][input_index][output_index] = true
              queue.push({ state: destination, input_index, output_index, })
            }
          }
          _ => ()
        }
      }
    }
    cursor = cursor + 1
  }
  Ok(false)
}