class_docstr: Computes the Needleman-Wunsch measure between two strings.
  The Needleman-Wunsch generalizes the Levenshtein distance and considers global
  alignment between two strings. Specifically, it is computed by assigning
  a score to each alignment between two input strings and choosing the
  score of the best alignment, that is, the maximal score.
  An alignment between two strings is a set of correspondences between the
  characters of between them, allowing for gaps.
  
  https://en.wikipedia.org/wiki/Needleman%E2%80%93Wunsch_algorithm
class_docstr_tok: ["Computes","the","Needleman-Wunsch","measure","between","two","strings",".","The","Needleman-Wunsch","generalizes","the","Levenshtein","distance","and","considers","global","alignment","between","two","strings",".","Specifically",",","it","is","computed","by","assigning","a","score","to","each","alignment","between","two","input","strings","and","choosing","the","score","of","the","best","alignment",",","that","is",",","the","maximal","score",".","An","alignment","between","two","strings","is","a","set","of","correspondences","between","the","characters","of","between","them",",","allowing","for","gaps",".","https",":","\/\/en.wikipedia.org\/wiki\/Needleman","%","E2","%","80","%","93Wunsch_algorithm"]
code: def __call__(self, s1: Sequence[T], s2: Sequence[T]) -> float:
      if not numpy:
          raise ImportError(
              "Please, install numpy for Needleman-Wunsch measure"
          )
  
      s1, s2 = self._get_sequences(s1, s2)
  
      # result = self.quick_answer(s1, s2)
      # if result is not None:
      #     return result * self.maximum(s1, s2)
  
      dist_mat = numpy.zeros(
          (len(s1) + 1, len(s2) + 1),
          dtype=float,
      )
      # DP initialization
      for i in range(len(s1) + 1):
          dist_mat[i, 0] = -(i * self.gap_cost)
      # DP initialization
      for j in range(len(s2) + 1):
          dist_mat[0, j] = -(j * self.gap_cost)
      # Needleman-Wunsch DP calculation
      for i, c1 in enumerate(s1, 1):
          for j, c2 in enumerate(s2, 1):
              match = dist_mat[i - 1, j - 1] + self.sim_func(c1, c2)
              delete = dist_mat[i - 1, j] - self.gap_cost
              insert = dist_mat[i, j - 1] - self.gap_cost
              dist_mat[i, j] = max(match, delete, insert)
      return dist_mat[dist_mat.shape[0] - 1, dist_mat.shape[1] - 1]
  
imports: from __future__ import annotations
  from collections import defaultdict
  from itertools import zip_longest
  from typing import Any, Sequence, TypeVar
  from .base import Base, BaseSimilarity
  from .types import SimFunc, TestFunc
label_desc: Use image node_id 7 for calling the NeedlemanWunsch obj's underlying member method code with example usage: obj.__call__(s1, s2) and returns: dist_mat