package abstrasy.pcfx;
import abstrasy.Node;
import abstrasy.interpreter.InterpreterException;
import abstrasy.interpreter.StdErrors;
/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
* http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/
public class PCFx_crossover_erx extends PCFx {
/*****
* Implémente nativement l'algorithme 'edge recombination crossover' du script suivant:
* ===================================================================================
*
#
# crossover-erx (Edge Recombination Crossover)
#
(define 'p1 [1 2 3 4 5 6])
(define 'p2 [2 4 3 1 5 6])
#(define 'p1 [4 1 3 2 5 6])
#(define 'p2 [4 3 2 1 5 6])
(define 'l (length p1))
(define 'l2 (- l 1))
(function 'corr{(args 'l 'x 'h)
(if{>? x h} then{return l} elif{<? x l} then{return h} else{return x})
})
(function 'find-edge{(args 's)
(define 'edge
(foreach s list{(args 'ex ...)
(define 'le [])
(foreach ex do{(args 'e ...) (if{zero? (length(find e in le))}then{append! e to le}) })
})
)
(define 'mxedge)
(define 'edge-index 0)
(foreach edge do{(args 'e 'i)
(if{nothing? edge-index} then{
(set! edge-index i)
(set! mxedge (length e))
}
elif{<? mxedge (length e)} then{
(set! edge-index i)
(set! mxedge (length e))
}
elif{and{=? mxedge (length e)}{zero? (round(random 1))}} then{
(set! edge-index i)
(set! mxedge (length e))
})
})
(return edge-index)
})
(define 'o1 [])
(define 's1
(foreach p1 list{(args 'e 'i)
(define 'pp1b (corr 0 (+ i 1) l2))
(define 'pp1a (corr 0 (- i 1) l2))
(define 'j (@(find e in p2) 0))
(define 'pp2b (corr 0 (+ j 1) l2))
(define 'pp2a (corr 0 (- j 1) l2))
([(@p1 pp1a)(@p1 pp1b)(@p2 pp2a)(@p2 pp2b)])
})
)
(display s1)
(define 'i (find-edge s1))
(while{<? (length o1) (length p1)} do{
(define 'a (@p1 i))
(append! a to o1)
(foreach s1 do{(args 'l ...)
(define 'f (find a in l))
(if{f} then{remove! f from l})
})
(define 'nmx)
(define 'ne)
(define 'sli (@s1 i))
(foreach sli do{(args 'e ...)
(define 'f (find e in sli))
(if{nothing? ne} then{
(set! ne e)
(set! nmx (length f))
}
elif{<? nmx (length f)} then{
(set! ne e)
(set! nmx (length f))
}
elif{and{=? nmx (length f)}{zero? (round(random 1))}} then{
(set! ne e)
(set! nmx (length f))
})
})
(if{something? ne} then{
(set! i (@(find ne in p1) 0))
}
else{
(set! i (find-edge s1))
})
})
(define 'o2 [])
(define 's2
(foreach p2 list{(args 'e 'i)
(define 'pp1b (corr 0 (+ i 1) l2))
(define 'pp1a (corr 0 (- i 1) l2))
(define 'j (@(find e in p1) 0))
(define 'pp2b (corr 0 (+ j 1) l2))
(define 'pp2a (corr 0 (- j 1) l2))
([(@p2 pp1a)(@p2 pp1b)(@p1 pp2a)(@p1 pp2b)])
})
)
(define 'i (find-edge s2))
(while{<? (length o2) (length p2)} do{
(define 'a (@p2 i))
(append! a to o2)
(foreach s2 do{(args 'l ...)
(define 'f (find a in l))
(if{f} then{remove! f from l})
})
(define 'nmx)
(define 'ne)
(define 'sli (@s2 i))
(foreach sli do{(args 'e ...)
(define 'f (find e in sli))
(if{nothing? ne} then{
(set! ne e)
(set! nmx (length f))
}
elif{<? nmx (length f)} then{
(set! ne e)
(set! nmx (length f))
}
elif{and{=? nmx (length f)}{zero? (round(random 1))}} then{
(set! ne e)
(set! nmx (length f))
})
})
(if{something? ne} then{
(set! i (@(find ne in p2) 0))
}
else{
(set! i (find-edge s2))
})
})
(display "p1 = " p1)
(display "p2 = " p2)
(display "o1 = " o1)
(display "o2 = " o2)
=>
[
[6 2 3 5]
[1 3 6 4]
[2 4 4 1]
[3 5 2 3]
[4 6 1 6]
[5 1 5 2]
]
p1 = [1 2 3 4 5 6]
p2 = [2 4 3 1 5 6]
o1 = [1 5 6 2 4 3]
o2 = [2 6 5 4 3 1]
Ready...
*
* On obtient 4 nouveaux chromozomes (2 fils et les 2 parents).
*
*****/
public PCFx_crossover_erx() {
}
private final static boolean isIn(Node a, Node liste) throws Exception {
for (int i = 0; i < liste.size(); i++) {
if (Node.equalsNodes(a, liste.elementAt(i))) {
return true;
}
}
return false;
}
private final static int getPos(Node a, Node liste) throws Exception {
for (int i = 0; i < liste.size(); i++) {
if (Node.equalsNodes(a, liste.elementAt(i))) {
return i;
}
}
return -1;
}
private final static int corr(int l, int x, int h) {
if (x > h) {
return l;
}
else if (x < l) {
return h;
}
else {
return x;
}
}
private final static boolean randomChoise() {
return ((Math.random() * 2d) <= 1.0d);
}
private final static int findEdge(Node s) throws Exception {
Node edge = Node.createCList();
for (int i = 0; i < s.size(); i++) {
Node ex = s.elementAt(i);
Node le = Node.createCList();
for (int j = 0; j < ex.size(); j++) {
Node e = ex.elementAt(j);
if (!isIn(e, le)) {
le.addElement(e);
}
}
edge.addElement(le);
}
int mxedge = -1;
int edgeIndex = -1;
for (int i = 0; i < edge.size(); i++) {
Node e = edge.elementAt(i);
if (mxedge < 0) {
mxedge = e.size();
edgeIndex = i;
}
else if (e.size() > 0 && mxedge < e.size()) {
mxedge = e.size();
edgeIndex = i;
}
else if (e.size() > 0 && mxedge == e.size() && randomChoise()) {
mxedge = e.size();
edgeIndex = i;
}
}
return edgeIndex;
}
/**
* eval
*
* @param startAt Node
* @return Node
* @throws Exception
* @todo Implémenter cette méthode abstrasy.PCFx
*/
public Node eval(Node startAt) throws Exception {
/*
* forme: (crossover-erx [liste1] [liste2])
*/
startAt.isGoodArgsCnt(3);
Node p1 = startAt.getSubNode(1, Node.TYPE_CLIST);
Node p2 = startAt.getSubNode(2, Node.TYPE_CLIST);
int l = p1.size();
int l2 = l - 1;
if (l != p2.size()) {
throw new InterpreterException(StdErrors.extend(StdErrors.List_size_mismatch, "(<>? " + l + " " + p2.size() + ")"));
}
Node o1 = Node.createCList();
Node s1 = Node.createCList();
for (int i = 0; i < l; i++) {
int pp1b = corr(0, i + 1, l2);
int pp1a = corr(0, i - 1, l2);
int j = getPos(p1.elementAt(i), p2);
int pp2b = corr(0, j + 1, l2);
int pp2a = corr(0, j - 1, l2);
s1.addElement(Node.createCList().append(p1.elementAt(pp1a)).append(p1.elementAt(pp1b)).append(p2.elementAt(pp2a)).append(p2.elementAt(pp2b)));
}
int index = findEdge(s1);
while (o1.size() < l && index >= 0) {
Node a = p1.elementAt(index);
if (isIn(a, o1)) {
// auto-correction
int i = 0;
while (isIn(a, o1)) {
a = p1.elementAt(i++);
}
index = i;
}
o1.addElement(a);
for (int i = 0; i < s1.size(); i++) {
Node ltmp = s1.elementAt(i);
for (int j = 0; j < ltmp.size(); j++) {
if (Node.equalsNodes(a, ltmp.elementAt(j))) {
ltmp.removeElementAt(j--);
}
}
}
int nmx = -1;
Node ne = null;
Node sli = s1.elementAt(index);
for (int i = 0; i < sli.size(); i++) {
Node e = sli.elementAt(i);
int f = 0;
for (int j = 0; j < sli.size(); j++) {
if (Node.equalsNodes(e, sli.elementAt(j))) {
f++;
}
}
if (ne == null) {
ne = e;
nmx = f;
}
else if (nmx < f) {
ne = e;
nmx = f;
}
else if (nmx == f && randomChoise()) {
ne = e;
nmx = f;
}
}
if (ne != null) {
index = getPos(ne, p1);
if (index < 0) {
throw new InterpreterException(StdErrors.Internal_error);
}
}
else {
index = findEdge(s1);
if (index < 0) {
throw new InterpreterException(StdErrors.Internal_error);
}
}
}
Node o2 = o1;
while (Node.equalsNodes(o2, o1)) {
o2 = Node.createCList();
Node s2 = Node.createCList();
for (int i = 0; i < l; i++) {
int pp1b = corr(0, i + 1, l2);
int pp1a = corr(0, i - 1, l2);
int j = getPos(p2.elementAt(i), p1);
int pp2b = corr(0, j + 1, l2);
int pp2a = corr(0, j - 1, l2);
s2.addElement(Node.createCList().append(p2.elementAt(pp1a)).append(p2.elementAt(pp1b)).append(p1.elementAt(pp2a)).append(p1.elementAt(pp2b)));
}
index = findEdge(s2);
while (o2.size() < l && index >= 0) {
Node a = p2.elementAt(index);
if (isIn(a, o2)) {
// auto-correction
int i = 0;
while (isIn(a, o2)) {
a = p2.elementAt(i++);
}
index = i;
}
o2.addElement(a);
for (int i = 0; i < s2.size(); i++) {
Node ltmp = s2.elementAt(i);
for (int j = 0; j < ltmp.size(); j++) {
if (Node.equalsNodes(a, ltmp.elementAt(j))) {
ltmp.removeElementAt(j--);
}
}
}
int nmx = -1;
Node ne = null;
Node sli = s2.elementAt(index);
for (int i = 0; i < sli.size(); i++) {
Node e = sli.elementAt(i);
int f = 0;
for (int j = 0; j < sli.size(); j++) {
if (Node.equalsNodes(e, sli.elementAt(j))) {
f++;
}
}
if (ne == null) {
ne = e;
nmx = f;
}
else if (nmx < f) {
ne = e;
nmx = f;
}
else if (nmx == f && randomChoise()) {
ne = e;
nmx = f;
}
}
if (ne != null) {
index = getPos(ne, p2);
if (index < 0) {
throw new InterpreterException(StdErrors.Internal_error);
}
}
else {
index = findEdge(s2);
if (index < 0) {
throw new InterpreterException(StdErrors.Internal_error);
}
}
}
}
Node o3 = Node.createCList();
for (int i = 0; i < l; i++) {
o3.addElement(p1.elementAt(i));
}
Node o4 = Node.createCList();
for (int i = 0; i < l; i++) {
o4.addElement(p2.elementAt(i));
}
// ne pas oublier de sécuriser (à l'aide de select)...
return Node.createCList()
.append(o1.select(0, o1.size()))
.append(o2.select(0, o2.size()))
.append(o3.select(0, o3.size()))
.append(o4.select(0, o4.size()));
}
}