/**
 * 
 */
package edu.neu.ccs.evergreen.ir;

import static org.junit.Assert.*;

import org.junit.Test;

/**
 * @author mohsen
 *
 */
public class RelationCoreSwapRenameTest {

    int maxRank = RelationCore.MaxRank;
    /**
     * Test method for {@link edu.neu.ccs.evergreen.ir.RelationCore#swap(int, int, int, int)}.
     */
    @Test
    public final void testSwap() {
        //swapping a magic number produces another magic number
        for (int rank = 1; rank < maxRank; rank++) {
            for (int variablePosition1 = 0; variablePosition1 < rank; variablePosition1++) {
                for (int variablePosition2 = 0; variablePosition2 < rank; variablePosition2++) {
                    for (int value = 0; value <= 1; value++) {
                        int relationNumber1 = RelationCore.getMagicNumber(rank, variablePosition1, value);
                        int relationNumber2 = RelationCore.getMagicNumber(rank, variablePosition2, value);
                        int swappedRelationNumber1 = RelationCore.swap(relationNumber1, rank, variablePosition1, variablePosition2);
                        assertTrue(swappedRelationNumber1 == relationNumber2);
                    }
                }
            }
        }
        //swapping the same pair of vars twice will give us the same original relation number
        for(int rank=1;rank<maxRank;rank++){
            if(RelationCore.getMask(rank)>0){
                for(int relationNumber=0;relationNumber<RelationCore.getMask(rank);relationNumber++){
                    for(int variablePosition1=0;variablePosition1<rank;variablePosition1++){
                        for(int variablePosition2=0;variablePosition2<rank;variablePosition2++){
                            int swappedRelationNumber = RelationCore.swap(relationNumber, rank, variablePosition1, variablePosition2);
                            int originalRelationNumber = RelationCore.swap(swappedRelationNumber, rank, variablePosition1, variablePosition2);
                                            
                            assertTrue(relationNumber==originalRelationNumber);
                        }
                    }
                }
            }else{
                for(int relationNumber=0xFFFFFFFF;relationNumber<0x7FFFFFFE;relationNumber++){
                    for(int variablePosition1=0;variablePosition1<rank;variablePosition1++){
                        for(int variablePosition2=0;variablePosition2<rank;variablePosition2++){
                            int swappedRelationNumber = RelationCore.swap(relationNumber, rank, variablePosition1, variablePosition2);
                            int originalRelationNumber = RelationCore.swap(swappedRelationNumber, rank, variablePosition1, variablePosition2);
                                            
                            assertTrue(relationNumber==originalRelationNumber);
                        }
                    }
                }
                for(int variablePosition1=0;variablePosition1<rank;variablePosition1++){
                    int relationNumber=0x7FFFFFFF;
                    for(int variablePosition2=0;variablePosition2<rank;variablePosition2++){
                        int swappedRelationNumber = RelationCore.swap(relationNumber, rank, variablePosition1, variablePosition2);
                        int originalRelationNumber = RelationCore.swap(swappedRelationNumber, rank, variablePosition1, variablePosition2);
                                        
                        assertTrue(relationNumber==originalRelationNumber);
                    }
                }

            }
        }       
    }

    /**
     * Test method for {@link edu.neu.ccs.evergreen.ir.RelationCore#renme(int, int, int, int[])}.
     */
    @Test
    public final void testRenme() {
        //comutative relation such as and of all posititive/negative vars,or of all positive/negative vars stay the same
        //also try relations such as 0in3,1in3,2in3,3in3
        for(int rank=1;rank<=maxRank;rank++){
            int[] allVars = new int[rank];
            for(int var=0;var<rank;var++){
                allVars[var] = var;
            }
            int[] relationNumbers = new int[4+rank+1];
            relationNumbers[0] = RelationNumberUtil.and(rank, allVars);
            relationNumbers[1] = RelationNumberUtil.nMap(RelationNumberUtil.and(rank, allVars), rank, allVars);
            relationNumbers[2] = RelationNumberUtil.or(rank, allVars);
            relationNumbers[3] = RelationNumberUtil.nMap(RelationNumberUtil.or(rank, allVars), rank, allVars);
            for(int i=0;i<=rank;i++){
                relationNumbers[4+i] = RelationNumberUtil.xTrueVars(rank, i);
            }
            for(int relationNumber:relationNumbers){
                CustomCounter p = new CustomCounter(rank,0,rank-1);
                while(p.hasNextPermutation()){
                    int[] permutation = p.nextPermutation(); 
                    int permutedRelationNumber = RelationCore.renme(relationNumber, rank, RelationCore.SOURCE, permutation);
                    assertTrue(relationNumber==permutedRelationNumber);
                    permutation = p.getPermutation();
                    int originalRelationNumber = RelationCore.renme(relationNumber, rank, RelationCore.TARGET, permutation);
                    //System.out.println(relationNumber);
                    assertTrue(relationNumber==originalRelationNumber);
                }
            }
        }
        //Source and Target Permutations undo each other
        for(int rank=1;rank<maxRank;rank++){
            if(RelationCore.getMask(rank)>0){
                for(int relationNumber=0;relationNumber<RelationCore.getMask(rank);relationNumber++){
                    CustomCounter p = new CustomCounter(rank,0,rank-1);
                    while(p.hasNextPermutation()){
                        int[] permutation = p.nextPermutation(); 
                        int permutedRelationNumber = RelationCore.renme(relationNumber, rank, RelationCore.SOURCE, permutation);
                        permutation = p.getPermutation();
                        int originalRelationNumber = RelationCore.renme(permutedRelationNumber, rank, RelationCore.TARGET, permutation);
                        
                        assertTrue(relationNumber==originalRelationNumber);
                    }
                }
            }else{
                for(int relationNumber=0xFFFFFFFF;relationNumber<0x7FFFFFFE;relationNumber++){
                    CustomCounter p = new CustomCounter(rank,0,rank-1);
                    while(p.hasNextPermutation()){
                        int[] permutation = p.nextPermutation(); 
                        int permutedRelationNumber = RelationCore.renme(relationNumber, rank, RelationCore.SOURCE, permutation);
                        int originalRelationNumber = RelationCore.renme(permutedRelationNumber, rank, RelationCore.SOURCE, permutation);
                        
                        assertTrue(relationNumber==originalRelationNumber);
                    }
                }
                for(int variablePosition1=0;variablePosition1<rank;variablePosition1++){
                    int relationNumber=0x7FFFFFFF;
                    CustomCounter p = new CustomCounter(rank,0,rank-1);
                    while(p.hasNextPermutation()){
                        int[] permutation = p.nextPermutation(); 
                        int permutedRelationNumber = RelationCore.renme(relationNumber, rank, RelationCore.SOURCE, permutation);
                        int originalRelationNumber = RelationCore.renme(permutedRelationNumber, rank, RelationCore.SOURCE, permutation);
                        
                        assertTrue(relationNumber==originalRelationNumber);
                    }
                }
            }
        }
    }

}