docs: def rule_satisfied(x, features, categories):
      """
      return a logical array representing whether entries in x satisfied the rules denoted by features and categories
      :param x: a categorical 2D array
      :param features: a list of feature indices
      :param categories: a list of categories
      :return:
      """
      satisfied = []
      if features[0] == -1 and len(features) == 1:
          # Default rule, all satisfied
          return np.ones(x.shape[0], dtype=bool)
      for idx, cat in zip(features, categories):
          # Every single condition needs to be satisfied.
          satisfied.append(x[:, idx] == cat)
      return functools.reduce(np.logical_and, satisfied)