Commit ff7c803e authored by maitre's avatar maitre
Browse files

Elitism and reductions ok

parent 029d40c9
......@@ -72,6 +72,7 @@ Centre de Math
bool bWaitingForSemiColon,bFinishNB_GEN,bFinishMINIMISE,bFinishMINIMIZE,bGenerationFunction;
bool bCatchNextSemiColon,bWaitingToClosePopulation, bMethodsInGenome, bFinalizationFunction;
bool bWithinCUDA_Initializer, bWithinMAKEFILEOPTION, bWithinCUDA_Evaluator, bBoundCheckingFunction;
bool bIsParentReduce, bIsOffspringReduce;
CSymbol *pASymbol;
public:
......@@ -87,6 +88,7 @@ Centre de Math
bWaitingForSemiColon=bFinishNB_GEN=bFinishMINIMISE=bFinishMINIMIZE=bGenerationFunction=0;
bCatchNextSemiColon,bWaitingToClosePopulation=bMethodsInGenome=0;
bBoundCheckingFunction = bWithinCUDA_Initializer=bWithinMAKEFILEOPTION =bWithinCUDA_Evaluator=0;
bIsParentReduce = bIsOffspringReduce = false;
}
// macros
......@@ -584,6 +586,14 @@ exponent ([Ee][+-]?[0-9]+)
}
}
<TEMPLATE_ANALYSIS>"\\IS_PARENT_REDUCTION" {
fprintf(fpOutputFile,"%d",bIsParentReduce);
}
<TEMPLATE_ANALYSIS>"\\IS_OFFSPRING_REDUCTION" {
fprintf(fpOutputFile,"%d",bIsOffspringReduce);
}
<TEMPLATE_ANALYSIS>"\\INSERT_INIT_FCT_CALL" {
if (bInitFunction) fprintf(fpOutputFile,"\n EASEAInitFunction(argc, argv);\n");
}
......@@ -619,10 +629,43 @@ exponent ([Ee][+-]?[0-9]+)
//DEBUG_PRT("elitism is %d, elite size is %d",bELITISM, nELITE);
}
<TEMPLATE_ANALYSIS>"\\RED_PAR" {fprintf(fpOutputFile,"%s",sRED_PAR);}
<TEMPLATE_ANALYSIS>"\\RED_PAR_PRM" {fprintf(fpOutputFile,"%s",sRED_PAR_PRM);}
<TEMPLATE_ANALYSIS>"\\RED_OFF" {fprintf(fpOutputFile,"%s",sRED_OFF);}
<TEMPLATE_ANALYSIS>"\\RED_OFF_PRM" {fprintf(fpOutputFile,"%s",sRED_OFF_PRM);}
<TEMPLATE_ANALYSIS>"\\RED_PAR" {
if( TARGET==CUDA || TARGET==STD){
DEBUG_PRT("Parent reduction is \"%s\" | Goal is %s",sSELECTOR,(nMINIMISE?"Minimize":"Maximize"));
char* selectorClass = selectorDetermination(nMINIMISE,sSELECTOR);
if( !selectorClass ){
fprintf(stderr,"Error %d : selection operator %s doesn't exist in CUDA/STD template\n",yylineno,sSELECTOR);
return -1;
}
DEBUG_PRT("Created class is %s",selectorClass);
fprintf(fpOutputFile,"%s",selectorClass);
}
else fprintf(fpOutputFile,"%s",sRED_PAR);
}
<TEMPLATE_ANALYSIS>"\\RED_PAR_PRM" {
if( (TARGET==CUDA || TARGET==STD) && strlen(sRED_PAR_PRM)==0)
fprintf(fpOutputFile,"0");
else
fprintf(fpOutputFile,"%s",sRED_PAR_PRM);
}
<TEMPLATE_ANALYSIS>"\\RED_OFF" {
if( TARGET==CUDA || TARGET==STD){
DEBUG_PRT("Offspring reduction is \"%s\" | Goal is %s",sSELECTOR,(nMINIMISE?"Minimize":"Maximize"));
char* selectorClass = selectorDetermination(nMINIMISE,sSELECTOR);
if( !selectorClass ){
fprintf(stderr,"Error %d : selection operator %s doesn't exist in CUDA/STD template\n",yylineno,sSELECTOR);
return -1;
}
DEBUG_PRT("Created class is %s",selectorClass);
fprintf(fpOutputFile,"%s",selectorClass);
}
else fprintf(fpOutputFile,"%s",sRED_OFF);
}
<TEMPLATE_ANALYSIS>"\\RED_OFF_PRM" {
if( (TARGET==CUDA || TARGET==STD ) && strlen(sRED_OFF_PRM)==0 )
fprintf(fpOutputFile,"0");
else
fprintf(fpOutputFile,"%s",sRED_OFF_PRM);}
<TEMPLATE_ANALYSIS>"\\RED_FINAL" {
if( TARGET==CUDA || TARGET==STD){
DEBUG_PRT("Replacement selector is \"%s\" | Goal is %s",sRED_FINAL,(nMINIMISE?"Minimize":"Maximize"));
......@@ -1736,10 +1779,23 @@ exponent ([Ee][+-]?[0-9]+)
<GET_PARAMETERS>"Mutation"[ \t\n]+"probability"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tMut Prob...\n");return MUT_PROB;}
<GET_PARAMETERS>"Crossover"[ \t\n]+"probability"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tXov Prob...\n");return XOVER_PROB;}
<GET_PARAMETERS>"Offspring"[ \t\n]+"size"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tOff Size...\n");return OFFSPRING;}
<GET_PARAMETERS>"Reduce"[ \t\n]+"parents"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tReduce Par...\n");return RED_PAR;}
<GET_PARAMETERS>"Reduce"[ \t\n]+"parents"[ \t\n]*":"[ \t\n]* {
if (bVERBOSE) printf ("\tReduce Par...\n");
bIsParentReduce = true;
return RED_PAR;
}
<GET_PARAMETERS>"Surviving"[ \t\n]+"parents"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tSurv Par...\n");return SURVPAR;}
<GET_PARAMETERS>"Reduce"[ \t\n]+"offspring"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tRed Off...\n");return RED_OFF;}
<GET_PARAMETERS>"Reduce"[ \t\n]+"offspring"[ \t\n]*":"[ \t\n]* {
if (bVERBOSE) printf ("\tRed Off...\n");
bIsOffspringReduce = true;
return RED_OFF;
}
<GET_PARAMETERS>"Surviving"[ \t\n]+"offspring"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tSurv Off...\n");return SURVOFF;}
<GET_PARAMETERS>"Final"[ \t\n]+"reduce"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tFinal Red...\n");return RED_FINAL;}// DISCARD;}
<GET_PARAMETERS>"Elitism"[ \t\n]*":" {if (bVERBOSE) printf ("\tElitism...\n");return ELITISM;}
<GET_PARAMETERS>"Evaluator"[ \t\n]+"goal"[ \t\n]*":"[ \t\n]* {if (bVERBOSE) printf ("\tMinMax...\n");return MINIMAXI;}
......
This diff is collapsed.
#include "Easea.h"
#include "EaseaLex.h"
#include "debug.h"
void pickupSTDSelector(char* sSELECTOR, char* sSELECT_PRM, char* sEZ_FILE_NAME, CEASEALexer* EASEALexer){
DEBUG_PRT("Picking up selector without argument %s",sSELECTOR);
if (!mystricmp(sSELECTOR,"RouletteWheel")){
if (nMINIMISE==1) {
fprintf(stderr,"\n%s - Error line %d: The RouletteWheel selection scheme cannot be\n selected when \"minimising the fitness\" is the evaluator goal.\n",
sEZ_FILE_NAME,EASEALexer->yylineno);
exit(1);
}
else sprintf(sSELECTOR,"Roulette");
}
else if (!mystricmp(sSELECTOR,"Tournament")){
sprintf(sSELECTOR,"DetTour");
// as there is no selection pressure, we put 2
sprintf(sSELECT_PRM,"(2)");
}
else if (!mystricmp(sSELECTOR,"StochTrn")) sprintf(sSELECTOR,"StochTour");
else if (!mystricmp(sSELECTOR,"Random")){
sprintf(sSELECTOR,"Random");
if( TARGET==CUDA || TARGET==STD )
sprintf(sSELECT_PRM,"(0)");
}
else if (!mystricmp(sSELECTOR,"Ranking")) sprintf(sSELECTOR,"Ranking");
else if (!mystricmp(sSELECTOR,"Sequential")){
sprintf(sSELECTOR,"Sequential");
if( TARGET==CUDA || TARGET==STD) sprintf(sSELECT_PRM,"(0)");
}
else {
fprintf(stderr,"\n%s - Error line %d: The %s selection scheme does not exist in CUDA/STD.\n",sEZ_FILE_NAME,EASEALexer->yylineno, sSELECTOR);
exit(1);
}
}
void pickupSTDSelectorArgument(char* sSELECTOR, char* sSELECTOR_PRM, char* sEZ_FILE_NAME, float thirdParam, CEASEALexer* EASEALexer){
DEBUG_PRT("Picking up selector with argument %s %d",sSELECTOR,(int) thirdParam);
if (!mystricmp(sSELECTOR,"Tournament")||!mystricmp(sSELECTOR,"StochTrn")) {
if (thirdParam>=2) {sprintf(sSELECTOR,"DetTour");
sprintf(sSELECTOR_PRM,"(%d)",(int) thirdParam);}
else if ((thirdParam>.5)&&(thirdParam<=1.0)) {
sprintf(sSELECTOR,"StochTour");
sprintf(sSELECTOR_PRM,"(%f)",(float) thirdParam);
}
else {
fprintf(stderr,"\n%s - Error line %d: The parameter of the Tournament selector must be either >=2 or within ]0.5, 1].\n",
sEZ_FILE_NAME,EASEALexer->yylineno);
exit(1);
}
}
else if (!mystricmp(sSELECTOR,"RouletteWheel")) {
sprintf(sSELECTOR,"Roulette");
if (thirdParam<1) {fprintf(stderr,"\n%s - Warning line %d: The parameter of RouletteWheel must be greater than one.\nThe parameter will therefore be ignored.",
sEZ_FILE_NAME,EASEALexer->yylineno);
nWARNINGS++;
}
else sprintf(sSELECTOR_PRM,"(%f)",(float) thirdParam);
}
else if (!mystricmp(sSELECTOR,"Random")) {
sprintf(sSELECTOR,"Random");
fprintf(stderr,"\n%s - Warning line %d: The Uniform selector does not (yet) take any parameter in CUDA/STD.\nThe parameter will therefore be ignored.",
sEZ_FILE_NAME,EASEALexer->yylineno);
nWARNINGS++;
}
else if (!mystricmp(sSELECTOR,"Ranking")) {
sprintf(sSELECTOR,"Ranking");
if ((thirdParam<=1)||(thirdParam>2)) {
fprintf(stderr,"\n%s - Warning line %d: The parameter of Ranking must be in (1,2].\nThe parameter will default to 2.",sEZ_FILE_NAME,EASEALexer->yylineno);
nWARNINGS++;
sprintf(sSELECTOR_PRM,"(2)");
}
else sprintf(sSELECTOR_PRM,"(%f)",(float) thirdParam);
}
else if (!mystricmp(sSELECTOR,"Sequential")) {
sprintf(sSELECTOR,"Sequential");
if (thirdParam==0)
if( TARGET==CUDA || TARGET==STD )
sprintf(sSELECT_PRM,"(0)");
else
sprintf(sSELECT_PRM,"(unordered)");
else if (thirdParam==1) sprintf(sSELECTOR_PRM,"(ordered)");
else {
fprintf(stderr,"\n%s - Warning line %d: The parameter of Sequential must be either 0 (unordered) or 1 (ordered).\nThe parameter will default to 1.",
sEZ_FILE_NAME,EASEALexer->yylineno);
nWARNINGS++;
sprintf(sSELECTOR_PRM,"(ordered)");
}
}
else {
fprintf(stderr,"\n%s - Error line %d: The %s selection scheme does not exist in CUDA/STD.\n",sEZ_FILE_NAME,EASEALexer->yylineno, sSELECTOR);
exit(1);
}
}
#include "EaseaLex.h"
void pickupSTDSelector(char* sSELECTOR, char* sSELECT_PRM, char* sEZ_FILE_NAME, CEASEALexer* EASEALexer);
void pickupSTDSelectorArgument(char* sSELECTOR, char* sSELECTOR_PRM, char* sEZ_FILE_NAME, float thirdParam, CEASEALexer* EASEALexer);
......@@ -231,12 +231,19 @@ CPPFLAGS+=
Number of generations : 100 // NB_GEN
Mutation probability : 1 // MUT_PROB
Crossover probability : 1 // XOVER_PROB
Population size : 10 // POP_SIZE
Population size : 20 // POP_SIZE
Offspring size : 20 // 40%
Genitors selector: Tournament 2
Final reduce: Tournament 2
Final reduce: Tournament 3
Reduce parents: Tournament 2
Surviving parents : 5
Reduce offspring: Tournament 2
Surviving offspring: 17
// Selection operator : Tournament // RouletteWheel, Deterministic, Ranking, Random
Offspring size : 80% // 40%
//Replacement strategy : Plus // Comma, SteadyState, Generational
// Discarding operator : Worst // Best, Tournament, Parent, Random
Evaluator goal : Minimise // Maximise
......
......@@ -5,7 +5,7 @@ LDFLAGS =
$(EXEC):EaseaSym.o EaseaParse.o EaseaLex.o alexyacc/libalex.a
$(EXEC):EaseaSym.o EaseaParse.o EaseaLex.o alexyacc/libalex.a EaseaYTools.o
$(CPPC) $(CPPFLAGS) $(LDFLAGS) $^ -o $@
#
# Congratulations ! It looks like you compiled EASEA successfully.
......@@ -42,7 +42,7 @@ $(EXEC):EaseaSym.o EaseaParse.o EaseaLex.o alexyacc/libalex.a
EaseaParse.o: EaseaParse.cpp EaseaLex.cpp
EaseaParse.o: EaseaParse.cpp EaseaLex.cpp
$(CPPC) $(CPPFLAGS) $< -o $@ -c
%.o:%.cpp
......
......@@ -30,15 +30,21 @@ int main(int argc, char** argv){
SelectionOperator* selectionOperator = new \SELECTOR;
SelectionOperator* replacementOperator = new \RED_FINAL;
SelectionOperator* parentReductionOperator = new \RED_PAR;
SelectionOperator* offspringReductionOperator = new \RED_OFF;
float selectionPressure = \SELECT_PRM;
float replacementPressure = \RED_FINAL_PRM;
float parentReductionPressure = \RED_PAR_PRM;
float offspringReductionPressure = \RED_OFF_PRM;
string outputfile = setVariable("outputfile","");
string inputfile = setVariable("inputfile","");
EASEAInit(argc,argv);
EvolutionaryAlgorithm ea(parentPopulationSize,offspringPopulationSize,selectionPressure,replacementPressure,
selectionOperator,replacementOperator,pCrossover, pMutation, pMutationPerGene,outputfile,inputfile);
EvolutionaryAlgorithm ea(parentPopulationSize,offspringPopulationSize,selectionPressure,replacementPressure,parentReductionPressure,offspringReductionPressure,
selectionOperator,replacementOperator,parentReductionOperator, offspringReductionOperator, pCrossover, pMutation, pMutationPerGene,
outputfile,inputfile);
StoppingCriterion* sc = new GenerationalCriterion(&ea,setVariable("nbGen",\NB_GEN));
ea.addStoppingCriterion(sc);
......@@ -180,39 +186,40 @@ size_t Individual::mutate( float pMutationPerGene ){
EvolutionaryAlgorithm class
****************************************/
/**
@DEPRECATED This contructor will be deleted. It was for test only, because it
is too much constrained (default selection/replacement operator)
*/
EvolutionaryAlgorithm::EvolutionaryAlgorithm( size_t parentPopulationSize,
size_t offspringPopulationSize,
float selectionPressure, float replacementPressure,
float pCrossover, float pMutation,
float pMutationPerGene){
RandomGenerator* rg = globalRandomGenerator;
/* /\** */
/* @DEPRECATED This contructor will be deleted. It was for test only, because it */
/* is too much constrained (default selection/replacement operator) */
/* *\/ */
/* EvolutionaryAlgorithm::EvolutionaryAlgorithm( size_t parentPopulationSize, */
/* size_t offspringPopulationSize, */
/* float selectionPressure, float replacementPressure, */
/* float pCrossover, float pMutation, */
/* float pMutationPerGene){ */
/* RandomGenerator* rg = globalRandomGenerator; */
SelectionOperator* so = new MaxTournament(rg);
SelectionOperator* ro = new MaxTournament(rg);
/* SelectionOperator* so = new MaxTournament(rg); */
/* SelectionOperator* ro = new MaxTournament(rg); */
Individual::initRandomGenerator(rg);
Population::initPopulation(so,ro,selectionPressure,replacementPressure);
/* Individual::initRandomGenerator(rg); */
/* Population::initPopulation(so,ro,selectionPressure,replacementPressure); */
this->population = new Population(parentPopulationSize,offspringPopulationSize,
pCrossover,pMutation,pMutationPerGene,rg);
/* this->population = new Population(parentPopulationSize,offspringPopulationSize, */
/* pCrossover,pMutation,pMutationPerGene,rg); */
this->currentGeneration = 0;
/* this->currentGeneration = 0; */
this->reduceParents = 0;
this->reduceOffsprings = 0;
/* this->reduceParents = 0; */
/* this->reduceOffsprings = 0; */
}
/* } */
EvolutionaryAlgorithm::EvolutionaryAlgorithm( size_t parentPopulationSize,
size_t offspringPopulationSize,
float selectionPressure, float replacementPressure,
float selectionPressure, float replacementPressure, float parentReductionPressure, float offspringReductionPressure,
SelectionOperator* selectionOperator, SelectionOperator* replacementOperator,
SelectionOperator* parentReductionOperator, SelectionOperator* offspringReductionOperator,
float pCrossover, float pMutation,
float pMutationPerGene, string& outputfile, string& inputfile){
......@@ -222,7 +229,7 @@ EvolutionaryAlgorithm::EvolutionaryAlgorithm( size_t parentPopulationSize,
SelectionOperator* ro = replacementOperator;
Individual::initRandomGenerator(rg);
Population::initPopulation(so,ro,selectionPressure,replacementPressure);
Population::initPopulation(so,ro,parentReductionOperator,offspringReductionOperator,selectionPressure,replacementPressure,parentReductionPressure,offspringReductionPressure);
this->population = new Population(parentPopulationSize,offspringPopulationSize,
pCrossover,pMutation,pMutationPerGene,rg);
......@@ -266,25 +273,28 @@ void EvolutionaryAlgorithm::runEvolutionaryLoop(){
population->produceOffspringPopulation();
\INSERT_BOUND_CHECKING_FCT_CALL
population->evaluateOffspringPopulation();
#if \IS_PARENT_REDUCTION
population->reduceParentPopulation(\SURV_PAR_SIZE);
#endif
if(reduceParents)
population->reduceParentPopulation(reduceParents);
if(reduceOffsprings)
population->reduceOffspringPopulation(reduceOffsprings);
#if \IS_OFFSPRING_REDUCTION
population->reduceOffspringPopulation(\SURV_OFF_SIZE);
#endif
population->reduceTotalPopulation();
\INSERT_GEN_FCT_CALL
showPopulationStats(begin);
showPopulationStats(begin);
currentGeneration += 1;
}
population->sortParentPopulation();
//std::cout << *population << std::endl;
std::cout << "Generation : " << currentGeneration << std::endl;
}
......@@ -405,12 +415,15 @@ class Individual{
****************************************/
class EvolutionaryAlgorithm{
public:
EvolutionaryAlgorithm( size_t parentPopulationSize, size_t offspringPopulationSize,
float selectionPressure, float replacementPressure,
float pCrossover, float pMutation, float pMutationPerGene);
EvolutionaryAlgorithm( size_t parentPopulationSize,size_t offspringPopulationSize,
float selectionPressure, float replacementPressure,
/* EvolutionaryAlgorithm( size_t parentPopulationSize, size_t offspringPopulationSize, */
/* float selectionPressure, float replacementPressure, */
/* float pCrossover, float pMutation, float pMutationPerGene); */
EvolutionaryAlgorithm( size_t parentPopulationSize,
size_t offspringPopulationSize,
float selectionPressure, float replacementPressure, float parentReductionPressure, float offspringReductionPressure,
SelectionOperator* selectionOperator, SelectionOperator* replacementOperator,
SelectionOperator* parentReductionOperator, SelectionOperator* offspringReductionOperator,
float pCrossover, float pMutation,
float pMutationPerGene, std::string& outputfile, std::string& inputfile);
......@@ -656,9 +669,15 @@ bool GenerationalCriterion::reached(){
****************************************/
SelectionOperator* Population::selectionOperator;
SelectionOperator* Population::replacementOperator;
SelectionOperator* Population::parentReductionOperator;
SelectionOperator* Population::offspringReductionOperator;
float Population::selectionPressure;
float Population::replacementPressure;
float Population::parentReductionPressure;
float Population::offspringReductionPressure;
Population::Population(){
......@@ -710,11 +729,20 @@ Population::~Population(){
void Population::initPopulation(SelectionOperator* selectionOperator,
SelectionOperator* replacementOperator,
float selectionPressure, float replacementPressure){
SelectionOperator* parentReductionOperator,
SelectionOperator* offspringReductionOperator,
float selectionPressure, float replacementPressure,
float parentReductionPressure, float offspringReductionPressure){
Population::selectionOperator = selectionOperator;
Population::replacementOperator = replacementOperator;
Population::parentReductionOperator = parentReductionOperator;
Population::offspringReductionOperator = offspringReductionOperator;
Population::selectionPressure = selectionPressure;
Population::replacementPressure = replacementPressure;
Population::parentReductionPressure = parentReductionPressure;
Population::offspringReductionPressure = offspringReductionPressure;
}
......@@ -800,19 +828,23 @@ Individual** Population::reduceParentPopulation(size_t obSize){
}
Individual** Population::reduceOffspringPopulation(size_t obSize){
Individual** nextGeneration = new Individual*[obSize];
// this array has offspringPopulationSize because it will be used as offspring population in
// the next generation
Individual** nextGeneration = new Individual*[offspringPopulationSize];
reducePopulation(offsprings,actualOffspringPopulationSize,nextGeneration,obSize,
Population::replacementOperator);
// free no longer needed individuals
for( size_t i=0 ; i<actualOffspringPopulationSize-obSize ; i++ )
delete(parents[i]);
delete[](parents);
delete(offsprings[i]);
delete[](offsprings);
this->actualParentPopulationSize = obSize;
parents = nextGeneration;
this->actualOffspringPopulationSize = obSize;
offsprings = nextGeneration;
return nextGeneration;
}
......@@ -877,7 +909,7 @@ void Population::reduceTotalPopulation(){
Population::reducePopulation(globalPopulation,actualGlobalSize,\ELITE_SIZE+nextGeneration,
parentPopulationSize-\ELITE_SIZE,replacementOperator);
for( size_t i=0 ; i<offspringPopulationSize ; i++ )
for( size_t i=0 ; i<((int)actualGlobalSize+\ELITE_SIZE)-(int)parentPopulationSize ; i++ )
delete(globalPopulation[i]);
delete[](parents);
......@@ -1386,6 +1418,8 @@ class Population {
static SelectionOperator* selectionOperator;
static SelectionOperator* replacementOperator;
static SelectionOperator* parentReductionOperator;
static SelectionOperator* offspringReductionOperator;
size_t currentEvaluationNb;
RandomGenerator* rg;
......@@ -1414,9 +1448,15 @@ class Population {
static float selectionPressure;
static float replacementPressure;
static float parentReductionPressure;
static float offspringReductionPressure;
static void initPopulation(SelectionOperator* selectionOperator,
SelectionOperator* replacementOperator,
float selectionPressure, float replacementPressure);
SelectionOperator* parentReductionOperator,
SelectionOperator* offspringReductionOperator,
float selectionPressure, float replacementPressure,
float parentReductionPressure, float offspringReductionPressure);
static void sortPopulation(Individual** population, size_t populationSize);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment