예제 #1
0
def seek_convergence(at=1e-3, rt=1e-2, term_verb=True, **kwargs):
    """
    Perform a convergence procedure by using a list of (ordered) values of a parameter.
    Take as input a list of instances of runner built with the values of the convergence parameter.
    These objects have to provide as the result of runner.run() a quantity that can be compared.
    The convergence is performed by comparing the results associated to two (subsequent) values of the
    parameter. The procedures stop if the difference between the result is below a given tolerance, if not
    further run are performed using the values of the parameter in the list.
    The method returns a dictionary with the input parameters, the results of all the computation performed,
    the value of the convergence parameter and a boolean that states if the convergence procedure succeeds
    or not.

    Args:
        kwargs['label']     : the name of the convergence parameter
        kwargs['values']    : the array with the (ordered) values of the convergence parameter
        kwargs['data']      : the array with the dataset buit with kwargs['values']
        at,rt               : absolute and relative tol of np.allclose
    """
    label = kwargs['label']
    values = kwargs['values']
    data = kwargs['data']
    results = {}
    for v in values:
        results[v] = None
    out = {'label': label, 'values': values}

    if term_verb: print 'Perform the run with', label, values[0]
    results[values[0]] = data[0].run()

    for ind in range(1, len(values)):
        if term_verb: print 'Perform the run with', label, values[ind]
        results[values[ind]] = data[ind].run()
        convergence = np.allclose(results[values[ind - 1]],
                                  results[values[ind]],
                                  atol=at,
                                  rtol=rt)
        if convergence:
            if term_verb:
                write('Convergence achieved for', label, values[ind - 1])
            out['results'] = results
            out['converged'] = True
            out['converged_value'] = values[ind - 1]
            break
        else:
            if term_verb:
                write('Convergence for', label, values[ind - 1], 'failed')

    if convergence == False:
        print 'Return the value associated to', label, values[
            -1], '. Perform further check!!!'
        out['results'] = results
        out['converged'] = False
        out['converged_value'] = values[-1]

    return out
예제 #2
0
 def __init__(self, *args, **kwargs):
     """
     Perform sanity checks on the loaded matrix
     """
     log = kwargs.get('log')
     if log is not None:
         self.norb_occ, self.norb_virt = _occ_and_virt(log)
     else:
         self.norb_occ = kwargs.get('norb_occ')
         self.norb_virt = kwargs.get('norb_virt')
     assert (self.shape[0] == self._total_transitions())
     write("Shape is conformal with the number of orbitals")
     self._sanity_check()
예제 #3
0
 def _doc_finder(self, stream):
     #first find the stream of the document start
     startpos = 0
     import sys
     write('Loading...')
     while startpos < len(stream):
         try:
             startpos += self._event_finder(stream[startpos:],
                                            yaml.events.DocumentEndEvent)
         except:
             startpos = len(stream)
         write(int((100.0 * startpos) / len(stream)), '%')
         yield startpos
예제 #4
0
 def __new__(cls, matrix=None, norb_occ=None, norb_virt=None, log=None):
     """
     Create the object from the arguments and return the ``self`` instance
     """
     import os
     if log is not None:
         datadir = log.log.get('radical', '')
         datadir = 'data-' + datadir if len(datadir) > 0 else 'data'
         cmfile = os.path.join(log.srcdir, datadir, cls._filename)
         if not os.path.isfile(cmfile):
             raise ValueError('The file "' + cmfile + '" does not exist')
         norb, norbv = _occ_and_virt(log)
         write('Loading data with ', norb, ' occupied and ', norbv,
               ' empty states, from file "', cmfile, '"')
         try:
             import pandas as pd
             write('Using pandas:')
             mat = pd.read_csv(cmfile, delim_whitespace=True, header=None)
         except ImportError:
             write('Using numpy:')
             mat = np.loadtxt(cmfile)
         write('done')
     else:
         mat = matrix
     return super(TransitionMatrix, cls).__new__(cls, mat)
예제 #5
0
    def diagonalize(self):
        """
        Diagonalize the Coupling Matrix

        Returns:
            (np.matrix, np.matrix):
            tuple of the Eigenvvalues and Eigenvectors of the coupling matrix,
              as returned by :meth:`numpy.linalg.eigh`. We perform the
              transpose of the matrix with eigenvectors to have them sorted as
              row vectors
        """
        write('Diagonalizing Coupling matrix of shape', self.shape)
        E2, C_E2 = np.linalg.eigh(self)
        write('Eigensystem solved')
        C_E2 = C_E2.T
        return E2, C_E2
예제 #6
0
 def _event_finder(self, present, event, end=False):
     for i in yaml.parse(present, Loader=yaml.CLoader):
         if isinstance(i, event):
             if end:
                 key = i.value
                 startpos = i.start_mark.index
                 endpos = startpos + self._find_endblock(present[startpos:])
                 substream = present[i.end_mark.index:endpos]
                 return key, substream, endpos
             else:
                 startpos = i.end_mark.index
                 return startpos
     #in the case of absent event
     if end:
         write('here', present, 'end')
         return 'nothing', '', len(present)
     else:
         return len(present)
예제 #7
0
    def seek_convergence(self,
                         rtol=1.e-5,
                         atol=1.e-8,
                         selection=None,
                         **kwargs):
        """
        Search for the first result of the dataset which matches the provided
        tolerance parameter. The results are in dataset order
        (provided by the :py:meth:`append_run` method) if `selection` is not
        specified.
        Employs the numpy :py:meth:`allclose` method for comparison.

        Args:
          rtol (float): relative tolerance parameter
          atol (float): absolute tolerance parameter
          selection (list): list of the id of the runs in which to perform the
               convergence search. Each id should be unique in the dataset.
          **kwargs: arguments to be passed to the :py:meth:`fetch_results`
               method.

        Returns:
          id,result (tuple): the id of the last run which matches the
                convergence, together with the result, if convergence is
                reached.

        Raises:
           LookupError: if the parameter for convergence were not found.
               The dataset has to be enriched or the convergence parameters
               loosened.
        """
        from numpy import allclose
        from futile.Utils import write
        to_get = self.ids if selection is None else selection

        id_ref = to_get[0]
        write('Fetching results for id "', id_ref, '"')
        ref = self.fetch_results(id=id_ref, **kwargs)
        ref = ref[0]
        for id in to_get[1:]:
            write('Fetching results for id "', id, '"')
            val = self.fetch_results(id=id, **kwargs)
            val = val[0]
            if allclose(ref, val, rtol=rtol, atol=atol):
                res = self.fetch_results(id=id_ref)
                label = self.get_global_option('label')
                write(
                    'Convergence reached in Dataset "' + label + '" for id "',
                    id_ref, '"')
                return (id_ref, res[0])
            ref = val
            id_ref = id
        raise LookupError('Convergence not reached, enlarge the dataset'
                          ' or change tolerance values')
예제 #8
0
def clean_logfile(logfile_lines, to_remove):
    """Remove yaml fields from a list of lines.

  Removes from a set of lines the yaml_fields contained in the to_remove list.

  Arguments:
      logfile_lines (list): list of the lines of the logfile. Generated from a file by e.g. :py:meth:`~io.IOBase.readlines`.
      to_remove (list): list of keys to remove from logfile_lines

  Returns:
      list of lines where the removed keys have as values the `"<folded>"` string
  """
    line_rev = logfile_lines  #list of the lines of the logfile
    #loop in the reversed from (such as to parse by blocks)
    extra_lines = 20  #internal variable to be customized
    line_rev.reverse()
    #clean the log
    cleaned_logfile = []
    removed = []
    #for line in line_rev: #line_iter:
    while len(line_rev) > 0:
        line = line_rev.pop()
        to_print = line
        #check if the line contains interesting information
        for remove_it in to_remove:
            stream_list = []
            #line without comments
            valid_line = line.split('#')[0]
            spaces = 'nospace'
            #control that the string between the key and the semicolon is only spaces
            if remove_it in valid_line and ":" in valid_line:
                #print "here",remove_it,remove_it in valid_line and ":" in valid_line,valid_line
                starting_point = valid_line.find(remove_it)
                tmp_buf = valid_line[:starting_point]
                #find the closest comma to the staring point, if exists
                tmp_buf = tmp_buf[::-1]
                starting_comma = tmp_buf.find(',')
                if starting_comma < 0: st = 0
                tmp_buf = tmp_buf[st:]
                tmp_buf = tmp_buf[::-1]
                tmp_buf = tmp_buf.strip(' ')
                #print "there",tmp_buf,'starting',starting_point,len(tmp_buf)
                valid_line = valid_line[starting_point + len(remove_it):]
                spaces = valid_line[1:valid_line.find(':')]
                #if remove_it+':' in line.split('#')[0]:
            if len(spaces.strip(' ')) == 0 and len(
                    tmp_buf) == 0:  #this means that the key has been found
                #creates a new Yaml document starting from the line
                #treat the rest of the line following the key to be removed
                header = ''.join(line.split(':')[1:])
                header = header.rstrip() + '\n'
                #eliminate the anchor
                header = header.lstrip(' ')
                header = header.lstrip('*')
                if len(header) > 0:
                    stream_list.append(header)
                #part to be printed, updated
                to_print = line.split(':')[0] + ": <folded> \n"

                #then check when the mapping will end:
                while True:
                    #create a stream with extra_lines block
                    for i in range(0, min(extra_lines, len(line_rev))):
                        stream_list.append(line_rev.pop())
                    #create a stream to be parsed
                    stream = ''.join(stream_list)
                    #then parse the stream until the last valid position has been found
                    try:
                        for i in yaml.parse(stream, Loader=yaml.CLoader):
                            endpos = i.end_mark.index
                    except Exception(e):
                        #  print 'error',str(e),stream
                        #convert back the valid stream into a list
                        #if needed the stream can be loaded into a document
                        item_list = stream[:endpos].split('\n')
                        #if lengths are different there is no need to add lines
                        if len(item_list) != len(stream_list):
                            #last line might be shorter, therefore treat it separately
                            last_line = item_list.pop()
                            #purge the stream
                            for item in item_list:
                                stream_list.remove(item + '\n')
                            #extract the remaining line which should be compared with the last one
                            strip_size = len(last_line.rstrip())
                            if strip_size > 0:
                                first_line = stream_list.pop(0)[strip_size:]
                                if '*' in first_line or '&' in first_line:
                                    first_line = ''  #eliminate anchors
                            else:
                                first_line = ''
                            #then put the rest in the line to be treated
                            to_print.rstrip('\n')
                            to_print += first_line + '\n'
                            # the item has been found
                            break
                stream_list.reverse()
                #put back the unused part in the document
                line_rev.extend(stream_list)
                # mark that the key has been removed
                if (remove_it not in removed):
                    removed.append(remove_it)
                    write('removed: ', remove_it)
    # then print out the line
        cleaned_logfile.append(to_print)

    # check that everything has been removed, at least once
    if (set(removed) != set(to_remove)):
        write('WARNING, not all the requested items have been removed!')
        write('To_remove : ', to_remove)
        write('removed   : ', removed)
        write('Difference: ', list(set(to_remove) - set(removed)))
    return cleaned_logfile
예제 #9
0
def load(file=None,
         stream=None,
         doc_lists=True,
         safe_mode=False,
         archive=None,
         member=None):
    """Encapsulate the loading of yaml documents.

    Provides a dictionary, or a list of dictionaries, which
    represents the structure of the stream to be loaded.
    It also wraps the yaml loader to perform a optimized parsing when the
    `minloader` of PyYaml 3.13 is available.
    This wrapper ensures to extract from the stream the maximum possible
    information by choosing the best loader available.

    Arguments:
        file (str): path of the yaml-compliant file containing the stream
             to be loaded

        stream (str): the stream to load, overrides the ``file`` argument
             if present

        archive (str): path of the archive to be used for the retrieval
             of the stream

        member (str): name of the file to be extracted from the archive.
            the entire archive is parsed if absent

        doc_lists (bool): if True, ensures that the results is always in a form
           of lists of documents, even in the case of a single doc
           When False, the return type is either a dictionary or a generator
           according to the specifications of yaml.load and
           yaml.load_all respectively.

        safe_mode (bool): When true, in the case of multiple documents
           in the stream, it loads the document one after another.
           This is useful to avoid losing of all the document list
           in the case when one of the document is
           not yaml compliant, like in the case of a broken logfile.
           It may works only when the separation of the
           documents is indicated by the usual syntax ``"---\\n"``
           (i.e. no yaml tags between documents)

    Returns:
        * a list of dictionaries, if ``doc_lists`` is set to ``True``;
        * a dictionary, if the stream or the file, or the archive contains a
             single yaml document;
        * a generator if the parsed stream is made of multiple
             documents *and* ``safe_mode`` = ``False``;
        * a list of dictionaries if the stream is made of multiple documents
             and ``safe_mode`` is ``True``.
    """
    # choose the loader
    try:
        ldr = yaml.MinLoader
    except Exception as e:
        try:
            ldr = yaml.CLoader
        except Exception as f:
            ldr = yaml.Loader

    # load the documents
    ld = []

    # verify if we are in the archive case
    if archive is not None:
        import tarfile
        tar = tarfile.open(archive)
        if member is not None:
            members = [tar.getmember(member)]
        else:
            members = tar.getmembers()
        ld = []
        for memb in members:
            f = tar.extractfile(memb)
            if safe_mode:
                try:
                    ll = yaml.load(f.read(), Loader=ldr)
                except Exception as f:
                    write('Document', member, 'of archive NOT loaded, error:',
                          f)
            else:
                ll = yaml.load(f.read(), Loader=ldr)
            ld += ll
            if len(members) == 1 and not doc_lists:
                return ll
        return ld

    # Detect None otherwise a doc == '' gives an error
    strm = stream if stream is not None else open(file, 'r').read()
    try:
        ld = yaml.load(strm, Loader=ldr)
        if doc_lists:
            ld = [ld]
    except Exception as e:
        if safe_mode:
            ld = []
            documents = [v for v in strm.split('---\n') if len(v) > 0]
            for i, raw_doc in enumerate(documents):
                try:
                    ld.append(yaml.load(raw_doc, Loader=ldr))
                except Exception as f:
                    write('Document', i, 'of stream NOT loaded, error:', f)
        else:
            ld = yaml.load_all(strm, Loader=ldr)
            if doc_lists:
                ld = [l for l in ld]
    return ld
예제 #10
0
 def _sanity_check(self):
     write('Casida Matrix is symmetric',
           np.allclose(self, self.T, atol=1.e-12))