class_docstr: Individual fairness perturbation for person names.
class_docstr_tok: ["Individual","fairness","perturbation","for","person","names","."]
docstr: Initialize the person name perturbation.
  
  If name_file_path isn't provided, we use our default name mapping
  file, which can be found at:
  
      https://worksheets.codalab.org/rest/bundles/0xa65e8f9a107c44f198eb4ad356bbda34/contents/blob/
  
  The **available categories** in our default file and their values are as follows:
  
      If person_name_type == "last_name":
  
          (1) "race"   => "asian", "chinese", "hispanic", "russian", "white"
  
      If person_name_type == "first_name":
  
          (1) "race"   => "white_american", "black_american"
          (2) "gender" => "female", "male"
  
  The first names in our default file come from Caliskan et al. (2017),
  which derives its list from Greenwald (1998). The former removed some
  names from the latter because the corresponding tokens infrequently
  occurred in Common Crawl, which was used as the training corpus for
  GloVe. We include the full list from the latter in our default file.
  
  The last names in our default file and their associated categories come
  from Garg et. al. (2017), which derives its list from
  Chalabi and Flowers (2014).
  
  Args:
      prob: Probability of substituting a word in the source class with
          a word in the target class given that a substitution is
          available.
      source_class: The properties of the source class. The keys of the
          dictionary should correspond to categories ("race", "gender",
          "religion, "age", etc.) and the values should be the
          corresponding values. If more than one category is provided,
          the source_names list will be constructed by finding the
          intersection of the names list for the provided categories.
          Assuming the 'first_name' mode is selected, an example
          dictionary can be: {'race': 'white_american'}. Case-insensitive.
      target_class: Same as source_class, but specifies the target_class.
      name_file_path: The absolute path to a file containing the
          category associations of names. Each row of the file must
          have the following format:
  
              <name>,<name_type>[,<category>,<value>]*
  
          Here is a breakdown of the fields:
              <name>: The name (e.g. Alex).
              <name_type>: Must be one of "first_name" or "last_name".
              <category>: The name of the category (e.g. race, gender,
                  age, religion, etc.)
              <value>: Value of the preceding category.
  
          [,<category>,<value>]* denotes that any number of category
              and value pairs can be appended to a line.
  
          Here are some example lines:
              li,last_name,race,chinese
              aiesha,first_name,race,black_american,gender,female
  
          Notes:
              (1) For each field, the leading and trailing spaces are
                  ignored, but those in between words in a field are
                  kept.
              (2) All the fields are lowered.
              (3) It is possible for a name to have multiple associations
                  (e.g. with more than one age, gender etc.)
  
          We use the default file if None is provided.
      person_name_type: One of "first_name" or "last_name". If
          "last_name", preserve_gender field must be False.
          Case-insensitive.
      preserve_gender: If set to True, we preserve the gender when
          mapping names of one category to those of another. If we can't
          find the gender association for a source_word, we randomly
          pick from one of the target names.
docstr_tok: ["Initialize","the","person","name","perturbation",".","If","name_file_path","is","n't","provided",",","we","use","our","default","name","mapping","file",",","which","can","be","found","at",":","https",":","\/\/worksheets.codalab.org\/rest\/bundles\/0xa65e8f9a107c44f198eb4ad356bbda34\/contents\/blob\/","The","*","*","available","categories","*","*","in","our","default","file","and","their","values","are","as","follows",":","If","person_name_type","==","``","last_name","''",":","(","1",")","``","race","''","=",">","``","asian","''",",","``","chinese","''",",","``","hispanic","''",",","``","russian","''",",","``","white","''","If","person_name_type","==","``","first_name","''",":","(","1",")","``","race","''","=",">","``","white_american","''",",","``","black_american","''","(","2",")","``","gender","''","=",">","``","female","''",",","``","male","''","The","first","names","in","our","default","file","come","from","Caliskan","et","al",".","(","2017",")",",","which","derives","its","list","from","Greenwald","(","1998",")",".","The","former","removed","some","names","from","the","latter","because","the","corresponding","tokens","infrequently","occurred","in","Common","Crawl",",","which","was","used","as","the","training","corpus","for","GloVe",".","We","include","the","full","list","from","the","latter","in","our","default","file",".","The","last","names","in","our","default","file","and","their","associated","categories","come","from","Garg","et",".","al",".","(","2017",")",",","which","derives","its","list","from","Chalabi","and","Flowers","(","2014",")",".","Args",":","prob",":","Probability","of","substituting","a","word","in","the","source","class","with","a","word","in","the","target","class","given","that","a","substitution","is","available",".","source_class",":","The","properties","of","the","source","class",".","The","keys","of","the","dictionary","should","correspond","to","categories","(","``","race","''",",","``","gender","''",",","``","religion",",","``","age","''",",","etc",".",")","and","the","values","should","be","the","corresponding","values",".","If","more","than","one","category","is","provided",",","the","source_names","list","will","be","constructed","by","finding","the","intersection","of","the","names","list","for","the","provided","categories",".","Assuming","the","'first_name","'","mode","is","selected",",","an","example","dictionary","can","be",":","{","'race","'",":","'white_american","'","}",".","Case-insensitive",".","target_class",":","Same","as","source_class",",","but","specifies","the","target_class",".","name_file_path",":","The","absolute","path","to","a","file","containing","the","category","associations","of","names",".","Each","row","of","the","file","must","have","the","following","format",":","<","name",">",",","<","name_type",">","[",",","<","category",">",",","<","value",">","]","*","Here","is","a","breakdown","of","the","fields",":","<","name",">",":","The","name","(","e.g",".","Alex",")",".","<","name_type",">",":","Must","be","one","of","``","first_name","''","or","``","last_name","''",".","<","category",">",":","The","name","of","the","category","(","e.g",".","race",",","gender",",","age",",","religion",",","etc",".",")","<","value",">",":","Value","of","the","preceding","category",".","[",",","<","category",">",",","<","value",">","]","*","denotes","that","any","number","of","category","and","value","pairs","can","be","appended","to","a","line",".","Here","are","some","example","lines",":","li",",","last_name",",","race",",","chinese","aiesha",",","first_name",",","race",",","black_american",",","gender",",","female","Notes",":","(","1",")","For","each","field",",","the","leading","and","trailing","spaces","are","ignored",",","but","those","in","between","words","in","a","field","are","kept",".","(","2",")","All","the","fields","are","lowered",".","(","3",")","It","is","possible","for","a","name","to","have","multiple","associations","(","e.g",".","with","more","than","one","age",",","gender","etc",".",")","We","use","the","default","file","if","None","is","provided",".","person_name_type",":","One","of","``","first_name","''","or","``","last_name","''",".","If","``","last_name","''",",","preserve_gender","field","must","be","False",".","Case-insensitive",".","preserve_gender",":","If","set","to","True",",","we","preserve","the","gender","when","mapping","names","of","one","category","to","those","of","another",".","If","we","can't","find","the","gender","association","for","a","source_word",",","we","randomly","pick","from","one","of","the","target","names","."]
code: def __init__(
      self,
      prob: float,
      source_class: Dict[str, str],
      target_class: Dict[str, str],
      name_file_path: Optional[str] = None,
      person_name_type: str = FIRST_NAME,
      preserve_gender: bool = True,
  ):
      """Initialize the person name perturbation.
  
      If name_file_path isn't provided, we use our default name mapping
      file, which can be found at:
  
          https://worksheets.codalab.org/rest/bundles/0xa65e8f9a107c44f198eb4ad356bbda34/contents/blob/
  
      The **available categories** in our default file and their values are as follows:
  
          If person_name_type == "last_name":
  
              (1) "race"   => "asian", "chinese", "hispanic", "russian", "white"
  
          If person_name_type == "first_name":
  
              (1) "race"   => "white_american", "black_american"
              (2) "gender" => "female", "male"
  
      The first names in our default file come from Caliskan et al. (2017),
      which derives its list from Greenwald (1998). The former removed some
      names from the latter because the corresponding tokens infrequently
      occurred in Common Crawl, which was used as the training corpus for
      GloVe. We include the full list from the latter in our default file.
  
      The last names in our default file and their associated categories come
      from Garg et. al. (2017), which derives its list from
      Chalabi and Flowers (2014).
  
      Args:
          prob: Probability of substituting a word in the source class with
              a word in the target class given that a substitution is
              available.
          source_class: The properties of the source class. The keys of the
              dictionary should correspond to categories ("race", "gender",
              "religion, "age", etc.) and the values should be the
              corresponding values. If more than one category is provided,
              the source_names list will be constructed by finding the
              intersection of the names list for the provided categories.
              Assuming the 'first_name' mode is selected, an example
              dictionary can be: {'race': 'white_american'}. Case-insensitive.
          target_class: Same as source_class, but specifies the target_class.
          name_file_path: The absolute path to a file containing the
              category associations of names. Each row of the file must
              have the following format:
  
                  <name>,<name_type>[,<category>,<value>]*
  
              Here is a breakdown of the fields:
                  <name>: The name (e.g. Alex).
                  <name_type>: Must be one of "first_name" or "last_name".
                  <category>: The name of the category (e.g. race, gender,
                      age, religion, etc.)
                  <value>: Value of the preceding category.
  
              [,<category>,<value>]* denotes that any number of category
                  and value pairs can be appended to a line.
  
              Here are some example lines:
                  li,last_name,race,chinese
                  aiesha,first_name,race,black_american,gender,female
  
              Notes:
                  (1) For each field, the leading and trailing spaces are
                      ignored, but those in between words in a field are
                      kept.
                  (2) All the fields are lowered.
                  (3) It is possible for a name to have multiple associations
                      (e.g. with more than one age, gender etc.)
  
              We use the default file if None is provided.
          person_name_type: One of "first_name" or "last_name". If
              "last_name", preserve_gender field must be False.
              Case-insensitive.
          preserve_gender: If set to True, we preserve the gender when
              mapping names of one category to those of another. If we can't
              find the gender association for a source_word, we randomly
              pick from one of the target names.
      """
      # TODO: Update path so it is not hard-coded to benchmark_output
      # https://github.com/stanford-crfm/benchmarking/issues/493
      self.output_path: str = self.OUTPUT_PATH
      Path(self.output_path).mkdir(parents=True, exist_ok=True)
  
      # Assign parameters to instance variables
      assert 0 <= prob <= 1
      self.prob = prob
  
      self.source_class: Dict[str, str] = self.lower_dictionary(
          source_class
      )
      self.target_class: Dict[str, str] = self.lower_dictionary(
          target_class
      )
  
      person_name_type = person_name_type.lower()
      assert person_name_type in [self.FIRST_NAME, self.LAST_NAME]
      self.person_name_type = person_name_type
  
      self.name_file_path: Optional[str] = name_file_path
      if not self.name_file_path:
          self.name_file_path = self.download_name_file()
  
      # Get the possible source_names and target_names
      self.mapping_dict: Dict[
          str, Dict[str, List[str]]
      ] = self.load_name_file(self.name_file_path)
      assert self.mapping_dict
      self.source_names: List[str] = self.get_possible_names(
          source_class
      )
      self.target_names: List[str] = self.get_possible_names(
          target_class
      )
  
      self.preserve_gender: bool = preserve_gender
      if self.preserve_gender:
          assert self.person_name_type == self.FIRST_NAME
          assert self.GENDER_CATEGORY in self.mapping_dict and len(
              self.mapping_dict[self.GENDER_CATEGORY]
          )
  
imports: import os
  import re
  from collections import defaultdict
  from dataclasses import dataclass, replace
  from functools import reduce
  from pathlib import Path
  from random import Random
  from typing import Dict, List, Optional, Set
  from helm.benchmark.scenarios.scenario import Input, Instance, Reference, Output
  from helm.common.general import ensure_file_downloaded, ensure_directory_exists, match_case
  from .perturbation_description import PerturbationDescription
  from .perturbation import Perturbation
label_desc: Use image node_id 1 to create a new PersonNamePerturbation object from inherited base classes: Perturbation with example: obj = PersonNamePerturbation(prob, source_class, target_class, name_file_path, person_name_type, preserve_gender)