예제 #1
0
def planar_graph_grammar():
    """Constructs the grammar for planar graphs.

    Returns
    -------
    grammar : DecompositionGrammar
        The grammar for sampling from G, G_dx and G_dx_dx.
    """

    # Some shortcuts to make the grammar more readable.
    Rule = pybo.AliasSampler
    G_1 = Rule('G_1')
    G_1_dx = Rule('G_1_dx')
    G_1_dx_dx = Rule('G_1_dx_dx')
    G_1_dx_dx_dx = Rule('G_1_dx_dx_dx')
    G = Rule('G')
    G_dx = Rule('G_dx')
    G_dx_dx = Rule('G_dx')
    Set = pybo.SetSampler

    grammar = pybo.DecompositionGrammar()
    grammar.rules = one_connected_graph_grammar().rules
    EarlyRejectionControl.grammar = grammar

    grammar.add_rules({
        'G':
        Set(0, G_1),
        'G_dx':
        G_1_dx * G,
        'G_dx_dx':
        G_1_dx_dx * G + G_1_dx * G_dx,
        'G_dx_dx_dx':
        G_1_dx_dx_dx * G + G_1_dx_dx * G_dx + G_1_dx_dx * G_dx +
        G_1_dx * G_dx_dx
    })
    grammar.set_builder(['G', 'G_dx', 'G_dx_dx', 'G_dx_dx_dx'],
                        PlanarGraphBuilder())

    return grammar
예제 #2
0
def irreducible_dissection_grammar():
    """Builds the dissection grammar. Must still be initialized with init().

    Returns
    -------
    DecompositionGrammar
        The grammar for sampling from J_a and J_a_dx.
    """

    # Some shorthands to keep the grammar readable.
    L = pybo.LAtomSampler
    Rule = pybo.AliasSampler
    K = Rule('K')
    K_dx = Rule('K_dx')
    K_dx_dx = Rule('K_dx_dx')
    I = Rule('I')
    I_dx = Rule('I_dx')
    I_dx_dx = Rule('I_dx_dx')
    J = Rule('J')
    J_dx = Rule('J_dx')
    J_dx_dx = Rule('J_dx_dx')
    Bij = pybo.BijectionSampler
    Rej = pybo.RejectionSampler

    grammar = pybo.DecompositionGrammar()
    # This grammar depends on the binary tree grammar so we add it.
    grammar.rules = binary_tree_grammar().rules
    EarlyRejectionControl.grammar = grammar

    grammar.add_rules({

        # Non-derived dissections (standard, rooted, admissible).
        'I':
        Bij(K, closure),

        # We drop the 3*L*U factor here.
        # This bijection does not preserve l-size/u-size.
        'J':
        Bij(I, add_random_root_edge),
        'J_a':
        Rej(J, is_admissible),

        # Derived dissections.

        # The result is not a derived class, the bijection does not preserve l-size.
        'I_dx':
        Bij(K_dx, closure),

        # We drop the factor 3*U.
        # This bijection does not preserve l-size/u-size.
        'J_dx':
        Bij(I + L() * I_dx, add_random_root_edge),
        'J_a_dx':
        Rej(J_dx, is_admissible),

        # Bi-derived dissections.

        # Does not preserve l-size, result is not a derived class.
        'I_dx_dx':
        Bij(K_dx_dx, closure),

        # We dropped a factor.
        'J_dx_dx':
        Bij(2 * I_dx + L() * I_dx_dx, add_random_root_edge),
        'J_a_dx_dx':
        Rej(J_dx_dx, is_admissible)
    })
    return grammar
예제 #3
0
def one_connected_graph_grammar():
    """Constructs the grammar for connected planar graphs.

    Returns
    -------
    DecompositionGrammar
        The grammar for sampling from G_1_dx and G_1_dx_dx.
    """

    # Some shortcuts to make the grammar more readable.
    L = pybo.LAtomSampler
    Rule = pybo.AliasSampler
    G_2_dx = Rule('G_2_dx')
    G_2_dx_dx = Rule('G_2_dx_dx')
    G_2_dx_dx_dx = Rule('G_2_dx_dx_dx')
    G_1_dx = Rule('G_1_dx')
    G_1_dx_dx = Rule('G_1_dx_dx')
    G_1_dx_dx_dx = Rule('G_1_dx_dx_dx')
    Set = pybo.SetSampler
    LSubs = pybo.LSubsSampler
    Bij = pybo.BijectionSampler
    Rej = pybo.RejectionSampler

    grammar = pybo.DecompositionGrammar()
    grammar.rules = two_connected_graph_grammar().rules
    EarlyRejectionControl.grammar = grammar

    grammar.add_rules({

        'G_1':
            Bij(
                Rej(
                    G_1_dx,
                    rej_to_G_1  # See lemma 15.
                ),
                underive
            ),

        'G_1_dx':
            Set(
                0,
                LSubs(
                    G_2_dx,
                    L() * G_1_dx
                )
            ),

        'G_1_dx_dx':
            Bij(
                Bij(
                    (G_1_dx + L() * G_1_dx_dx) * LSubs(G_2_dx_dx, L() * G_1_dx),
                    subs_marked_vertex
                ) * G_1_dx,
                merge
            ),

        'G_1_dx_dx_dx':
            Bij(
                Bij(
                    (2 * G_1_dx_dx + L() * G_1_dx_dx_dx) * LSubs(G_2_dx_dx, L() * G_1_dx),
                    subs_marked_vertex
                ) * G_1_dx,
                merge
            )

            + Bij(
                Bij(
                    (G_1_dx + L() * G_1_dx_dx) ** 2 * LSubs(G_2_dx_dx_dx, L() * G_1_dx),
                    subs_marked_vertex_2
                ) * G_1_dx,
                merge
            )

            + Bij(
                Bij(
                    (G_1_dx + L() * G_1_dx_dx) * LSubs(G_2_dx_dx, L() * G_1_dx),
                    subs_marked_vertex
                ) * G_1_dx_dx,
                merge
            ),

    })

    grammar.set_builder(['G_1_dx'], Merger())

    return grammar
def two_connected_graph_grammar():
    """Constructs the grammar for two connected planar graphs.

    Returns
    -------
    DecompositionGrammar
        The grammar for sampling from G_2_dx and G_2_dx_dx.
    """

    Z = pybo.ZeroAtomSampler
    L = pybo.LAtomSampler
    Rule = pybo.AliasSampler
    D = Rule('D')
    D_dx = Rule('D_dx')
    D_dx_dx = Rule('D_dx_dx')
    F = Rule('F')
    F_dx = Rule('F_dx')
    F_dx_dx = Rule('F_dx_dx')
    G_2_dy = Rule('G_2_dy')
    G_2_dx_dy = Rule('G_2_dx_dy')
    G_2_dx_dx_dy = Rule('G_2_dx_dx_dy')
    G_2_arrow = Rule('G_2_arrow')
    G_2_arrow_dx = Rule('G_2_arrow_dx')
    G_2_arrow_dx_dx = Rule('G_2_arrow_dx_dx')
    Trans = pybo.TransformationSampler
    Bij = pybo.BijectionSampler
    DxFromDy = pybo.LDerFromUDerSampler

    grammar = pybo.DecompositionGrammar()
    grammar.rules = network_grammar().rules
    EarlyRejectionControl.grammar = grammar

    grammar.add_rules({

        # two connected
        'G_2_arrow':
        Trans(Z() + D, to_G_2_arrow,
              eval_transform=divide_by_1_plus_y),  # see 5.5
        'F':
        Bij(L()**2 * G_2_arrow, to_G_2),
        'G_2_dy':
        Trans(F, to_u_derived_class, eval_transform=divide_by_2),
        'G_2_dx':
        Bij(
            DxFromDy(
                G_2_dy, alpha_l_u=2.0
            ),  # see p. 26 TODO check this, error in paper? (no error, 2 is caused by the link graph)
            mark_l_atom),

        # l-derived two connected
        'G_2_arrow_dx':
        Trans(D_dx, to_G_2_arrow_dx, eval_transform=divide_by_1_plus_y),
        'F_dx':
        Bij(L()**2 * G_2_arrow_dx + 2 * L() * G_2_arrow, to_G_2_dx),
        'G_2_dx_dy':
        Trans(F_dx, to_u_derived_class, eval_transform=divide_by_2),
        'G_2_dx_dx':
        Bij(
            DxFromDy(G_2_dx_dy, alpha_l_u=1.0),  # see 5.5
            mark_2_l_atoms),

        # bi-l-derived two connected
        'G_2_arrow_dx_dx':
        Trans(D_dx_dx, to_G_2_arrow_dx_dx, eval_transform=divide_by_1_plus_y),
        'F_dx_dx':
        Bij(L()**2 * G_2_arrow_dx_dx + 4 * L() * G_2_arrow_dx + 2 * G_2_arrow,
            to_G_2_dx_dx),
        'G_2_dx_dx_dy':
        Trans(F_dx_dx, to_u_derived_class, eval_transform=divide_by_2),
        'G_2_dx_dx_dx':
        Bij(DxFromDy(G_2_dx_dx_dy, alpha_l_u=1.0), mark_3_l_atoms),
    })

    grammar.set_builder(['G_2_arrow'], ZeroAtomGraphBuilder())

    return grammar
예제 #5
0
def network_grammar():
    """Constructs the grammar for networks.

    Returns
    -------
    DecompositionGrammar
        The grammar for sampling from D and D_dx.
    """

    L = pybo.LAtomSampler
    U = pybo.UAtomSampler
    Rule = pybo.AliasSampler
    G_3_arrow = Rule('G_3_arrow')
    G_3_arrow_dx = Rule('G_3_arrow_dx')
    G_3_arrow_dy = Rule('G_3_arrow_dy')
    D = Rule('D')
    D_dx = Rule('D_dx')
    S = Rule('S')
    S_dx = Rule('S_dx')
    P = Rule('P')
    P_dx = Rule('P_dx')
    H = Rule('H')
    H_dx = Rule('H_dx')
    D_dx_dx = Rule('D_dx_dx')
    S_dx_dx = Rule('S_dx_dx')
    P_dx_dx = Rule('P_dx_dx')
    H_dx_dx = Rule('H_dx_dx')
    G_3_arrow_dx_dx = Rule('G_3_arrow_dx_dx')
    G_3_arrow_dx_dy = Rule('G_3_arrow_dx_dy')
    G_3_arrow_dy_dy = Rule('G_3_arrow_dy_dy')
    Bij = pybo.BijectionSampler
    Set = pybo.SetSampler
    USubs = pybo.USubsSampler

    grammar = pybo.DecompositionGrammar()
    grammar.rules = three_connected_graph_grammar().rules

    grammar.add_rules({

        # networks

        'D': U() + S + P + H,

        'S': (U() + P + H) * D * L(),

        'P': U() * Set(1, S + H) + Set(2, S + H),

        'H': Bij(USubs(G_3_arrow, D), g_3_arrow_to_network),

        # l-derived networks

        'D_dx': S_dx + P_dx + H_dx,

        'S_dx':
            (P_dx + H_dx) * D * L()
            + (U() + P + H) * D_dx * L()
            + (U() + P + H) * D,

        'P_dx':
            U() * (S_dx + H_dx) * Set(0, S + H)
            + (S_dx + H_dx) * Set(1, S + H),

        'H_dx':
            Bij(
                USubs(G_3_arrow_dx, D) + D_dx * USubs(G_3_arrow_dy, D),
                g_3_arrow_to_network
            ),

        # bi-l-derived networks

        'D_dx_dx':
            S_dx_dx + P_dx_dx + H_dx_dx,

        'S_dx_dx':
            (P_dx_dx + H_dx_dx) * D * L()
            + 2 * (P_dx + H_dx) * D_dx * L()
            + (U() + P + H) * D_dx_dx * L()
            + 2 * (P_dx + H_dx) * D
            + 2 * (U() + P + H) * D_dx,

        'P_dx_dx':
            U() * (S_dx_dx + H_dx_dx) * Set(0, S + H)
            + U() * (S_dx + H_dx) ** 2 * Set(0, S + H)
            + (S_dx_dx + H_dx_dx) * Set(1, S + H)
            + (S_dx + H_dx) ** 2 * Set(0, S + H),

        'H_dx_dx':
            Bij(
                USubs(G_3_arrow_dx_dx, D)
                + 2 * D_dx * USubs(G_3_arrow_dx_dy, D)
                + D_dx_dx * USubs(G_3_arrow_dy, D)
                + D_dx ** 2 * USubs(G_3_arrow_dy_dy, D),
                g_3_arrow_to_network
            ),

    })

    # Set up builders.
    grammar.set_builder(['D', 'S', 'P', 'H',
                         'D_dx', 'S_dx', 'P_dx', 'H_dx',
                         'D_dx_dx', 'S_dx_dx', 'P_dx_dx', 'H_dx_dx'], NetworkBuilder())
    grammar.set_builder(['P', 'P_dx', 'P_dx_dx'], PNetworkBuilder())
    grammar.set_builder(['S', 'S_dx', 'S_dx_dx'], SNetworkBuilder())
    EarlyRejectionControl.grammar = grammar

    return grammar
def binary_tree_grammar():
    """
    Builds the bicolored binary tree grammar. Must still be initialized with init().

    Returns
    -------
    DecompositionGrammar
        The grammar for sampling K and K_dx.
    """

    # Some shorthands to keep the grammar readable.
    L = pybo.LAtomSampler
    U = pybo.UAtomSampler
    Rule = pybo.AliasSampler
    K_dy = Rule('K_dy')
    R_b_as = Rule('R_b_as')
    R_w_as = Rule('R_w_as')
    R_b_head = Rule('R_b_head')
    R_b_head_help = Rule('R_b_head_help')
    R_w_head = Rule('R_w_head')
    R_b = Rule('R_b')
    R_w = Rule('R_w')
    K_dy_dx = Rule('K_dy_dx')
    R_b_dx = Rule('R_b_dx')
    R_w_dx = Rule('R_w_dx')
    R_b_as_dx = Rule('R_b_as_dx')
    R_w_as_dx = Rule('R_w_as_dx')
    R_b_head_dx = Rule('R_b_head_dx')
    R_w_head_dx = Rule('R_w_head_dx')
    Bij = pybo.BijectionSampler
    Trans = pybo.TransformationSampler
    Hook = pybo.HookSampler
    DxFromDy = pybo.LDerFromUDerSampler

    grammar = pybo.DecompositionGrammar()

    # Add the decomposition rules.
    grammar.rules = {

        # Underived and derived binary trees.
        'K':
        Hook(Trans(K_dy, underive),
             before=EarlyRejectionControl.activate_rejection,
             after=EarlyRejectionControl.deactivate_rejection),  # See 4.1.6.
        'K_dx':
        DxFromDy(
            K_dy,
            alpha_l_u=2 / 3  # See 5.3.1.
        ),
        'K_dy':
        pybo.RestartableSampler(
            Hook(
                Bij(R_b_as + R_w_as, to_K_dy),
                EarlyRejectionControl.
                reset  # Reset leaf-counter before sampling from this rule.
            ), ),
        'R_b_as':
        R_w * L() * U() + U() * L() * R_w + R_w * L() * R_w,
        'R_w_as':
        R_b_head * U() + U() * R_b_head + R_b**2,
        'R_b_head':
        R_w_head * L() * R_b_head_help + R_b_head_help * L() * R_w_head +
        R_w_head * L() * R_w_head,
        'R_b_head_help':
        U() * U(),
        'R_w_head':
        U() + R_b * U() + U() * R_b + R_b**2,
        'R_b': (U() + R_w) * L() * (U() + R_w),
        'R_w': (U() + R_b)**2,

        # Bi-derived binary trees.
        'K_dx_dx':
        DxFromDy(
            K_dy_dx,
            alpha_l_u=2 / 3  # See 5.3.1, 2/3 is also valid for K_dx.
        ),
        'K_dy_dx':
        Bij(R_b_as_dx + R_w_as_dx, to_K_dy_dx),
        'R_b_as_dx':
        U() * L() * R_w_dx + R_w_dx * L() * U() + R_w * L() * R_w_dx +
        R_w_dx * L() * R_w + U() * R_w + R_w * U() + R_w**2,
        'R_w_as_dx':
        R_b_head_dx * U() + U() * R_b_head_dx + R_b * R_b_dx + R_b_dx * R_b,
        'R_b_head_dx':
        R_b_head_help * L() * R_w_head_dx + R_w_head_dx * L() * R_b_head_help +
        R_w_head * L() * R_w_head_dx + R_w_head_dx * L() * R_w_head +
        R_w_head * R_b_head_help + R_b_head_help * R_w_head + R_w_head**2,
        'R_w_head_dx':
        R_b_dx * (R_b + U()) + (R_b + U()) * R_b_dx,  # is the same as R_w_dx!
        'R_b_dx': (U() + R_w)**2 + R_w_dx * L() * (U() + R_w) +
        (U() + R_w) * L() * R_w_dx,
        'R_w_dx':
        R_b_dx * (U() + R_b) + (U() + R_b) * R_b_dx,
    }

    # Set builders.
    grammar.set_builder([
        'R_w', 'R_w_head', 'R_w_as', 'R_b_head_help', 'R_w_dx', 'R_w_head_dx',
        'R_w_as_dx'
    ], WhiteRootedBinaryTreeBuilder())
    grammar.set_builder(
        ['R_b', 'R_b_head', 'R_b_as', 'R_b_dx', 'R_b_head_dx', 'R_b_as_dx'],
        BlackRootedBinaryTreeBuilder())

    # Set the grammar in the early rejection control variables.
    EarlyRejectionControl.grammar = grammar

    # We do not init the grammar here.
    return grammar
def three_connected_graph_grammar():
    """Builds the three-connected planar graph grammar.

    Returns
    -------
    DecompositionGrammar
        The grammar for sampling from G_3_arrow_dx and G_3_arrow_dy
    """

    # Some shorthands to keep the grammar readable.
    Rule = pybo.AliasSampler
    J_a = Rule('J_a')
    J_a_dx = Rule('J_a_dx')
    J_a_dx_dx = Rule('J_a_dx_dx')
    G_3_arrow = Rule('G_3_arrow')
    G_3_arrow_dx = Rule('G_3_arrow_dx')
    G_3_arrow_dx_dx = Rule('G_3_arrow_dx_dx')
    G_3_arrow_dx_dy = Rule('G_3_arrow_dx_dy')
    M_3_arrow = Rule('M_3_arrow')
    M_3_arrow_dx = Rule('M_3_arrow_dx')
    M_3_arrow_dx_dx = Rule('M_3_arrow_dx_dx')
    Bij = pybo.BijectionSampler
    Rej = pybo.RejectionSampler
    Trans = pybo.TransformationSampler
    DyFromDx = pybo.UDerFromLDerSampler

    grammar = pybo.DecompositionGrammar()
    # Depends on irreducible dissection so we add those rules.
    grammar.rules = irreducible_dissection_grammar().rules
    EarlyRejectionControl.grammar = grammar

    grammar.add_rules({

        # Non-derived 3-connected rooted planar maps/graphs.
        'M_3_arrow':
        Bij(J_a, primal_map),
        'G_3_arrow':
        Trans(M_3_arrow, eval_transform=divide_by_2),  # See 4.1.9.

        # Derived 3-connected rooted planar maps/graphs.
        'M_3_arrow_dx':
        Bij(J_a_dx, primal_map),
        'G_3_arrow_dx':
        Trans(M_3_arrow_dx, to_l_derived_class, eval_transform=divide_by_2),
        'G_3_arrow_dy':
        Bij(
            DyFromDx(G_3_arrow_dx, alpha_u_l=3),  # See 5.3.3.
            mark_u_atom),

        # Bi-derived 3-connected rooted planar maps/graphs.
        'M_3_arrow_dx_dx':
        Bij(J_a_dx_dx, primal_map),
        'G_3_arrow_dx_dx':
        Trans(M_3_arrow_dx_dx,
              to_bi_l_derived_class,
              eval_transform=divide_by_2),
        'G_3_arrow_dx_dy':
        Bij(DyFromDx(G_3_arrow_dx_dx, alpha_u_l=3), mark_u_atom),
        'G_3_arrow_dy_dy':
        Bij(
            DyFromDx(Bij(G_3_arrow_dx_dy,
                         lambda gamma: gamma.invert_derivation_order()),
                     alpha_u_l=3), mark_2_u_atoms),

        # Usual 3-connected planar graphs for testing/debugging purposes.
        'G_3':
        Bij(Rej(G_3_arrow, lambda g: pybo.bern(1 / g.number_of_edges)),
            lambda g: HalfEdgeGraph(g.half_edge)),
    })

    return grammar