def compute_part_coverages(sentence, disconnected_graph_parts):
    """
    Construct disconnected graph part coverages, including coverage of the main graph part.
    :param sentence: Sentence object
    :param disconnected_graph_parts: List of disconnected graph parts, formed as sets of Node objects
    :return: List of part coverage tuples, sorted from most covering to least
    """

    part_coverages = []

    reference_coverage = sorted([node.node_id for node in sentence.source.graph.nodes])

    main_part_coverage = ['1'] * len(reference_coverage)

    for disconnected_graph_part in disconnected_graph_parts:

        part_coverage = ['0'] * len(reference_coverage)

        for node in disconnected_graph_part:
            node_index = reference_coverage.index(node.node_id)
            part_coverage[node_index] = '1'

            assert main_part_coverage[node_index] == '1'  # Make sure part coverages are non-overlapping
            main_part_coverage[node_index] = '0'

        part_coverages.append(part_coverage)

    part_coverages.append(main_part_coverage)

    # Sort part coverages from most covering to least
    part_coverages = sorted(part_coverages, key=lambda x: sum(1 for node in x if node == '1'), reverse=True)

    return part_coverages