Пример #1
0
def optimize(config):
    """ This is the core function."""
    #---------------------------------------------------------------------------
    # Config validation.
    #---------------------------------------------------------------------------
    if config.feasinfeas_2N:
        assert config.novelty is not None, 'Must set a novelty method for feasinfeas_2N'
    assert config.novelty is False or config.novelty in novelty.archives, 'Novelty method does not exist:' + config.novelty
    feasinfeas = bool(config.feasinfeas) or bool(config.feasinfeas_2N)
    if config.out is not None:
        os.makedirs(config.out, exist_ok=False)
    for k, v in vars(config).items():
        if k[0] != '_': print(f'{k}: {v}')
    original_state = State.fromFile(config.state)
    original_state = original_state.mergeIslands()[0]
    if config.seed is not None:
        random.seed(config.seed)
        np.random.seed(config.seed)
    # for metric_name, limit, in config.metrics:
    #     assert (type(limit) is float and 0 <= limit <= 1), F'{limit} is not a number.'
    #     assert hasattr(metrics, metric_name), F'{metric_name} is not a metric.'
    print('-' * 80)
    #---------------------------------------------------------------------------
    # The core of the code. First, contract the state graph.
    #---------------------------------------------------------------------------
    print('Subdividing State:')
    states = [original_state]
    mappings = [None]
    while states[-1].n_tiles > config.max_start_tiles:
        state, mapping = states[-1].contract()
        states.append(state)
        mappings.append(mapping)
    states = states[::-1]
    mappings = mappings[::-1]
    #---------------------------------------------------------------------------
    # Second, Create an initial population that has populaiton equality.
    #---------------------------------------------------------------------------
    state = states[0]
    print(f"{'-'*80}\nCreating Initial Population:")
    seeds = np.array(feasible_seeds(state, config))
    #---------------------------------------------------------------------------
    # Create metrics and hypervolume-masks. Masks determine which metrics are
    # used for hypervolume.
    #---------------------------------------------------------------------------
    used_metrics = []  # list of funtions that return floats.
    used_constraints = []  # list of funtions that return binary.
    if feasinfeas:
        feas_mask = []  # Binary array if metric_i is used in feas.
        infeas_mask = []  # Binary array if metric_i is used in infeas.

    metrics_limits = np.array([metrics.limits[m] for m in config.metrics])
    for mi, name in enumerate(config.metrics):
        limit = metrics.limits[name]
        used_metrics.append(getattr(metrics, name))

        if limit < 1.0:
            used_constraints.append(
                partial(value_constraint, index=mi, threshold=limit))
        if feasinfeas:
            feas_mask.append(True)
            infeas_mask.append(
                limit < 1.0)  # If it has a limit it is a constraint.

    if config.equality_constraint > 0:
        used_constraints.append(
            partial(equality_constraint, threshold=config.equality_constraint))
        if feasinfeas:  # FI uses contraints as objectives in infeas population.
            used_metrics.append(
                partial(metrics.equality
                        ))  # Equality objective does not have a threshold.
            feas_mask.append(False)  # Only infeas population considers this.
            infeas_mask.append(True)

    if feasinfeas and config.novelty:  # add the flag for novelty last.
        infeas_mask.append(True)  # Infeas always uses novelty.
        feas_mask.append(config.feasinfeas_2N
                         )  # Feas pop only uses novelty if this flag set.

    ALG = NSGA2
    if config.NSGA3:
        from pymoo.factory import get_reference_directions
        #TODO: grid search nsga3 params.
        ref_dirs = get_reference_directions("das-dennis",
                                            len(hv_mask),
                                            n_partitions=50)
        ALG = partial(NSGA3, ref_dirs=ref_dirs)

    if feasinfeas:
        run_fi = partial(run_fi_optimization,
                         feas_mask=feas_mask,
                         infeas_mask=infeas_mask)
        assert len(feas_mask) == len(infeas_mask) == (len(used_metrics) +
                                                      bool(config.novelty))

    #---------------------------------------------------------------------------
    # Run a optimization process for each resolution using the previous
    # outputs as the seeds for the next.
    #---------------------------------------------------------------------------
    print('-' * 80 + '\n' + 'Starting Optimization:')
    hv_histories = []
    # pf_histories = []
    n_gens = config.n_gens // len(states)

    for opt_i, (state, mapping) in enumerate(zip(states, mappings)):
        print('-' * 80)
        print(f'Optimizing {opt_i} / {len(states)}')
        print(f'\tNum tiles: {state.n_tiles}')
        last_phase = opt_i == len(states) - 1
        OPT = run_fi if feasinfeas else run_optimization
        result, hv_history = OPT(ALG, state, used_metrics, used_constraints,
                                 seeds, config, n_gens, opt_i)
        hv_histories.append(hv_history)
        # pf_histories.append(pf_history)
        if config.out is not None:
            save_results(config, state, result, opt_i,
                         hv_history)  #, pf_history)
            plot_results(config, state, result, opt_i,
                         hv_history)  #, pf_history)
        if not last_phase:
            # seeds = upscale(result.X, mapping)
            seeds = upscale(result.pop.get('X'), mapping)
        print('Final HV %f' % hv_history[-1])

    return result.X.tolist(), result.F.tolist(), hv_histories
Пример #2
0
def upscale(districts, mapping):
    upscaled = np.zeros((districts.shape[0], mapping.shape[0]), dtype='i')
    for i in range(districts.shape[0]):
        for j in range(mapping.shape[0]):
            upscaled[i, j] = districts[i, mapping[j]]
    return upscaled

pygame.init()
# seed = 1337
seed = 1

if len(sys.argv) == 1:
    states = [ State.makeRandom(1000, seed=seed) ]
else:
    states = [ State.fromFile(sys.argv[1]) ]

if len(sys.argv) == 1:
    ### Subdivide voronoi grid map. ###
    n_districts = 10
    n_divisions = 2
    mappings = [ None ]

    screen = pygame.display.set_mode(( 2000, 500 ))
    screen.fill(( 255, 255, 255 ))

    for _ in range(n_divisions):
        state, mapping = states[-1].contract(seed=seed)
        states.append(state)
        mappings.append(mapping)