code: def match(
      input_types,
      features,
      replace=False,
      commutative=False,
      require_direct_input=False,
  ):
      to_match = input_types[0]
  
      matches = match_by_schema(features, to_match)
  
      if len(input_types) == 1:
          return [
              (m,)
              for m in matches
              if (
                  not require_direct_input
                  or isinstance(m, DirectFeature)
              )
          ]
  
      matching_inputs = set()
  
      for m in matches:
          copy = features[:]
  
          if not replace:
              copy = [
                  c for c in copy if c.unique_name() != m.unique_name()
              ]
  
          # If we need a DirectFeature and this is not a DirectFeature then one of the rest must be.
          still_require_direct_input = (
              require_direct_input
              and not isinstance(
                  m,
                  DirectFeature,
              )
          )
          rest = match(
              input_types[1:],
              copy,
              replace,
              require_direct_input=still_require_direct_input,
          )
  
          for r in rest:
              new_match = [m] + list(r)
  
              # commutative uses frozenset instead of tuple because it doesn't
              # want multiple orderings of the same input
              if commutative:
                  new_match = frozenset(new_match)
              else:
                  new_match = tuple(new_match)
              matching_inputs.add(new_match)
  
      if commutative:
          matching_inputs = {
              tuple(sorted(s, key=lambda x: x.get_name().lower()))
              for s in matching_inputs
          }
  
      return matching_inputs
  
imports: import functools
  import logging
  import operator
  import warnings
  from collections import defaultdict
  from typing import Any, DefaultDict, Dict, List, Tuple, Type
  from woodwork.column_schema import ColumnSchema
  from woodwork.logical_types import Boolean, BooleanNullable
  from featuretools import primitives
  from featuretools.entityset.entityset import LTI_COLUMN_NAME
  from featuretools.entityset.relationship import RelationshipPath
  from featuretools.feature_base import AggregationFeature, DirectFeature, FeatureBase, GroupByTransformFeature, IdentityFeature, TransformFeature
  from featuretools.feature_base.cache import CacheType, feature_cache
  from featuretools.feature_base.utils import is_valid_input
  from featuretools.primitives.base import AggregationPrimitive, PrimitiveBase, TransformPrimitive
  from featuretools.primitives.options_utils import filter_groupby_matches_by_options, filter_matches_by_options, generate_all_primitive_options, ignore_dataframe_for_primitive
  from featuretools.utils.gen_utils import Library, camel_and_title_to_snake
label_desc: Use image node_id 8 for calling a global function with example usage: match(input_types, features, replace, commutative, require_direct_input) and returns: matching_inputs, unknown