def resonance_dominant_bond_orders(rgr): """ resonance-dominant bond orders, by bond """ bnd_keys = list(_bond_keys(rgr)) bnd_ords_by_res = [ dict_.values_by_key(_bond_orders(dom_rgr), bnd_keys) for dom_rgr in dominant_resonances(rgr)] bnd_ords_lst = list(map(frozenset, zip(*bnd_ords_by_res))) bnd_dom_res_ords_dct = dict(zip(bnd_keys, bnd_ords_lst)) return bnd_dom_res_ords_dct
def _bond_capacities(rgr): """ the number of electron pairs available for further pi-bonding, by bond """ atm_unsat_vlc_dct = _atom_unsaturated_valences(rgr) def _pi_capacities(bnd_key): return min(map(atm_unsat_vlc_dct.__getitem__, bnd_key)) bnd_keys = list(_bond_keys(rgr)) bnd_caps = tuple(map(_pi_capacities, bnd_keys)) bnd_cap_dct = dict(zip(bnd_keys, bnd_caps)) return bnd_cap_dct
def resonance_avg_bond_orders(rgr): """ resonance-dominant bond orders, by bond """ bnd_keys = list(_bond_keys(rgr)) bnd_ords_by_res = [ dict_.values_by_key(_bond_orders(dom_rgr), bnd_keys) for dom_rgr in dominant_resonances(rgr)] nres = len(bnd_ords_by_res) bnd_ords_lst = zip(*bnd_ords_by_res) avg_bnd_ord_lst = [sum(bnd_ords)/nres for bnd_ords in bnd_ords_lst] avg_bnd_ord_dct = dict(zip(bnd_keys, avg_bnd_ord_lst)) return avg_bnd_ord_dct
def _add_pi_bonds(rgr, bnd_ord_inc_dct): """ add pi bonds to this graph """ bnd_keys = _bond_keys(rgr) assert set(bnd_ord_inc_dct.keys()) <= bnd_keys bnd_keys = list(bnd_keys) bnd_ords = dict_.values_by_key(_bond_orders(rgr), bnd_keys) bnd_ord_incs = dict_.values_by_key(bnd_ord_inc_dct, bnd_keys, fill_val=0) new_bnd_ords = numpy.add(bnd_ords, bnd_ord_incs) bnd_ord_dct = dict(zip(bnd_keys, new_bnd_ords)) rgr = _set_bond_orders(rgr, bnd_ord_dct) return rgr
def subresonances(rgr): """ this connected graph and its lower-spin (more pi-bonded) resonances """ def _inc_range(bnd_cap): return tuple(range(0, bnd_cap+1)) add_pi_bonds_ = functools.partial(_add_pi_bonds, rgr) atm_keys = list(_atom_keys(rgr)) bnd_keys = list(_bond_keys(rgr)) atm_unsat_vlcs = dict_.values_by_key( _atom_unsaturated_valences(rgr), atm_keys) atm_bnd_keys_lst = dict_.values_by_key(_atom_bond_keys(rgr), atm_keys) bnd_caps = dict_.values_by_key(_bond_capacities(rgr), bnd_keys) bnd_ord_dct = _bond_orders(rgr) def _is_valid(bnd_ord_inc_dct): # check if pi bonds exceed unsaturated valences def __tally(atm_bnd_keys): return sum(dict_.values_by_key(bnd_ord_inc_dct, atm_bnd_keys)) atm_unsat_vlc_decs = tuple(map(__tally, atm_bnd_keys_lst)) enough_elecs = numpy.all( numpy.less_equal(atm_unsat_vlc_decs, atm_unsat_vlcs)) # check if all bond orders are less than 4 (should only affect C2) bnd_inc_keys = bnd_ord_inc_dct.keys() bnd_incs = dict_.values_by_key(bnd_ord_inc_dct, bnd_inc_keys) bnd_ords = dict_.values_by_key(bnd_ord_dct, bnd_inc_keys) new_bnd_ords = numpy.add(bnd_ords, bnd_incs) not_too_many = numpy.all(numpy.less(new_bnd_ords, 4)) return enough_elecs and not_too_many def _bond_value_dictionary(bnd_vals): return dict(zip(bnd_keys, bnd_vals)) bnd_ord_incs_itr = itertools.product(*map(_inc_range, bnd_caps)) bnd_ord_inc_dct_itr = map(_bond_value_dictionary, bnd_ord_incs_itr) bnd_ord_inc_dct_itr = filter(_is_valid, bnd_ord_inc_dct_itr) rgrs = tuple(sorted(map(add_pi_bonds_, bnd_ord_inc_dct_itr), key=_frozen)) return rgrs