docs: def create_design_matrix(long_form,
                           specification_dict,
                           alt_id_col,
                           names=None):
      """
      Parameters
      ----------
      long_form : pandas dataframe.
          Contains one row for each available alternative, for each observation.
      specification_dict : OrderedDict.
          Keys are a proper subset of the columns in `long_form_df`. Values are
          either a list or a single string, `"all_diff"` or `"all_same"`. If a
          list, the elements should be:
  
              - single objects that are within the alternative ID column of
                `long_form_df`
              - lists of objects that are within the alternative ID column of
                `long_form_df`. For each single object in the list, a unique
                column will be created (i.e. there will be a unique coefficient
                for that variable in the corresponding utility equation of the
                corresponding alternative). For lists within the
                `specification_dict` values, a single column will be created for
                all the alternatives within iterable (i.e. there will be one
                common coefficient for the variables in the iterable).
      alt_id_col : str.
          Column name which denotes the column in `long_form` that contains the
          alternative ID for each row in `long_form`.
      names : OrderedDict, optional.
          Should have the same keys as `specification_dict`. For each key:
  
              - if the corresponding value in `specification_dict` is "all_same",
                then there should be a single string as the value in names.
              - if the corresponding value in `specification_dict` is "all_diff",
                then there should be a list of strings as the value in names.
                There should be one string in the value in names for each
                possible alternative.
              - if the corresponding value in `specification_dict` is a list,
                then there should be a list of strings as the value in names.
                There should be one string the value in names per item in the
                value in `specification_dict`.
          Default == None.
  
      Returns
      -------
      design_matrix, var_names: tuple with two elements.
          First element is the design matrix, a numpy array with some number of
          columns and as many rows as are in `long_form`. Each column corresponds
          to a coefficient to be estimated. The second element is a list of
          strings denoting the names of each coefficient, with one variable name
          per column in the design matrix.
      """
      ##########
      # Check that the arguments meet this functions assumptions.
      # Fail gracefully if the arguments do not meet the function's requirements.
      #########
      check_argument_type(long_form, specification_dict)
  
      ensure_alt_id_in_long_form(alt_id_col, long_form)
  
      ensure_specification_cols_are_in_dataframe(specification_dict, long_form)
  
      # Find out what and how many possible alternatives there are
      unique_alternatives = np.sort(long_form[alt_id_col].unique())
      num_alternatives = len(unique_alternatives)
  
      check_type_and_values_of_specification_dict(specification_dict,
                                                  unique_alternatives)
  
      # Check the user passed dictionary of names if the user passed such a list
      if names is not None:
          ensure_object_is_ordered_dict(names, "names")
  
          check_keys_and_values_of_name_dictionary(names,
                                                   specification_dict,
                                                   num_alternatives)
  
      ##########
      # Actually create the design matrix
      ##########
      # Create a list of the columns of independent variables
      independent_vars = []
      # Create a list of variable names
      var_names = []
  
      # Create the columns of the design matrix based on the specification dict.
      for variable in specification_dict:
          specification = specification_dict[variable]
          if specification == "all_same":
              # Create the variable column
              independent_vars.append(long_form[variable].values)
              # Create the column name
              var_names.append(variable)
          elif specification == "all_diff":
              for alt in unique_alternatives:
                  # Create the variable column
                  independent_vars.append((long_form[alt_id_col] == alt).values *
                                          long_form[variable].values)
                  # create the column name
                  var_names.append("{}_{}".format(variable, alt))
          else:
              for group in specification:
                  if isinstance(group, list):
                      # Create the variable column
                      independent_vars.append(
                                       long_form[alt_id_col].isin(group).values *
                                       long_form[variable].values)
                      # Create the column name
                      var_names.append("{}_{}".format(variable, str(group)))
  
                  else:  # the group is an integer
                      # Create the variable column
                      new_col_vals = ((long_form[alt_id_col] == group).values *
                                      long_form[variable].values)
                      independent_vars.append(new_col_vals)
                      # Create the column name
                      var_names.append("{}_{}".format(variable, group))
  
      # Create the final design matrix
      design_matrix = np.hstack((x[:, None] for x in independent_vars))
  
      # Use the list of names passed by the user, if the user passed such a list
      if names is not None:
          var_names = []
          for value in names.values():
              if isinstance(value, str):
                  var_names.append(value)
              else:
                  for inner_name in value:
                      var_names.append(inner_name)
  
      return design_matrix, var_names