


"""simple docstring"""







import datasets

from .evaluate import evaluate


lowerCAmelCase__      				=   '''\
@article{hendrycks2021cuad,
      title={CUAD: An Expert-Annotated NLP Dataset for Legal Contract Review},
      author={Dan Hendrycks and Collin Burns and Anya Chen and Spencer Ball},
      journal={arXiv preprint arXiv:2103.06268},
      year={2021}
}
'''

lowerCAmelCase__      				=   '''
This metric wrap the official scoring script for version 1 of the Contract
Understanding Atticus Dataset (CUAD).
Contract Understanding Atticus Dataset (CUAD) v1 is a corpus of more than 13,000 labels in 510
commercial legal contracts that have been manually labeled to identify 41 categories of important
clauses that lawyers look for when reviewing contracts in connection with corporate transactions.
'''

lowerCAmelCase__      				=   '''
Computes CUAD scores (EM, F1, AUPR, Precision@80%Recall, and Precision@90%Recall).
Args:
    predictions: List of question-answers dictionaries with the following key-values:
        - \'id\': id of the question-answer pair as given in the references (see below)
        - \'prediction_text\': list of possible texts for the answer, as a list of strings
        depending on a threshold on the confidence probability of each prediction.
    references: List of question-answers dictionaries with the following key-values:
        - \'id\': id of the question-answer pair (see above),
        - \'answers\': a Dict in the CUAD dataset format
            {
                \'text\': list of possible texts for the answer, as a list of strings
                \'answer_start\': list of start positions for the answer, as a list of ints
            }
            Note that answer_start values are not taken into account to compute the metric.
Returns:
    \'exact_match\': Exact match (the normalized answer exactly match the gold answer)
    \'f1\': The F-score of predicted tokens versus the gold answer
    \'aupr\': Area Under the Precision-Recall curve
    \'prec_at_80_recall\': Precision at 80% recall
    \'prec_at_90_recall\': Precision at 90% recall
Examples:
    >>> predictions = [{\'prediction_text\': [\'The seller:\', \'The buyer/End-User: Shenzhen LOHAS Supply Chain Management Co., Ltd.\'], \'id\': \'LohaCompanyltd_20191209_F-1_EX-10.16_11917878_EX-10.16_Supply Agreement__Parties\'}]
    >>> references = [{\'answers\': {\'answer_start\': [143, 49], \'text\': [\'The seller:\', \'The buyer/End-User: Shenzhen LOHAS Supply Chain Management Co., Ltd.\']}, \'id\': \'LohaCompanyltd_20191209_F-1_EX-10.16_11917878_EX-10.16_Supply Agreement__Parties\'}]
    >>> cuad_metric = datasets.load_metric("cuad")
    >>> results = cuad_metric.compute(predictions=predictions, references=references)
    >>> print(results)
    {\'exact_match\': 100.0, \'f1\': 100.0, \'aupr\': 0.0, \'prec_at_80_recall\': 1.0, \'prec_at_90_recall\': 1.0}
'''


@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION   ,    _KWARGS_DESCRIPTION				)
class       SCREAMING_SNAKE_CASE__				(		datasets.Metric				):
       """simple docstring"""


       def        lowercase__							(						self						):






         """simple docstring"""





         return datasets.MetricInfo(
             description=_DESCRIPTION		,     citation=_CITATION		,     inputs_description=_KWARGS_DESCRIPTION		,     features=datasets.Features(
                 {
                     "predictions": {
                         "id": datasets.Value("string"						),
                         "prediction_text": datasets.features.Sequence(datasets.Value("string"						)						),
                     },
                     "references": {
                         "id": datasets.Value("string"						),
                         "answers": datasets.features.Sequence(
                             {
                                 "text": datasets.Value("string"						),
                                 "answer_start": datasets.Value("int32"						),
                             }						),
                     },
                 }						)		,     codebase_urls=["https://www.atticusprojectai.org/cuad"]		,     reference_urls=["https://www.atticusprojectai.org/cuad"]		,     )







       def        lowercase__							(						self		,     snake_case__		,     snake_case__						):






         """simple docstring"""





         lowerCAmelCase     :     Optional[int]								=							{prediction["id"]: prediction["prediction_text"] for prediction in predictions}
         lowerCAmelCase     :     List[Any]								=							[
             {
                 "paragraphs": [
                     {
                         "qas": [
                             {
                                 "answers": [{"text": answer_text} for answer_text in ref["answers"]["text"]],
                                 "id": ref["id"],
                             }
                             for ref in references
                         ]
                     }
                 ]
             }
         ]
         lowerCAmelCase     :     Any								=							evaluate(dataset=snake_case__		,     predictions=snake_case__						)
         return score









"""simple docstring"""







class       SCREAMING_SNAKE_CASE__				:
       """simple docstring"""


       def __init__(						self		,     snake_case__ = ""		,     snake_case__ = False						):






         """simple docstring"""





         lowerCAmelCase     :     dict[str, RadixNode]								=							{}

         # A node will be a leaf if the tree contains its word
         lowerCAmelCase     :     str								=							is_leaf

         lowerCAmelCase     :     str								=							prefix

       def        lowercase__							(						self		,     snake_case__						):






         """simple docstring"""





         lowerCAmelCase     :     Dict								=							0
         for q, w in zip(self.prefix		,     snake_case__						):
           if q != w:
             break

           x += 1

         return self.prefix[:x], self.prefix[x:], word[x:]

       def        lowercase__							(						self		,     snake_case__						):






         """simple docstring"""





         for word in words:
           self.insert(snake_case__						)

       def        lowercase__							(						self		,     snake_case__						):






         """simple docstring"""





         if self.prefix == word:
           lowerCAmelCase     :     Union[str, Any]								=							True

         # Case 2: The node has no edges that have a prefix to the word
         # Solution: We create an edge from the current node to a new one
         # containing the word
         elif word[0] not in self.nodes:
           lowerCAmelCase     :     Optional[Any]								=							RadixNode(prefix=snake_case__		,     is_leaf=snake_case__						)

         else:
           lowerCAmelCase     :     Tuple								=							self.nodes[word[0]]
           lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase     :     Optional[Any]								=							incoming_node.match(
               snake_case__						)

           # Case 3: The node prefix is equal to the matching
           # Solution: We insert remaining word on the next node
           if remaining_prefix == "":
             self.nodes[matching_string[0]].insert(snake_case__						)

           # Case 4: The word is greater equal to the matching
           # Solution: Create a node in between both nodes, change
           # prefixes and add the new node for the remaining word
           else:
             lowerCAmelCase     :     Optional[Any]								=							remaining_prefix

             lowerCAmelCase     :     int								=							self.nodes[matching_string[0]]
             lowerCAmelCase     :     List[Any]								=							RadixNode(snake_case__		,     snake_case__						)
             lowerCAmelCase     :     Optional[int]								=							aux_node

             if remaining_word == "":
               lowerCAmelCase     :     Optional[int]								=							True
             else:
               self.nodes[matching_string[0]].insert(snake_case__						)

       def        lowercase__							(						self		,     snake_case__						):






         """simple docstring"""





         lowerCAmelCase     :     str								=							self.nodes.get(word[0]		,     snake_case__						)
         if not incoming_node:
           return False
         else:
           lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase     :     int								=							incoming_node.match(
               snake_case__						)
           # If there is remaining prefix, the word can't be on the tree
           if remaining_prefix != "":
             return False
           # This applies when the word and the prefix are equal
           elif remaining_word == "":
             return incoming_node.is_leaf
           # We have word remaining so we check the next node
           else:
             return incoming_node.find(snake_case__						)

       def        lowercase__							(						self		,     snake_case__						):






         """simple docstring"""





         lowerCAmelCase     :     int								=							self.nodes.get(word[0]		,     snake_case__						)
         if not incoming_node:
           return False
         else:
           lowerCAmelCase						,  lowerCAmelCase						,  lowerCAmelCase     :     Union[str, Any]								=							incoming_node.match(
               snake_case__						)
           # If there is remaining prefix, the word can't be on the tree
           if remaining_prefix != "":
             return False
           # We have word remaining so we check the next node
           elif remaining_word != "":
             return incoming_node.delete(snake_case__						)
           else:
             # If it is not a leaf, we don't have to delete
             if not incoming_node.is_leaf:
               return False
             else:
               # We delete the nodes if no edges go from it
               if len(incoming_node.nodes						) == 0:
                 del self.nodes[word[0]]
                 # We merge the current node with its only child
                 if len(self.nodes						) == 1 and not self.is_leaf:
                   lowerCAmelCase     :     List[str]								=							list(self.nodes.values()						)[0]
                   lowerCAmelCase     :     List[str]								=							merging_node.is_leaf
                   self.prefix += merging_node.prefix
                   lowerCAmelCase     :     Optional[int]								=							merging_node.nodes
                    # If there is more than 1 edge, we just mark it as non-leaf
               elif len(incoming_node.nodes						) > 1:
                 lowerCAmelCase     :     Optional[int]								=							False
               # If there is 1 edge, we merge it with its child
               else:
                 lowerCAmelCase     :     Optional[Any]								=							list(incoming_node.nodes.values()						)[0]
                 lowerCAmelCase     :     int								=							merging_node.is_leaf
                 incoming_node.prefix += merging_node.prefix
                 lowerCAmelCase     :     Tuple								=							merging_node.nodes

               return True







       def        lowercase__							(						self		,     snake_case__ = 0						):






         """simple docstring"""





         if self.prefix != "":
           print("-" * height		,     self.prefix		,     "  (leaf)" if self.is_leaf else ""						)

         for value in self.nodes.values():
           value.print_tree(height + 1						)

def 					a__			(				):


  '''simple docstring'''







  lowerCAmelCase     :     Union[str, Any]								=							"banana bananas bandana band apple all beast".split()
  lowerCAmelCase     :     List[str]								=							RadixNode()
  root.insert_many(SCREAMING_SNAKE_CASE				)

  assert all(root.find(SCREAMING_SNAKE_CASE				) for word in words				)
  assert not root.find("bandanas"				)
  assert not root.find("apps"				)
  root.delete("all"				)
  assert not root.find("all"				)
  root.delete("banana"				)
  assert not root.find("banana"				)
  assert root.find("bananas"				)

  return True
def 					a__			(				):


  '''simple docstring'''







  assert test_trie()
def 					a__			(				):


  '''simple docstring'''







  lowerCAmelCase     :     Dict								=							RadixNode()
  lowerCAmelCase     :     Optional[Any]								=							"banana bananas bandanas bandana band apple all beast".split()
  root.insert_many(SCREAMING_SNAKE_CASE				)

  print("Words:"				,      SCREAMING_SNAKE_CASE				)
  print("Tree:"				)
  root.print_tree()


if __name__ == "__main__":
     main()





