Commit e9cf927c authored by Ogier Maitre's avatar Ogier Maitre

New Makefile

parent b08f027d
This diff is collapsed.
......@@ -173,6 +173,7 @@ exponent ([Ee][+-]?[0-9]+)
if (bVERBOSE) printf ("Inserting initialisation function.\n");
yyreset();
yyin = fpGenomeFile; // switch to .ez file and analyser
lineCounter = 1;
BEGIN COPY_INITIALISATION_FUNCTION;
}
......@@ -188,10 +189,14 @@ exponent ([Ee][+-]?[0-9]+)
<TEMPLATE_ANALYSIS>"\\INSERT_BEGIN_GENERATION_FUNCTION" {
//DEBUG_PRT_PRT("insert beg");
if (bVERBOSE) printf ("Inserting at the begining of each generation function.\n");
if( bLINE_NUM_EZ_FILE )
fprintf(fpOutputFile,"#line %d \"%s.ez\"\n",lineCounter+1, sRAW_PROJECT_NAME);
yyreset();
yyin = fpGenomeFile;
bBeginGeneration = true;
bEndGeneration = false;
lineCounter = 1;
BEGIN COPY_BEG_GENERATION_FUNCTION;
}
......@@ -559,6 +564,7 @@ exponent ([Ee][+-]?[0-9]+)
yyreset();
yyin = fpGenomeFile;
if (bVERBOSE) printf ("Evaluation population in a single function!!.\n");
lineCounter = 1;
BEGIN COPY_INSTEAD_EVAL;
}
......@@ -900,6 +906,7 @@ exponent ([Ee][+-]?[0-9]+)
<TEMPLATE_ANALYSIS>"\\INSERT_INITIALISER" {
yyreset();
yyin = fpGenomeFile; // switch to .ez file and analyser
lineCounter = 1;
BEGIN COPY_INITIALISER;
}
......@@ -907,6 +914,7 @@ exponent ([Ee][+-]?[0-9]+)
if (bVERBOSE) printf ("Inserting Finalization function.\n");
yyreset();
yyin = fpGenomeFile; // switch to .ez file and analyser
lineCounter=1;
BEGIN COPY_FINALIZATION_FUNCTION;
}
......@@ -1281,9 +1289,11 @@ if(OPERATING_SYSTEM=WINDOWS)
}
<COPY_INITIALISATION_FUNCTION>"\\Before"[ \t\n]+"everything"[ \t\n]+"else"[ \t\n]+"function"[ \t\n]*":" {
fprintf (fpOutputFile,"// Initialisation function\nvoid EASEAInitFunction(int argc, char *argv[]){");
fprintf (fpOutputFile,"// Initialisation function\nvoid EASEAInitFunction(int argc, char *argv[]){\n");
bFunction=1; bInitFunction=1;
if( bLINE_NUM_EZ_FILE )
fprintf(fpOutputFile,"#line %d \"%s.ez\"\n",lineCounter, sRAW_PROJECT_NAME);
BEGIN COPY;
}
<COPY_INITIALISATION_FUNCTION><<EOF>> {bInitFunction=0; // No before everything else function was found in the .ez file
......@@ -1291,16 +1301,21 @@ if(OPERATING_SYSTEM=WINDOWS)
fprintf(fpOutputFile,"\n// No before everything else function.\n");
rewind(fpGenomeFile);
yyin = fpTemplateFile;
BEGIN TEMPLATE_ANALYSIS;
bNotFinishedYet=1;
}
<COPY_INITIALISATION_FUNCTION>.|\n {}
<COPY_INITIALISATION_FUNCTION>. {}
<COPY_INITIALISATION_FUNCTION>\n {lineCounter++;}
//****************************************
// Easea GPGPU & EO Finalization function
//****************************************
<COPY_FINALIZATION_FUNCTION>"\\After"[ \t\n]+"everything"[ \t\n]+"else"[ \t\n]+"function"[ \t\n]*":" {
fprintf (fpOutputFile,"// Finalization function\nvoid EASEAFinalization(CPopulation* population){");
fprintf (fpOutputFile,"// Finalization function\nvoid EASEAFinalization(CPopulation* population){\n");
if( bLINE_NUM_EZ_FILE )
fprintf(fpOutputFile,"#line %d \"%s.ez\"\n",lineCounter, sRAW_PROJECT_NAME);
bFunction=1; bFinalizationFunction=1;
BEGIN COPY;
}
......@@ -1313,7 +1328,8 @@ if(OPERATING_SYSTEM=WINDOWS)
BEGIN TEMPLATE_ANALYSIS;
bNotFinishedYet=1;
}
<COPY_FINALIZATION_FUNCTION>.|\n {}
<COPY_FINALIZATION_FUNCTION>. {}
<COPY_FINALIZATION_FUNCTION>\n {lineCounter++;}
<COPY_END_GENERATION_FUNCTION>"\\At"[ \t\n]+"the"[ \t\n]+"end"[ \t\n]+"of"[ \t\n]+"each"[ \t\n]+"generation"[ \t\n]+"function"[ \t\n]*":" {
......@@ -1347,6 +1363,8 @@ if(OPERATING_SYSTEM=WINDOWS)
bFunction=1;
bBeginGeneration = 0;
bBeginGenerationFunction = 1;
if( bLINE_NUM_EZ_FILE )
fprintf(fpOutputFile,"#line %d \"%s.ez\"\n",lineCounter, sRAW_PROJECT_NAME);
BEGIN COPY_USER_GENERATION;
}
}
......@@ -1356,11 +1374,15 @@ if(OPERATING_SYSTEM=WINDOWS)
if( (TARGET==CUDA || TARGET==STD)){
fprintf (fpOutputFile,"{\n");
bFunction=1;
if( bLINE_NUM_EZ_FILE )
fprintf(fpOutputFile,"#line %d \"%s.ez\"\n",lineCounter, sRAW_PROJECT_NAME);
BEGIN COPY_USER_GENERATION;
}
}
<COPY_INSTEAD_EVAL>.|\n {}
<COPY_INSTEAD_EVAL>. {}
<COPY_INSTEAD_EVAL>\n {lineCounter++;}
<COPY_INSTEAD_EVAL><<EOF>> {
bBeginGenerationFunction=0; // No Generation function was found in the .ez file
......@@ -1384,7 +1406,8 @@ if(OPERATING_SYSTEM=WINDOWS)
BEGIN TEMPLATE_ANALYSIS;
bNotFinishedYet=1;
}
<COPY_BEG_GENERATION_FUNCTION>.|\n {}
<COPY_BEG_GENERATION_FUNCTION>\n {lineCounter++;}
<COPY_BEG_GENERATION_FUNCTION>. {}
......
......@@ -18,7 +18,7 @@ ifeq ($(UNAME), Darwin)
@echo "export EZ_PATH=\"$(PWD)/\"">>$(HOME)/.profile
else
echo "this one"
@if [ $(EZ_PATH) != $(PWD)/ ] ; then echo -e "\nexport EZ_PATH=$(PWD)/">>$(HOME)/.bashrc ; fi
@if [ -z "$(EZ_PATH)" -a "$(EZ_PATH)" != $(PWD)/ ] ; then echo "\nexport EZ_PATH=$(PWD)/">>$(HOME)/.bashrc ; fi
endif
#
# Congratulations ! It looks like you compiled EASEA successfully.
......
/*_________________________________________________________
Test functions
log normal adaptive mutation
Selection operator: Tournament
__________________________________________________________*/
\User functions:
\end
\At the beginning of each generation function:
\end
\At the end of each generation function:
\end
\At each generation before reduce function:
\end
\GenomeClass::display:
\end
\User declarations :
#include <base.h>
#include <genome.h>
#include <tree.h>
#include <omp.h>
#define X_MIN -1.
#define X_MAX 1.
#define ITER 120
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
#define SIGMA 1. /* mutation parameter */
#define PI 3.141592654
#define G_SIZE 96 // fixme this size is defined in genome.h as GENOME_SIZE
float pMutPerGene=0.15;
float pMutDesCard = 0.1;
struct base* train_table = NULL;
struct base* car_table = NULL;
float* uniq_instances[2];
unsigned uniq_cnt[2];
\end
\User classes :
GenomeClass {
float x[G_SIZE];
}
\end
\Before everything else function:
{
INSTEAD_EVAL_STEP = true;
cout << "Seed : " << globalRandomGenerator->get_seed() << endl;
//cout<<"Before everything else function called "<<endl;
train_table = ba_postgres_load_train();
car_table = ba_postgres_load_car();
ba_set_links(train_table,car_table);
ba_mix_instances(train_table);
//ba_print_db(train_table);
uniq_instances[0] = ba_compute_uniq_values(car_table, 1, uniq_cnt+0);
uniq_instances[1] = ba_compute_uniq_values(car_table, 2, uniq_cnt+1);
printf("%d %d\n",uniq_cnt[0],uniq_cnt[1]);
for( unsigned i=0 ; i<uniq_cnt[0] ; i++ ){
printf("%f,",uniq_instances[0][i]);
}
printf("\n");
for( unsigned i=0 ; i<uniq_cnt[1] ; i++ ){
printf("%f,",uniq_instances[1][i]);
}
printf("\n");
}
\end
\After everything else function:
{
EA->population->sortParentPopulation();
IndividualImpl* best = (IndividualImpl*)EA->population->parents[0];
printf("best fitness %f\n",best->evaluate());
for( unsigned i=0 ; i<G_SIZE ; i+=3 ){
printf("%f %f >= %f\n",best->x[i],best->x[i+1],best->x[i+2]);
}
printf("\n");
cTreeNode* root = generate_tree(best->x,train_table,car_table);
struct base* tmp_table = table_from_genome(best->x,train_table,car_table);
show_tree(tmp_table,root);
struct base* tmp_learning_table, * tmp_test_table; // fixme
tmp_learning_table = (struct base*)malloc(sizeof(*tmp_learning_table));
tmp_test_table = (struct base*)malloc(sizeof(*tmp_test_table));
printf("depth of resulting tree %d\n",root->tree_depth());
#if 0
// prepare learning and test table.
tmp_test_table->hdr = tmp_learning_table->hdr = tmp_table->hdr; // affect tmp hdr to every table.
tmp_learning_table->no_instances = (unsigned)(tmp_table->no_instances*(2.f/3));
tmp_test_table->no_instances = (unsigned)(tmp_table->no_instances*(1./3));
tmp_learning_table->instances = new float*[tmp_learning_table->no_instances];
tmp_test_table->instances = new float*[tmp_test_table->no_instances];
memcpy(tmp_learning_table->instances,tmp_table->instances,
sizeof(*tmp_learning_table->instances)*tmp_learning_table->no_instances);
memcpy(tmp_test_table->instances,tmp_learning_table->no_instances+tmp_table->instances,
sizeof(*tmp_learning_table->instances)*tmp_test_table->no_instances);
for( unsigned i=0 ; i<tmp_test_table->no_instances ; i++ ){
unsigned predicted_class = root->classify_instance(tmp_test_table->instances[i]);
unsigned real_class = (unsigned)tmp_test_table->instances[i][tmp_test_table->hdr->whichis_class];
printf("%d - %d\n",predicted_class,real_class);
}
#endif
delete root;
ba_delete( tmp_table );
}
\end
\GenomeClass::initialiser :
{
for( unsigned i=0; i<G_SIZE ; i+=3 ) {
//Genome.x[i] = random(0,101);
//Genome.x[i+1] = random(0,101);
//Genome.x[i] = car_table->hdr->attributes[1]->threshold[random(0,car_table->hdr->attributes[1]->no_threshold)];
//Genome.x[i+1] = car_table->hdr->attributes[2]->threshold[random(0,car_table->hdr->attributes[2]->no_threshold)];
Genome.x[i] = car_table->instances[random(0,car_table->no_instances)][i+1];
Genome.x[i+1] = car_table->instances[random(0,car_table->no_instances)][i+2];
if( tossCoin(pMutDesCard))
Genome.x[i+2] = 0;
else
Genome.x[i+2] = random(1,11);
}
}
\end
\GenomeClass::crossover :
{
for (int i=0; i<G_SIZE; i++){
if( tossCoin(0.5) )
child.x[i] = parent1.x[i];
else
child.x[i] = parent2.x[i];
}
}
\end
\GenomeClass::mutator : // Must return the number of mutations
{
int NbMut=0;
for (int i=0; i<G_SIZE; i+=GENE_SIZE){
// mutate the cardinality
if( tossCoin(pMutPerGene) ){
if( tossCoin(pMutDesCard) ){
Genome.x[i+GENE_SIZE-1] = 0;
NbMut++;
}
else{
float value = random_gauss(Genome.x[GENE_SIZE*i+GENE_SIZE-1],2);
value = (value<0 ? 0 : value); //if value less than 0, then value is 0
value = (value>10 ? 10 :value); // if value grether than 10 then value is 10
Genome.x[i+GENE_SIZE-1] = roundf(value);
NbMut++;
}
}
for( unsigned j=0 ; j<GENE_SIZE-1 ; j++ ){
if( tossCoin(pMutPerGene) ){
//Genome.x[i+j] = car_table->instances[random(0,car_table->no_instances)][j+1];
//Genome.x[i+j] = car_table->hdr->attributes[j+1]->threshold[random(0,car_table->hdr->attributes[j+1]->no_threshold)];
float value = random_gauss(Genome.x[i+j],2);
//value = (value<0 ? 0 : value); //if value less than 0, then value is 0
//value = (value>101 ? 101 :value); // if value grether than 10 then value is 10
//Genome.x[i+j] = value;
Genome.x[i+j] = ba_nearest_greather_table_value(car_table,j+1,value);
NbMut++;
}
} // for each threshold
}// for each gene
return NbMut;
}
\end
// The population evaluation.
\Instead evaluation function:
{
ba_mix_instances(train_table);
#pragma omp parallel for
for( unsigned i=0 ; i<popSize ; i++ ){
population[i]->evaluate();
}
}
\end
\GenomeClass::evaluator : // Returns the score
{
struct base* tmp_table = table_from_genome(Genome.x,train_table,car_table);
struct base* tmp_learning_table, * tmp_test_table; // fixme
float fitness_value = 0;
tmp_learning_table = (struct base*)malloc(sizeof(*tmp_learning_table));
tmp_test_table = (struct base*)malloc(sizeof(*tmp_test_table));
// prepare learning and test table.
tmp_test_table->hdr = tmp_learning_table->hdr = tmp_table->hdr; // affect tmp hdr to every table.
tmp_learning_table->no_instances = (unsigned)(tmp_table->no_instances*(2.f/3));
tmp_test_table->no_instances = (unsigned)(tmp_table->no_instances*(1./3));
tmp_learning_table->instances = new float*[tmp_learning_table->no_instances];
tmp_test_table->instances = new float*[tmp_test_table->no_instances];
memcpy(tmp_learning_table->instances,tmp_table->instances,
sizeof(*tmp_learning_table->instances)*tmp_learning_table->no_instances);
memcpy(tmp_test_table->instances,tmp_learning_table->no_instances+tmp_table->instances,
sizeof(*tmp_learning_table->instances)*tmp_test_table->no_instances);
cTreeNode* t = genereate_decision_tree(tmp_learning_table);
for( unsigned i=0 ; i<tmp_test_table->no_instances ; i++ ){
unsigned predicted_class = t->classify_instance(tmp_test_table->instances[i]);
unsigned real_class = (unsigned)tmp_test_table->instances[i][tmp_test_table->hdr->whichis_class];
// here compute classification error, or any quality measurment
if( predicted_class!=real_class ){
fitness_value++;
}
}
fitness_value += ((float)t->tree_depth());
delete t;
delete[] tmp_learning_table->instances;
delete[] tmp_test_table->instances;
free( tmp_learning_table );
free( tmp_test_table );
ba_delete(tmp_table);
return fitness_value;
}
\end
\User Makefile options:
CXXFLAGS+=-I/home/maitre/sources/c4.5/include/ -fopenmp -O3 -pg
LDFLAGS+= -lpq -O3 -lm -fopenmp libc45.a -pg
\end
\Default run parameters : // Please let the parameters appear in this order
Number of generations : 100 // NB_GEN
Time limit: 0 // In seconds, 0 to deactivate
Population size : 100 //POP_SIZE
Offspring size : 100 // 40%
Mutation probability : 0 // MUT_PROB
Crossover probability : 1 // XOVER_PROB
Evaluator goal : minimise // Maximise
Selection operator: Tournament 2.0
Surviving parents: 100%//percentage or absolute
Surviving offspring: 100%
Reduce parents operator: Tournament 2
Reduce offspring operator: Tournament 2
Final reduce operator: Tournament 2
Elitism: Strong //Weak or Strong
Elite: 1
Print stats:1 //Default: 1
Generate csv stats file:0
Generate gnuplot script:0
Generate R script:0
Plot stats:0 //Default: 0
\end
......@@ -36,10 +36,10 @@ __________________________________________________________*/
#define K 5
#define GENE_SIZE 4
#define GENOME_SIZE 32
#define GENOME_SIZE 128
float pMutPerGene=0.1;
float pMutPerGene=0.01;
float pMutDesCard = 0.05;
float pMutDesThre = 0.5;
......@@ -69,9 +69,10 @@ GenomeClass {
cout << "Seed : " << globalRandomGenerator->get_seed() << endl;
srand(globalRandomGenerator->get_seed());
t1 = ba_postgres_load_ilot(1);
t2 = ba_postgres_load_batiment(1);
t1 = ba_postgres_load_ilot(2);
t2 = ba_postgres_load_batiment(2);
ba_set_links(t1,t2);
//ba_print_links(t1);
//printf("+ %d - %d\n",t1->class_repartition[1],t1->class_repartition[0]);
for( unsigned i=0 ; i<t1->hdr->attributes[t1->hdr->whichis_class]->no_values; i++ )
......@@ -79,14 +80,14 @@ GenomeClass {
uniq_instances[0] = ba_compute_uniq_values(t2, 1, uniq_cnt+0);
uniq_instances[1] = ba_compute_uniq_values(t2, 2, uniq_cnt+1);
printf("%d %d\n",uniq_cnt[0],uniq_cnt[1]);
// allocating K packets
generate_k_fold(K,packets_size,t1,k_tables);
#if 1
#if 0
// try the perfect solution
IndividualImpl* i = new IndividualImpl();
i->x[0] = 30;
......@@ -104,7 +105,7 @@ GenomeClass {
show_tree(tc,t,0);
#endif
exit(-1);
//exit(-1);
}
\end
......@@ -143,7 +144,6 @@ GenomeClass {
printf(" error on the whole set : %d\n",error);
#endif
delete root;
ba_delete( tmp_table );
}
......@@ -153,11 +153,11 @@ GenomeClass {
{
for( unsigned i=0; i<GENOME_SIZE ; i+=GENE_SIZE ) {
Genome.x[i] = random(9,11364);
Genome.x[i+1] = random(77,999);
Genome.x[i+2] = random(569,1000);
Genome.x[i] = random(9.,11364.);
Genome.x[i+1] = random(77.,999.);
Genome.x[i+2] = random(569.,1000.);
Genome.x[i+GENE_SIZE-1] = random(0,5);
Genome.x[i+GENE_SIZE-1] = roundf(random(0.,10.));
}
}
\end
......@@ -206,15 +206,31 @@ GenomeClass {
for( unsigned j=0 ; j<GENE_SIZE-1 ; j++ ){
if( tossCoin(pMutPerGene) ){
if( tossCoin(pMutDesThre) ){
Genome.x[i+j] = INFINITY;
Genome.x[i+j] = INFINITY;
}
else{
float value;
if( __isinf(Genome.x[i+j]) ) Genome.x[i+j] = random(0,1000);
float value = random_gauss(Genome.x[i+j],10);
Genome.x[i+j] = roundf(value);
//value = ba_nearest_table_value(t2,j+1,value);
switch(j){
case 0:
value = random_gauss(Genome.x[i+j],100);
Genome.x[i+j] = roundf(value);
Genome.x[i+j] = ba_nearest_table_value(t2,j+1,value);
break;
case 1:
value = random_gauss(Genome.x[i+j],20);
Genome.x[i+j] = roundf(value);
Genome.x[i+j] = ba_nearest_table_value(t2,j+1,value);
break;
case 2:
value = random_gauss(Genome.x[i+j],10);
Genome.x[i+j] = roundf(value);
Genome.x[i+j] = ba_nearest_table_value(t2,j+1,value);
break;
}
//}
NbMut++;
}
NbMut++;
}
} // for each threshold
......@@ -331,7 +347,7 @@ GenomeClass {
}
fitness_value = (((float)error) / t1->no_instances)*100;// + ((float)tree_size)/K;
fitness_value = (((float)error) / t1->no_instances)*100 ;//+ ((float)tree_size)/K;
for( unsigned i=0 ; i<K ; i++ ){
ba_delete(k_tmp_tables[i]);
......@@ -346,14 +362,14 @@ LDFLAGS+= -lpq -lm -fopenmp ../c4.5_common/libc45.a
\end
\Default run parameters : // Please let the parameters appear in this order
Number of generations : 100 // NB_GEN
Number of generations : 200 // NB_GEN
Time limit: 0 // In seconds, 0 to deactivate
Population size : 200 //POP_SIZE
Population size : 100 //POP_SIZE
Offspring size : 100 // 40%
Mutation probability : 1 // MUT_PROB
Crossover probability : 1 // XOVER_PROB
Evaluator goal : minimise // Maximise
Selection operator: Tournament 6.0
Selection operator: Tournament 4.0
Surviving parents: 100%//percentage or absolute
Surviving offspring: 100%
Reduce parents operator: Tournament 2
......
......@@ -516,17 +516,17 @@
\GenomeClass::crossover:
int locusC = random(0,child1.Size-1);
int locusC = random(0,child.Size-1);
int locusP2 = random(0,parent2.Size-1);
Element * elt1=chercheNoeud(child1.arbre,locusC);
Element * elt1=chercheNoeud(child.arbre,locusC);
Element * eltParent2=chercheNoeud(parent2.arbre,locusP2);
Element *elt11 = copierSousArbreRec(eltParent2, elt1->profondeur,profondeurMax1);
remplace(child1.arbre,elt11,locusC);
regenSize(child1.arbre);
child1.Size=SIZE;
remplace(child.arbre,elt11,locusC);
regenSize(child.arbre);
child.Size=SIZE;
\end
......
......@@ -306,7 +306,7 @@ void CEvolutionaryAlgorithm::showPopulationStats(struct timeval beginTime){
#ifdef __linux__
if(this->params->plotStats && this->gnuplot->valid){
if(currentGeneration==0)
fprintf(this->gnuplot->fWrit,"plot \'%s.dat\' using 3:4 t \'Best Fitness\' w lines, \'%s.dat\' using 3:5 t \'Average\' w lines, \'%s.dat\' using 3:6 t \'StdDev\' w lines\n", params->outputFilename,params->outputFilename,params->outputFilename);
fprintf(this->gnuplot->fWrit,"plot \'%s.dat\' using 3:4 t \'Best Fitness\' w lines ls 1, \'%s.dat\' using 3:5 t \'Average\' w lines ls 4, \'%s.dat\' using 3:6 t \'StdDev\' w lines ls 3\n", params->outputFilename,params->outputFilename,params->outputFilename);
else
fprintf(this->gnuplot->fWrit,"replot\n");
fflush(this->gnuplot->fWrit);
......
......@@ -49,7 +49,7 @@ CGnuplot::CGnuplot(int nbEval){
this->fWrit = (FILE *)fdopen(toFils[1],"w");
this->fRead = (FILE *)fdopen(toPere[0],"r");
this->pid = sonPid;
fprintf(this->fWrit,"set term x11 persist\n");
fprintf(this->fWrit,"set term wxt persist\n");
fprintf(this->fWrit,"set grid\n");
fprintf(this->fWrit,"set xrange[0:%d]\n",nbEval);
fprintf(this->fWrit,"set xlabel \"Number of Evaluations\"\n");
......
......@@ -623,7 +623,7 @@ LDFLAGS=-lboost_program_options $(LIBAESAE)libeasea.a
#USER MAKEFILE OPTIONS :
\INSERT_MAKEFILE_OPTION#END OF USER MAKEFILE OPTIONS
CPPFLAGS+= -I$(LIBAESAE)include
CPPFLAGS+= -I$(LIBAESAE)include -I/usr/local/cuda/include/
NVCCFLAGS+=
......
......@@ -448,6 +448,11 @@ clean:
rm -f $(OBJS) $(TARGET)
easeaclean:
rm -f $(TARGET) *.o *.cpp *.hpp EASEA.png EASEA.dat EASEA.prm EASEA.mak Makefile EASEA.vcproj EASEA.csv EASEA.r EASEA.plot
gen:
../../easea EASEA
gent:
../../easea tl EASEA
\START_VISUAL_TPL<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
......
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