nodes: 0, module; 1, function_definition; 2, function_name:commutative_sequence_variable_partition_iter; 3, parameters; 4, type; 5, block; 6, typed_parameter; 7, typed_parameter; 8, generic_type; 9, expression_statement; 10, if_statement; 11, expression_statement; 12, for_statement; 13, expression_statement; 14, comment:# type: Dict[str, 'Multiset[T]']; 15, for_statement; 16, identifier:values; 17, type; 18, identifier:variables; 19, type; 20, identifier:Iterator; 21, type_parameter; 22, comment:"""Yield all possible variable substitutions for given values and variables.
  
      .. note::
  
          The results are not yielded in any particular order because the algorithm uses dictionaries. Dictionaries until
          Python 3.6 do not keep track of the insertion order.
  
      Example:
  
          For a subject like ``fc(a, a, a, b, b, c)`` and a pattern like ``f(x__, y___, y___)`` one can define the
          following input parameters for the partitioning:
  
          >>> x = VariableWithCount(name='x', count=1, minimum=1, default=None)
          >>> y = VariableWithCount(name='y', count=2, minimum=0, default=None)
          >>> values = Multiset('aaabbc')
  
          Then the solutions are found (and sorted to get a unique output):
  
          >>> substitutions = commutative_sequence_variable_partition_iter(values, [x, y])
          >>> as_strings = list(str(Substitution(substitution)) for substitution in substitutions)
          >>> for substitution in sorted(as_strings):
          ...     print(substitution)
          {x ↦ {a, a, a, b, b, c}, y ↦ {}}
          {x ↦ {a, a, a, c}, y ↦ {b}}
          {x ↦ {a, b, b, c}, y ↦ {a}}
          {x ↦ {a, c}, y ↦ {a, b}}
  
      Args:
          values:
              The multiset of values which are partitioned and distributed among the variables.
          variables:
              A list of the variables to distribute the values among. Each variable has a name, a count of how many times
              it occurs and a minimum number of values it needs.
  
      Yields:
          Each possible substitutions that is a valid partitioning of the values among the variables.
      """; 23, comparison_operator:len(variables) == 1; 24, block; 25, assignment; 26, pattern_list; 27, call; 28, block; 29, assignment; 30, identifier:subst; 31, call; 32, block; 33, identifier:Multiset; 34, generic_type; 35, type; 36, call; 37, integer:1; 38, expression_statement; 39, return_statement; 40, identifier:generators; 41, list; 42, identifier:value; 43, identifier:count; 44, attribute; 45, argument_list; 46, expression_statement; 47, identifier:initial; 48, call; 49, identifier:generator_chain; 50, argument_list; 51, expression_statement; 52, for_statement; 53, if_statement; 54, identifier:List; 55, type_parameter; 56, generic_type; 57, identifier:len; 58, argument_list; 59, yield; 60, identifier:values; 61, identifier:items; 62, call; 63, identifier:dict; 64, generator_expression; 65, identifier:initial; 66, list_splat; 67, assignment; 68, identifier:var; 69, identifier:variables; 70, block; 71, identifier:valid; 72, block; 73, type; 74, identifier:Dict; 75, type_parameter; 76, identifier:variables; 77, call; 78, attribute; 79, argument_list; 80, tuple; 81, for_in_clause; 82, identifier:generators; 83, identifier:valid; 84, True; 85, if_statement; 86, if_statement; 87, expression_statement; 88, identifier:VariableWithCount; 89, type; 90, type; 91, identifier:_commutative_single_variable_partiton_iter; 92, argument_list; 93, identifier:generators; 94, identifier:append; 95, call; 96, attribute; 97, call; 98, identifier:var; 99, identifier:variables; 100, boolean_operator; 101, block; 102, elif_clause; 103, comparison_operator:None in subst; 104, block; 105, yield; 106, identifier:str; 107, identifier:Multiset; 108, identifier:values; 109, subscript; 110, identifier:_make_variable_generator_factory; 111, argument_list; 112, identifier:var; 113, identifier:name; 114, identifier:Multiset; 115, argument_list; 116, comparison_operator:var.default is not None; 117, comparison_operator:len(subst[var.name]) == 0; 118, expression_statement; 119, comparison_operator:len(subst[var.name]) < var.minimum; 120, block; 121, None; 122, identifier:subst; 123, delete_statement; 124, identifier:subst; 125, identifier:variables; 126, integer:0; 127, identifier:value; 128, identifier:count; 129, identifier:variables; 130, attribute; 131, None; 132, call; 133, integer:0; 134, assignment; 135, call; 136, attribute; 137, expression_statement; 138, break_statement; 139, subscript; 140, identifier:var; 141, identifier:default; 142, identifier:len; 143, argument_list; 144, subscript; 145, attribute; 146, identifier:len; 147, argument_list; 148, identifier:var; 149, identifier:minimum; 150, assignment; 151, identifier:subst; 152, None; 153, subscript; 154, identifier:subst; 155, attribute; 156, identifier:var; 157, identifier:default; 158, subscript; 159, identifier:valid; 160, False; 161, identifier:subst; 162, attribute; 163, identifier:var; 164, identifier:name; 165, identifier:subst; 166, attribute; 167, identifier:var; 168, identifier:name; 169, identifier:var; 170, identifier:name
code: def commutative_sequence_variable_partition_iter(values: Multiset, variables: List[VariableWithCount]
                                                  ) -> Iterator[Dict[str, Multiset]]:
      """Yield all possible variable substitutions for given values and variables.
  
      .. note::
  
          The results are not yielded in any particular order because the algorithm uses dictionaries. Dictionaries until
          Python 3.6 do not keep track of the insertion order.
  
      Example:
  
          For a subject like ``fc(a, a, a, b, b, c)`` and a pattern like ``f(x__, y___, y___)`` one can define the
          following input parameters for the partitioning:
  
          >>> x = VariableWithCount(name='x', count=1, minimum=1, default=None)
          >>> y = VariableWithCount(name='y', count=2, minimum=0, default=None)
          >>> values = Multiset('aaabbc')
  
          Then the solutions are found (and sorted to get a unique output):
  
          >>> substitutions = commutative_sequence_variable_partition_iter(values, [x, y])
          >>> as_strings = list(str(Substitution(substitution)) for substitution in substitutions)
          >>> for substitution in sorted(as_strings):
          ...     print(substitution)
          {x ↦ {a, a, a, b, b, c}, y ↦ {}}
          {x ↦ {a, a, a, c}, y ↦ {b}}
          {x ↦ {a, b, b, c}, y ↦ {a}}
          {x ↦ {a, c}, y ↦ {a, b}}
  
      Args:
          values:
              The multiset of values which are partitioned and distributed among the variables.
          variables:
              A list of the variables to distribute the values among. Each variable has a name, a count of how many times
              it occurs and a minimum number of values it needs.
  
      Yields:
          Each possible substitutions that is a valid partitioning of the values among the variables.
      """
      if len(variables) == 1:
          yield from _commutative_single_variable_partiton_iter(values, variables[0])
          return
  
      generators = []
      for value, count in values.items():
          generators.append(_make_variable_generator_factory(value, count, variables))
  
      initial = dict((var.name, Multiset()) for var in variables)  # type: Dict[str, 'Multiset[T]']
      for subst in generator_chain(initial, *generators):
          valid = True
          for var in variables:
              if var.default is not None and len(subst[var.name]) == 0:
                  subst[var.name] = var.default
              elif len(subst[var.name]) < var.minimum:
                  valid = False
                  break
          if valid:
              if None in subst:
                  del subst[None]
              yield subst