Пример #1
0
def _is_valid_combo(combo, mol, distances):
    """
    Check if the combination of atom indices refers to
    atoms that are adjacent in the molecule.
    """
    cython.declare(
        agglomerates=list,
        new_distances=list,
        orig_dist=dict,
        new_dist=dict,
    )

    # compute shortest path between atoms
    agglomerates = agglomerate(combo)
    new_distances = _compute_agglomerate_distance(agglomerates, mol)

    # combo is valid if the distance is equal to the parameter distance

    if len(distances) != len(new_distances): return False

    for orig_dist, new_dist in zip(distances, new_distances):
        # only compare the values of the dictionaries:
        if sorted(orig_dist.values()) != sorted(new_dist.values()):
            return False

    return True
Пример #2
0
def _is_valid_combo(combo, mol, distances):
    """
    Check if the combination of atom indices refers to
    atoms that are adjacent in the molecule.
    """
    cython.declare(
        agglomerates=list,
        new_distances=list,
        orig_dist=dict,
        new_dist=dict,
    )

    # compute shortest path between atoms
    agglomerates = agglomerate(combo)
    new_distances = _compute_agglomerate_distance(agglomerates, mol)

    # combo is valid if the distance is equal to the parameter distance

    if len(distances) != len(new_distances): return False

    for orig_dist, new_dist in zip(distances, new_distances):
        # only compare the values of the dictionaries:
        if sorted(orig_dist.values()) != sorted(new_dist.values()):
            return False

    return True
Пример #3
0
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)
Пример #4
0
    def test_normal(self):
        groups = [[1, 2, 3], [4], [5, 6], [7]]
        agglomerates = agglomerate(groups)
        expected = [[1, 2, 3], [5, 6], [4, 7]]

        self.assertEquals(agglomerates, expected)
Пример #5
0
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)