Adding the Lesson5 - how to create your own genotype
This commit is contained in:
parent
b407bf5e81
commit
c5e225551a
14 changed files with 2476 additions and 72 deletions
351
eo/tutorial/html/make_op_OneMax.html
Normal file
351
eo/tutorial/html/make_op_OneMax.html
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR" content="Mozilla/4.78 [en] (X11; U; Linux 2.4.7-10 i686) [Netscape]">
|
||||
<title>Templates/make_op_OneMax.h</title>
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#C3C2B4" link="#0000EE" vlink="#551A8B" alink="#FF0000">
|
||||
<a href="eoLesson5.html">Back to Lesson 5</a>
|
||||
- <a href="eoTutorial.html">Tutorial main page </a>- <a href="eoTopDown.html">Top-Down
|
||||
page</a> - <a href="eoBottomUp.html">Bottom-up page</a> - <a href="eoProgramming.html">Programming
|
||||
hints</a> - <font face="Arial,Helvetica"><a href="doc/html/index.html">EO
|
||||
documentation</a></font>
|
||||
<br>
|
||||
<hr WIDTH="100%"><!-- -------------- End of header ------------------ --><!-- ----------------------------------------------- -->
|
||||
<center>
|
||||
<h1>
|
||||
<font color="#FF0000">Templates/make_op_OneMax.h</font></h1></center>
|
||||
The places where you have to put some code are on <b><font color="#FF6666">pink
|
||||
background</font></b>.. Only the the <a href="eoTutorial.html#colors">character
|
||||
colors have the usual meaning</a>.
|
||||
<p><a NAME="start"></a>
|
||||
<table BORDER=0 CELLSPACING=0 COLS=1 WIDTH="100%" BGCOLOR="#CCCCCC" NOSAVE >
|
||||
<tr NOSAVE>
|
||||
<td NOSAVE><tt><font color="#993300">// -*- mode: c++; c-indent-level:
|
||||
4; c++-member-init-indent: 8; comment-column: 35; -*-</font></tt>
|
||||
<p><tt><font color="#993300">//-----------------------------------------------------------------------------</font></tt>
|
||||
<br><tt><font color="#993300">// make_op_OneMax.h</font></tt>
|
||||
<br><tt><font color="#993300">// (c) Marc Schoenauer, Maarten Keijzer and
|
||||
GeNeura Team, 2001</font></tt>
|
||||
<br><tt><font color="#993300">/* </font></tt>
|
||||
<br><tt><font color="#993300"> This library is
|
||||
free software; you can redistribute it and/or</font></tt>
|
||||
<br><tt><font color="#993300"> modify it under
|
||||
the terms of the GNU Lesser General Public</font></tt>
|
||||
<br><tt><font color="#993300"> License as published
|
||||
by the Free Software Foundation; either</font></tt>
|
||||
<br><tt><font color="#993300"> version 2 of the
|
||||
License, or (at your option) any later version.</font></tt>
|
||||
<br><tt><font color="#993300"> This library is
|
||||
distributed in the hope that it will be useful,</font></tt>
|
||||
<br><tt><font color="#993300"> but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of</font></tt>
|
||||
<br><tt><font color="#993300"> MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</font></tt>
|
||||
<br><tt><font color="#993300"> Lesser General Public
|
||||
License for more details.</font></tt>
|
||||
<br><tt><font color="#993300"> You should have
|
||||
received a copy of the GNU Lesser General Public</font></tt>
|
||||
<br><tt><font color="#993300"> License along with
|
||||
this library; if not, write to the Free Software</font></tt>
|
||||
<br><tt><font color="#993300"> Foundation, Inc.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</font></tt>
|
||||
<br><tt><font color="#993300"> Contact: todos@geneura.ugr.es,
|
||||
http://geneura.ugr.es</font></tt>
|
||||
<br><tt><font color="#993300">
|
||||
Marc.Schoenauer@inria.fr</font></tt>
|
||||
<br><tt><font color="#993300">
|
||||
mkeijzer@dhi.dk</font></tt>
|
||||
<br><tt><font color="#993300">*/</font></tt>
|
||||
<br><tt><font color="#993300">//-----------------------------------------------------------------------------</font></tt>
|
||||
<p><b><tt><font color="#993300">#ifndef _make_op_OneMax_h</font></tt></b>
|
||||
<br><b><tt><font color="#993300">#define _make_op_OneMax_h</font></tt></b>
|
||||
<p><tt><font color="#993300">// the operators</font></tt>
|
||||
<br><b><tt><font color="#993300">#include <eoOp.h></font></tt></b>
|
||||
<br><b><tt><font color="#993300">#include <eoGenOp.h></font></tt></b>
|
||||
<br><b><tt><font color="#993300">#include <eoCloneOps.h></font></tt></b>
|
||||
<br><b><tt><font color="#993300">#include <eoOpContainer.h></font></tt></b>
|
||||
<br><tt><font color="#993300">// combinations of simple eoOps (eoMonOp
|
||||
and eoQuadOp)</font></tt>
|
||||
<br><b><tt><font color="#993300">#include <eoProportionalCombinedOp.h></font></tt></b>
|
||||
<p><tt><font color="#993300">/** definition of mutation: </font></tt>
|
||||
<br><tt><font color="#993300">* class eoOneMaxMonop MUST derive from eoMonOp<eoOneMax></font></tt>
|
||||
<br><tt><font color="#993300">*/</font></tt>
|
||||
<br><b><tt><font color="#993300">#include "eoOneMaxMutation.h"</font></tt></b>
|
||||
<p><tt><font color="#993300">/** definition of crossover (either as eoBinOp
|
||||
(2->1) or eoQuadOp (2->2): </font></tt>
|
||||
<br><tt><font color="#993300">* class eoOneMaxBinCrossover MUST derive
|
||||
from eoBinOp<eoOneMax></font></tt>
|
||||
<br><tt><font color="#993300">* OR </font></tt>
|
||||
<br><tt><font color="#993300">* class eoOneMaxQuadCrossover MUST derive
|
||||
from eoQuadOp<eoOneMax></font></tt>
|
||||
<br><tt><font color="#993300">*/</font></tt>
|
||||
<br><tt><font color="#993300">// #include "eoOneMaxBinOp.h"</font></tt>
|
||||
<br><tt><font color="#993300">// OR</font></tt>
|
||||
<br><b><tt><font color="#993300">#include "eoOneMaxQuadCrossover.h"</font></tt></b>
|
||||
<p><tt><font color="#993300"><b> </b> // also need the parser and
|
||||
state includes</font></tt>
|
||||
<br><b><tt><font color="#993300">#include <utils/eoParser.h></font></tt></b>
|
||||
<br><b><tt><font color="#993300">#include <utils/eoState.h></font></tt></b>
|
||||
<p><tt><font color="#993300">/////////////////// variation operators ///////////////</font></tt>
|
||||
<br><tt><font color="#993300">// canonical (crossover + mutation) only
|
||||
at the moment //</font></tt>
|
||||
<p><tt><font color="#993300">/*</font></tt>
|
||||
<br><tt><font color="#993300">* This function builds the operators that
|
||||
will be applied to the eoOneMax</font></tt>
|
||||
<br><tt><font color="#993300">*</font></tt>
|
||||
<br><tt><font color="#993300">* It uses a parser (to get user parameters),
|
||||
a state (to store the memory)</font></tt>
|
||||
<br><tt><font color="#993300">* the last
|
||||
parameter is an eoInit: if some operator needs some info </font></tt>
|
||||
<br><tt><font color="#993300">* about the
|
||||
genotypes, the init has it all (e.g. bounds, ...)</font></tt>
|
||||
<br><tt><font color="#993300">* Simply do </font></tt>
|
||||
<br><tt><font color="#993300">*
|
||||
EOT myEO;</font></tt>
|
||||
<br><tt><font color="#993300">*
|
||||
_init(myEO);</font></tt>
|
||||
<br><tt><font color="#993300">* and myEO
|
||||
is then an ACTUAL object</font></tt>
|
||||
<br><tt><font color="#993300">*</font></tt>
|
||||
<br><tt><font color="#993300">* As usual, the template is the complete
|
||||
EOT even though only the fitness</font></tt>
|
||||
<br><tt><font color="#993300">* is actually templatized here: the following
|
||||
only applies to eoOneMax</font></tt>
|
||||
<br><tt><font color="#993300">*/</font></tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
<a NAME="operators"></a>
|
||||
<table BORDER=0 CELLSPACING=0 COLS=1 WIDTH="100%" BGCOLOR="#CCCCCC" NOSAVE >
|
||||
<tr>
|
||||
<td><b><tt><font color="#993399">template <class EOT></font></tt></b>
|
||||
<br><b><tt><font color="#993399">eoGenOp<EOT> & do_make_op(eoParameterLoader&
|
||||
_parser, eoState& _state, eoInit<EOT>& _init)</font></tt></b>
|
||||
<br><b><tt><font color="#993399">{</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> </b> // this is a temporary version,
|
||||
while Maarten codes the full tree-structured</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // general operator input</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // BTW we must leave that simple
|
||||
version available somehow, as it is the one</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // that 90% people use!</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> /////////////////////////////</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
Variation operators</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> ////////////////////////////</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
read crossover and mutations, combine each in a proportional Op</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
and create the eoGenOp that calls crossover at rate pCross </font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
then mutation with rate pMut</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // the
|
||||
crossovers</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> /////////////////</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // here
|
||||
we can have eoQuadOp (2->2) only - no time for the eoBinOp case</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // you
|
||||
can have more than one - combined in a proportional way</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // first,
|
||||
define the crossover objects and read their rates from the parser</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // A
|
||||
first crossover </font></tt>
|
||||
<br><a NAME="cross_ctor"></a><tt><font color="#993399"><b>
|
||||
eoQuadOp<Indi> *cross = new eoOneMaxQuadCrossover<Indi> </b>/* </font><font color="#FF6666">(varType
|
||||
_anyVariable)</font><font color="#993399"> */;</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
store in the state</font></tt>
|
||||
<br><b><tt><font color="#993399"> _state.storeFunctor(cross);</font></tt></b>
|
||||
<p><tt><font color="#993399"><b> </b> // read its relative rate in
|
||||
the combination</font></tt>
|
||||
<br><b><tt><font color="#993399"> double cross1Rate
|
||||
= _parser.createParam(1.0, "cross1Rate", "Relative rate for crossover 1",
|
||||
'1', "Variation Operators").value();</font></tt></b>
|
||||
<p><tt><font color="#993399"><b> </b> // and create the combined operator
|
||||
with this one</font></tt>
|
||||
<br><b><tt><font color="#993399"> eoPropCombinedQuadOp<Indi> *propXover
|
||||
= </font></tt></b>
|
||||
<br><b><tt><font color="#993399"> new eoPropCombinedQuadOp<Indi>(*cross,
|
||||
cross1Rate);</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> </b> // and of course stor it in
|
||||
the state</font></tt>
|
||||
<br><b><tt><font color="#993399"> _state.storeFunctor(propXover);</font></tt></b>
|
||||
<br> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table BORDER=0 CELLSPACING=0 COLS=1 WIDTH="100%" BGCOLOR="#FFCCCC" NOSAVE >
|
||||
<tr>
|
||||
<td><a NAME="crossover"></a><tt><font color="#993399"><b> </b>
|
||||
// Optional: A second(and third, and ...) crossover </font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
of course you must create the corresponding classes</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
and all ***MUST*** derive from eoQuadOp<Indi></font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> /* Uncomment if necessary -
|
||||
and replicate as many time as you need</font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
cross = new eoOneMaxSecondCrossover<Indi>(varType _anyVariable); </font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
_state.storeFunctor(cross);</font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
double cross2Rate = _parser.createParam(1.0, "cross2Rate", "Relative rate
|
||||
for crossover 2", '2', "Variation Operators").value(); </font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
propXover.add(*cross, cross2Rate); </font></tt>
|
||||
<br><tt><font color="#993399"> */</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // if you want some gentle
|
||||
output, the last one shoudl be like</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // propXover.add(*cross,
|
||||
crossXXXRate, true);</font></tt>
|
||||
<br> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table BORDER=0 CELLSPACING=0 COLS=1 WIDTH="100%" BGCOLOR="#CCCCCC" NOSAVE >
|
||||
<tr>
|
||||
<td>
|
||||
<br><tt><font color="#993399"><b> </b> // the mutation: same story</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> ////////////////</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // you can have more than one
|
||||
- combined in a proportional way</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // for each mutation, </font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // - define the mutator object</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // - read its rate from the
|
||||
parser</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // - add it to the proportional
|
||||
combination</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // a first mutation </font></tt>
|
||||
<br><a NAME="mut_ctor"></a><tt><font color="#993399"><b>eoMonOp<Indi>
|
||||
*mut = new eoOneMaxMutation<Indi></b> /* </font><font color="#FF6666">(varType
|
||||
_anyVariable)</font><font color="#993399"> */;</font></tt>
|
||||
<br><b><tt><font color="#993399"> _state.storeFunctor(mut);</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> </b> // its relative rate in the
|
||||
combination</font></tt>
|
||||
<br><b><tt><font color="#993399"> double mut1Rate = _parser.createParam(1.0,
|
||||
"mut1Rate", "Relative rate for mutation 1", '1', "Variation Operators").value();</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> </b> // and the creation of the
|
||||
combined operator with this one</font></tt>
|
||||
<br><b><tt><font color="#993399"> eoPropCombinedMonOp<Indi> *propMutation
|
||||
= new eoPropCombinedMonOp<Indi>(*mut, mut1Rate);</font></tt></b>
|
||||
<br><b><tt><font color="#993399"> _state.storeFunctor(propMutation);</font></tt></b>
|
||||
<br> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table BORDER=0 CELLSPACING=0 COLS=1 WIDTH="100%" BGCOLOR="#FFCCCC" NOSAVE >
|
||||
<tr>
|
||||
<td><a NAME="mutation"></a><tt><font color="#993399"><b> </b>
|
||||
// Optional: A second(and third, and ...) mutation with their rates</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
of course you must create the corresponding classes</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
and all ***MUST*** derive from eoMonOp<Indi></font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> /* Uncomment if necessary -
|
||||
and replicate as many time as you need</font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
mut = new eoOneMaxSecondMutation<Indi>(varType _anyVariable);</font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
_state.storeFunctor(mut);</font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
double mut2Rate = _parser.createParam(1.0, "mut2Rate", "Relative rate for
|
||||
mutation 2", '2', "Variation Operators").value(); </font></tt>
|
||||
<br><tt><font color="#993399">
|
||||
propMutation.add(*mut, mut2Rate); </font></tt>
|
||||
<br><tt><font color="#993399"> */</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // if you want some gentle
|
||||
output, the last one shoudl be like</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // propMutation.add(*mut,
|
||||
mutXXXRate, true);</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // end of crossover and mutation
|
||||
definitions</font></tt>
|
||||
<br> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table BORDER=0 CELLSPACING=0 COLS=1 WIDTH="100%" BGCOLOR="#CCCCCC" NOSAVE >
|
||||
<tr>
|
||||
<td>
|
||||
<br><tt><font color="#993399">// from now on, you do not need to modify
|
||||
anything</font></tt>
|
||||
<br><tt><font color="#993399">// though you CAN add things to the checkpointing
|
||||
(see tutorial)</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // now build the eoGenOp:</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // to simulate SGA (crossover
|
||||
with proba pCross + mutation with proba pMut</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // we must construct</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
a sequential combination of</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
with proba 1, a proportional combination of </font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
a QuadCopy and our crossover</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
with proba pMut, our mutation</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // but of course you're free
|
||||
to use any smart combination you could think of</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // especially, if you have
|
||||
to use eoBinOp rather than eoQuad Op youùll have</font></tt>
|
||||
<br><tt><font color="#993399"><b> </b> // to modify that part</font></tt>
|
||||
<p><a NAME="donottouch"></a><tt><font color="#993399"><b> </b> //
|
||||
First read the individual level parameters</font></tt>
|
||||
<br><b><tt><font color="#993399"> eoValueParam<double>&
|
||||
pCrossParam = _parser.createParam(0.6, "pCross", "Probability of Crossover",
|
||||
'C', "Variation Operators" );</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
minimum check</font></tt>
|
||||
<br><b><tt><font color="#993399"> if ( (pCrossParam.value()
|
||||
< 0) || (pCrossParam.value() > 1) )</font></tt></b>
|
||||
<br><b><tt><font color="#993399">
|
||||
throw runtime_error("Invalid pCross");</font></tt></b>
|
||||
<p><b><tt><font color="#993399"> eoValueParam<double>&
|
||||
pMutParam = _parser.createParam(0.1, "pMut", "Probability of Mutation",
|
||||
'M', "Variation Operators" );</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> </b> //
|
||||
minimum check</font></tt>
|
||||
<br><b><tt><font color="#993399"> if ( (pMutParam.value()
|
||||
< 0) || (pMutParam.value() > 1) )</font></tt></b>
|
||||
<br><b><tt><font color="#993399">
|
||||
throw runtime_error("Invalid pMut");</font></tt></b>
|
||||
<p><tt><font color="#993399"><b> </b> // the crossover - with probability
|
||||
pCross</font></tt>
|
||||
<br><b><tt><font color="#993399"> eoProportionalOp<Indi> * propOp
|
||||
= new eoProportionalOp<Indi> ;</font></tt></b>
|
||||
<br><b><tt><font color="#993399"> _state.storeFunctor(propOp);</font></tt></b>
|
||||
<br><b><tt><font color="#993399"> eoQuadOp<Indi> *ptQuad = new
|
||||
eoQuadCloneOp<Indi>;</font></tt></b>
|
||||
<br><b><tt><font color="#993399"> _state.storeFunctor(ptQuad);</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> propOp->add(*propXover, pCrossParam.value());
|
||||
</b>//
|
||||
crossover, with proba pcross</font></tt>
|
||||
<br><tt><font color="#993399"><b> propOp->add(*ptQuad, 1-pCrossParam.value());
|
||||
</b>//
|
||||
nothing, with proba 1-pcross</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // now the sequential</font></tt>
|
||||
<br><b><tt><font color="#993399"> eoSequentialOp<Indi> *op = new
|
||||
eoSequentialOp<Indi>;</font></tt></b>
|
||||
<br><b><tt><font color="#993399"> _state.storeFunctor(op);</font></tt></b>
|
||||
<br><tt><font color="#993399"><b> op->add(*propOp, 1.0); </b>// always
|
||||
do combined crossover</font></tt>
|
||||
<br><tt><font color="#993399"><b> op->add(*propMutation, pMutParam.value());
|
||||
</b>//
|
||||
then mutation, with proba pmut</font></tt>
|
||||
<p><tt><font color="#993399"><b> </b> // that's it - return a reference</font></tt>
|
||||
<br><b><tt><font color="#993399"> return *op;</font></tt></b>
|
||||
<br><b><tt><font color="#993399">}</font></tt></b>
|
||||
<p><b><tt><font color="#993399">#endif</font></tt></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr WIDTH="100%"><a href="eoLesson5.html">Back to Lesson 5</a> - <a href="eoTutorial.html">Tutorial
|
||||
main page </a>- <a href="eoTopDown.html">Top-Down page</a> - <a href="eoBottomUp.html">Bottom-up
|
||||
page</a> - <a href="eoProgramming.html">Programming hints</a> - <font face="Arial,Helvetica"><a href="doc/html/index.html">EO
|
||||
documentation</a></font>
|
||||
<hr>
|
||||
<address>
|
||||
<a href="mailto:marc.schoenauer@inria.fr">Marc Schoenauer</a></address>
|
||||
|
||||
<br><!-- Created: Nov 2000 --><!-- hhmts start -->Last modified: Fri May
|
||||
3 08:06:20 2002<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
||||
Reference in a new issue