Code to generate test graphs
This commit is contained in:
		
							parent
							
								
									4203b1e5cc
								
							
						
					
					
						commit
						38374e293f
					
				| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
#!/bin/bash
 | 
			
		||||
#
 | 
			
		||||
# Generate a set of test graphs.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
SRCDIR="$(dirname $0)"
 | 
			
		||||
 | 
			
		||||
# Usage: gen_random SEED N M
 | 
			
		||||
gen_random() {
 | 
			
		||||
    python3 $SRCDIR/make_random_graph.py --seed $1 $2 $3 \
 | 
			
		||||
      > graph_rnd_s${1}_n${2}_m${3}.gr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Usage: gen_slow STRUCTURE N M
 | 
			
		||||
gen_slow() {
 | 
			
		||||
    python3 $SRCDIR/make_slow_graph.py --structure $1 $2 \
 | 
			
		||||
      > graph_slow_${1}_n${2}_m${3}.gr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
gen_random 101 250 31125
 | 
			
		||||
gen_random 102 250 31125
 | 
			
		||||
gen_random 103 250  3952
 | 
			
		||||
gen_random 104 250  3952
 | 
			
		||||
gen_random 105 250  2500
 | 
			
		||||
gen_random 106 250  2500
 | 
			
		||||
 | 
			
		||||
gen_random 111 500 124750
 | 
			
		||||
gen_random 112 500 124750
 | 
			
		||||
gen_random 113 500  11180
 | 
			
		||||
gen_random 114 500  11180
 | 
			
		||||
gen_random 115 500   5000
 | 
			
		||||
gen_random 116 500   5000
 | 
			
		||||
 | 
			
		||||
gen_random 121 1000 499500
 | 
			
		||||
gen_random 122 1000 499500
 | 
			
		||||
gen_random 123 1000  31622
 | 
			
		||||
gen_random 124 1000  31622
 | 
			
		||||
gen_random 125 1000  10000
 | 
			
		||||
gen_random 126 1000  10000
 | 
			
		||||
 | 
			
		||||
gen_random 133 2000   89442
 | 
			
		||||
gen_random 134 2000   89442
 | 
			
		||||
gen_random 135 2000   20000
 | 
			
		||||
gen_random 136 2000   20000
 | 
			
		||||
 | 
			
		||||
gen_random 143 5000  353553
 | 
			
		||||
gen_random 144 5000  353553
 | 
			
		||||
gen_random 145 5000   50000
 | 
			
		||||
gen_random 146 5000   50000
 | 
			
		||||
 | 
			
		||||
gen_random 155 10000 100000
 | 
			
		||||
gen_random 156 10000 100000
 | 
			
		||||
 | 
			
		||||
gen_slow dense    252  4095
 | 
			
		||||
gen_slow dense    500 15875
 | 
			
		||||
gen_slow dense   1000 63000
 | 
			
		||||
gen_slow sparse   252   312
 | 
			
		||||
gen_slow sparse   500   622
 | 
			
		||||
gen_slow sparse  1004  1252
 | 
			
		||||
gen_slow sparse  2004  2502
 | 
			
		||||
gen_slow sparse  5004  6252
 | 
			
		||||
gen_slow sparse 10004 12502
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,131 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Generate a random graph in DIMACS format.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import argparse
 | 
			
		||||
import random
 | 
			
		||||
from typing import TextIO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def write_dimacs_graph(
 | 
			
		||||
        f: TextIO,
 | 
			
		||||
        edges: list[tuple[int, int, int|float]]
 | 
			
		||||
        ) -> None:
 | 
			
		||||
    """Write a graph in DIMACS edge list format."""
 | 
			
		||||
 | 
			
		||||
    num_vertex = 1 + max(max(x, y) for (x, y, _w) in edges)
 | 
			
		||||
    num_edge = len(edges)
 | 
			
		||||
 | 
			
		||||
    print(f"p edge {num_vertex} {num_edge}", file=f)
 | 
			
		||||
 | 
			
		||||
    integer_weights = all(isinstance(w, int) for (_x, _y, w) in edges)
 | 
			
		||||
 | 
			
		||||
    for (x, y, w) in edges:
 | 
			
		||||
        if integer_weights:
 | 
			
		||||
            print(f"e {x+1} {y+1} {w}", file=f)
 | 
			
		||||
        else:
 | 
			
		||||
            print(f"e {x+1} {y+1} {w:.12g}", file=f)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def make_random_graph(
 | 
			
		||||
        n: int,
 | 
			
		||||
        m: int,
 | 
			
		||||
        max_weight: float,
 | 
			
		||||
        float_weights: bool,
 | 
			
		||||
        rng: random.Random
 | 
			
		||||
        ) -> list[tuple[int, int, int|float]]:
 | 
			
		||||
    """Generate a random graph with random edge weights."""
 | 
			
		||||
 | 
			
		||||
    edge_set: set[tuple[int, int]] = set()
 | 
			
		||||
 | 
			
		||||
    if 3 * m < n * (n - 2) // 2:
 | 
			
		||||
        # Simply add random edges until we have enough.
 | 
			
		||||
        while len(edge_set) < m:
 | 
			
		||||
            x = rng.randint(0, n - 2)
 | 
			
		||||
            y = rng.randint(x + 1, n - 1)
 | 
			
		||||
            edge_set.add((x, y))
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
        # We need a very dense graph.
 | 
			
		||||
        # Generate all edge candidates and choose a random subset.
 | 
			
		||||
        edge_candidates = [(x, y)
 | 
			
		||||
                           for x in range(n - 1)
 | 
			
		||||
                           for y in range(x + 1, n)]
 | 
			
		||||
        rng.shuffle(edge_candidates)
 | 
			
		||||
        edge_set.update(edge_candidates[:m])
 | 
			
		||||
 | 
			
		||||
    edges: list[tuple[int, int, int|float]] = []
 | 
			
		||||
    for (x, y) in sorted(edge_set):
 | 
			
		||||
        w: int|float
 | 
			
		||||
        if float_weights:
 | 
			
		||||
            w = rng.uniform(1.0e-8, max_weight)
 | 
			
		||||
        else:
 | 
			
		||||
            w = rng.randint(1, int(max_weight))
 | 
			
		||||
        edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
    return edges
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main() -> int:
 | 
			
		||||
    """Main program."""
 | 
			
		||||
 | 
			
		||||
    parser = argparse.ArgumentParser()
 | 
			
		||||
    parser.description = "Generate a random graph in DIMACS format."
 | 
			
		||||
 | 
			
		||||
    parser.add_argument("--seed",
 | 
			
		||||
                        action="store",
 | 
			
		||||
                        type=int,
 | 
			
		||||
                        help="random seed")
 | 
			
		||||
    parser.add_argument("--maxweight",
 | 
			
		||||
                        action="store",
 | 
			
		||||
                        type=float,
 | 
			
		||||
                        default=1000000,
 | 
			
		||||
                        help="maximum edge weight")
 | 
			
		||||
    parser.add_argument("--float",
 | 
			
		||||
                        action="store_true",
 | 
			
		||||
                        help="use floating point edge weights")
 | 
			
		||||
    parser.add_argument("n",
 | 
			
		||||
                        action="store",
 | 
			
		||||
                        type=int,
 | 
			
		||||
                        help="number of vertices")
 | 
			
		||||
    parser.add_argument("m",
 | 
			
		||||
                        action="store",
 | 
			
		||||
                        type=int,
 | 
			
		||||
                        help="number of edges")
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    if args.n < 2:
 | 
			
		||||
        print("ERROR: Number of vertices must be >= 2", file=sys.stderr)
 | 
			
		||||
        return 1
 | 
			
		||||
 | 
			
		||||
    if args.m < 1:
 | 
			
		||||
        print("ERROR: Number of edges must be >= 1", file=sys.stderr)
 | 
			
		||||
        return 1
 | 
			
		||||
 | 
			
		||||
    if args.m > args.n * (args.n - 1) // 2:
 | 
			
		||||
        print("ERROR: Too many edges", file=sys.stderr)
 | 
			
		||||
        return 1
 | 
			
		||||
 | 
			
		||||
    if args.maxweight < 1.0e-6:
 | 
			
		||||
        print("ERROR: Invalid maximum edge weight", file=sys.stderr)
 | 
			
		||||
        return 1
 | 
			
		||||
 | 
			
		||||
    if args.seed is None:
 | 
			
		||||
        rng = random.Random()
 | 
			
		||||
    else:
 | 
			
		||||
        rng = random.Random(args.seed)
 | 
			
		||||
 | 
			
		||||
    edges = make_random_graph(args.n, args.m, args.maxweight, args.float, rng)
 | 
			
		||||
    write_dimacs_graph(sys.stdout, edges)
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    sys.exit(main())
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,301 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Generate a graph that is "difficult" for the O(n**3) matching algorithm.
 | 
			
		||||
 | 
			
		||||
Output in DIMACS format.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import argparse
 | 
			
		||||
from typing import TextIO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
count_make_blossom = [0]
 | 
			
		||||
count_delta_step = [0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def patch_matching_code() -> None:
 | 
			
		||||
    """Patch the matching code to count events."""
 | 
			
		||||
 | 
			
		||||
    import max_weight_matching
 | 
			
		||||
 | 
			
		||||
    orig_make_blossom = max_weight_matching._MatchingContext.make_blossom
 | 
			
		||||
    orig_substage_calc_dual_delta = (
 | 
			
		||||
        max_weight_matching._MatchingContext.substage_calc_dual_delta)
 | 
			
		||||
 | 
			
		||||
    def stub_make_blossom(*args, **kwargs):
 | 
			
		||||
        count_make_blossom[0] += 1
 | 
			
		||||
        return orig_make_blossom(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def stub_substage_calc_dual_delta(*args, **kwargs):
 | 
			
		||||
        count_delta_step[0] += 1
 | 
			
		||||
        ret = orig_substage_calc_dual_delta(*args, **kwargs)
 | 
			
		||||
#        print("DELTA", ret)
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
    max_weight_matching._MatchingContext.make_blossom = stub_make_blossom
 | 
			
		||||
    max_weight_matching._MatchingContext.substage_calc_dual_delta = (
 | 
			
		||||
        stub_substage_calc_dual_delta)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run_max_weight_matching(
 | 
			
		||||
        edges: list[tuple[int, int, int]]
 | 
			
		||||
        ) -> tuple[list[tuple[int, int]], int, int]:
 | 
			
		||||
    """Run the matching algorithm and count subroutine calls."""
 | 
			
		||||
    import max_weight_matching
 | 
			
		||||
 | 
			
		||||
    count_make_blossom[0] = 0
 | 
			
		||||
    count_delta_step[0] = 0
 | 
			
		||||
 | 
			
		||||
    pairs = max_weight_matching.maximum_weight_matching(edges)
 | 
			
		||||
    return (pairs, count_make_blossom[0], count_delta_step[0])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def write_dimacs_graph(
 | 
			
		||||
        f: TextIO,
 | 
			
		||||
        edges: list[tuple[int, int, int]]
 | 
			
		||||
        ) -> None:
 | 
			
		||||
    """Write a graph in DIMACS edge list format."""
 | 
			
		||||
 | 
			
		||||
    num_vertex = 1 + max(max(x, y) for (x, y, _w) in edges)
 | 
			
		||||
    num_edge = len(edges)
 | 
			
		||||
 | 
			
		||||
    print(f"p edge {num_vertex} {num_edge}", file=f)
 | 
			
		||||
 | 
			
		||||
    for (x, y, w) in edges:
 | 
			
		||||
        print(f"e {x+1} {y+1} {w}", file=f)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def make_dense_slow_graph(n: int) -> list[tuple[int, int, int]]:
 | 
			
		||||
    """Generate a dense (not complete) graph with N vertices.
 | 
			
		||||
 | 
			
		||||
    N must be divisible by 4.
 | 
			
		||||
 | 
			
		||||
    Number of edges = M = (N**2/16 + N/2).
 | 
			
		||||
    Number of delta steps required to solve the matching = (M - 1).
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    assert n % 4 == 0
 | 
			
		||||
 | 
			
		||||
    edges: list[tuple[int, int, int]] = []
 | 
			
		||||
 | 
			
		||||
    num_peripheral_pairs = n // 4
 | 
			
		||||
    num_central_pairs = n // 4
 | 
			
		||||
    max_weight = 2 * num_central_pairs * (num_peripheral_pairs + 1)
 | 
			
		||||
 | 
			
		||||
    # Peripheral pairs will be matched up first.
 | 
			
		||||
    for i in range(num_peripheral_pairs):
 | 
			
		||||
        x = 2 * i
 | 
			
		||||
        y = x + 1
 | 
			
		||||
        w = max_weight - i
 | 
			
		||||
        edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
    # Then for each central pair:
 | 
			
		||||
    for k in range(num_central_pairs):
 | 
			
		||||
 | 
			
		||||
        x = 2 * num_peripheral_pairs + 2 * k
 | 
			
		||||
 | 
			
		||||
        # Central pair discovers all peripheral pairs.
 | 
			
		||||
        for i in range(num_peripheral_pairs):
 | 
			
		||||
            y = 2 * i
 | 
			
		||||
            if k % 2 == 0:
 | 
			
		||||
                w = max_weight - (1 + k // 2) * (num_peripheral_pairs + 1) + 1
 | 
			
		||||
            else:
 | 
			
		||||
                w = max_weight - (1 + k // 2) * (num_peripheral_pairs + 1) - i
 | 
			
		||||
            edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
        # Then this central pair gets matched.
 | 
			
		||||
        y = x + 1
 | 
			
		||||
        w = max_weight - (k + 1) * (2 * num_peripheral_pairs + 1)
 | 
			
		||||
        edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
    return edges
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def make_sparse_slow_graph(n: int) -> list[tuple[int, int, int]]:
 | 
			
		||||
    """Generate a sparse graph with N vertices.
 | 
			
		||||
 | 
			
		||||
    N must be 4 modulo 8.
 | 
			
		||||
 | 
			
		||||
    Number of edges = M = (5/4 * N - 3).
 | 
			
		||||
    Number of delta steps required to solve the matching ~ (N**2 / 16).
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    assert n >= 12
 | 
			
		||||
    assert n % 8 == 4
 | 
			
		||||
 | 
			
		||||
    num_p_pairs = (n - 4) // 4
 | 
			
		||||
    num_q_pairs = num_p_pairs // 2
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Graph structure:
 | 
			
		||||
    #
 | 
			
		||||
    #   O       O       O       O       O
 | 
			
		||||
    #   |       |       |       |       |     (P pairs of nodes)
 | 
			
		||||
    #   |       |       |       |       |     (one edge in each pair)
 | 
			
		||||
    #   O___    O       O       O    ___O
 | 
			
		||||
    #    \_ \   |\     / \    _/|   /  /
 | 
			
		||||
    #      \    |    _/    __/  |    _/       (2 * P edges)
 | 
			
		||||
    #       \_  |  _/   __/     |  _/         (connecting both coupling pairs
 | 
			
		||||
    #         \ | /  __/      \ | /            to each top-layer pair)
 | 
			
		||||
    #          \|/__/       \  \|/
 | 
			
		||||
    #           O------/  \--\--O
 | 
			
		||||
    #           |               |             (2 coupling pairs)
 | 
			
		||||
    #           |               |             (1 edge in each pair)
 | 
			
		||||
    #           O               O
 | 
			
		||||
    #          / \             / \            (2 * Q edges)
 | 
			
		||||
    #         /   \           /   \           (connecting each coupling pair
 | 
			
		||||
    #        /     \         /     \           to the Q pairs below it)
 | 
			
		||||
    #       O       O       O       O
 | 
			
		||||
    #       |       |       |       |         (2 groups of Q pairs of nodes)
 | 
			
		||||
    #       |       |       |       |         (1 edge in each pair)
 | 
			
		||||
    #       O       O       O       O
 | 
			
		||||
    #
 | 
			
		||||
    # Plan:
 | 
			
		||||
    #  - First, match each pair in the top layer.
 | 
			
		||||
    #  - Then, pull all edges between the top-layer and the
 | 
			
		||||
    #    left coupling pair tight (without matching anything).
 | 
			
		||||
    #  - Then match the left coupling pair.
 | 
			
		||||
    #  - Then pull all edges between the top-layer and the
 | 
			
		||||
    #    right coupling pair tight. (This will loosen the edges
 | 
			
		||||
    #    between the top-layer and the left coupling pair.)
 | 
			
		||||
    #  - Then match the right coupling pair.
 | 
			
		||||
    #  - Then alternate between the bottom left group and bottom right group
 | 
			
		||||
    #    of pairs:
 | 
			
		||||
    #     - Pick a new pair from the selected bottom group.
 | 
			
		||||
    #     - Pull the edge to its coupling pair tight.
 | 
			
		||||
    #     - Pull all edges between the coupling pair and the top-layer tight.
 | 
			
		||||
    #       (This will loosen the edges between the top-layer and the other
 | 
			
		||||
    #        coupling pair.)
 | 
			
		||||
    #     - Match the selected bottom pair.
 | 
			
		||||
    #
 | 
			
		||||
    # The trick is to assign edge weights that force the matching
 | 
			
		||||
    # algorithm to execute the plan as descibed above.
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    edges: list[tuple[int, int, int]] = []
 | 
			
		||||
 | 
			
		||||
    max_weight = 16 * (num_q_pairs + 1) * (num_p_pairs + 2)
 | 
			
		||||
 | 
			
		||||
    # Make the top pairs.
 | 
			
		||||
    for i in range(num_p_pairs):
 | 
			
		||||
        x = 2 * i
 | 
			
		||||
        y = 2 * i + 1
 | 
			
		||||
        w = max_weight - i
 | 
			
		||||
        edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
    # Make the coupling pairs.
 | 
			
		||||
    for k in range(2):
 | 
			
		||||
 | 
			
		||||
        # Connect the coupling pair to the top layer.
 | 
			
		||||
        for i in range(num_p_pairs):
 | 
			
		||||
            x = 2 * i + 1
 | 
			
		||||
            y = 2 * num_p_pairs + 2 * k
 | 
			
		||||
            if k == 0:
 | 
			
		||||
                w = max_weight - num_p_pairs
 | 
			
		||||
            else:
 | 
			
		||||
                w = max_weight - num_p_pairs - 1 - i
 | 
			
		||||
            edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
        # Make the internal edge in the coupling pair.
 | 
			
		||||
        x = 2 * num_p_pairs + 2 * k
 | 
			
		||||
        y = 2 * num_p_pairs + 2 * k + 1
 | 
			
		||||
        if k == 0:
 | 
			
		||||
            w = max_weight - 2 * num_p_pairs - 1
 | 
			
		||||
        else:
 | 
			
		||||
            w = max_weight - 4 * num_p_pairs - 2
 | 
			
		||||
        edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
    # Make the bottom groups.
 | 
			
		||||
    for k in range(2):
 | 
			
		||||
 | 
			
		||||
        # Connect the coupling pair to the bottom layer.
 | 
			
		||||
        for i in range(num_q_pairs):
 | 
			
		||||
            x = 2 * num_p_pairs + 2 * k + 1
 | 
			
		||||
            y = 2 * num_p_pairs + 4 + 2 * num_q_pairs * k + 2 * i
 | 
			
		||||
            w = (max_weight
 | 
			
		||||
                 - (2 * i + k) * (2 * num_p_pairs + 4)
 | 
			
		||||
                 - 4 * num_p_pairs + 1)
 | 
			
		||||
            edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
        # Make the pairs in this half of the bottom layer.
 | 
			
		||||
        for i in range(num_q_pairs):
 | 
			
		||||
            x = 2 * num_p_pairs + 4 + 2 * num_q_pairs * k + 2 * i
 | 
			
		||||
            y = 2 * num_p_pairs + 4 + 2 * num_q_pairs * k + 2 * i + 1
 | 
			
		||||
            w = (max_weight
 | 
			
		||||
                 - (2 * i + k + 1) * 8 * num_p_pairs
 | 
			
		||||
                 - (2 * i + k) * 12)
 | 
			
		||||
            edges.append((x, y, w))
 | 
			
		||||
 | 
			
		||||
    return edges
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main() -> int:
 | 
			
		||||
    """Main program."""
 | 
			
		||||
 | 
			
		||||
    parser = argparse.ArgumentParser()
 | 
			
		||||
    parser.description = "Generate a difficult graph."
 | 
			
		||||
 | 
			
		||||
    parser.add_argument("--structure",
 | 
			
		||||
                        action="store",
 | 
			
		||||
                        choices=("sparse", "dense"),
 | 
			
		||||
                        default="sparse",
 | 
			
		||||
                        help="choose graph structure")
 | 
			
		||||
    parser.add_argument("--check",
 | 
			
		||||
                        action="store_true",
 | 
			
		||||
                        help="solve the matching and count delta steps")
 | 
			
		||||
    parser.add_argument("n",
 | 
			
		||||
                        action="store",
 | 
			
		||||
                        type=int,
 | 
			
		||||
                        help="number of vertices")
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    if args.check:
 | 
			
		||||
        patch_matching_code()
 | 
			
		||||
 | 
			
		||||
    if args.structure == "sparse":
 | 
			
		||||
 | 
			
		||||
        if args.n < 12:
 | 
			
		||||
            print("ERROR: Number of vertices must be >= 12", file=sys.stderr)
 | 
			
		||||
            return 1
 | 
			
		||||
 | 
			
		||||
        if args.n % 8 != 4:
 | 
			
		||||
            print("ERROR: Number of vertices must be 4 modulo 8",
 | 
			
		||||
                  file=sys.stderr)
 | 
			
		||||
            return 1
 | 
			
		||||
 | 
			
		||||
        edges = make_sparse_slow_graph(args.n)
 | 
			
		||||
 | 
			
		||||
    elif args.structure == "dense":
 | 
			
		||||
 | 
			
		||||
        if args.n < 4:
 | 
			
		||||
            print("ERROR: Number of vertices must be >= 4", file=sys.stderr)
 | 
			
		||||
            return 1
 | 
			
		||||
 | 
			
		||||
        if args.n % 4 != 0:
 | 
			
		||||
            print("ERROR: Number of vertices must be divisible by 4",
 | 
			
		||||
                  file=sys.stderr)
 | 
			
		||||
            return 1
 | 
			
		||||
 | 
			
		||||
        edges = make_dense_slow_graph(args.n)
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
        assert False
 | 
			
		||||
 | 
			
		||||
    if args.check:
 | 
			
		||||
        (pairs, num_blossom, num_delta) = run_max_weight_matching(edges)
 | 
			
		||||
        print(f"n={args.n} m={len(edges)} "
 | 
			
		||||
              f"nblossom={num_blossom} ndelta={num_delta}",
 | 
			
		||||
              file=sys.stderr)
 | 
			
		||||
 | 
			
		||||
    write_dimacs_graph(sys.stdout, edges)
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    sys.exit(main())
 | 
			
		||||
		Loading…
	
		Reference in New Issue