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

import static org.junit.Assert.*;

import org.junit.Test;

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

    int maxRank = RelationCore.MaxRank; // for loops over all possible relation ranks to use
    
    /**
     * Test method for {@link edu.neu.ccs.evergreen.ir.RelationCore#isForced(int, int, int)}.
     */
    @Test
    public final void testIsForced() {
        
        // As long as we are using "and" in constructing the relations we have forced vars
        // for example:
        //All magic numbers are forced
        //The and of two or three or four or five magic number are also forced
        
        //Must be independent of the rest of the variables
        //CustomCounter c,d;
        //int r,rn;
        //int[] forcedVars;
        //int[] negatedVars;
        // for every rank
        for(int rank=1;rank<=maxRank;rank++){
            //for every subset of variables
            for(int vars=1;vars<=rank;vars++){
                CustomCounter c = new CustomCounter(vars,0,rank-1);
                while(c.hasNextDistinctPermutation()){
                    int[] forcedVars = c.nextDistinctPermutation();
                    int r = RelationNumberUtil.and(rank, forcedVars);
                    CustomCounter d = new CustomCounter(vars,0,1);
                    while(d.hasNext()){
                        int[] negatedVars = d.next();
                        int rn = RelationNumberUtil.nMap(r, rank, c.filter(negatedVars));
                        //checks that vars are forced
                        for(int variablePosition=0;variablePosition<rank;variablePosition++){
                            int forced = RelationCore.isForced(rn, rank, variablePosition);
                            switch(forced){
                            case -1:
                                //Make sure that var is not in forced vars
                                for(int i:forcedVars){
                                    assertTrue(i!=variablePosition);
                                }
                                break;
                            case 0:
                                //Make sure that var is in forced vars
                                boolean flag=false;
                                for(int i=0;i<forcedVars.length;i++){
                                    if((forcedVars[i]==variablePosition)&&(negatedVars[i]==1)){
                                        flag=true;
                                    }
                                }
                                assertTrue(flag);
                                break;
                                //Make sure that var is negated
                            case 1:
                                //Make sure that var is n forced vars
                                boolean flag2=false;
                                for(int i=0;i<forcedVars.length;i++){
                                    if((forcedVars[i]==variablePosition)&&(negatedVars[i]==0)){
                                        flag2=true;
                                    }
                                }
                                assertTrue(flag2);
                                break;
                            default:
                                fail("invalid return value");
                            }
                        }
                    }
                }
            }
        }
        
        //the number of variables forced to 0 should be the same as the number of variables forced to 1
        
    }

    /**
     * Test method for {@link edu.neu.ccs.evergreen.ir.RelationCore#firstForcedVariable(int, int, int)}.
     */
    @Test
    public final void testFirstForcedVariable() {
        CustomCounter c,d;
        int r,rn;
        int[] forcedVars;
        int[] negatedVars;
        // for every rank
        for(int rank=1;rank<=maxRank;rank++){
            //for every subset of variables
            for(int vars=1;vars<=rank;vars++){
                c = new CustomCounter(vars,0,rank-1);
                while(c.hasNextDistinctPermutation()){
                    forcedVars = c.nextDistinctPermutation();
                    r = RelationNumberUtil.and(rank, forcedVars);
                    d = new CustomCounter(vars,0,1);
                    while(d.hasNext()){
                        negatedVars = d.next();
                        rn = RelationNumberUtil.nMap(r, rank, c.filter(negatedVars));
                        //checks that vars are forced
                        
                        int startPosition=0;
                        int countForcedVars=0;
                        for(startPosition=0,countForcedVars=0;startPosition<rank;startPosition++,countForcedVars++){
                            startPosition = RelationCore.firstForcedVariable(rn, rank, startPosition);
                            if(startPosition==-1){
                                assertTrue(countForcedVars==vars);
                                break;
                            }
                            int forced = RelationCore.isForced(rn, rank, startPosition);
                            assertTrue(forced!=-1);
                        }
                    }
                }
            }
        }       
    }

}