mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
extras/curs/curs.m:
extras/curs/curs.panel.m:
Make panel a separate submodule of curs, not a nested submodule.
extras/base64/base64.m:
extras/curses/mcurses.basics.m:
extras/curses/mcurses.m:
extras/curses/mcurses.misc.m:
extras/curses/mcurses.user.m:
extras/gator/evolve.m:
extras/gator/genotype.m:
extras/gator/phenotype.m:
extras/gator/tausworthe3.m:
extras/monte/dots.m:
extras/monte/geom.m:
extras/monte/hg.m:
extras/monte/monte.m:
extras/monte/rnd.m:
extras/moose/grammar.m:
extras/moose/moose.m:
extras/mopenssl/mopenssl.m:
extras/net/echo.m:
extras/net/errno.m:
extras/net/getaddrinfo.m:
extras/net/net.m:
extras/net/netdb.m:
extras/net/sockets.m:
extras/net/streams.m:
extras/net/tcp.m:
extras/net/test_lookups.m:
extras/net/types.m:
extras/odbc/odbc.m:
extras/odbc/odbc_test.m:
extras/references/README:
extras/references/reference.m:
extras/references/scoped_update.m:
extras/solver_types/library/any.m:
extras/solver_types/library/any_array.m:
extras/solver_types/library/any_assoc_list.m:
extras/solver_types/library/any_list.m:
extras/solver_types/library/any_map.m:
extras/solver_types/library/any_tree234.m:
extras/solver_types/library/any_util.m:
extras/trail/trail.m:
extras/trailed_update/samples/interpreter.m:
extras/trailed_update/samples/vqueens.m:
extras/trailed_update/tests/var_test.m:
extras/trailed_update/tr_array.m:
extras/trailed_update/tr_store.m:
extras/trailed_update/trailed_update.m:
extras/trailed_update/unsafe.m:
extras/trailed_update/var.m:
Bring programming style up to date.
259 lines
9.2 KiB
Mathematica
259 lines
9.2 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2005-2006, 2010 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: evolve.m.
|
|
% Main author: samrith.
|
|
%
|
|
% This program implements part of a genetic algorithm to determine an
|
|
% optimal set of optimisation flags to be passed to the Mercury compiler
|
|
% for a given program.
|
|
%
|
|
% It expects to be given two pieces of data as input. The first is a
|
|
% list of genotypes, where each genotype is a set of strings representing
|
|
% optimisation flags. The second is a list of phenotypes, where each
|
|
% phenotype is a list of benchmarks. These are read from the files
|
|
% generations/$n/genotypes and generations/$n/phenotypes, respectively.
|
|
%
|
|
% The program will then determine the next set of genotypes, which it
|
|
% will write in the file generations/$n+1/genotypes. It will also create
|
|
% the file generations/$n/ladder, which contains a table with all of the
|
|
% genotypes and their fitness values.
|
|
%
|
|
% Note that this program does not perform the actual benchmarking tests,
|
|
% nor does it control the evolution over multiple generations. These
|
|
% tasks are handled by the evaluate and gator scripts, respectively.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module evolve.
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module genotype.
|
|
:- import_module phenotype.
|
|
:- import_module tausworthe3.
|
|
|
|
:- import_module bool.
|
|
:- import_module char.
|
|
:- import_module float.
|
|
:- import_module getopt.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module require.
|
|
:- import_module std_util.
|
|
:- import_module string.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
main(!IO) :-
|
|
% Process any command line arguments.
|
|
io.command_line_arguments(Args, !IO),
|
|
OptionOps = option_ops_multi(short_option, long_option, option_default),
|
|
getopt.process_options(OptionOps, Args, _, Result),
|
|
(
|
|
Result = ok(OptionTable),
|
|
|
|
getopt.lookup_string_option(OptionTable, config_file,
|
|
PathToConfigFile),
|
|
getopt.lookup_string_option(OptionTable, genotypes, PathToGenotypes),
|
|
getopt.lookup_string_option(OptionTable, next_genotypes,
|
|
PathToNextGenotypes),
|
|
getopt.lookup_string_option(OptionTable, ladder, PathToLadder),
|
|
getopt.lookup_string_option(OptionTable, phenotypes, PathToPhenotypes),
|
|
|
|
getopt.lookup_int_option(OptionTable, first_seed, FirstSeed),
|
|
getopt.lookup_int_option(OptionTable, second_seed, SecondSeed),
|
|
getopt.lookup_int_option(OptionTable, third_seed, ThirdSeed)
|
|
;
|
|
Result = error(Error),
|
|
require.error(option_error_to_string(Error))
|
|
),
|
|
|
|
% Read the input files.
|
|
read_config_file(PathToConfigFile, Weightings, Flags, !IO),
|
|
genotype.read_genotypes(PathToGenotypes, Genotypes, !IO),
|
|
phenotype.read_phenotypes(PathToPhenotypes, Phenotypes, !IO),
|
|
|
|
% Apply the genetic operators to the genotypes.
|
|
some [!RNG] (
|
|
Tausworthe3Seed = tausworthe3_seed(FirstSeed, SecondSeed, ThirdSeed),
|
|
!:RNG = init_tausworthe3,
|
|
seed(Tausworthe3Seed, !RNG),
|
|
|
|
% We ensure that the following condition holds:
|
|
%
|
|
% length(Genotypes) / 2 = length(Mothers) = length(Fathers).
|
|
%
|
|
% Since the crossover/6 predicate creates two children for
|
|
% every two parents, the population will remain constant
|
|
% over generations. This is a simple way of avoiding extinction.
|
|
%
|
|
% Note that map_2in_2out_foldl/7 will simply ignore leftover elements
|
|
% if the two lists (Mothers and Fathers) are of unequal lengths.
|
|
%
|
|
Fitness = list.map(phenotype.fitness(Weightings), Phenotypes),
|
|
list.map_foldl(phenotype.selection(Genotypes, Fitness),
|
|
Genotypes, Parents, !RNG),
|
|
list.det_split_list(length(Parents) / 2, Parents, Mothers, Fathers),
|
|
map_2in_2out_foldl(genotype.crossover, Mothers, Fathers,
|
|
Sons, Daughters, !RNG),
|
|
list.append(Sons, Daughters, Children),
|
|
list.map_foldl(genotype.mutation(Flags), Children, NextGenotypes,
|
|
!.RNG, _)
|
|
),
|
|
|
|
% Print the output files.
|
|
genotype.print_genotypes(PathToNextGenotypes, NextGenotypes, !IO),
|
|
print_ladder(PathToLadder, Fitness, Genotypes, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Command line argument parsing.
|
|
%
|
|
% This section contains all the code for the predicates required by
|
|
% getopt.process_options.
|
|
%
|
|
|
|
:- type option
|
|
---> config_file
|
|
; genotypes
|
|
; next_genotypes
|
|
; ladder
|
|
; phenotypes
|
|
; first_seed
|
|
; second_seed
|
|
; third_seed.
|
|
|
|
:- pred short_option(char::in, option::out) is semidet.
|
|
|
|
short_option('c', config_file).
|
|
short_option('g', genotypes).
|
|
short_option('h', next_genotypes).
|
|
short_option('l', ladder).
|
|
short_option('p', phenotypes).
|
|
short_option('s', first_seed).
|
|
short_option('t', second_seed).
|
|
short_option('u', third_seed).
|
|
|
|
:- pred long_option(string::in, option::out) is semidet.
|
|
|
|
long_option("config-file", config_file).
|
|
long_option("genotypes", genotypes).
|
|
long_option("next-genotypes", next_genotypes).
|
|
long_option("ladder", ladder).
|
|
long_option("phenotypes", phenotypes).
|
|
long_option("first-seed", first_seed).
|
|
long_option("second-seed", second_seed).
|
|
long_option("third-seed", third_seed).
|
|
|
|
:- pred option_default(option::out, option_data::out) is multi.
|
|
|
|
option_default(config_file, string("evolve.conf")).
|
|
option_default(genotypes, string("generations/1/genotypes")).
|
|
option_default(next_genotypes, string("generations/2/genotypes")).
|
|
option_default(ladder, string("generations/1/ladder")).
|
|
option_default(phenotypes, string("generations/1/phenotypes")).
|
|
option_default(first_seed, int(0)).
|
|
option_default(second_seed, int(0)).
|
|
option_default(third_seed, int(0)).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Code for reading configuration files.
|
|
%
|
|
|
|
:- pred read_config_file(string::in, list(weighting)::out, list(flag)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
read_config_file(Path, Weightings, Flags, !IO) :-
|
|
io.open_input(Path, OpenResult, !IO),
|
|
(
|
|
OpenResult = ok(Stream),
|
|
io.read(Stream, ReadWeightingsResult, !IO),
|
|
(
|
|
ReadWeightingsResult = ok(Weightings),
|
|
io.read(Stream, ReadFlagsResult, !IO),
|
|
(
|
|
ReadFlagsResult = ok(Flags),
|
|
io.close_input(Stream, !IO)
|
|
;
|
|
ReadFlagsResult = eof,
|
|
require.error("unexpected EOF")
|
|
;
|
|
ReadFlagsResult = error(ErrorMsg, LineNum),
|
|
string.format("%d: %s", [i(LineNum), s(ErrorMsg)], Message),
|
|
require.error(Message)
|
|
)
|
|
;
|
|
ReadWeightingsResult = eof,
|
|
require.error("unexpected EOF")
|
|
;
|
|
ReadWeightingsResult = error(ErrorMsg, LineNum),
|
|
string.format("%d: %s", [i(LineNum), s(ErrorMsg)], Message),
|
|
require.error(Message)
|
|
)
|
|
;
|
|
OpenResult = error(ErrorCode),
|
|
io.error_message(ErrorCode, ErrorMessage),
|
|
require.error(ErrorMessage)
|
|
).
|
|
|
|
:- pred print_ladder(string::in, list(fitness)::in, list(genotype)::in,
|
|
io::di, io::uo) is det.
|
|
|
|
print_ladder(Path, Fitness, Genotypes, !IO) :-
|
|
io.open_output(Path, OpenResult, !IO),
|
|
(
|
|
OpenResult = ok(Stream),
|
|
|
|
list.map(string.int_to_string, 1..list.length(Fitness), C1),
|
|
C2 = list.map(phenotype.fitness_to_string, Fitness),
|
|
C3 = list.map(genotype.genotype_to_string, Genotypes),
|
|
|
|
Table = string.format_table([right(C1), right(C2), left(C3)], " * "),
|
|
io.write_string(Stream, Table, !IO),
|
|
|
|
io.close_output(Stream, !IO)
|
|
;
|
|
OpenResult = error(ErrorCode),
|
|
io.error_message(ErrorCode, ErrorMessage),
|
|
require.error(ErrorMessage)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Miscellaneous.
|
|
%
|
|
|
|
% map_2in_2out_foldl(Pred, InList1, InList2, OutList1, OutList2, !A).
|
|
%
|
|
% This predicate is the same as list.map_foldl, except that it takes
|
|
% two input lists and two output lists.
|
|
%
|
|
:- pred map_2in_2out_foldl(
|
|
pred(L, M, N, O, A, A)::(pred(in, in, out, out, in, out) is det),
|
|
list(L)::in, list(M)::in, list(N)::out, list(O)::out, A::in, A::out)
|
|
is det.
|
|
|
|
map_2in_2out_foldl(_, [], [], [], [], !A).
|
|
map_2in_2out_foldl(_, [], [_H | _T], [], [], !A).
|
|
map_2in_2out_foldl(_, [_H | _T], [], [], [], !A).
|
|
map_2in_2out_foldl(P, [H0 | T0], [H1 | T1], [H2 | T2], [H3 | T3], !A) :-
|
|
P(H0, H1, H2, H3, !A),
|
|
map_2in_2out_foldl(P, T0, T1, T2, T3, !A).
|
|
|
|
%---------------------------------------------------------------------------%
|