def __init__(self, hydrogens_attached, bonds_to_scores, matching_parameters):
    """Class to perform bonding assessments.

    Args:
      hydrogens_attached: a BondTopology that has all atoms, and the bonds
        associated with the Hydrogen atoms.
      bonds_to_scores: A dict that maps tuples of pairs of atoms, to a numpy
        array of scores [0,3], for each possible bond type.
      matching_parameters: contains possible optional behaviour modifiers.

    Returns:
    """
    self._starting_bond_topology = hydrogens_attached
    self._natoms = len(hydrogens_attached.atoms)
    self._heavy_atoms = sum(1 for atom in hydrogens_attached.atoms
                            if atom != dataset_pb2.BondTopology.ATOM_H)

    self._contains_both_oxygen_and_nitrogen = False
    # If the molecule contains both N and O atoms, then we can
    # do more extensive atom type matching if requested.
    if matching_parameters.neutral_forms_during_bond_matching:
      self.set_contains_both_oxygen_and_nitrogen(hydrogens_attached)

    # For each atom, the maximum number of bonds that can be attached.
    self._max_bonds = np.zeros(self._natoms, dtype=np.int32)
    if matching_parameters.neutral_forms_during_bond_matching and self._contains_both_oxygen_and_nitrogen:
      for i in range(0, self._natoms):
        self._max_bonds[i] = smu_utils_lib.ATOM_TYPE_TO_MAX_BONDS_ANY_FORM[
            hydrogens_attached.atoms[i]]
    else:
      for i in range(0, self._natoms):
        self._max_bonds[i] = smu_utils_lib.ATOM_TYPE_TO_MAX_BONDS[
            hydrogens_attached.atoms[i]]

    # With the Hydrogens attached, the number of bonds to each atom.
    self._bonds_with_hydrogens_attached = np.zeros((self._natoms),
                                                   dtype=np.int32)
    for bond in hydrogens_attached.bonds:
      self._bonds_with_hydrogens_attached[bond.atom_a] += 1
      self._bonds_with_hydrogens_attached[bond.atom_b] += 1

    self._current_bonds_attached = np.zeros((self._natoms), dtype=np.int32)

    # We turn bonds_to_scores into two arrays. So they can be iterated
    # via itertools.

    self._bonds = list(bonds_to_scores.keys())
    self._scores = list(bonds_to_scores.values())

    # Initialize for probability type accumulation
    self._initial_score = 1.0
    self._accumulate_score = operator.mul

    # For testing, it can be convenient to allow for partial matches
    # For example this allows matching C-C and C=C without the need
    # to add explicit hydrogens
    self._must_match_all_bonds = matching_parameters.must_match_all_bonds