def test_2_elements(self): samples = [[1, 2, 3], [6]] sample_spaces = [[1, 2, 3, 4], [5, 6]] combos = generate_combo(samples, sample_spaces) expected = 1 for sample, sample_space in zip(samples, sample_spaces): expected *= comb(len(sample_space), len(sample), exact=True) # we leave out the original combination expected -= 1 self.assertEquals(len(combos), expected)
def _find_lowest_u_layer(mol, u_layer, equivalent_atoms): """ Searches for the "minimum" combination of indices of atoms that bear unpaired electrons. It does so by using the information on equivalent atoms to permute equivalent atoms to obtain a combination of atoms that is the (numerically) lowest possible combination. Each possible combination is valid if and only if the distances between the atoms of the combination is identical to the distances between the original combination. First, the algorithm partitions equivalent atoms that bear an unpaired electron. Next, the combinations are generated, and for each combination it is verified whether it pertains to a "valid" combination. Returns a list of indices corresponding to the lowest combination of atom indices bearing unpaired electrons. """ cython.declare( new_u_layer=list, grouped_electrons=list, corresponding_E_layers=list, group=list, e_layer=list, combos=list, orig_agglomerates=list, orig_distances=list, selected_group=list, combo=list, ) if not equivalent_atoms: return u_layer new_u_layer = [] grouped_electrons, corresponding_E_layers = partition( u_layer, equivalent_atoms) # don't process atoms that do not belong to an equivalence layer for group, e_layer in zip(grouped_electrons[:], corresponding_E_layers[:]): if not e_layer: new_u_layer.extend(group) grouped_electrons.remove(group) corresponding_E_layers.remove(e_layer) combos = generate_combo(grouped_electrons, corresponding_E_layers) # compute original distance: orig_agglomerates = agglomerate(grouped_electrons) orig_distances = _compute_agglomerate_distance(orig_agglomerates, mol) # deflate the list of lists to be able to numerically compare them selected_group = sorted(itertools.chain.from_iterable(grouped_electrons)) # see if any of the combos is valid and results in a lower numerical combination than the original for combo in combos: if _is_valid_combo(combo, mol, orig_distances): combo = sorted(itertools.chain.from_iterable(combo)) if combo < selected_group: selected_group = combo # add the minimized unpaired electron positions to the u-layer: new_u_layer.extend(selected_group) return sorted(new_u_layer)
def _find_lowest_u_layer(mol, u_layer, equivalent_atoms): """ Searches for the "minimum" combination of indices of atoms that bear unpaired electrons. It does so by using the information on equivalent atoms to permute equivalent atoms to obtain a combination of atoms that is the (numerically) lowest possible combination. Each possible combination is valid if and only if the distances between the atoms of the combination is identical to the distances between the original combination. First, the algorithm partitions equivalent atoms that bear an unpaired electron. Next, the combinations are generated, and for each combination it is verified whether it pertains to a "valid" combination. Returns a list of indices corresponding to the lowest combination of atom indices bearing unpaired electrons. """ cython.declare( new_u_layer=list, grouped_electrons=list, corresponding_E_layers=list, group=list, e_layer=list, combos=list, orig_agglomerates=list, orig_distances=list, selected_group=list, combo=list, ) if not equivalent_atoms: return u_layer new_u_layer = [] grouped_electrons, corresponding_E_layers = partition(u_layer, equivalent_atoms) # don't process atoms that do not belong to an equivalence layer for group, e_layer in zip(grouped_electrons[:], corresponding_E_layers[:]): if not e_layer: new_u_layer.extend(group) grouped_electrons.remove(group) corresponding_E_layers.remove(e_layer) combos = generate_combo(grouped_electrons, corresponding_E_layers) # compute original distance: orig_agglomerates = agglomerate(grouped_electrons) orig_distances = _compute_agglomerate_distance(orig_agglomerates, mol) # deflate the list of lists to be able to numerically compare them selected_group = sorted(itertools.chain.from_iterable(grouped_electrons)) # see if any of the combos is valid and results in a lower numerical combination than the original for combo in combos: if _is_valid_combo(combo, mol, orig_distances): combo = sorted(itertools.chain.from_iterable(combo)) if combo < selected_group: selected_group = combo # add the minimized unpaired electron positions to the u-layer: new_u_layer.extend(selected_group) return sorted(new_u_layer)