#include "stdafx.h"
#include "ebd.h"
EBD::EBD(Genome* inputGenomes, int geneNum): ED(inputGenomes, geneNum)
{
currentPos[0] = NULL;
currentPos[1] = NULL;
}
int EBD::currentSolution (Pair* p, int currentCost)
{
return p->cost + currentCost;
}
int EBD::isNext(int genome, int t1, int t2)
{
int t11 = t1 < t2? t1: t2;
int t12 = t1 < t2? t2: t1;
t11 ++;
while (t11 < t12)
{
if (g[genome][t11].fixed == 0)
t11 ++;
else break;
}
return (t11 == t12);
}
int EBD::isAdjacent (int genome, int t1, int t2)
{
//assert (t1 < t2);
int gene1 = abs (g[genome][t1].gene);
int gene2 = abs (g[genome][t2].gene);
int u1 = currentPos[1 - genome][gene1];
int u2 = currentPos[1 - genome][gene2];
if (!isNext(1 - genome, u1, u2))
return 0;
if (u1 < u2)
return (g[1 - genome][u1].gene == g[genome][t1].gene &&
g[1 - genome][u2].gene == g[genome][t2].gene);
else
return (g[1 - genome][u1].gene == -g[genome][t1].gene &&
g[1 - genome][u2].gene == -g[genome][t2].gene);
}
int EBD::distInc (Pair* p) throw(char*)
{
try
{
incCounter();
}
catch (char* e)
{
throw;
}
int nb[2][2];
int i;
for (i = 0; i < 2; i ++)
{
int t;
if (i == 0)
t = p->g;
else t = p->h;
nb[i][0] = t;
while (!g[i][nb[i][0]].fixed)
nb[i][0] --;
nb[i][1] = t;
while (!g[i][nb[i][1]].fixed)
nb[i][1] ++;
}
int deleted = 0;
if (!isAdjacent (0, nb[0][0], nb[0][1]))
deleted = 1;
g[0][p->g].fixed = 1;
g[1][p->h].fixed = 1;
currentPos[0][abs(g[0][p->g].gene)] = p->g;
currentPos[1][abs(g[0][p->g].gene)] = p->h;
int created = 0;
int ok = 0;
if (!isAdjacent (0, nb[0][0], p->g))
created ++;
if (!isAdjacent (0, p->g, nb[0][1]))
created ++;
if (isAdjacent (1, nb[1][0], nb[1][1]))
created ++;
p->cost = created - deleted;
g[0][p->g].fixed = 0;
g[1][p->h].fixed = 0;
currentPos[0][abs(g[0][p->g].gene)] = -1;
currentPos[1][abs(g[0][p->g].gene)] = -1;
return p->cost;
}
int EBD::exemplarDist () throw (char*)
{
int i;
//build two exemplars
std::vector<int> e1;
std::vector<int> e2;
for (i = 0; i < g[0].size(); i ++)
if (g[0][i].fixed == 1)
e1.push_back (g[0][i].gene);
for (i = 0; i < g[1].size(); i ++)
if (g[1][i].fixed == 1)
e2.push_back (g[1][i].gene);
//calculate breakpoint distance between two exemplars
int map_size = n;
int* map = new int[map_size];
memset (map, 0, map_size * sizeof (int));
for (i = 0; i < (int)e1.size(); i ++)
{
int t = abs (e1[i]);
//assert (t < n);
map[t] = i;
}
int bpdist = 0;
int t1 = map[abs (e2[0])];
int t2;
//assert (t1 >= 0);
for (i = 1; i < (int)e2.size(); i ++)
{
t2 = map[abs (e2[i])];
//assert (t2 >= 0);
if (abs (t1 - t2) != 1) bpdist ++;
else
{
if (t1 < t2)
{
if (e1[t1] != e2[i - 1] || e1[t2] != e2[i])
bpdist ++;
}
else
{
if (e1[t1] != -e2[i - 1] || e1[t2] != -e2[i])
bpdist ++;
}
}
t1 = t2;
}
delete[] map;
return bpdist;
}
void EBD::updateCost (Pair* p, int* currentCost)
{
*currentCost += p->cost;
currentPos[0][abs(g[0][p->g].gene)] = p->g;
currentPos[1][abs(g[1][p->h].gene)] = p->h;
}
void EBD::restoreCost (Pair* p, int* currentCost)
{
*currentCost -= p->cost;
currentPos[0][abs(g[0][p->g].gene)] = -1;
currentPos[1][abs(g[1][p->h].gene)] = -1;
}
void EBD::preprocess ()
{
ED::preprocess();
currentPos[0] = new int[n];
currentPos[1] = new int[n];
int i;
for (i = 0; i < n; i ++)
{
if (gfList[i].pairs.size() == 1)
{
currentPos[0][i] = gfList[i].pairs[0]->g;
currentPos[1][i] = gfList[i].pairs[0]->h;
}
else
{
currentPos[0][i] = -1;
currentPos[1][i] = -1;
}
}
}
void EBD::postprocess ()
{
ED::postprocess();
delete[] currentPos[0];
delete[] currentPos[1];
}