def __call__(self, *args, **kwargs): fail_reasons = [] for typespec in self._versions: fargs, fkwargs_or_fail_reason = typespec.get_arg_list(*args, **kwargs) if fargs is not None: return typespec.func(*fargs, **fkwargs_or_fail_reason) else: fail_reasons.append(fkwargs_or_fail_reason or '<unknown reason for failed match>') # Should we fall back on the original function's code here? If so, we should catch and reraise any type errors raise TypeError("invalid function signature {0}.\n Available signatures are:\n{1}".format( argtypespec.get_call_signature(self.__name__, *args, **kwargs), indented('\n'.join(line + "\n" + indented("Not valid signature because: " + reason) for line, reason in zip(self._build_allowed_string().splitlines(), fail_reasons))) ))
def parse_qchem_matrix(data): ret_val = [[]] def parse_line(cols, m): row = int(m.group(1)) - 1 data = [float(f) for f in m.group(2).strip().split()] while len(ret_val) < row + 1: ret_val.append([]) while len(ret_val[row]) < cols[-1] + 1: ret_val[row].append(None) if len(cols) != len(data): raise OutputParsingError("ragged matrix in output:\n{}".format(indented(data))) for d, col in zip(data, cols): ret_val[row][col] = d def parse_group_of_lines(m): columns = [int(s.strip()) - 1 for s in m.group(1).split()] re.sub(r"(\d)((?:\s+-?\d+\.\d+)+)", partial(parse_line, columns), m.group(2)) re.sub(r"((?:\d+[ \t]*)+\n)[ \t]+((?:\d+(?:\s+-?\d+\.\d+)+\s+)+)", parse_group_of_lines, data) if None in flattened(ret_val): raise OutputParsingError("output matrix missing value:\n{}".format(indented(data))) return Matrix(ret_val)
def __str__(self): return "InternalRepresentation of {} with coordinates\n{}".format( shortstr(self.molecule), indented('\n'.join('[{}] {}: {}'.format( i, shortstr(coord), str(coord.value_with_units) ) for i, coord in enumerate(self.coords))) )
def assertOkayFdiffDerivative(self, poly, vars, places=4, robustness=2, forward=False): """ Assert almost equal with significant figures rather than digits after the decimal """ df = FiniteDifferenceDerivative(poly, *tuple(vars), robustness=robustness, forward=forward).value exp = poly.actual_derivative(*tuple(vars)) if abs(exp) > 0: div = 10.0**float(math.ceil(math.log(abs(exp), 10.0))) ract = round(df / div, places) rexp = round(exp / div, places) else: ract = round(df, places) rexp = round(exp, places) tmp = self.longMessage self.longMessage = True try: #("%"+str(places+1)+"f") % rexp, ("%"+str(places+1)+"f") % ract, self.assertAlmostEqual( ract, rexp, places, msg="\nfor derivative {} with robustness {} of function:\n{}". format(vars, robustness, indented(str(poly)))) finally: self.longMessage = tmp
def validate(self): bmat = self.b_matrix evals = np.linalg.eigvalsh(bmat * bmat.T) nvalid = len([e for e in evals if abs(e) > InternalRepresentation.zero_eigenvalue]) if nvalid != self.molecule.ninternals: raise RepresentationError("Have {} nonredundant internal coordinates, but need {}.\nCoordnates are:\n{}".format( nvalid, self.molecule.ninternals, indented('\n'.join('[' + str(i) + '] ' + shortstr(c) for i, c in enumerate(self.coords))) ))
def __repr__(self): return "FiniteDifferenceFormula({dord}, {rob}, [\n{terms}\n])".format( dord=repr(self.orders), rob=self.robustness, terms=indented( ',\n'.join(repr((coeff, deltas)) for deltas, coeff in sorted(self.coefficients.items(), key=lambda x: ' '.join(str(i) for i in x[0])) if coeff != 0) ) )
def __call__(self, *args, **kwargs): fargs, fkwargs = self._typespec.get_arg_list(*args, **kwargs) if fargs is not None: return self._typespec.func(*fargs, **fkwargs) else: raise TypeError("invalid function signature {0}.\n Function call must have" \ " the form:\n{1}\n which is not a valid signature because: {2}".format( argtypespec.get_call_signature(self.__name__, *args, **kwargs), indented(self._typespec.signature), fkwargs ))
def parse_line(cols, m): row = int(m.group(1)) - 1 data = [float(f) for f in m.group(2).strip().split()] while len(ret_val) < row + 1: ret_val.append([]) while len(ret_val[row]) < cols[-1] + 1: ret_val[row].append(None) if len(cols) != len(data): raise OutputParsingError("ragged matrix in output:\n{}".format(indented(data))) for d, col in zip(data, cols): ret_val[row][col] = d
def __call__(self, *args, **kwargs): fail_reasons = [] for typespec in self._versions: fargs, fkwargs_or_fail_reason = typespec.get_arg_list( *args, **kwargs) if fargs is not None: return typespec.func(*fargs, **fkwargs_or_fail_reason) else: fail_reasons.append(fkwargs_or_fail_reason or '<unknown reason for failed match>') # Should we fall back on the original function's code here? If so, we should catch and reraise any type errors raise TypeError( "invalid function signature {0}.\n Available signatures are:\n{1}" .format( argtypespec.get_call_signature(self.__name__, *args, **kwargs), indented('\n'.join( line + "\n" + indented("Not valid signature because: " + reason) for line, reason in zip( self._build_allowed_string().splitlines(), fail_reasons)))))
def __repr__(self): return "FiniteDifferenceFormula({dord}, {rob}, [\n{terms}\n])".format( dord=repr(self.orders), rob=self.robustness, terms=indented( ",\n".join( repr((coeff, deltas)) for deltas, coeff in sorted(self.coefficients.items(), key=lambda x: " ".join(str(i) for i in x[0])) if coeff != 0 ) ), )
def validate(self): bmat = self.b_matrix evals = np.linalg.eigvalsh(bmat * bmat.T) nvalid = len([ e for e in evals if abs(e) > InternalRepresentation.zero_eigenvalue ]) if nvalid != self.molecule.ninternals: raise RepresentationError( "Have {} nonredundant internal coordinates, but need {}.\nCoordnates are:\n{}" .format( nvalid, self.molecule.ninternals, indented('\n'.join('[' + str(i) + '] ' + shortstr(c) for i, c in enumerate(self.coords)))))
def assertOkayFdiffDerivative(self, poly, vars, places=4, robustness=2, forward=False): """ Assert almost equal with significant figures rather than digits after the decimal """ df = FiniteDifferenceDerivative(poly, *tuple(vars), robustness=robustness, forward=forward).value exp = poly.actual_derivative(*tuple(vars)) if abs(exp) > 0: div = 10.0 ** float(math.ceil(math.log(abs(exp), 10.0))) ract = round(df/div, places) rexp = round(exp/div, places) else: ract = round(df, places) rexp = round(exp, places) tmp = self.longMessage self.longMessage = True try: #("%"+str(places+1)+"f") % rexp, ("%"+str(places+1)+"f") % ract, self.assertAlmostEqual(ract, rexp, places, msg="\nfor derivative {} with robustness {} of function:\n{}".format( vars, robustness, indented(str(poly))) ) finally: self.longMessage = tmp
def __str__(self): return "InternalRepresentation of {} with coordinates\n{}".format( shortstr(self.molecule), indented('\n'.join('[{}] {}: {}'.format( i, shortstr(coord), str(coord.value_with_units)) for i, coord in enumerate(self.coords))))
def __str__(self): max_width = 80 indent_size = 4 function_name = "F" disp_name = "h" # ----------------------------------------# def var(idx): vars = "xyz" + str(reversed(string.ascii_lowercase[:-3])) vars = vars.replace(disp_name, "") vars = vars.replace(function_name, "") try: return vars[idx] except IndexError: return "x_" + idx # ----------------------------------------# flines = [] curr_line = "[" for dispnum, (disp, coeff) in enumerate(sorted(self.coefficients.items())): if coeff == 0: continue if coeff.denominator == 1: # Only print non-unit coefficients if abs(coeff) != 1: disp_f = str(abs(coeff)) else: disp_f = "" else: disp_f = "(" + str(abs(coeff)) + ")" disp_f += function_name + "(" for idx, d in enumerate(disp): disp_f += var(idx) if d == -1: disp_f += " - " + disp_name + "_" + var(idx) elif d == 1: disp_f += " + " + disp_name + "_" + var(idx) elif d < 0: disp_f += " - " + str(abs(d)) + disp_name + "_" + var(idx) elif d > 0: disp_f += " + " + str(d) + disp_name + "_" + var(idx) if d is not disp[-1]: disp_f += ", " disp_f += ")" if dispnum != 0: if coeff < 0: disp_f = " - " + disp_f else: disp_f = " + " + disp_f elif coeff < 0: # and dispnum == 0 disp_f = "-" + disp_f if len(curr_line + disp_f) > (max_width if len(flines) == 0 else max_width - indent_size): if curr_line != "": flines.append(curr_line) curr_line = disp_f else: # one term per line is the best we can do, and we still overflow...yikes... flines.append(disp_f) else: curr_line += disp_f denom = "] / " if len(self.orders) > 1: denom += "(" for idx, exp in enumerate(self.orders): denom += disp_name + "_" + var(idx) if exp > 1: denom += "^" + str(exp) if len(self.orders) > 1: denom += ")" if len(curr_line + denom) > (max_width if len(flines) == 0 else max_width - indent_size): if curr_line != "": flines.append(curr_line) curr_line = denom else: curr_line = denom else: curr_line += denom flines.append(curr_line) return ( "{cent} finite difference formula for df/{dvars}," " correct to order {order} in displacement ({terms} terms):\n{formula}".format( cent="Central" if self.direction == FiniteDifferenceFormula.CENTRAL else "Forward", order=self.robustness, dvars="".join( "d" + var(idx) + ("^" + str(exp) if exp > 1 else "") for idx, exp in enumerate(self.orders) ), formula=indented(("\n" + " " * indent_size).join(flines), indent_size), terms=len([c for c in self.coefficients.values() if c != 0]), ) )
def value_for_displacements(self, pairs): # Type checking and sanity checking if type_checking_enabled: if not all(len(pair) == 2 and isinstance(pair[0], FiniteDifferenceVariable) and isinstance(pair[1], int) for pair in pairs): raise TypeError if sanity_checking_enabled: for pair in pairs: if not isinstance(pair[0], Coordinate): raise ValueError( "FiniteDifferenceVariable instances passed to" " DisplacementManager.value_for_displacements" " must be instances of Coordinate subclasses." " (Got at least one that was a {0})".format( type(pair[0]).__name__ )) #--------------------------------------------------------------------------------# # prepare the increments increments = [0]*len(self.representation) for coord, ndeltas in pairs: i = self.representation.coords.index(coord) increments[i] = ndeltas increments = tuple(increments) #--------------------------------------------------------------------------------# # get the displacement, and ask the displaced molecule for the property try: displacement = self.displacement_for(increments) rv = displacement.displaced_molecule.get_property( self.differentiable, details=self.details ) if rv is None: raise ValueError("couldn't get displacement for increments {}".format(increments)) return rv #--------------------------------------------------------------------------------# # Old debugging code. Only applies to LegacyXMLResultGetter except RuntimeError as e: if all(isinstance(rg, LegacyXMLResultGetter) for rg in self.displacements[increments].displaced_molecule.result_getters): legacy_getters = [rg for rg in self.base_molecule.result_getters if isinstance(rg, LegacyXMLResultGetter)] molecule = self.displacements[increments].displaced_molecule smallest_dist = float('inf') * molecule.cartesian_units smallest_dist_stub = None best_rg = None mol = copy(molecule); mol.convert_units(DistanceUnit.default) for rg in legacy_getters: for stub in rg.properties.keys(): st = copy(stub); st.convert_units(DistanceUnit.default) ldiff = rg.properties.key_representation.value_for_molecule(stub) ldiff -= rg.properties.key_representation.value_for_molecule(mol) ldiff = abs(ldiff) if max(ldiff) < smallest_dist: best_rg = rg smallest_dist = max(ldiff) smallest_dist_stub = st if smallest_dist_stub is not None: # Print debugging information for legacy xml parser print("Failed to find match. Smallest " \ "maximum geometric difference was {}".format(smallest_dist), file=sys.stderr) print(indented( "Desired molecule representation " \ "was:\n{}".format(indented(str(molecule.internal_representation.copy_with_molecule(mol)))) ), file=sys.stderr) print(indented( '-'*40 + "\nClosest stub in the same representation:\n{}".format( indented(str(molecule.internal_representation.copy_with_molecule(smallest_dist_stub)))) ), file=sys.stderr) print("Tree leaf: \n{}".format( best_rg.properties._get_possibilities(mol) ), file=sys.stderr) print("Chains: \nMolecule:\n{}\nStub:\n{}".format( indented(str(best_rg.properties._key_chain_str(mol))), indented(str(best_rg.properties._key_chain_str(smallest_dist_stub))), ), file=sys.stderr) sys.stderr.flush() raise RuntimeError("couldn't get {} for displacements {}".format( self.differentiable.__name__, increments )) else: raise
def __str__(self): max_width=80 indent_size = 4 function_name = 'F' disp_name = 'h' #----------------------------------------# def var(idx): vars = 'xyz' + str(reversed(string.ascii_lowercase[:-3])) vars = vars.replace(disp_name, '') vars = vars.replace(function_name, '') try: return vars[idx] except IndexError: return 'x_' + idx #----------------------------------------# flines = [] curr_line = '[' for dispnum, (disp, coeff) in enumerate(sorted(self.coefficients.items())): if coeff == 0: continue if coeff.denominator == 1: # Only print non-unit coefficients if abs(coeff) != 1: disp_f = str(abs(coeff)) else: disp_f = '' else: disp_f = '(' + str(abs(coeff)) + ')' disp_f += function_name + '(' for idx, d in enumerate(disp): disp_f += var(idx) if d == -1: disp_f += ' - ' + disp_name + '_' + var(idx) elif d == 1: disp_f += ' + ' + disp_name + '_' + var(idx) elif d < 0: disp_f += ' - ' + str(abs(d)) + disp_name + '_' + var(idx) elif d > 0: disp_f += ' + ' + str(d) + disp_name + '_' + var(idx) if d is not disp[-1]: disp_f += ', ' disp_f += ')' if dispnum != 0: if coeff < 0: disp_f = ' - ' + disp_f else: disp_f = ' + ' + disp_f elif coeff < 0: # and dispnum == 0 disp_f = '-' + disp_f if len(curr_line + disp_f) > (max_width if len(flines) == 0 else max_width - indent_size): if curr_line != '': flines.append(curr_line) curr_line = disp_f else: # one term per line is the best we can do, and we still overflow...yikes... flines.append(disp_f) else: curr_line += disp_f denom = '] / ' if len(self.orders) > 1: denom += '(' for idx, exp in enumerate(self.orders): denom += disp_name + '_' + var(idx) if exp > 1: denom += '^' + str(exp) if len(self.orders) > 1: denom += ')' if len(curr_line + denom) > (max_width if len(flines) == 0 else max_width - indent_size): if curr_line != '': flines.append(curr_line) curr_line = denom else: curr_line = denom else: curr_line += denom flines.append(curr_line) return '{cent} finite difference formula for df/{dvars},' \ ' correct to order {order} in displacement ({terms} terms):\n{formula}'.format( cent='Central' if self.direction == FiniteDifferenceFormula.CENTRAL else 'Forward', order = self.robustness, dvars=''.join('d' + var(idx) + ('^'+str(exp) if exp > 1 else '') for idx, exp in enumerate(self.orders)), formula=indented(('\n' + ' ' * indent_size).join(flines), indent_size), terms=len([c for c in self.coefficients.values() if c != 0]) )