📄 genome.cpp
字号:
/*************************************************************************** genome.cpp - description ------------------- begin : Sat Dec 8 2001 copyright : (C) 2001 by Rudiger Koch email : rkoch@rkoch.org ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include "amygdala/genome.h"#include "amygdala/utilities.h"#include "amygdala/logging.h"#include "amygdala/visualstub.h"#include "amygdala/network.h"#include <netdb.h>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <iostream>#include <stdexcept>using namespace Amygdala;using namespace std;Genome::Genome(const string & _url) : mutationHeat(1), url(_url){ gHandler = NULL;}Genome::~Genome(){}void Genome::Get(){ if(url.substr(0,4) == string("file")){ string path = url.substr(5); GetFile(path); } else if(url.substr(0,7) == string("http://")){ GetHttp(); } else { throw runtime_error("malformed url: " + url); }}void Genome::GetFile(const string & path){ cout << "Loading genome from file " << path << endl; int fd; char buffer[20]; string filename = path.substr(path.length()-13); geneId = atoi(filename.c_str()); if((fd = open(path.c_str(), O_RDONLY)) == -1) throw runtime_error("cannot open genefile"); int amount; while((amount = read(fd, buffer, sizeof(buffer)))>0) { if(amount <=-1) throw runtime_error("read error"); for(int i=0; i<amount;i++){ genome += buffer[i]; } } string::size_type crlf = genome.find("\r\n"); Format(genome.substr(0, crlf)); genome = genome.substr(crlf+2); if (close(fd) < 0) throw runtime_error("closing filedescriptor failed");}void Genome::GetHttp(){ char buffer[256]; string download; int msgsock = OpenSocket(); string req = string("GET /genome HTTP/1.0\r\n\r\n"); if (write(msgsock, req.c_str(), req.length()) < 0) throw runtime_error("cannot send request"); int amount; while((amount = read(msgsock, buffer, sizeof(buffer)))>0) { if(amount <=-1){ throw runtime_error("error reading from server");} for(int i=0; i<amount;i++){ download += buffer[i]; } } string::size_type httpResultpos = download.find("\r\nHTTP/") + 1; string httpResult = download.substr(httpResultpos, download.find("\r\n", httpResultpos) - httpResultpos); if(httpResult.find(" 200 ") == string::npos) throw runtime_error(httpResult); string idHeader = "Genome-Id:"; string::size_type pos = download.find(idHeader)+idHeader.length(); if(pos == string::npos) throw runtime_error("No Genome-Id header"); string id = download.substr(pos, download.find("\r\n", pos)); geneId = atoi(id.c_str()); if(!geneId) throw runtime_error(string("Malformed Gene-Id header. ID = ") + id); cout << "Got Genome ID " << geneId << endl; unsigned int pos1 = download.find("\r\n\r\n") + 4; if(pos1 == string::npos) throw runtime_error("No Body"); unsigned int pos2 = download.find("\r\n", pos1); string format = download.substr(pos1, pos2-pos1); if(pos2 == string::npos) throw runtime_error("Malformed Chromosome-Format"); Format(format); genome = download.substr(pos2 + 2); if (close(msgsock) < 0) throw runtime_error("cannot close socket");}void Genome::Submit(const int score) const{ char buffer[100]; LOGGER (1, "Submitting. Score: " << score); int msgsock = OpenSocket(); string req = string("GET /result HTTP/1.0\r\n") + "Genome-Id: " + Utilities::itostr(geneId) + "\r\n" + "Score: " + Utilities::itostr(score) + "\r\n\r\n"; if (write(msgsock, req.c_str(), req.length()) < 0) throw runtime_error("write error"); int amount; while((amount = read(msgsock, buffer, sizeof(buffer)))>0) { if(amount <=-1) throw runtime_error("read error"); } if (close(msgsock) < 0) throw runtime_error("cannot close socket");}void Genome::SetHandler(GenomeHandler *gh){ gHandler = gh;}void Genome::Parse(){ LOGGER(2, "Parsing genome"); if(!gHandler) throw runtime_error("no genome handler registered"); int pos=0; for(unsigned int i=0; i<chromosomes.size(); i++){ for(unsigned int j=0; j<chromosomes[i].genes; j++){ try { gHandler->Gene(genome.substr(pos, chromosomes[i].gene_size), i); } catch (out_of_range e) { throw runtime_error("premature end of genome while parsing"); } pos += (chromosomes[i].gene_size + mutationHeat); } } gHandler->FinishParsing(); VisualStub * visualStub = Network::GetNetworkRef()->GetVisualStub(); if(visualStub == NULL) { while(gHandler->Step()); } else { LOGGER(2, "Running Morphogenesis in GLDebugger"); visualStub->RunGA(gHandler); }}void Genome::Format(const string & fmt){ unsigned int lbracket = 0; unsigned int rbracket, comma; chromosomes.clear(); while ((lbracket = fmt.find('{', lbracket)) != string::npos){ lbracket++; comma = fmt.find(',', lbracket); if(comma == string::npos) throw runtime_error("error in format string\n"); rbracket = fmt.find('}', lbracket); if(rbracket == string::npos) throw runtime_error("error in format string\n"); ChromosomeFormat chr; chr.genes = atoi(fmt.substr(lbracket, comma).c_str()); chr.gene_size = atoi(fmt.substr(comma+1, rbracket).c_str()); chromosomes.push_back(chr); }}int Genome::OpenSocket() const{ int msgsock=0; struct sockaddr_in server; uint16_t port = 10080; // default port if(url.empty()) throw runtime_error("No server URL specified - cannot submit a score"); if ((msgsock = socket( AF_INET, SOCK_STREAM, 0)) < 0) throw runtime_error("cannot open socket"); string hostname; string::size_type colon = url.find(':', 9); if(colon == string::npos){ hostname = url.substr(7, url.find('/', 9) - 7); } else { hostname = url.substr(7, colon - 7); port = atoi(url.substr(colon+1).c_str()); } struct hostent *serverh = gethostbyname(hostname.c_str()); if (!serverh) throw runtime_error(string("cannot resolve hostname ") + hostname) ; memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; memcpy((char *)&server.sin_addr.s_addr, serverh->h_addr, serverh->h_length); server.sin_port = htons(port); if (connect(msgsock, (struct sockaddr*)(void*)&server, sizeof(server)) < 0) throw runtime_error(string("cannot connect to server ") + hostname + " at port " + Utilities::itostr(port)); return msgsock;}void Genome::Upload() const{ string resultStr; char buffer[100]; int msgsock = OpenSocket(); string chromosomeFormat; for(vector <ChromosomeFormat>::const_iterator it = chromosomes.begin(); it != chromosomes.end(); it++){ chromosomeFormat += "{" + Utilities::itostr((*it).genes) + "," + Utilities::itostr((*it).gene_size) + "," + (*it).mutationMode +"}"; } unsigned int contentLength = genome.length() + 2 + chromosomeFormat.length(); string req = "PUT /upload HTTP/1.0\r\n"; req += "Content-Length: " + Utilities::itostr(contentLength) + "\r\n\r\n"; req += chromosomeFormat + "\r\n" + genome; LOGGER(4, "Submitting genome, format string=" << chromosomeFormat << " length=" << contentLength); int amount; if ((amount = write(msgsock, req.c_str(), req.length())) < 0) throw runtime_error("write error"); if(amount < signed(req.length())) cerr << "Could only write " << amount << " of " << req.length() << " bytes" << endl; while((amount = read(msgsock, buffer, sizeof(buffer)))>0) { if(amount <=-1) throw runtime_error("read error"); for(int i=0; i<amount;i++){ resultStr += buffer[i]; } } LOGGER(2, "Server says:" << endl << resultStr); LOGGER(2, "End of server result string"); if (close(msgsock) < 0) throw runtime_error("cannot close socket"); string::size_type errorPos = resultStr.find("Error:"); if(errorPos != string::npos) throw runtime_error(string("Geneserver says: ") + resultStr.substr(errorPos));}void Genome::StartChromosome(const char mutationMode){ ChromosomeFormat chrFmt; chrFmt.genes = chrFmt.gene_size = 0; chrFmt.mutationMode = mutationMode; chromosomes.push_back(chrFmt); LOGGER(4, "Started Chromosome " << chromosomes.size());}void Genome::AddGene(const string & gene){ ChromosomeFormat currChr = chromosomes[chromosomes.size() - 1]; LOGGER(4, "Adding gene " << currChr.genes + 1); if(currChr.genes == 0){ currChr.gene_size = gene.length(); } else { if(currChr.gene_size != gene.length()){ throw runtime_error("Error: All genes of a chromosome must have equal length"); } } currChr.genes++; genome += gene; for(unsigned int i=0; i<mutationHeat; i++) genome += (unsigned char)0xFF; chromosomes[chromosomes.size() - 1] = currChr;}void Genome::MakeChromosome(const unsigned int len, const unsigned int genesize, const char mutationMode){ if(mutationMode != 'n' && mutationMode != 'c' && mutationMode != 'v') throw runtime_error("Mutation Mode must be either 'n', 'c' or 'v'"); StartChromosome(mutationMode); for (unsigned int i=0; i<len; i++){ string gene = ""; for(unsigned int j=0; j<genesize; j++){ unsigned char amino = (unsigned char)(unsigned int)(256.0*rand()/(RAND_MAX+1.0)); gene.push_back( amino ); } AddGene(gene); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -