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_ox extends PCFx {
/*****
* Implémente nativement l'algorithme 'order based crossover' du script suivant:
* =============================================================================
*
#
# crossover-ox (order based crossover)
#
(define 'p1 [1 2 3 4 5 6 7 8 9])
(define 'p2 [4 5 2 1 8 7 6 9 3])
(define 'pivot1 3)
(define 'pivot2 6)
(define 'l (+ (- pivot2 pivot1) 1))
(define 'l1 (+ pivot1 1))
(define 'l2 (+ pivot2 1))
(define 'a1 (select p1 pivot1 l))
(define 'a2 (select p2 pivot1 l))
(define 'b1 (merge (select p1 l2 (- (length p1) l2)) (select p1 0 pivot1) a1))
(define 'b2 (merge (select p2 l2 (- (length p2) l2)) (select p2 0 pivot1) a2))
(display "p1 = " p1)
(display "p2 = " p2)
(display)
(display "a1 = " a1 ", b1 = " b1)
(display "a2 = " a2 ", b2 = " b2)
(foreach a1 do{ (args 'a ...) (remove! (find a in b2) from b2)})
(foreach a2 do{ (args 'a ...) (remove! (find a in b1) from b1)})
(display)
(display "b1 = " b1)
(display "b2 = " b2)
(define 'o1 (merge (select b1 (- (length b1) pivot1) pivot1) a2 (select b1 0 (- (length b1) pivot1))))
(define 'o2 (merge (select b2 (- (length b2) pivot1) pivot1) a1 (select b2 0 (- (length b2) pivot1))))
(display)
(display "o1 = " o1)
(display "o2 = " o2)
=>
p1 = [1 2 3 4 5 6 7 8 9]
p2 = [4 5 2 1 8 7 6 9 3]
a1 = [4 5 6 7], b1 = [8 9 1 2 3 4 5 6 7]
a2 = [1 8 7 6], b2 = [9 3 4 5 2 1 8 7 6]
b1 = [9 2 3 4 5]
b2 = [9 3 2 1 8]
o1 = [3 4 5 1 8 7 6 9 2]
o2 = [2 1 8 4 5 6 7 9 3]
Ready...
*
* On obtient 4 nouveaux chromozomes (2 fils et les 2 parents).
*
*****/
public PCFx_crossover_ox() {
}
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;
}
/**
* eval
*
* @param startAt Node
* @return Node
* @throws Exception
* @todo Implémenter cette méthode abstrasy.PCFx
*/
public Node eval(Node startAt) throws Exception {
/*
* formes: (crossover-ox [liste1] [liste2] pivot1 pivot2)
* (crossover-ox [liste1] [liste2] pivot1)
*/
startAt.isGoodArgsCnt(4, 5);
Node p1 = startAt.getSubNode(1, Node.TYPE_CLIST);
Node p2 = startAt.getSubNode(2, Node.TYPE_CLIST);
if(p1.size()!=p2.size()){
throw new InterpreterException(StdErrors.extend(StdErrors.List_size_mismatch,"(<>? "+p1.size()+" "+p2.size()+")"));
}
int pivot1 = (int)startAt.getSubNode(3, Node.TYPE_NUMBER).getNumber();
int pivot2 = startAt.size()==5 ? (int)startAt.getSubNode(4, Node.TYPE_NUMBER).getNumber() : p1.size()-1;
if(pivot1<0 || pivot1>=pivot2){
throw new InterpreterException(StdErrors.extend(StdErrors.Out_of_range,"(starting point "+pivot1+")"));
}
if(pivot2<=pivot1 || pivot2>p1.size()-1){
throw new InterpreterException(StdErrors.extend(StdErrors.Out_of_range,"(ending point "+pivot2+")"));
}
/*
* Préparatifs de l'algo
*/
int l = (pivot2 - pivot1) + 1;
int l2= pivot2 + 1;
Node a1 = Node.createCList();
for(int i=pivot1;i<(pivot1+l);i++){
a1.addElement(p1.elementAt(i));
}
Node a2 = Node.createCList();
for(int i=pivot1;i<(pivot1+l);i++){
a2.addElement(p2.elementAt(i));
}
Node b1 = Node.createCList();
for(int i=l2;i<p1.size();i++){
b1.addElement(p1.elementAt(i));
}
for(int i=0;i<pivot1;i++){
b1.addElement(p1.elementAt(i));
}
for(int i=0;i<a1.size();i++){
b1.addElement(a1.elementAt(i));
}
Node b2 = Node.createCList();
for(int i=l2;i<p2.size();i++){
b2.addElement(p2.elementAt(i));
}
for(int i=0;i<pivot1;i++){
b2.addElement(p2.elementAt(i));
}
for(int i=0;i<a2.size();i++){
b2.addElement(a2.elementAt(i));
}
for(int i=0;i<a1.size();i++){
Node a = a1.elementAt(i);
int found =getPos(a,b2);
if(found>=0){
b2.removeElementAt(found);
}
}
for(int i=0;i<a2.size();i++){
Node a = a2.elementAt(i);
int found =getPos(a,b1);
if(found>=0){
b1.removeElementAt(found);
}
}
int dp=b1.size()-pivot1;
// sécuriser la finalité
Node o1 = Node.createCList();
for(int i=dp;i<(dp+pivot1);i++){
o1.addElement(b1.elementAt(i));
}
for(int i=0;i<a2.size();i++){
o1.addElement(a2.elementAt(i));
}
for(int i=0;i<dp;i++){
o1.addElement(b1.elementAt(i));
}
Node o2 = Node.createCList();
for(int i=dp;i<(dp+pivot1);i++){
o2.addElement(b2.elementAt(i));
}
for(int i=0;i<a2.size();i++){
o2.addElement(a1.elementAt(i));
}
for(int i=0;i<dp;i++){
o2.addElement(b2.elementAt(i));
}
Node o3 = Node.createCList();
for(int i=0;i<p1.size();i++){
o3.addElement(p1.elementAt(i));
}
Node o4 = Node.createCList();
for(int i=0;i<p1.size();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()));
}
}