def main(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('output',
                        metavar='graph.pickle',
                        help='Ouput graph file')
    parser.add_argument(
        '--connection',
        default='postgresql://*****:*****@localhost/osrm',
        help='Postgres connection string.  Default %(default)s')
    parser.add_argument('--prune',
                        action='store_true',
                        help='Collapse redundant edges, prune tails')

    parser.add_argument('--verbose',
                        action='store_true',
                        help='Increase logging level')

    args = parser.parse_args()

    logging.basicConfig(
        level=logging.INFO if args.verbose else logging.WARNING)

    log.info("Creating DB engine")
    engine = create_engine(args.connection, echo=False)

    log.info("Creating DB session")
    Session = sessionmaker(bind=engine)
    session = Session()

    g = build_graph(session)

    if args.prune:
        log.info("Collapsing unidirectional strings")
        pruned = graphtools.collapse_degree_2_vtxs(g)
        log.info("Removed %i thru-nodes", pruned)
        log.info("Collapsing bidirectional strings")
        pruned = graphtools.collapse_bidirectional_streets(g)
        log.info("Removed %i thru-nodes", pruned)
        log.info("Snipping tails")
        snipped = graphtools.delete_degree_1_vtxs(g)
        log.info("Removed %i tails", snipped)
        loners = graphtools.delete_degree_0_vtxs(g)
        log.info("Removed %i loner-nodes (should be zero)", loners)
        redundancies = graphtools.identify_rendudant_nodes(g)
        log.info("Marked %i nodes as redundant", redundancies)

    log.info("Saving graph to %s", args.output)
    g.save(args.output)
def main(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('output', metavar='graph.pickle',
                        help='Ouput graph file')
    parser.add_argument(
        '--connection',
        default='postgresql://*****:*****@localhost/osrm',
        help='Postgres connection string.  Default %(default)s'
    )
    parser.add_argument('--prune', action='store_true',
                        help='Collapse redundant edges, prune tails')

    parser.add_argument('--verbose', action='store_true',
                        help='Increase logging level')

    args = parser.parse_args()

    logging.basicConfig(
        level=logging.INFO if args.verbose else logging.WARNING)

    log.info("Creating DB engine")
    engine = create_engine(args.connection, echo=False)

    log.info("Creating DB session")
    Session = sessionmaker(bind=engine)
    session = Session()

    g = build_graph(session)

    if args.prune:
        log.info("Collapsing unidirectional strings")
        pruned = graphtools.collapse_degree_2_vtxs(g)
        log.info("Removed %i thru-nodes", pruned)
        log.info("Collapsing bidirectional strings")
        pruned = graphtools.collapse_bidirectional_streets(g)
        log.info("Removed %i thru-nodes", pruned)
        log.info("Snipping tails")
        snipped = graphtools.delete_degree_1_vtxs(g)
        log.info("Removed %i tails", snipped)
        loners = graphtools.delete_degree_0_vtxs(g)
        log.info("Removed %i loner-nodes (should be zero)", loners)
        redundancies = graphtools.identify_rendudant_nodes(g)
        log.info("Marked %i nodes as redundant", redundancies)

    log.info("Saving graph to %s", args.output)
    g.save(args.output)
def test_identify_rendudant_nodes():
    g = igraph.Graph(directed=True)
    # A X with two sub-Ys at the end of each top bit.
    g.add_vertices(9)
    # the outer rectange
    g.add_edges([
        (0, 1),  # input X 1
        (8, 1),  # input X 2

        (1, 2),  # left leg
        (1, 3),  # right leg

        (2, 4),  # left leg subY 1
        (2, 5),  # left leg subY 2

        (3, 6),  # right leg subY 2
        (3, 7),  # right leg subY 2
    ])

    expected = [
        False,   # node 0 w/o ancestors, never redundant
        False,   # node 1 gets input from 0 and 8
        # everything else goes through node 1
        True,
        True,
        True,
        True,
        True,
        True,
        False,   # node 8 w/o ancestors, never redundant
    ]
    eq_(len(expected), 9)

    ret = gt.identify_rendudant_nodes(g)
    eq_(ret, 6)
    eq_(g.vs["redundant"], expected)