Instruction:
Make a summary of the following Python 3 code
def _win32_read_junction(path):
    if not jwfs.is_reparse_point(path):
        raise ValueError('not a junction')

    # --- Older version based on using shell commands ---
    # if not exists(path):
    #     if six.PY2:
    #         raise OSError('Cannot find path={}'.format(path))
    #     else:
    #         raise FileNotFoundError('Cannot find path={}'.format(path))
    # target_name = os.path.basename(path)
    # for type_or_size, name, pointed in _win32_dir(path, '*'):
    #     if type_or_size == '<JUNCTION>' and name == target_name:
    #         return pointed
    # raise ValueError('not a junction')

    # new version using the windows api
    handle = jwfs.api.CreateFile(
            path, 0, 0, None, jwfs.api.OPEN_EXISTING,
            jwfs.api.FILE_FLAG_OPEN_REPARSE_POINT |
            jwfs.api.FILE_FLAG_BACKUP_SEMANTICS,
            None)

    if handle == jwfs.api.INVALID_HANDLE_VALUE:
        raise WindowsError()

    res = jwfs.reparse.DeviceIoControl(
            handle, jwfs.api.FSCTL_GET_REPARSE_POINT, None, 10240)

    bytes = jwfs.create_string_buffer(res)
    p_rdb = jwfs.cast(bytes, jwfs.POINTER(jwfs.api.REPARSE_DATA_BUFFER))
    rdb = p_rdb.contents

    if rdb.tag not in [2684354563, jwfs.api.IO_REPARSE_TAG_SYMLINK]:
        raise RuntimeError(
                "Expected <2684354563 or 2684354572>, but got %d" % rdb.tag)

    jwfs.handle_nonzero_success(jwfs.api.CloseHandle(handle))
    subname = rdb.get_substitute_name()
    # probably has something to do with long paths, not sure
    if subname.startswith('?\\'):
        subname = subname[2:]
    return subname

Response: Return the location that the junction points at path raises ValueError if path is not a junction.


Instruction:
Write a Python 3 script to
remove all junctions in a directory

Response:
def _win32_rmtree(path, verbose=0):
    """
    rmtree for win32 that treats junctions like directory symlinks.
    The junction removal portion may not be safe on race conditions.

    There is a known issue that prevents shutil.rmtree from
    deleting directories with junctions.
    https://bugs.python.org/issue31226
    """

    # --- old version using the shell ---
    # def _rmjunctions(root):
    #     subdirs = []
    #     for type_or_size, name, pointed in _win32_dir(root):
    #         if type_or_size == '<DIR>':
    #             subdirs.append(name)
    #         elif type_or_size == '<JUNCTION>':
    #             # remove any junctions as we encounter them
    #             # os.unlink(join(root, name))
    #             os.rmdir(join(root, name))
    #     # recurse in all real directories
    #     for name in subdirs:
    #         _rmjunctions(join(root, name))

    def _rmjunctions(root):
        subdirs = []
        for name in os.listdir(root):
            current = join(root, name)
            if os.path.isdir(current):
                if _win32_is_junction(current):
                    # remove any junctions as we encounter them
                    os.rmdir(current)
                elif not os.path.islink(current):
                    subdirs.append(current)
        # recurse in all real directories
        for subdir in subdirs:
            _rmjunctions(subdir)

    if _win32_is_junction(path):
        if verbose:
            print('Deleting <JUNCTION> directory="{}"'.format(path))
        os.rmdir(path)
    else:
        if verbose:
            print('Deleting directory="{}"'.format(path))
        # first remove all junctions
        _rmjunctions(path)
        # now we can rmtree as normal
        import shutil
        shutil.rmtree(path)


Instruction:
Write a Python 3 script to
test if two hard links point to the same location.

Response:
def _win32_is_hardlinked(fpath1, fpath2):
    """
    Test if two hard links point to the same location

    CommandLine:
        python -m ubelt._win32_links _win32_is_hardlinked

    Example:
        >>> # xdoc: +REQUIRES(WIN32)
        >>> import ubelt as ub
        >>> root = ub.ensure_app_cache_dir('ubelt', 'win32_hardlink')
        >>> ub.delete(root)
        >>> ub.ensuredir(root)
        >>> fpath1 = join(root, 'fpath1')
        >>> fpath2 = join(root, 'fpath2')
        >>> ub.touch(fpath1)
        >>> ub.touch(fpath2)
        >>> fjunc1 = _win32_junction(fpath1, join(root, 'fjunc1'))
        >>> fjunc2 = _win32_junction(fpath2, join(root, 'fjunc2'))
        >>> assert _win32_is_hardlinked(fjunc1, fpath1)
        >>> assert _win32_is_hardlinked(fjunc2, fpath2)
        >>> assert not _win32_is_hardlinked(fjunc2, fpath1)
        >>> assert not _win32_is_hardlinked(fjunc1, fpath2)
    """
    # NOTE: jwf.samefile(fpath1, fpath2) seems to behave differently
    def get_read_handle(fpath):
        if os.path.isdir(fpath):
            dwFlagsAndAttributes = jwfs.api.FILE_FLAG_BACKUP_SEMANTICS
        else:
            dwFlagsAndAttributes = 0
        hFile = jwfs.api.CreateFile(fpath, jwfs.api.GENERIC_READ,
                                    jwfs.api.FILE_SHARE_READ, None,
                                    jwfs.api.OPEN_EXISTING,
                                    dwFlagsAndAttributes, None)
        return hFile

    def get_unique_id(hFile):
        info = jwfs.api.BY_HANDLE_FILE_INFORMATION()
        res = jwfs.api.GetFileInformationByHandle(hFile, info)
        jwfs.handle_nonzero_success(res)
        unique_id = (info.volume_serial_number, info.file_index_high,
                     info.file_index_low)
        return unique_id

    hFile1 = get_read_handle(fpath1)
    hFile2 = get_read_handle(fpath2)
    try:
        are_equal = (get_unique_id(hFile1) == get_unique_id(hFile2))
    except Exception:
        raise
    finally:
        jwfs.api.CloseHandle(hFile1)
        jwfs.api.CloseHandle(hFile2)
    return are_equal


Instruction:
Create a Python 3 function to
get information about a directory in Windows.

Response:
def _win32_dir(path, star=''):
    """
    Using the windows cmd shell to get information about a directory
    """
    from ubelt import util_cmd
    import re
    wrapper = 'cmd /S /C "{}"'  # the /S will preserve all inner quotes
    command = 'dir /-C "{}"{}'.format(path, star)
    wrapped = wrapper.format(command)
    info = util_cmd.cmd(wrapped, shell=True)
    if info['ret'] != 0:
        from ubelt import util_format
        print('Failed command:')
        print(info['command'])
        print(util_format.repr2(info, nl=1))
        raise OSError(str(info))
    # parse the output of dir to get some info
    # Remove header and footer
    lines = info['out'].split('\n')[5:-3]
    splitter = re.compile('( +)')
    for line in lines:
        parts = splitter.split(line)
        date, sep, time, sep, ampm, sep, type_or_size, sep = parts[:8]
        name = ''.join(parts[8:])
        # if type is a junction then name will also contain the linked loc
        if name == '.' or name == '..':
            continue
        if type_or_size in ['<JUNCTION>', '<SYMLINKD>', '<SYMLINK>']:
            # colons cannot be in path names, so use that to find where
            # the name ends
            pos = name.find(':')
            bpos = name[:pos].rfind('[')
            name = name[:bpos - 1]
            pointed = name[bpos + 1:-1]
            yield type_or_size, name, pointed
        else:
            yield type_or_size, name, None


Instruction:
Explain what the following Python 3 code does
def parse_generator_doubling(config):
    start = 1
    if 'start' in config:
        start = int(config['start'])

    # We cannot simply use start as the variable, because of scoping
    # limitations
    def generator():
        val = start
        while(True):
            yield val
            val = val * 2
    return generator()

Response:
Returns a generator that double with each value returned
AttributeNames Config includes optional start value


Instruction:
Write a Python 3 function for
parsing a contains validator which takes as the config a simple string to find

Response:
def parse(config):
        """ Parse a contains validator, which takes as the config a simple string to find """
        if not isinstance(config, basestring):
            raise TypeError("Contains input must be a simple string")
        validator = ContainsValidator()
        validator.contains_string = config
        return validator


Instruction:
Create a Python 3 function to
retrieve the adjacency matrix from the nx. DiGraph or np. ndarray.

Response:
def retrieve_adjacency_matrix(graph, order_nodes=None, weight=False):
    """Retrieve the adjacency matrix from the nx.DiGraph or numpy array."""
    if isinstance(graph, np.ndarray):
        return graph
    elif isinstance(graph, nx.DiGraph):
        if order_nodes is None:
            order_nodes = graph.nodes()
        if not weight:
            return np.array(nx.adjacency_matrix(graph, order_nodes, weight=None).todense())
        else:
            return np.array(nx.adjacency_matrix(graph, order_nodes).todense())
    else:
        raise TypeError("Only networkx.DiGraph and np.ndarray (adjacency matrixes) are supported.")


Instruction:
Can you generate the documentation for the following Python 3 function
def precision_recall(target, prediction, low_confidence_undirected=False):
    true_labels = retrieve_adjacency_matrix(target)
    pred = retrieve_adjacency_matrix(prediction, target.nodes()
                                            if isinstance(target, nx.DiGraph) else None,
                                            weight=True)

    if low_confidence_undirected:
        # Take account of undirected edges by putting them with low confidence
        pred[pred==pred.transpose()] *= min(min(pred[np.nonzero(pred)])*.5, .1)
    precision, recall, _ = precision_recall_curve(
        true_labels.ravel(), pred.ravel())
    aupr = auc(recall, precision, reorder=True)

    return aupr, list(zip(precision, recall))

Response: r Compute precision - recall statistics for a set of target graphs and predictions.


Instruction:
Given the following Python 3 function, write the documentation
def SHD(target, pred, double_for_anticausal=True):
    true_labels = retrieve_adjacency_matrix(target)
    predictions = retrieve_adjacency_matrix(pred, target.nodes()
                                            if isinstance(target, nx.DiGraph) else None)

    diff = np.abs(true_labels - predictions)
    if double_for_anticausal:
        return np.sum(diff)
    else:
        diff = diff + diff.transpose()
        diff[diff > 1] = 1  # Ignoring the double edges.
        return np.sum(diff)/2

Response: r Compute the Structural Hamming Distance between two graphs.


Instruction:
Implement a Python 3 function for
computing the Strutural Intervention Distance for a given target and prediction.

Response:
def SID(target, pred):
    """Compute the Strutural Intervention Distance.

    [R wrapper] The Structural Intervention Distance (SID) is a new distance
    for graphs introduced by Peters and Bühlmann (2013). This distance was
    created to account for the shortcomings of the SHD metric for a causal
    sense.
    It consists in computing the path between all the pairs of variables, and
    checks if the causal relationship between the variables is respected.
    The given graphs have to be DAGs for the SID metric to make sense.

    Args:
        target (numpy.ndarray or networkx.DiGraph): Target graph, must be of
            ones and zeros, and instance of either numpy.ndarray or
            networkx.DiGraph. Must be a DAG.

        prediction (numpy.ndarray or networkx.DiGraph): Prediction made by the
            algorithm to evaluate. Must be a DAG.

    Returns:
        int: Structural Intervention Distance.

            The value tends to zero as the graphs tends to be identical.

    .. note::
        Ref: Structural Intervention Distance (SID) for Evaluating Causal Graphs,
        Jonas Peters, Peter Bühlmann: https://arxiv.org/abs/1306.1043

    Examples:
        >>> from numpy.random import randint
        >>> tar = np.triu(randint(2, size=(10, 10)))
        >>> pred = np.triu(randint(2, size=(10, 10)))
        >>> SID(tar, pred)
   """
    if not RPackages.SID:
        raise ImportError("SID R package is not available. Please check your installation.")

    true_labels = retrieve_adjacency_matrix(target)
    predictions = retrieve_adjacency_matrix(pred, target.nodes()
                                            if isinstance(target, nx.DiGraph) else None)

    os.makedirs('/tmp/cdt_SID/')

    def retrieve_result():
        return np.loadtxt('/tmp/cdt_SID/result.csv')

    try:
        np.savetxt('/tmp/cdt_SID/target.csv', true_labels, delimiter=',')
        np.savetxt('/tmp/cdt_SID/pred.csv', predictions, delimiter=',')
        sid_score = launch_R_script("{}/R_templates/sid.R".format(os.path.dirname(os.path.realpath(__file__))),
                                    {"{target}": '/tmp/cdt_SID/target.csv',
                                     "{prediction}": '/tmp/cdt_SID/pred.csv',
                                     "{result}": '/tmp/cdt_SID/result.csv'},
                                    output_function=retrieve_result)
    # Cleanup
    except Exception as e:
        rmtree('/tmp/cdt_SID')
        raise e
    except KeyboardInterrupt:
        rmtree('/tmp/cdt_SID/')
        raise KeyboardInterrupt

    rmtree('/tmp/cdt_SID')
    return sid_score


Instruction:
Write a Python 3 script to
create a networkx. DiGraph from the data produced by the CCDR algorithm.

Response:
def create_graph_from_data(self, data, **kwargs):
        """Apply causal discovery on observational data using CCDr.

        Args:
            data (pandas.DataFrame): DataFrame containing the data

        Returns:
            networkx.DiGraph: Solution given by the CCDR algorithm.
        """
        # Building setup w/ arguments.
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        results = self._run_ccdr(data, verbose=self.verbose)
        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})


Instruction:
Explain what the following Python 3 code does
def init_variables(self, verbose=False):
        for j in range(1, self.nodes):
            nb_parents = np.random.randint(0, min([self.parents_max, j])+1)
            for i in np.random.choice(range(0, j), nb_parents, replace=False):
                self.adjacency_matrix[i, j] = 1

        try:
            self.g = nx.DiGraph(self.adjacency_matrix)
            assert not list(nx.simple_cycles(self.g))

        except AssertionError:
            if verbose:
                print("Regenerating, graph non valid...")
            self.init_variables()

        # Mechanisms
        self.cfunctions = [self.mechanism(int(sum(self.adjacency_matrix[:, i])),
                                          self.points, self.noise, noise_coeff=self.noise_coeff)
                           if sum(self.adjacency_matrix[:, i])
                           else self.initial_generator for i in range(self.nodes)]

Response: Redefine the causes of the graph.


Instruction:
Write a Python 3 function for
generating data from an FCM containing cycles.

Response:
def generate(self, rescale=True):
        """Generate data from an FCM containing cycles."""
        if self.cfunctions is None:
            self.init_variables()

        for i in nx.topological_sort(self.g):
            # Root cause

            if not sum(self.adjacency_matrix[:, i]):
                self.data['V{}'.format(i)] = self.cfunctions[i](self.points)
            # Generating causes
            else:
                self.data['V{}'.format(i)] = self.cfunctions[i](self.data.iloc[:, self.adjacency_matrix[:, i].nonzero()[0]].values)
            if rescale:
                self.data['V{}'.format(i)] = scale(self.data['V{}'.format(i)].values)

        return self.g, self.data


Instruction:
Here you have a function in Python 3, explain what it does
def to_csv(self, fname_radical, **kwargs):
        if self.data is not None:
            self.data.to_csv(fname_radical+'_data.csv', index=False, **kwargs)
            pd.DataFrame(self.adjacency_matrix).to_csv(fname_radical \
                                                       + '_target.csv',
                                                       index=False, **kwargs)

        else:
            raise ValueError("Graph has not yet been generated. \
                              Use self.generate() to do so.")

Response: Saves data to the csv format by default in two separate files.


Instruction:
Make a summary of the following Python 3 code
def launch_R_script(template, arguments, output_function=None,
                    verbose=True, debug=False):
    """Launch an R script, starting from a template and replacing text in file
    before execution.

    Args:
        template (str): path to the template of the R script
        arguments (dict): Arguments that modify the template's placeholders
            with arguments
        output_function (function): Function to execute **after** the execution
            of the R script, and its output is returned by this function. Used
            traditionally as a function to retrieve the results of the
            execution.
        verbose (bool): Sets the verbosity of the R subprocess.
        debug (bool): If True, the generated scripts are not deleted.

    Return:
        Returns the output of the ``output_function`` if not `None`
        else `True` or `False` depending on whether the execution was
        successful.
    """
    id = str(uuid.uuid4())
    os.makedirs('/tmp/cdt_R_script_' + id + '/')
    try:
        scriptpath = '/tmp/cdt_R_script_' + id + '/instance_{}'.format(os.path.basename(template))
        copy(template, scriptpath)

        with fileinput.FileInput(scriptpath, inplace=True) as file:
            for line in file:
                mline = line
                for elt in arguments:
                    mline = mline.replace(elt, arguments[elt])
                print(mline, end='')

        if output_function is None:
            output = subprocess.call("Rscript --vanilla {}".format(scriptpath), shell=True,
                                     stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        else:
            if verbose:
                process = subprocess.Popen("Rscript --vanilla {}".format(scriptpath), shell=True)
            else:
                process = subprocess.Popen("Rscript --vanilla {}".format(scriptpath), shell=True,
                                           stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            process.wait()
            output = output_function()

    # Cleaning up
    except Exception as e:
        if not debug:
            rmtree('/tmp/cdt_R_script_' + id + '/')
        raise e
    except KeyboardInterrupt:
        if not debug:
            rmtree('/tmp/cdt_R_script_' + id + '/')
        raise KeyboardInterrupt
    if not debug:
        rmtree('/tmp/cdt_R_script_' + id + '/')
    return output

Response:
Launch an R script in a virtual machine and replacing text in file
racket with arguments.


Instruction:
Write a Python 3 script for
executing a subprocess to check the package s availability.

Response:
def check_R_package(self, package):
        """Execute a subprocess to check the package's availability.

        Args:
            package (str): Name of the package to be tested.

        Returns:
            bool: `True` if the package is available, `False` otherwise
        """
        test_package = not bool(launch_R_script("{}/R_templates/test_import.R".format(os.path.dirname(os.path.realpath(__file__))),                                      {"{package}": package}, verbose=True))
        return test_package


Instruction:
Write a Python 3 script for
binning variables w / normalization.

Response:
def bin_variable(var, bins='fd'):  # bin with normalization
    """Bin variables w/ normalization."""
    var = np.array(var).astype(np.float)
    var = (var - np.mean(var)) / np.std(var)
    var = np.digitize(var, np.histogram(var, bins=bins)[1])

    return var


Instruction:
Given the following Python 3 function, write the documentation
def predict(self, a, b, **kwargs):
        binning_alg = kwargs.get('bins', 'fd')
        return metrics.adjusted_mutual_info_score(bin_variable(a, bins=binning_alg),
                                                  bin_variable(b, bins=binning_alg))

Response: Perform the independence test.


Instruction:
Can you generate the documentation for the following Python 3 function
def predict(self, df_data, graph=None, **kwargs):
        if graph is None:
            return self.create_graph_from_data(df_data, **kwargs)
        elif isinstance(graph, nx.DiGraph):
            return self.orient_directed_graph(df_data, graph, **kwargs)
        elif isinstance(graph, nx.Graph):
            return self.orient_undirected_graph(df_data, graph, **kwargs)
        else:
            print('Unknown Graph type')
            raise ValueError

Response: Orient a causal graph using the method defined by the arguments.


Instruction:
Can you tell what is the following Python 3 function doing
def graph_evaluation(data, adj_matrix, gpu=None, gpu_id=0, **kwargs):
    gpu = SETTINGS.get_default(gpu=gpu)
    device = 'cuda:{}'.format(gpu_id) if gpu else 'cpu'
    obs = th.FloatTensor(data).to(device)
    cgnn = CGNN_model(adj_matrix, data.shape[0], gpu_id=gpu_id, **kwargs).to(device)
    cgnn.reset_parameters()
    return cgnn.run(obs, **kwargs)

Response: Evaluate a graph taking account of the hardware.


Instruction:
Make a summary of the following Python 3 code
def parallel_graph_evaluation(data, adj_matrix, nb_runs=16,
                              nb_jobs=None, **kwargs):
    """Parallelize the various runs of CGNN to evaluate a graph."""
    nb_jobs = SETTINGS.get_default(nb_jobs=nb_jobs)
    if nb_runs == 1:
        return graph_evaluation(data, adj_matrix, **kwargs)
    else:
        output = Parallel(n_jobs=nb_jobs)(delayed(graph_evaluation)(data, adj_matrix,
                                          idx=run, gpu_id=run % SETTINGS.GPU,
                                          **kwargs) for run in range(nb_runs))
        return np.mean(output)

Response: Parallelize the various runs of CGNN to evaluate a graph.


Instruction:
Explain what the following Python 3 code does
def hill_climbing(data, graph, **kwargs):
    nodelist = list(data.columns)
    data = scale(data.values).astype('float32')
    tested_candidates = [nx.adj_matrix(graph, nodelist=nodelist, weight=None)]
    best_score = parallel_graph_evaluation(data, tested_candidates[0].todense(), ** kwargs)
    best_candidate = graph
    can_improve = True
    while can_improve:
        can_improve = False
        for (i, j) in best_candidate.edges():
            test_graph = deepcopy(best_candidate)
            test_graph.add_edge(j, i, weight=test_graph[i][j]['weight'])
            test_graph.remove_edge(i, j)
            tadjmat = nx.adj_matrix(test_graph, nodelist=nodelist, weight=None)
            if (nx.is_directed_acyclic_graph(test_graph) and not any([(tadjmat != cand).nnz ==
                                                                      0 for cand in tested_candidates])):
                tested_candidates.append(tadjmat)
                score = parallel_graph_evaluation(data, tadjmat.todense(), **kwargs)
                if score < best_score:
                    can_improve = True
                    best_candidate = test_graph
                    best_score = score
                    break
    return best_candidate

Response: Hill Climbing optimization: a greedy exploration algorithm.


Instruction:
Create a Python 3 function for
generating according to the topological order of the graph.

Response:
def forward(self):
        """Generate according to the topological order of the graph."""
        self.noise.data.normal_()
        if not self.confounding:
            for i in self.topological_order:
                self.generated[i] = self.blocks[i](th.cat([v for c in [
                                                   [self.generated[j] for j in np.nonzero(self.adjacency_matrix[:, i])[0]],
                                                   [self.noise[:, [i]]]] for v in c], 1))
        else:
            for i in self.topological_order:
                self.generated[i] = self.blocks[i](th.cat([v for c in [
                                                   [self.generated[j] for j in np.nonzero(self.adjacency_matrix[:, i])[0]],
                                                   [self.corr_noise[min(i, j), max(i, j)] for j in np.nonzero(self.i_adj_matrix[:, i])[0]]
                                                   [self.noise[:, [i]]]] for v in c], 1))
        return th.cat(self.generated, 1)


Instruction:
How would you code a function in Python 3 to
run the CGNN on a given graph.

Response:
def run(self, data, train_epochs=1000, test_epochs=1000, verbose=None,
            idx=0, lr=0.01, **kwargs):
        """Run the CGNN on a given graph."""
        verbose = SETTINGS.get_default(verbose=verbose)
        optim = th.optim.Adam(self.parameters(), lr=lr)
        self.score.zero_()
        with trange(train_epochs + test_epochs, disable=not verbose) as t:
            for epoch in t:
                optim.zero_grad()
                generated_data = self.forward()
                mmd = self.criterion(generated_data, data)
                if not epoch % 200:
                    t.set_postfix(idx=idx, epoch=epoch, loss=mmd.item())
                mmd.backward()
                optim.step()
                if epoch >= test_epochs:
                    self.score.add_(mmd.data)

        return self.score.cpu().numpy() / test_epochs


Instruction:
Can you write a function in Python 3 where it
uses CGNN to create a graph from a pandas. DataFrame.

Response:
def create_graph_from_data(self, data):
        """Use CGNN to create a graph from scratch. All the possible structures
        are tested, which leads to a super exponential complexity. It would be
        preferable to start from a graph skeleton for large graphs.

        Args:
            data (pandas.DataFrame): Observational data on which causal
               discovery has to be performed.
        Returns:
            networkx.DiGraph: Solution given by CGNN.

        """
        warnings.warn("An exhaustive search of the causal structure of CGNN without"
                      " skeleton is super-exponential in the number of variables.")

        # Building all possible candidates:
        nb_vars = len(list(data.columns))
        data = scale(data.values).astype('float32')

        candidates = [np.reshape(np.array(i), (nb_vars, nb_vars)) for i in itertools.product([0, 1], repeat=nb_vars*nb_vars)
                      if (np.trace(np.reshape(np.array(i), (nb_vars, nb_vars))) == 0
                          and nx.is_directed_acyclic_graph(nx.DiGraph(np.reshape(np.array(i), (nb_vars, nb_vars)))))]

        warnings.warn("A total of {} graphs will be evaluated.".format(len(candidates)))
        scores = [parallel_graph_evaluation(data, i, nh=self.nh, nb_runs=self.nb_runs, gpu=self.gpu,
                                            nb_jobs=self.nb_jobs, lr=self.lr, train_epochs=self.train_epochs,
                                            test_epochs=self.test_epochs, verbose=self.verbose) for i in candidates]
        final_candidate = candidates[scores.index(min(scores))]
        output = np.zeros(final_candidate.shape)

        # Retrieve the confidence score on each edge.
        for (i, j), x in np.ndenumerate(final_candidate):
            if x > 0:
                cand = final_candidate
                cand[i, j] = 0
                output[i, j] = min(scores) - scores[candidates.index(cand)]

        return nx.DiGraph(candidates[output],
                          {idx: i for idx, i in enumerate(data.columns)})


Instruction:
How would you code a function in Python 3 to
modify and improve a directed acyclic graph solution using CGNN.

Response:
def orient_directed_graph(self, data, dag, alg='HC'):
        """Modify and improve a directed acyclic graph solution using CGNN.

        Args:
            data (pandas.DataFrame): Observational data on which causal
               discovery has to be performed.
            dag (nx.DiGraph): Graph that provides the initial solution,
               on which the CGNN algorithm will be applied.
            alg (str): Exploration heuristic to use, among ["HC", "HCr",
               "tabu", "EHC"]
        Returns:
            networkx.DiGraph: Solution given by CGNN.

        """
        alg_dic = {'HC': hill_climbing, 'HCr': hill_climbing_with_removal,
                   'tabu': tabu_search, 'EHC': exploratory_hill_climbing}

        return alg_dic[alg](data, dag, nh=self.nh, nb_runs=self.nb_runs, gpu=self.gpu,
                            nb_jobs=self.nb_jobs, lr=self.lr, train_epochs=self.train_epochs,
                            test_epochs=self.test_epochs, verbose=self.verbose)


Instruction:
Make a summary of the following Python 3 code
def orient_undirected_graph(self, data, umg, alg='HC'):
        warnings.warn("The pairwise GNN model is computed on each edge of the UMG "
                      "to initialize the model and start CGNN with a DAG")
        gnn = GNN(nh=self.nh, lr=self.lr)

        og = gnn.orient_graph(data, umg, nb_runs=self.nb_runs, nb_max_runs=self.nb_runs,
                              nb_jobs=self.nb_jobs, train_epochs=self.train_epochs,
                              test_epochs=self.test_epochs, verbose=self.verbose, gpu=self.gpu)  # Pairwise method
        # print(nx.adj_matrix(og).todense().shape)
        # print(list(og.edges()))
        dag = dagify_min_edge(og)
        # print(nx.adj_matrix(dag).todense().shape)

        return self.orient_directed_graph(data, dag, alg=alg)

Response: Orient the undirected graph using GNN and apply CGNN to improve the graph.


Instruction:
Create a Python 3 function for
evaluating the entropy of the input variable.

Response:
def eval_entropy(x):
    """Evaluate the entropy of the input variable.

    :param x: input variable 1D
    :return: entropy of x
    """
    hx = 0.
    sx = sorted(x)
    for i, j in zip(sx[:-1], sx[1:]):
        delta = j-i
        if bool(delta):
            hx += np.log(np.abs(delta))
    hx = hx / (len(x) - 1) + psi(len(x)) - psi(1)

    return hx


Instruction:
Can you tell what is the following Python 3 function doing
def integral_approx_estimator(x, y):
    a, b = (0., 0.)
    x = np.array(x)
    y = np.array(y)
    idx, idy = (np.argsort(x), np.argsort(y))

    for x1, x2, y1, y2 in zip(x[[idx]][:-1], x[[idx]][1:], y[[idx]][:-1], y[[idx]][1:]):
        if x1 != x2 and y1 != y2:
            a = a + np.log(np.abs((y2 - y1) / (x2 - x1)))

    for x1, x2, y1, y2 in zip(x[[idy]][:-1], x[[idy]][1:], y[[idy]][:-1], y[[idy]][1:]):
        if x1 != x2 and y1 != y2:
            b = b + np.log(np.abs((x2 - x1) / (y2 - y1)))

    return (a - b)/len(x)

Response: Integral approximation estimator for causal inference.


Instruction:
Create a Python 3 function to
evaluate a pair using the IGCI model.

Response:
def predict_proba(self, a, b, **kwargs):
        """Evaluate a pair using the IGCI model.

        :param a: Input variable 1D
        :param b: Input variable 1D
        :param kwargs: {refMeasure: Scaling method (gaussian, integral or None),
                        estimator: method used to evaluate the pairs (entropy or integral)}
        :return: Return value of the IGCI model >0 if a->b otherwise if return <0
        """
        estimators = {'entropy': lambda x, y: eval_entropy(y) - eval_entropy(x), 'integral': integral_approx_estimator}
        ref_measures = {'gaussian': lambda x: standard_scale.fit_transform(x.reshape((-1, 1))),
                        'uniform': lambda x: min_max_scale.fit_transform(x.reshape((-1, 1))), 'None': lambda x: x}

        ref_measure = ref_measures[kwargs.get('refMeasure', 'gaussian')]
        estimator = estimators[kwargs.get('estimator', 'entropy')]

        a = ref_measure(a)
        b = ref_measure(b)

        return estimator(a, b)


Instruction:
How would you explain what the following Python 3 function does
def featurize_row(self, x, y):
        x = x.ravel()
        y = y.ravel()
        b = np.ones(x.shape)
        dx = np.cos(np.dot(self.W2, np.vstack((x, b)))).mean(1)
        dy = np.cos(np.dot(self.W2, np.vstack((y, b)))).mean(1)
        if(sum(dx) > sum(dy)):
            return np.hstack((dx, dy,
                              np.cos(np.dot(self.W, np.vstack((x, y, b)))).mean(1)))
        else:
            return np.hstack((dx, dy,
                              np.cos(np.dot(self.W, np.vstack((y, x, b)))).mean(1)))

Response: This function projects the causal pair to the RKHS using the sampled kernel approximation.


Instruction:
Explain what the following Python 3 code does
def fit(self, x, y):
        train = np.vstack((np.array([self.featurize_row(row.iloc[0],
                                                        row.iloc[1]) for idx, row in x.iterrows()]),
                           np.array([self.featurize_row(row.iloc[1],
                                                        row.iloc[0]) for idx, row in x.iterrows()])))
        labels = np.vstack((y, -y)).ravel()
        verbose = 1 if self.verbose else 0
        self.clf = CLF(verbose=verbose,
                       min_samples_leaf=self.L,
                       n_estimators=self.E,
                       max_depth=self.max_depth,
                       n_jobs=self.n_jobs).fit(train, labels)

Response:
Train the model.

        Args:
            x_tr (pd.DataFrame): CEPC format dataframe containing the pairs
            y_tr (pd.DataFrame or np.ndarray): labels associated to the pairs


Instruction:
Can you generate the documentation for the following Python 3 function
def predict_proba(self, x, y=None, **kwargs):
        if self.clf is None:
            raise ValueError("Model has to be trained before making predictions.")
        if x is pandas.Series:
            input_ = self.featurize_row(x.iloc[0], x.iloc[1]).reshape((1, -1))
        elif x is pandas.DataFrame:
            input_ = np.array([self.featurize_row(x.iloc[0], x.iloc[1]) for row in x])
        elif y is not None:
            input_ = self.featurize_row(x, y).reshape((1, -1))
        else:
            raise TypeError("DataType not understood.")
        return self.clf.predict(input_)

Response: Predict the causal score using a trained RCC model.


Instruction:
How would you explain what the following Python 3 function does
def predict_features(self, df_features, df_target, nh=20, idx=0, dropout=0.,
                         activation_function=th.nn.ReLU, lr=0.01, l1=0.1,  batch_size=-1,
                         train_epochs=1000, test_epochs=1000, device=None,
                         verbose=None, nb_runs=3):
        """For one variable, predict its neighbours.

        Args:
            df_features (pandas.DataFrame):
            df_target (pandas.Series):
            nh (int): number of hidden units
            idx (int): (optional) for printing purposes
            dropout (float): probability of dropout (between 0 and 1)
            activation_function (torch.nn.Module): activation function of the NN
            lr (float): learning rate of Adam
            l1 (float): L1 penalization coefficient
            batch_size (int): batch size, defaults to full-batch
            train_epochs (int): number of train epochs
            test_epochs (int): number of test epochs
            device (str): cuda or cpu device (defaults to ``cdt.SETTINGS.default_device``)
            verbose (bool): verbosity (defaults to ``cdt.SETTINGS.verbose``)
            nb_runs (int): number of bootstrap runs

        Returns:
            list: scores of each feature relatively to the target

        """
        device, verbose = SETTINGS.get_default(('device', device), ('verbose', verbose))
        x = th.FloatTensor(scale(df_features.values)).to(device)
        y = th.FloatTensor(scale(df_target.values)).to(device)
        out = []
        for i in range(nb_runs):
            model = FSGNN_model([x.size()[1] + 1, nh, 1],
                                dropout=dropout,
                                activation_function=activation_function).to(device)

            out.append(model.train(x, y, lr=0.01, l1=0.1, batch_size=-1,
                                   train_epochs=train_epochs, test_epochs=test_epochs,
                                   device=device, verbose=verbose))
        return list(np.mean(np.array(out), axis=0))

Response: For one variable predict features and target.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def predict_undirected_graph(self, data):
        graph = Graph()

        for idx_i, i in enumerate(data.columns):
            for idx_j, j in enumerate(data.columns[idx_i+1:]):
                score = self.predict(data[i].values, data[j].values)
                if abs(score) > 0.001:
                    graph.add_edge(i, j, weight=score)

        return graph

Response: Predict a skeleton using a pairwise independence criterion.


Instruction:
Write a Python 3 function that can
wrap around self. predict_features to predict the features relatively to the target variable.

Response:
def run_feature_selection(self, df_data, target, idx=0, **kwargs):
        """Run feature selection for one node: wrapper around
        ``self.predict_features``.

        Args:
            df_data (pandas.DataFrame): All the observational data
            target (str): Name of the target variable
            idx (int): (optional) For printing purposes

        Returns:
            list: scores of each feature relatively to the target
        """
        list_features = list(df_data.columns.values)
        list_features.remove(target)
        df_target = pd.DataFrame(df_data[target], columns=[target])
        df_features = df_data[list_features]

        return self.predict_features(df_features, df_target, idx=idx, **kwargs)


Instruction:
Can you write a function in Python 3 where it
predicts the skeleton of the graph from the raw data.

Response:
def predict(self, df_data, threshold=0.05, **kwargs):
        """Predict the skeleton of the graph from raw data.

        Returns iteratively the feature selection algorithm on each node.

        Args:
            df_data (pandas.DataFrame): data to construct a graph from
            threshold (float): cutoff value for feature selection scores
            kwargs (dict): additional arguments for algorithms

        Returns:
            networkx.Graph: predicted skeleton of the graph.
        """
        nb_jobs = kwargs.get("nb_jobs", SETTINGS.NB_JOBS)
        list_nodes = list(df_data.columns.values)
        if nb_jobs != 1:
            result_feature_selection = Parallel(n_jobs=nb_jobs)(delayed(self.run_feature_selection)
                                                                (df_data, node, idx, **kwargs)
                                                                for idx, node in enumerate(list_nodes))
        else:
            result_feature_selection = [self.run_feature_selection(df_data, node, idx, **kwargs) for idx, node in enumerate(list_nodes)]
        for idx, i in enumerate(result_feature_selection):
            try:
                i.insert(idx, 0)
            except AttributeError:  # if results are numpy arrays
                result_feature_selection[idx] = np.insert(i, idx, 0)
        matrix_results = np.array(result_feature_selection)
        matrix_results *= matrix_results.transpose()
        np.fill_diagonal(matrix_results, 0)
        matrix_results /= 2

        graph = nx.Graph()

        for (i, j), x in np.ndenumerate(matrix_results):
            if matrix_results[i, j] > threshold:
                graph.add_edge(list_nodes[i], list_nodes[j],
                               weight=matrix_results[i, j])
        for node in list_nodes:
            if node not in graph.nodes():
                graph.add_node(node)
        return graph


Instruction:
Implement a function in Python 3 to
run GIES on an undirected graph.

Response:
def orient_undirected_graph(self, data, graph):
        """Run GIES on an undirected graph.

        Args:
            data (pandas.DataFrame): DataFrame containing the data
            graph (networkx.Graph): Skeleton of the graph to orient

        Returns:
            networkx.DiGraph: Solution given by the GIES algorithm.

        """
        # Building setup w/ arguments.
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        self.arguments['{SCORE}'] = self.scores[self.score]

        fe = DataFrame(nx.adj_matrix(graph, weight=None).todense())
        fg = DataFrame(1 - fe.values)

        results = self._run_gies(data, fixedGaps=fg, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})


Instruction:
Can you tell what is the following Python 3 function doing
def create_graph_from_data(self, data):
        # Building setup w/ arguments.
        self.arguments['{SCORE}'] = self.scores[self.score]
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()

        results = self._run_gies(data, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

Response: Run the GIES algorithm and return a networkx. DiGraph with the results.


Instruction:
How would you explain what the following Python 3 function does
def _run_gies(self, data, fixedGaps=None, verbose=True):
        # Run gies
        id = str(uuid.uuid4())
        os.makedirs('/tmp/cdt_gies' + id + '/')
        self.arguments['{FOLDER}'] = '/tmp/cdt_gies' + id + '/'

        def retrieve_result():
            return read_csv('/tmp/cdt_gies' + id + '/result.csv', delimiter=',').values

        try:
            data.to_csv('/tmp/cdt_gies' + id + '/data.csv', header=False, index=False)
            if fixedGaps is not None:
                fixedGaps.to_csv('/tmp/cdt_gies' + id + '/fixedgaps.csv', index=False, header=False)
                self.arguments['{SKELETON}'] = 'TRUE'
            else:
                self.arguments['{SKELETON}'] = 'FALSE'

            gies_result = launch_R_script("{}/R_templates/gies.R".format(os.path.dirname(os.path.realpath(__file__))),
                                          self.arguments, output_function=retrieve_result, verbose=verbose)
        # Cleanup
        except Exception as e:
            rmtree('/tmp/cdt_gies' + id + '')
            raise e
        except KeyboardInterrupt:
            rmtree('/tmp/cdt_gies' + id + '/')
            raise KeyboardInterrupt
        rmtree('/tmp/cdt_gies' + id + '')
        return gies_result

Response: Run GIES with all arguments.


Instruction:
Write a Python 3 function for
plotting SAM's various losses.

Response:
def plot_curves(i_batch, adv_loss, gen_loss, l1_reg, cols):
    """Plot SAM's various losses."""
    from matplotlib import pyplot as plt
    if i_batch == 0:
        try:
            ax.clear()
            ax.plot(range(len(adv_plt)), adv_plt, "r-",
                    linewidth=1.5, markersize=4,
                    label="Discriminator")
            ax.plot(range(len(adv_plt)), gen_plt, "g-", linewidth=1.5,
                    markersize=4, label="Generators")
            ax.plot(range(len(adv_plt)), l1_plt, "b-",
                    linewidth=1.5, markersize=4,
                    label="L1-Regularization")
            plt.legend()

            adv_plt.append(adv_loss.cpu().data[0])
            gen_plt.append(gen_loss.cpu().data[0] / cols)
            l1_plt.append(l1_reg.cpu().data[0])

            plt.pause(0.0001)

        except NameError:
            plt.ion()
            fig, ax = plt.figure()
            plt.xlabel("Epoch")
            plt.ylabel("Losses")

            plt.pause(0.0001)

            adv_plt = [adv_loss.cpu().data[0]]
            gen_plt = [gen_loss.cpu().data[0] / cols]
            l1_plt = [l1_reg.cpu().data[0]]

    else:
        adv_plt.append(adv_loss.cpu().data[0])
        gen_plt.append(gen_loss.cpu().data[0] / cols)
        l1_plt.append(l1_reg.cpu().data[0])


Instruction:
How would you explain what the following Python 3 function does
def plot_gen(epoch, batch, generated_variables, pairs_to_plot=[[0, 1]]):
    from matplotlib import pyplot as plt
    if epoch == 0:
        plt.ion()
    plt.clf()
    for (i, j) in pairs_to_plot:

        plt.scatter(generated_variables[i].data.cpu().numpy(
        ), batch.data.cpu().numpy()[:, j], label="Y -> X")
        plt.scatter(batch.data.cpu().numpy()[
            :, i], generated_variables[j].data.cpu().numpy(), label="X -> Y")

        plt.scatter(batch.data.cpu().numpy()[:, i], batch.data.cpu().numpy()[
            :, j], label="original data")
        plt.legend()

    plt.pause(0.01)

Response: Plot generated pairs of variables.


Instruction:
Make a summary of the following Python 3 code
def run_SAM(df_data, skeleton=None, **kwargs):
    gpu = kwargs.get('gpu', False)
    gpu_no = kwargs.get('gpu_no', 0)

    train_epochs = kwargs.get('train_epochs', 1000)
    test_epochs = kwargs.get('test_epochs', 1000)
    batch_size = kwargs.get('batch_size', -1)

    lr_gen = kwargs.get('lr_gen', 0.1)
    lr_disc = kwargs.get('lr_disc', lr_gen)
    verbose = kwargs.get('verbose', True)
    regul_param = kwargs.get('regul_param', 0.1)
    dnh = kwargs.get('dnh', None)
    plot = kwargs.get("plot", False)
    plot_generated_pair = kwargs.get("plot_generated_pair", False)

    d_str = "Epoch: {} -- Disc: {} -- Gen: {} -- L1: {}"
    try:
        list_nodes = list(df_data.columns)
        df_data = (df_data[list_nodes]).values
    except AttributeError:
        list_nodes = list(range(df_data.shape[1]))
    data = df_data.astype('float32')
    data = th.from_numpy(data)
    if batch_size == -1:
        batch_size = data.shape[0]
    rows, cols = data.size()

    # Get the list of indexes to ignore
    if skeleton is not None:
        zero_components = [[] for i in range(cols)]
        skel = nx.adj_matrix(skeleton, weight=None)
        for i, j in zip(*((1-skel).nonzero())):
            zero_components[j].append(i)
    else:
        zero_components = [[i] for i in range(cols)]
    sam = SAM_generators((rows, cols), zero_components, batch_norm=True, **kwargs)

    # Begin UGLY
    activation_function = kwargs.get('activation_function', th.nn.Tanh)
    try:
        del kwargs["activation_function"]
    except KeyError:
        pass
    discriminator_sam = SAM_discriminator(
        [cols, dnh, dnh, 1], batch_norm=True,
        activation_function=th.nn.LeakyReLU,
        activation_argument=0.2, **kwargs)
    kwargs["activation_function"] = activation_function
    # End of UGLY

    if gpu:
        sam = sam.cuda(gpu_no)
        discriminator_sam = discriminator_sam.cuda(gpu_no)
        data = data.cuda(gpu_no)

    # Select parameters to optimize : ignore the non connected nodes
    criterion = th.nn.BCEWithLogitsLoss()
    g_optimizer = th.optim.Adam(sam.parameters(), lr=lr_gen)
    d_optimizer = th.optim.Adam(
        discriminator_sam.parameters(), lr=lr_disc)

    true_variable = Variable(
        th.ones(batch_size, 1), requires_grad=False)
    false_variable = Variable(
        th.zeros(batch_size, 1), requires_grad=False)
    causal_filters = th.zeros(data.shape[1], data.shape[1])

    if gpu:
        true_variable = true_variable.cuda(gpu_no)
        false_variable = false_variable.cuda(gpu_no)
        causal_filters = causal_filters.cuda(gpu_no)

    data_iterator = DataLoader(data, batch_size=batch_size, shuffle=True)

    # TRAIN
    for epoch in range(train_epochs + test_epochs):
        for i_batch, batch in enumerate(data_iterator):
            batch = Variable(batch)
            batch_vectors = [batch[:, [i]] for i in range(cols)]

            g_optimizer.zero_grad()
            d_optimizer.zero_grad()

            # Train the discriminator
            generated_variables = sam(batch)
            disc_losses = []
            gen_losses = []

            for i in range(cols):
                generator_output = th.cat([v for c in [batch_vectors[: i], [
                    generated_variables[i]],
                    batch_vectors[i + 1:]] for v in c], 1)
                # 1. Train discriminator on fake
                disc_output_detached = discriminator_sam(
                    generator_output.detach())
                disc_output = discriminator_sam(generator_output)
                disc_losses.append(
                    criterion(disc_output_detached, false_variable))

                # 2. Train the generator :
                gen_losses.append(criterion(disc_output, true_variable))

            true_output = discriminator_sam(batch)
            adv_loss = sum(disc_losses)/cols + \
                criterion(true_output, true_variable)
            gen_loss = sum(gen_losses)

            adv_loss.backward()
            d_optimizer.step()

            # 3. Compute filter regularization
            filters = th.stack(
                [i.fs_filter[0, :-1].abs() for i in sam.blocks], 1)
            l1_reg = regul_param * filters.sum()
            loss = gen_loss + l1_reg

            if verbose and epoch % 200 == 0 and i_batch == 0:

                print(str(i) + " " + d_str.format(epoch,
                                                  adv_loss.item(),
                                                  gen_loss.item() / cols,
                                                  l1_reg.item()))
            loss.backward()

            # STORE ASSYMETRY values for output
            if epoch > train_epochs:
                causal_filters.add_(filters.data)
            g_optimizer.step()

            if plot:
                plot_curves(i_batch, adv_loss, gen_loss, l1_reg, cols)

            if plot_generated_pair and epoch % 200 == 0:
                plot_gen(epoch, batch, generated_variables)

    return causal_filters.div_(test_epochs).cpu().numpy()

Response: Execute the SAM model.


Instruction:
Given the following Python 3 function, write the documentation
def reset_parameters(self):
        stdv = 1. / math.sqrt(self.weight.size(1))
        self.weight.data.uniform_(-stdv, stdv)
        if self.bias is not None:
            self.bias.data.uniform_(-stdv, stdv)

Response: Reset the parameters of the class.


Instruction:
How would you explain what the following Python 3 function does
def forward(self, input):
        return th.nn.functional.linear(input, self.weight.div(self.weight.pow(2).sum(0).sqrt()))

Response: Feed - forward through the network.


Instruction:
Can you generate the documentation for the following Python 3 function
def forward(self, x):
        return self.layers(x * (self._filter *
                                self.fs_filter).expand_as(x))

Response: Feed - forward the model.


Instruction:
Implement a Python 3 function for
feeding - forward the model.

Response:
def forward(self, x):
        """Feed-forward the model."""
        for i in self.noise:
            i.data.normal_()

        self.generated_variables = [self.blocks[i](
            th.cat([x, self.noise[i]], 1)) for i in range(self.cols)]
        return self.generated_variables


Instruction:
Create a Python 3 function for
executing SAM on a dataset given a skeleton or not.

Response:
def predict(self, data, graph=None, nruns=6, njobs=None, gpus=0, verbose=None,
                plot=False, plot_generated_pair=False, return_list_results=False):
        """Execute SAM on a dataset given a skeleton or not.

        Args:
            data (pandas.DataFrame): Observational data for estimation of causal relationships by SAM
            skeleton (numpy.ndarray): A priori knowledge about the causal relationships as an adjacency matrix.
                      Can be fed either directed or undirected links.
            nruns (int): Number of runs to be made for causal estimation.
                   Recommended: >=12 for optimal performance.
            njobs (int): Numbers of jobs to be run in Parallel.
                   Recommended: 1 if no GPU available, 2*number of GPUs else.
            gpus (int): Number of available GPUs for the algorithm.
            verbose (bool): verbose mode
            plot (bool): Plot losses interactively. Not recommended if nruns>1
            plot_generated_pair (bool): plots a generated pair interactively.  Not recommended if nruns>1
        Returns:
            networkx.DiGraph: Graph estimated by SAM, where A[i,j] is the term
            of the ith variable for the jth generator.
        """
        verbose, njobs = SETTINGS.get_default(('verbose', verbose), ('nb_jobs', njobs))
        if njobs != 1:
            list_out = Parallel(n_jobs=njobs)(delayed(run_SAM)(data,
                                                               skeleton=graph,
                                                               lr_gen=self.lr, lr_disc=self.dlr,
                                                               regul_param=self.l1, nh=self.nh, dnh=self.dnh,
                                                               gpu=bool(gpus), train_epochs=self.train,
                                                               test_epochs=self.test, batch_size=self.batchsize,
                                                               plot=plot, verbose=verbose, gpu_no=idx % max(gpus, 1))
                                              for idx in range(nruns))
        else:
            list_out = [run_SAM(data, skeleton=graph,
                                lr_gen=self.lr, lr_disc=self.dlr,
                                regul_param=self.l1, nh=self.nh, dnh=self.dnh,
                                gpu=bool(gpus), train_epochs=self.train,
                                test_epochs=self.test, batch_size=self.batchsize,
                                plot=plot, verbose=verbose, gpu_no=0)
                        for idx in range(nruns)]
        if return_list_results:
            return list_out
        else:
            W = list_out[0]
            for w in list_out[1:]:
                W += w
            W /= nruns
        return nx.relabel_nodes(nx.DiGraph(W), {idx: i for idx, i in enumerate(data.columns)})


Instruction:
Write a Python 3 script to
infer causal relationships between two variables using the RECI statistic

Response:
def predict_proba(self, a, b, **kwargs):
        """ Infer causal relationships between 2 variables using the RECI statistic

        :param a: Input variable 1
        :param b: Input variable 2
        :return: Causation coefficient (Value : 1 if a->b and -1 if b->a)
        :rtype: float
        """
        return self.b_fit_score(b, a) - self.b_fit_score(a, b)


Instruction:
How would you explain what the following Python 3 function does
def b_fit_score(self, x, y):
        x = np.reshape(minmax_scale(x), (-1, 1))
        y = np.reshape(minmax_scale(y), (-1, 1))
        poly = PolynomialFeatures(degree=self.degree)
        poly_x = poly.fit_transform(x)

        poly_x[:,1] = 0
        poly_x[:,2] = 0

        regressor = LinearRegression()
        regressor.fit(poly_x, y)

        y_predict = regressor.predict(poly_x)
        error = mean_squared_error(y_predict, y)

        return error

Response: Compute the RECI fit score for a specific set of items.


Instruction:
Here you have a function in Python 3, explain what it does
def predict_proba(self, a, b, **kwargs):
        return self.cds_score(b, a) - self.cds_score(a, b)

Response: Infer causal relationships between two variables using the CDS statistic


Instruction:
Create a Python 3 function to
compute the cds fit score from variable 1 to variable 2.

Response:
def cds_score(self, x_te, y_te):
        """ Computes the cds statistic from variable 1 to variable 2

        Args:
            x_te (numpy.ndarray): Variable 1
            y_te (numpy.ndarray): Variable 2

        Returns:
            float: CDS fit score
        """
        if type(x_te) == np.ndarray:
            x_te, y_te = pd.Series(x_te.reshape(-1)), pd.Series(y_te.reshape(-1))
        xd, yd = discretized_sequences(x_te,  y_te,  self.ffactor, self.maxdev)
        cx = Counter(xd)
        cy = Counter(yd)
        yrange = sorted(cy.keys())
        ny = len(yrange)
        py = np.array([cy[i] for i in yrange], dtype=float)
        py = py / py.sum()
        pyx = []
        for a in cx:
            if cx[a] > self.minc:
                yx = y_te[xd == a]
                # if not numerical(ty):
                #     cyx = Counter(yx)
                #     pyxa = np.array([cyx[i] for i in yrange], dtype=float)
                #     pyxa.sort()
                if count_unique(y_te) > len_discretized_values(y_te, "Numerical", self.ffactor, self.maxdev):

                    yx = (yx - np.mean(yx)) / np.std(y_te)
                    yx = discretized_sequence(yx, "Numerical", self.ffactor, self.maxdev, norm=False)
                    cyx = Counter(yx.astype(int))
                    pyxa = np.array([cyx[i] for i in discretized_values(y_te, "Numerical", self.ffactor, self.maxdev)],
                                    dtype=float)

                else:
                    cyx = Counter(yx)
                    pyxa = [cyx[i] for i in yrange]
                    pyxax = np.array([0] * (ny - 1) + pyxa + [0] * (ny - 1), dtype=float)
                    xcorr = [sum(py * pyxax[i:i + ny]) for i in range(2 * ny - 1)]
                    imax = xcorr.index(max(xcorr))
                    pyxa = np.array([0] * (2 * ny - 2 - imax) + pyxa + [0] * imax, dtype=float)
                assert pyxa.sum() == cx[a]
                pyxa = pyxa / pyxa.sum()

                pyx.append(pyxa)

        if len(pyx) == 0:
            return 0

        pyx = np.array(pyx)
        pyx = pyx - pyx.mean(axis=0)
        return np.std(pyx)


Instruction:
Make a summary of the following Python 3 code
def predict_proba(self, a, b, **kwargs):
        a = scale(a).reshape((-1, 1))
        b = scale(b).reshape((-1, 1))

        return self.anm_score(b, a) - self.anm_score(a, b)

Response: Predicts the probability of a pair of causal income.


Instruction:
Explain what the following Python 3 code does
def anm_score(self, x, y):
        gp = GaussianProcessRegressor().fit(x, y)
        y_predict = gp.predict(x)
        indepscore = normalized_hsic(y_predict - y, x)

        return indepscore

Response: Compute the fitness score of the ANM model in the x - direction y - direction


Instruction:
How would you explain what the following Python 3 function does
def orient_undirected_graph(self, data, graph, **kwargs):
        # Building setup w/ arguments.
        self.arguments['{CITEST}'] = self.dir_CI_test[self.CI_test]
        self.arguments['{METHOD_INDEP}'] = self.dir_method_indep[self.method_indep]
        self.arguments['{DIRECTED}'] = 'TRUE'
        self.arguments['{ALPHA}'] = str(self.alpha)
        self.arguments['{NJOBS}'] = str(self.nb_jobs)
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()

        fe = DataFrame(nx.adj_matrix(graph, weight=None).todense())
        fg = DataFrame(1 - fe.values)

        results = self._run_pc(data, fixedEdges=fe, fixedGaps=fg, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

Response: Run PC on an undirected graph.


Instruction:
Create a Python 3 function for
running the PC algorithm and return a networkx. DiGraph that represents the solution given by PC on the given data.

Response:
def create_graph_from_data(self, data, **kwargs):
        """Run the PC algorithm.

        Args:
            data (pandas.DataFrame): DataFrame containing the data

        Returns:
            networkx.DiGraph: Solution given by PC on the given data.
       """
        # Building setup w/ arguments.
        self.arguments['{CITEST}'] = self.dir_CI_test[self.CI_test]
        self.arguments['{METHOD_INDEP}'] = self.dir_method_indep[self.method_indep]
        self.arguments['{DIRECTED}'] = 'TRUE'
        self.arguments['{ALPHA}'] = str(self.alpha)
        self.arguments['{NJOBS}'] = str(self.nb_jobs)
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()

        results = self._run_pc(data, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})


Instruction:
Explain what the following Python 3 code does
def _run_pc(self, data, fixedEdges=None, fixedGaps=None, verbose=True):
        # Checking coherence of arguments
        # print(self.arguments)
        if (self.arguments['{CITEST}'] == self.dir_CI_test['hsic']
           and self.arguments['{METHOD_INDEP}'] == self.dir_method_indep['corr']):
            warnings.warn('Selected method for indep is unfit for the hsic test,'
                          ' setting the hsic.gamma method.')
            self.arguments['{METHOD_INDEP}'] = self.dir_method_indep['hsic_gamma']

        elif (self.arguments['{CITEST}'] == self.dir_CI_test['gaussian']
              and self.arguments['{METHOD_INDEP}'] != self.dir_method_indep['corr']):
            warnings.warn('Selected method for indep is unfit for the selected test,'
                          ' setting the classic correlation-based method.')
            self.arguments['{METHOD_INDEP}'] = self.dir_method_indep['corr']

        # Run PC
        id = str(uuid.uuid4())
        os.makedirs('/tmp/cdt_pc' + id + '/')
        self.arguments['{FOLDER}'] = '/tmp/cdt_pc' + id + '/'

        def retrieve_result():
            return read_csv('/tmp/cdt_pc' + id + '/result.csv', delimiter=',').values

        try:
            data.to_csv('/tmp/cdt_pc' + id + '/data.csv', header=False, index=False)
            if fixedGaps is not None and fixedEdges is not None:
                fixedGaps.to_csv('/tmp/cdt_pc' + id + '/fixedgaps.csv', index=False, header=False)
                fixedEdges.to_csv('/tmp/cdt_pc' + id + '/fixededges.csv', index=False, header=False)
                self.arguments['{SKELETON}'] = 'TRUE'
            else:
                self.arguments['{SKELETON}'] = 'FALSE'

            pc_result = launch_R_script("{}/R_templates/pc.R".format(os.path.dirname(os.path.realpath(__file__))),
                                        self.arguments, output_function=retrieve_result, verbose=verbose)
        # Cleanup
        except Exception as e:
            rmtree('/tmp/cdt_pc' + id + '')
            raise e
        except KeyboardInterrupt:
            rmtree('/tmp/cdt_pc' + id + '/')
            raise KeyboardInterrupt
        rmtree('/tmp/cdt_pc' + id + '')
        return pc_result

Response: Run the PC with all arguments.


Instruction:
Can you generate the documentation for the following Python 3 function
def b_fit_score(self, x, y):
        x = np.reshape(scale(x), (-1, 1))
        y = np.reshape(scale(y), (-1, 1))
        gp = GaussianProcessRegressor().fit(x, y)
        y_predict = gp.predict(x)
        error = mean_squared_error(y_predict, y)

        return error

Response: Computes the BF fit score for cds in the kernel.


Instruction:
Given the following Python 3 function, write the documentation
def predict(self, data, alpha=0.01, max_iter=2000, **kwargs):
        edge_model = GraphLasso(alpha=alpha, max_iter=max_iter)
        edge_model.fit(data.values)

        return nx.relabel_nodes(nx.DiGraph(edge_model.get_precision()),
                                {idx: i for idx, i in enumerate(data.columns)})

Response: Predict the graph skeleton.


Instruction:
Here you have a function in Python 3, explain what it does
def predict_features(self, df_features, df_target, idx=0, **kwargs):

        y = np.transpose(df_target.values)
        X = np.transpose(df_features.values)

        path, beta, A, lam = hsiclasso(X, y)

        return beta

Response: For one variable predict its neighbouring nodes.


Instruction:
How would you code a function in Python 3 to
set the variable GPU and NB_JOBS to the number of CUDA devices.

Response:
def autoset_settings(set_var):
    """Autoset GPU parameters using CUDA_VISIBLE_DEVICES variables.

    Return default config if variable not set.
    :param set_var: Variable to set. Must be of type ConfigSettings
    """
    try:
        devices = ast.literal_eval(os.environ["CUDA_VISIBLE_DEVICES"])
        if type(devices) != list and type(devices) != tuple:
            devices = [devices]
        if len(devices) != 0:
            set_var.GPU = len(devices)
            set_var.NB_JOBS = len(devices)
            warnings.warn("Detecting CUDA devices : {}".format(devices))

    except KeyError:
        set_var.GPU = check_cuda_devices()
        set_var.NB_JOBS = set_var.GPU
        warnings.warn("Detecting {} CUDA devices.".format(set_var.GPU))
        if not set_var.GPU:
            warnings.warn("No GPU automatically detected. Setting SETTINGS.GPU to 0, " +
                          "and SETTINGS.NB_JOBS to cpu_count.")
            set_var.GPU = 0
            set_var.NB_JOBS = multiprocessing.cpu_count()

    return set_var


Instruction:
Given the following Python 3 function, write the documentation
def check_cuda_devices():
    import ctypes

    # Some constants taken from cuda.h
    CUDA_SUCCESS = 0

    libnames = ('libcuda.so', 'libcuda.dylib', 'cuda.dll')
    for libname in libnames:
        try:
            cuda = ctypes.CDLL(libname)
        except OSError:
            continue
        else:
            break
    else:
        # raise OSError("could not load any of: " + ' '.join(libnames))
        return 0

    nGpus = ctypes.c_int()
    error_str = ctypes.c_char_p()

    result = cuda.cuInit(0)
    if result != CUDA_SUCCESS:
        cuda.cuGetErrorString(result, ctypes.byref(error_str))
        # print("cuInit failed with error code %d: %s" % (result, error_str.value.decode()))
        return 0
    result = cuda.cuDeviceGetCount(ctypes.byref(nGpus))
    if result != CUDA_SUCCESS:
        cuda.cuGetErrorString(result, ctypes.byref(error_str))
        # print("cuDeviceGetCount failed with error code %d: %s" % (result, error_str.value.decode()))
        return 0
    # print("Found %d device(s)." % nGpus.value)
    return nGpus.value

Response: Check CUDA devices on the computer and return the number of devices.


Instruction:
Given the following Python 3 function, write the documentation
def get_default(self, *args, **kwargs):
        def retrieve_param(i):
            try:
                return self.__getattribute__(i)
            except AttributeError:
                if i == "device":
                    return self.default_device
                else:
                    return self.__getattribute__(i.upper())
        if len(args) == 0:
            if len(kwargs) == 1 and kwargs[list(kwargs.keys())[0]] is not None:
                return kwargs[list(kwargs.keys())[0]]
            elif len(kwargs) == 1:
                return retrieve_param(list(kwargs.keys())[0])
            else:
                raise TypeError("As dict is unordered, it is impossible to give"
                                "the parameters in the correct order.")
        else:
            out = []
            for i in args:
                if i[1] is None:
                    out.append(retrieve_param(i[0]))
                else:
                    out.append(i[1])
            return out

Response: This function returns the default value of the specified parameters.


Instruction:
Make a summary of the following Python 3 code
def read_causal_pairs(filename, scale=True, **kwargs):
    def convert_row(row, scale):
        """Convert a CCEPC row into numpy.ndarrays.

        :param row:
        :type row: pandas.Series
        :return: tuple of sample ID and the converted data into numpy.ndarrays
        :rtype: tuple
        """
        a = row["A"].split(" ")
        b = row["B"].split(" ")

        if a[0] == "":
            a.pop(0)
            b.pop(0)
        if a[-1] == "":
            a.pop(-1)
            b.pop(-1)

        a = array([float(i) for i in a])
        b = array([float(i) for i in b])
        if scale:
            a = scaler(a)
            b = scaler(b)
        return row['SampleID'], a, b
    if isinstance(filename, str):
        data = read_csv(filename, **kwargs)
    elif isinstance(filename, DataFrame):
        data = filename
    else:
        raise TypeError("Type not supported.")
    conv_data = []

    for idx, row in data.iterrows():
        conv_data.append(convert_row(row, scale))
    df = DataFrame(conv_data, columns=['SampleID', 'A', 'B'])
    df = df.set_index("SampleID")
    return df

Response: Read a ChaLearn Cause effect pairs from a CSV file.


Instruction:
Write a Python 3 script for
reading a file containing an adjacency matrix and convert it into a networkx graph.

Response:
def read_adjacency_matrix(filename, directed=True, **kwargs):
    """Read a file (containing an adjacency matrix) and convert it into a
    directed or undirected networkx graph.

    :param filename: file to read or DataFrame containing the data
    :type filename: str or pandas.DataFrame
    :param directed: Return directed graph
    :type directed: bool
    :param kwargs: extra parameters to be passed to pandas.read_csv
    :return: networkx graph containing the graph.
    :rtype: **networkx.DiGraph** or **networkx.Graph** depending on the
      ``directed`` parameter.
    """
    if isinstance(filename, str):
        data = read_csv(filename, **kwargs)
    elif isinstance(filename, DataFrame):
        data = filename
    else:
        raise TypeError("Type not supported.")
    if directed:
        return nx.relabel_nodes(nx.DiGraph(data.values),
                                {idx: i for idx, i in enumerate(data.columns)})
    else:
        return nx.relabel_nodes(nx.Graph(data.values),
                                {idx: i for idx, i in enumerate(data.columns)})


Instruction:
Implement a function in Python 3 to
read a file containing list of edges and return a directed networkx graph.

Response:
def read_list_edges(filename, directed=True, **kwargs):
    """Read a file (containing list of edges) and convert it into a directed
    or undirected networkx graph.

    :param filename: file to read or DataFrame containing the data
    :type filename: str or pandas.DataFrame
    :param directed: Return directed graph
    :type directed: bool
    :param kwargs: extra parameters to be passed to pandas.read_csv
    :return: networkx graph containing the graph.
    :rtype: **networkx.DiGraph** or **networkx.Graph** depending on the
      ``directed`` parameter.

    """
    if isinstance(filename, str):
        data = read_csv(filename, **kwargs)
    elif isinstance(filename, DataFrame):
        data = filename
    else:
        raise TypeError("Type not supported.")
    if directed:
        graph = nx.DiGraph()
    else:
        graph = nx.Graph()

    for idx, row in data.iterrows():
        try:
            score = row["Score"]
        except KeyError:
            score = 1
        graph.add_edge(row['Cause'], row["Effect"], weight=score)

    return graph


Instruction:
Can you generate the documentation for the following Python 3 function
def forward(self, pred, target):
        loss = th.FloatTensor([0])
        for i in range(1, self.moments):
            mk_pred = th.mean(th.pow(pred, i), 0)
            mk_tar = th.mean(th.pow(target, i), 0)

            loss.add_(th.mean((mk_pred - mk_tar) ** 2))  # L2

        return loss

Response: Compute the loss model.


Instruction:
Explain what the following Python 3 code does
def predict(self, a, b):
        a = np.array(a).reshape((-1, 1))
        b = np.array(b).reshape((-1, 1))
        return (mutual_info_regression(a, b.reshape((-1,))) + mutual_info_regression(b, a.reshape((-1,))))/2

Response: Compute the test statistic for the cluster cluster


Instruction:
Can you implement a function in Python 3 that
computes the test statistic for the statistic in the logarithmic system.

Response:
def predict(self, a, b):
        """ Compute the test statistic

        Args:
            a (array-like): Variable 1
            b (array-like): Variable 2

        Returns:
            float: test statistic
        """
        a = np.array(a).reshape((-1, 1))
        b = np.array(b).reshape((-1, 1))
        return sp.kendalltau(a, b)[0]


Instruction:
Can you tell what is the following Python 3 function doing
def predict(self, a, b, sig=[-1, -1], maxpnt=500):
        a = (a - np.mean(a)) / np.std(a)
        b = (b - np.mean(b)) / np.std(b)

        return FastHsicTestGamma(a, b, sig, maxpnt)

Response: Compute the test statistic for the current cluster and return it


Instruction:
Can you tell what is the following Python 3 function doing
def predict(self, x, *args, **kwargs):
        if len(args) > 0:
            if type(args[0]) == nx.Graph or type(args[0]) == nx.DiGraph:
                return self.orient_graph(x, *args, **kwargs)
            else:
                return self.predict_proba(x, *args, **kwargs)
        elif type(x) == DataFrame:
            return self.predict_dataset(x, *args, **kwargs)
        elif type(x) == Series:
            return self.predict_proba(x.iloc[0], x.iloc[1], *args, **kwargs)

Response: Generic predict method. This method will execute the predict_proba method of the more specific subfunction.


Instruction:
Make a summary of the following Python 3 code
def predict_dataset(self, x, **kwargs):
        printout = kwargs.get("printout", None)
        pred = []
        res = []
        x.columns = ["A", "B"]
        for idx, row in x.iterrows():
            a = scale(row['A'].reshape((len(row['A']), 1)))
            b = scale(row['B'].reshape((len(row['B']), 1)))

            pred.append(self.predict_proba(a, b, idx=idx))

            if printout is not None:
                res.append([row['SampleID'], pred[-1]])
                DataFrame(res, columns=['SampleID', 'Predictions']).to_csv(
                    printout, index=False)
        return pred

Response: Generic dataset prediction function. Runs the score independently on all pairs of CEPC dataframes.


Instruction:
Implement a Python 3 function for
orienting an undirected graph using the pairwise method defined by the subclass.

Response:
def orient_graph(self, df_data, graph, nb_runs=6, printout=None, **kwargs):
        """Orient an undirected graph using the pairwise method defined by the subclass.

        The pairwise method is ran on every undirected edge.

        Args:
            df_data (pandas.DataFrame): Data
            umg (networkx.Graph): Graph to orient
            nb_runs (int): number of times to rerun for each pair (bootstrap)
            printout (str): (optional) Path to file where to save temporary results

        Returns:
            networkx.DiGraph: a directed graph, which might contain cycles

        .. warning:
           Requirement : Name of the nodes in the graph correspond to name of
           the variables in df_data
        """
        if type(graph) == nx.DiGraph:
            edges = [a for a in list(graph.edges()) if (a[1], a[0]) in list(graph.edges())]
            oriented_edges = [a for a in list(graph.edges()) if (a[1], a[0]) not in list(graph.edges())]
            for a in edges:
                if (a[1], a[0]) in list(graph.edges()):
                    edges.remove(a)
            output = nx.DiGraph()
            for i in oriented_edges:
                output.add_edge(*i)

        elif type(graph) == nx.Graph:
            edges = list(graph.edges())
            output = nx.DiGraph()

        else:
            raise TypeError("Data type not understood.")

        res = []

        for idx, (a, b) in enumerate(edges):
            weight = self.predict_proba(
                df_data[a].values.reshape((-1, 1)), df_data[b].values.reshape((-1, 1)), idx=idx,
                nb_runs=nb_runs, **kwargs)
            if weight > 0:  # a causes b
                output.add_edge(a, b, weight=weight)
            else:
                output.add_edge(b, a, weight=abs(weight))
            if printout is not None:
                res.append([str(a) + '-' + str(b), weight])
                DataFrame(res, columns=['SampleID', 'Predictions']).to_csv(
                    printout, index=False)

        for node in list(df_data.columns.values):
            if node not in output.nodes():
                output.add_node(node)

        return output


Instruction:
How would you implement a function in Python 3 that
runs the algorithm on an undirected graph.

Response:
def orient_undirected_graph(self, data, graph):
        """Run the algorithm on an undirected graph.

        Args:
            data (pandas.DataFrame): DataFrame containing the data
            graph (networkx.Graph): Skeleton of the graph to orient

        Returns:
            networkx.DiGraph: Solution on the given skeleton.

        """
        # Building setup w/ arguments.
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        self.arguments['{SCORE}'] = self.score
        self.arguments['{BETA}'] = str(self.beta)
        self.arguments['{OPTIM}'] = str(self.optim).upper()
        self.arguments['{ALPHA}'] = str(self.alpha)

        whitelist = DataFrame(list(nx.edges(graph)), columns=["from", "to"])
        blacklist = DataFrame(list(nx.edges(nx.DiGraph(DataFrame(-nx.adj_matrix(graph, weight=None).to_dense() + 1,
                                                                 columns=list(graph.nodes()),
                                                                 index=list(graph.nodes()))))), columns=["from", "to"])
        results = self._run_bnlearn(data, whitelist=whitelist,
                                   blacklist=blacklist, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})


Instruction:
Here you have a function in Python 3, explain what it does
def orient_directed_graph(self, data, graph):
        warnings.warn("The algorithm is ran on the skeleton of the given graph.")
        return self.orient_undirected_graph(data, nx.Graph(graph))

Response: Run the algorithm on a directed_graph.


Instruction:
Create a Python 3 function to
run the algorithm on data and return a networkx. DiGraph

Response:
def create_graph_from_data(self, data):
        """Run the algorithm on data.

        Args:
            data (pandas.DataFrame): DataFrame containing the data

        Returns:
            networkx.DiGraph: Solution given by the algorithm.

        """
        # Building setup w/ arguments.
        self.arguments['{SCORE}'] = self.score
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        self.arguments['{BETA}'] = str(self.beta)
        self.arguments['{OPTIM}'] = str(self.optim).upper()
        self.arguments['{ALPHA}'] = str(self.alpha)

        results = self._run_bnlearn(data, verbose=self.verbose)
        graph = nx.DiGraph()
        graph.add_edges_from(results)
        return graph


Instruction:
Write a Python 3 script for
computing the gaussian kernel on a 1D vector.

Response:
def computeGaussKernel(x):
    """Compute the gaussian kernel on a 1D vector."""
    xnorm = np.power(euclidean_distances(x, x), 2)
    return np.exp(-xnorm / (2.0))


Instruction:
Here you have a function in Python 3, explain what it does
def normal_noise(points):
    return np.random.rand(1) * np.random.randn(points, 1) \
        + random.sample([2, -2], 1)

Response: Init a noise variable.


Instruction:
Can you generate the documentation for the following Python 3 function
def predict_dataset(self, df):
        if len(list(df.columns)) == 2:
            df.columns = ["A", "B"]
        if self.model is None:
            raise AssertionError("Model has not been trained before predictions")
        df2 = DataFrame()

        for idx, row in df.iterrows():
            df2 = df2.append(row, ignore_index=True)
            df2 = df2.append({'A': row["B"], 'B': row["A"]}, ignore_index=True)
        return predict.predict(deepcopy(df2), deepcopy(self.model))[::2]

Response: Runs Jarfo independently on all pairs of CEPC dataframes.


Instruction:
Write a Python 3 script for
using Jarfo to predict the causal direction of a pair of vars.

Response:
def predict_proba(self, a, b, idx=0, **kwargs):
        """ Use Jarfo to predict the causal direction of a pair of vars.

        Args:
            a (numpy.ndarray): Variable 1
            b (numpy.ndarray): Variable 2
            idx (int): (optional) index number for printing purposes

        Returns:
            float: Causation score (Value : 1 if a->b and -1 if b->a)
        """
        return self.predict_dataset(DataFrame([[a, b]],
                                              columns=['A', 'B']))


Instruction:
Make a summary of the following Python 3 code
def network_deconvolution(mat, **kwargs):
    alpha = kwargs.get('alpha', 1)
    beta = kwargs.get('beta', 0.99)
    control = kwargs.get('control', 0)

    # ToDO : ASSERTS
    try:
        assert beta < 1 or beta > 0
        assert alpha <= 1 or alpha > 0

    except AssertionError:
        raise ValueError("alpha must be in ]0, 1] and beta in [0, 1]")

    #  Processing the input matrix, diagonal values are filtered
    np.fill_diagonal(mat, 0)

    # Thresholding the input matrix
    y = stat.mquantiles(mat[:], prob=[1 - alpha])
    th = mat >= y
    mat_th = mat * th

    # Making the matrix symetric if already not
    mat_th = (mat_th + mat_th.T) / 2

    # Eigen decomposition
    Dv, U = LA.eigh(mat_th)
    D = np.diag((Dv))
    lam_n = np.abs(np.min(np.min(np.diag(D)), 0))
    lam_p = np.abs(np.max(np.max(np.diag(D)), 0))

    m1 = lam_p * (1 - beta) / beta
    m2 = lam_n * (1 + beta) / beta
    m = max(m1, m2)

    # network deconvolution
    for i in range(D.shape[0]):
        D[i, i] = (D[i, i]) / (m + D[i, i])

    mat_new1 = np.dot(U, np.dot(D, LA.inv(U)))

    # Displying direct weights

    if control == 0:
        ind_edges = (mat_th > 0) * 1.0
        ind_nonedges = (mat_th == 0) * 1.0
        m1 = np.max(np.max(mat * ind_nonedges))
        m2 = np.min(np.min(mat_new1))
        mat_new2 = (mat_new1 + np.max(m1 - m2, 0)) * ind_edges + (mat * ind_nonedges)
    else:
        m2 = np.min(np.min(mat_new1))
        mat_new2 = (mat_new1 + np.max(-m2, 0))

    # linearly mapping the deconvolved matrix to be between 0 and 1
    m1 = np.min(np.min(mat_new2))
    m2 = np.max(np.max(mat_new2))
    mat_nd = (mat_new2 - m1) / (m2 - m1)

    return mat_nd

Response: Python implementation of network deconvolution by MIT - KELLIS LAB.


Instruction:
Implement a function in Python 3 to
remove undirected links from a graph.

Response:
def remove_indirect_links(g, alg="aracne", **kwargs):
    """Apply deconvolution to a networkx graph.

    Args:
       g (networkx.Graph): Graph to apply deconvolution to
       alg (str): Algorithm to use ('aracne', 'clr', 'nd')
       kwargs (dict): extra options for algorithms

    Returns:
       networkx.Graph: graph with undirected links removed.
    """
    alg = {"aracne": aracne,
           "nd": network_deconvolution,
           "clr": clr}[alg]
    mat = np.array(nx.adjacency_matrix(g).todense())
    return nx.relabel_nodes(nx.DiGraph(alg(mat, **kwargs)),
                            {idx: i for idx, i in enumerate(list(g.nodes()))})


Instruction:
Can you generate a brief explanation for the following Python 3 code
def dagify_min_edge(g):
    while not nx.is_directed_acyclic_graph(g):
        cycle = next(nx.simple_cycles(g))
        scores = []
        edges = []
        for i, j in zip(cycle[:1], cycle[:1]):
            edges.append((i, j))
            scores.append(g[i][j]['weight'])

        i, j = edges[scores.index(min(scores))]
        gc = deepcopy(g)
        gc.remove_edge(i, j)
        gc.add_edge(j, i)

        if len(list(nx.simple_cycles(gc))) < len(list(nx.simple_cycles(g))):
            g.add_edge(j, i, weight=min(scores))
        g.remove_edge(i, j)
    return g

Response:
Input a graph and output a DAG with the lowest score of the cycle
   .


Instruction:
Can you implement a function in Python 3 that
returns the weighted average and standard deviation.

Response:
def weighted_mean_and_std(values, weights):
    """
    Returns the weighted average and standard deviation.

    values, weights -- numpy ndarrays with the same shape.
    """
    average = np.average(values, weights=weights, axis=0)
    variance = np.dot(weights, (values - average) ** 2) / weights.sum()  # Fast and numerically precise
    return (average, np.sqrt(variance))


Instruction:
Create a Python 3 function to
run an instance of GNN on a GPU.

Response:
def GNN_instance(x, idx=0, device=None, nh=20, **kwargs):
    """Run an instance of GNN, testing causal direction.

    :param m: data corresponding to the config : (N, 2) data, [:, 0] cause and [:, 1] effect
    :param pair_idx: print purposes
    :param run: numner of the run (for GPU dispatch)
    :param device: device on with the algorithm is going to be run on.
    :return:
    """
    device = SETTINGS.get_default(device=device)
    xy = scale(x).astype('float32')
    inputx = th.FloatTensor(xy[:, [0]]).to(device)
    target = th.FloatTensor(xy[:, [1]]).to(device)
    GNNXY = GNN_model(x.shape[0], device=device, nh=nh).to(device)
    GNNYX = GNN_model(x.shape[0], device=device, nh=nh).to(device)
    GNNXY.reset_parameters()
    GNNYX.reset_parameters()
    XY = GNNXY.run(inputx, target, **kwargs)
    YX = GNNYX.run(target, inputx, **kwargs)

    return [XY, YX]


Instruction:
Implement a function in Python 3 to
pass data through the net structure.

Response:
def forward(self, x):
        """Pass data through the net structure.

        :param x: input data: shape (:,1)
        :type x: torch.Variable
        :return: output of the shallow net
        :rtype: torch.Variable

        """
        self.noise.normal_()
        return self.layers(th.cat([x, self.noise], 1))


Instruction:
Can you tell what is the following Python 3 function doing
def run(self, x, y, lr=0.01, train_epochs=1000, test_epochs=1000, idx=0, verbose=None, **kwargs):
        verbose = SETTINGS.get_default(verbose=verbose)
        optim = th.optim.Adam(self.parameters(), lr=lr)
        running_loss = 0
        teloss = 0

        for i in range(train_epochs + test_epochs):
            optim.zero_grad()
            pred = self.forward(x)
            loss = self.criterion(pred, y)
            running_loss += loss.item()

            if i < train_epochs:
                loss.backward()
                optim.step()
            else:
                teloss += running_loss

            # print statistics
            if verbose and not i % 300:
                print('Idx:{}; epoch:{}; score:{}'.
                      format(idx, i, running_loss/300))
                running_loss = 0.0

        return teloss / test_epochs

Response: Run the GNN on a pair x y.


Instruction:
Can you write a function in Python 3 where it
runs multiple times GNN to estimate the causal direction of the pair.

Response:
def predict_proba(self, a, b, nb_runs=6, nb_jobs=None, gpu=None,
                      idx=0, verbose=None, ttest_threshold=0.01,
                      nb_max_runs=16, train_epochs=1000, test_epochs=1000):
        """Run multiple times GNN to estimate the causal direction.

        Args:
            a (np.ndarray): Variable 1
            b (np.ndarray): Variable 2
            nb_runs (int): number of runs to execute per batch (before testing for significance with t-test).
            nb_jobs (int): number of runs to execute in parallel. (Initialized with ``cdt.SETTINGS.NB_JOBS``)
            gpu (bool): use gpu (Initialized with ``cdt.SETTINGS.GPU``)
            idx (int): (optional) index of the pair, for printing purposes
            verbose (bool): verbosity (Initialized with ``cdt.SETTINGS.verbose``)
            ttest_threshold (float): threshold to stop the boostraps before ``nb_max_runs`` if the difference is significant
            nb_max_runs (int): Max number of bootstraps
            train_epochs (int): Number of epochs during which the model is going to be trained
            test_epochs (int): Number of epochs during which the model is going to be tested

        Returns:
            float: Causal score of the pair (Value : 1 if a->b and -1 if b->a)
        """
        Nb_jobs, verbose, gpu = SETTINGS.get_default(('nb_jobs', nb_jobs), ('verbose', verbose), ('gpu', gpu))
        x = np.stack([a.ravel(), b.ravel()], 1)
        ttest_criterion = TTestCriterion(
            max_iter=nb_max_runs, runs_per_iter=nb_runs, threshold=ttest_threshold)

        AB = []
        BA = []

        while ttest_criterion.loop(AB, BA):
            if nb_jobs != 1:
                result_pair = Parallel(n_jobs=nb_jobs)(delayed(GNN_instance)(
                    x, idx=idx, device='cuda:{}'.format(run % gpu) if gpu else 'cpu',
                    verbose=verbose, train_epochs=train_epochs, test_epochs=test_epochs) for run in range(ttest_criterion.iter, ttest_criterion.iter + nb_runs))
            else:
                result_pair = [GNN_instance(x, idx=idx,
                                            device='cuda:0' if gpu else 'cpu',
                                            verbose=verbose,
                                            train_epochs=train_epochs,
                                            test_epochs=test_epochs)
                               for run in range(ttest_criterion.iter, ttest_criterion.iter + nb_runs)]
            AB.extend([runpair[0] for runpair in result_pair])
            BA.extend([runpair[1] for runpair in result_pair])

        if verbose:
            print("P-value after {} runs : {}".format(ttest_criterion.iter,
                                                      ttest_criterion.p_value))

        score_AB = np.mean(AB)
        score_BA = np.mean(BA)

        return (score_BA - score_AB) / (score_BA + score_AB)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def init_variables(self, verbose=False):
        # Resetting adjacency matrix
        for i in range(self.nodes):
            for j in np.random.choice(range(self.nodes),
                                      np.random.randint(
                                          0, self.parents_max + 1),
                                      replace=False):
                if i != j:
                    self.adjacency_matrix[j, i] = 1

        try:
            assert any([sum(self.adjacency_matrix[:, i]) ==
                        self.parents_max for i in range(self.nodes)])
            self.g = nx.DiGraph(self.adjacency_matrix)
            assert list(nx.simple_cycles(self.g))
            assert any(len(i) == 2 for i in nx.simple_cycles(self.g))

        except AssertionError:
            if verbose:
                print("Regenerating, graph non valid...")
            self.init_variables()

        if verbose:
            print("Matrix generated ! \
              Number of cycles: {}".format(len(list(nx.simple_cycles(self.g)))))

        for i in range(self.nodes):
            self.data.iloc[:, i] = scale(self.initial_generator(self.points))

        # Mechanisms
        self.cfunctions = [self.mechanism(int(sum(self.adjacency_matrix[:, i])),
                                          self.points, self.noise, noise_coeff=self.noise_coeff) for i in range(self.nodes)]

Response: Redefine the causes of the graph.


Instruction:
Given the following Python 3 function, write the documentation
def generate(self, nb_steps=100, averaging=50, rescale=True):
        if self.cfunctions is None:
            self.init_variables()
        new_df = pd.DataFrame()
        causes = [[c for c in np.nonzero(self.adjacency_matrix[:, j])[0]]
                  for j in range(self.nodes)]
        values = [[] for i in range(self.nodes)]

        for i in range(nb_steps):
            for j in range(self.nodes):
                new_df["V" + str(j)] = self.cfunctions[j](self.data.iloc[:, causes[j]].values)[:, 0]
                if rescale:
                    new_df["V" + str(j)] = scale(new_df["V" + str(j)])
                if i > nb_steps-averaging:
                    values[j].append(new_df["V" + str(j)])
            self.data = new_df
        self.data = pd.DataFrame(np.array([np.mean(values[i], axis=0)
                                           for i in range(self.nodes)]).transpose(),
                                 columns=["V{}".format(j) for j in range(self.nodes)])

        return self.g, self.data

Response: Generate data from an FCM containing cycles.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def create_graph_from_data(self, data, **kwargs):
        # Building setup w/ arguments.
        self.arguments['{SCORE}'] = self.scores[self.score]
        self.arguments['{CUTOFF}'] = str(self.cutoff)
        self.arguments['{VARSEL}'] = str(self.variablesel).upper()
        self.arguments['{SELMETHOD}'] = self.var_selection[self.selmethod]
        self.arguments['{PRUNING}'] = str(self.pruning).upper()
        self.arguments['{PRUNMETHOD}'] = self.var_selection[self.prunmethod]
        self.arguments['{NJOBS}'] = str(self.nb_jobs)
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        results = self._run_cam(data, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

Response: This method creates a networkx. DiGraph from the data provided by the CAM algorithm.


Instruction:
Can you tell what is the following Python 3 function doing
def predict_features(self, df_features, df_target, idx=0, **kwargs):
        estimator = SVR(kernel='linear')
        selector = RFECV(estimator, step=1)
        selector = selector.fit(df_features.values, df_target.values[:, 0])

        return selector.grid_scores_

Response: For one variable predict its neighbouring nodes.


Instruction:
Can you tell what is the following Python 3 function doing
def forward(self, x):

        features = self.conv(x).mean(dim=2)
        return self.dense(features)

Response: Passing data through the network.


Instruction:
Create a Python 3 function to
fit the NCC model to the given data.

Response:
def fit(self, x_tr, y_tr, epochs=50, batchsize=32,
            learning_rate=0.01, verbose=None, device=None):
        """Fit the NCC model.

        Args:
            x_tr (pd.DataFrame): CEPC format dataframe containing the pairs
            y_tr (pd.DataFrame or np.ndarray): labels associated to the pairs
            epochs (int): number of train epochs
            learning_rate (float): learning rate of Adam
            verbose (bool): verbosity (defaults to ``cdt.SETTINGS.verbose``)
            device (str): cuda or cpu device (defaults to ``cdt.SETTINGS.default_device``)
        """
        if batchsize > len(x_tr):
            batchsize = len(x_tr)
        verbose, device = SETTINGS.get_default(('verbose', verbose),
                                               ('device', device))
        self.model = NCC_model()
        opt = th.optim.Adam(self.model.parameters(), lr=learning_rate)
        criterion = th.nn.BCEWithLogitsLoss()
        y = y_tr.values if isinstance(y_tr, pd.DataFrame) else y_tr
        y = th.Tensor(y)/2 + .5
        # print(y)
        self.model = self.model.to(device)
        y = y.to(device)
        dataset = []
        for i, (idx, row) in enumerate(x_tr.iterrows()):

            a = row['A'].reshape((len(row['A']), 1))
            b = row['B'].reshape((len(row['B']), 1))
            m = np.hstack((a, b))
            m = m.astype('float32')
            m = th.from_numpy(m).t().unsqueeze(0)
            dataset.append(m)
        dataset = [m.to(device) for m in dataset]
        acc = [0]
        da = th.utils.data.DataLoader(Dataset(dataset, y), batch_size=batchsize,
                                      shuffle=True)
        data_per_epoch = (len(dataset) // batchsize)
        with trange(epochs, desc="Epochs", disable=not verbose) as te:
            for epoch in te:
                with trange(data_per_epoch, desc="Batches of {}".format(batchsize),
                            disable=not (verbose and batchsize == len(dataset))) as t:
                    output = []
                    labels = []
                    for (batch, label), i in zip(da, t):
                        opt.zero_grad()
                        # print(batch.shape, labels.shape)
                        out = th.stack([self.model(m) for m in batch], 0).squeeze(2)
                        loss = criterion(out, label)
                        loss.backward()
                        t.set_postfix(loss=loss.item())
                        opt.step()
                        output.append(out)
                        labels.append(label)
                    acc = th.where(th.cat(output, 0) > .5,
                                   th.ones(len(output)),
                                   th.zeros(len(output))) - th.cat(labels, 0)
                    te.set_postfix(Acc=1-acc.abs().mean().item())


Instruction:
How would you implement a function in Python 3 that
predicts causal directions using the trained NCC pairwise model.

Response:
def predict_proba(self, a, b, device=None):
        """Infer causal directions using the trained NCC pairwise model.

        Args:
            a (numpy.ndarray): Variable 1
            b (numpy.ndarray): Variable 2
            device (str): Device to run the algorithm on (defaults to ``cdt.SETTINGS.default_device``)

        Returns:
            float: Causation score (Value : 1 if a->b and -1 if b->a)
        """
        device = SETTINGS.get_default(device=device)
        if self.model is None:
            print('Model has to be trained before doing any predictions')
            raise ValueError
        if len(np.array(a).shape) == 1:
            a = np.array(a).reshape((-1, 1))
            b = np.array(b).reshape((-1, 1))
        m = np.hstack((a, b))
        m = scale(m)
        m = m.astype('float32')
        m = th.from_numpy(m).t().unsqueeze(0)

        if th.cuda.is_available():
            m = m.cuda()

        return (self.model(m).data.cpu().numpy()-.5) * 2


Instruction:
Can you tell what is the following Python 3 function doing
def predict_dataset(self, df, device=None, verbose=None):
        verbose, device = SETTINGS.get_default(('verbose', verbose),
                                               ('device', device))
        dataset = []
        for i, (idx, row) in enumerate(df.iterrows()):
            a = row['A'].reshape((len(row['A']), 1))
            b = row['B'].reshape((len(row['B']), 1))
            m = np.hstack((a, b))
            m = m.astype('float32')
            m = th.from_numpy(m).t().unsqueeze(0)
            dataset.append(m)

        dataset = [m.to(device) for m in dataset]
        return pd.DataFrame((th.cat([self.model(m) for m, t in zip(dataset, trange(len(dataset)),
                                                      disable=not verbose)]\
                       , 0).data.cpu().numpy() -.5) * 2)

Response: Predicts the causation coefficients for the given pairs of causal classes.