<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: <NAME> <<EMAIL>>

from networkx import DiGraph, dfs_edges, is_arborescence, topological_sort
from networkx.algorithms.traversal.depth_first_search import dfs_tree
from ordered_set import OrderedSet


def is_proper(tree):
    """
    returns True, iff input is a proper tree.
    A tree is proper if it contains at least one edge.
    """
    return True if len(tree.edges()) > 0 else False


def is_leave(tree, node_id):
    """returns True, if the given node is a leave node"""
    return True if tree.out_degree(node_id) == 0 else False


def get_production_rules(syntax_tree, root_node=None):
    """
    Iterates through a tree (starting at the given node) and returns
    a set of 'production rules'. each 'rule' is a tuple, consisting of a
    node ID (str) and a tuple of it successors (str, i.e. the node IDs of all
    the nodes connected via outgoing edges) as its value.

    I put 'production rules' in quotes, as they are based on unique node IDs,
    and not necessarily on syntactic categories.

    Parameters
    ----------
    syntax_tree : networkx.DiGraph
        a tree represented as a directed graph
    root_node : str or None
        the node ID of the tree's root node. if not specified, it will be
        determined automatically.

    Returns
    -------
    rules : list of (str, tuple of str) tuples
        each rule consists of a lhs (a string representing a node ID) and a rhs
        (a tuple of strings representing node IDs)
    """
    rules = set()

    if not root_node:
        # root node is the first element in a topological sort of the graph
        root_node = topological_sort(syntax_tree)[0]

    for source, _target in dfs_edges(syntax_tree, root_node):
        rules.add( (source, tuple(syntax_tree.successors(source))) )
    return rules


def contains_only_complete_productions(tree, subtree, subtree_root_node=None):
    """
    checks, if a syntax subtree only consists of complete productions from the
    given tree.
    """
    tree_rules = get_production_rules(tree)
    subtree_rules = get_production_rules(subtree, root_node=subtree_root_node)
    return all(st_rule in tree_rules for st_rule in subtree_rules)




def get_proper_corooted_subtrees(tree, root_node):
    """
    """
    if not is_proper(tree):<commit_msg>fixed #1: sorted rhs of production rules for later comparison<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: <NAME> <<EMAIL>>

from networkx import DiGraph, dfs_edges, is_arborescence, topological_sort
from networkx.algorithms.traversal.depth_first_search import dfs_tree
from ordered_set import OrderedSet


def is_proper(tree):
    """
    returns True, iff input is a proper tree.
    A tree is proper if it contains at least one edge.
    """
    return True if len(tree.edges()) > 0 else False


def is_leave(tree, node_id):
    """returns True, if the given node is a leave node"""
    return True if tree.out_degree(node_id) == 0 else False


def get_production_rules(syntax_tree, root_node=None):
    """
    Iterates through a tree (starting at the given node) and returns
    a set of 'production rules'. each 'rule' is a tuple, consisting of a
    node ID (str) and a tuple of it successors (str, i.e. the node IDs of all
    the nodes connected via outgoing edges) as its value.

    I put 'production rules' in quotes, as they are based on unique node IDs,
    and not necessarily on syntactic categories.

    Parameters
    ----------
    syntax_tree : networkx.DiGraph
        a tree represented as a directed graph
    root_node : str or None
        the node ID of the tree's root node. if not specified, it will be
        determined automatically.

    Returns
    -------
    rules : list of (str, tuple of str) tuples
        each rule consists of a lhs (a string representing a node ID) and a rhs
        (a tuple of strings representing node IDs)
    """
    rules = set()

    if not root_node:
        # root node is the first element in a topological sort of the graph
        root_node = topological_sort(syntax_tree)[0]

    for source, _target in dfs_edges(syntax_tree, root_node):
        rules.add( (source, tuple(sorted(syntax_tree.successors(source)))) )
    return rules


def contains_only_complete_productions(tree, subtree, subtree_root_node=None):
    """
    checks, if a syntax subtree only consists of complete productions from the
    given tree.
    """
    tree_rules = get_production_rules(tree)
    subtree_rules = get_production_rules(subtree, root_node=subtree_root_node)
    return all(st_rule in tree_rules for st_rule in subtree_rules)




def get_proper_corooted_subtrees(tree, root_node):
    """
    """
    if not is_proper(tree):
{'fraction_non_alphanumeric': 0.08151260504201681, 'fraction_numerical': 0.0018907563025210084, 'mean_word_length': 3.1836555360281196, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2680141', 'n_tokens_mistral': 1441, 'n_tokens_neox': 1366, 'n_words': 550}