Package com.anjlab.sat3

Source Code of com.anjlab.sat3.Join1Right

/*
* Copyright (c) 2010 AnjLab
*
* This file is part of
* Reference Implementation of Romanov's Polynomial Algorithm for 3-SAT Problem.
*
* Reference Implementation of Romanov's Polynomial Algorithm for 3-SAT Problem
* is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Reference Implementation of Romanov's Polynomial Algorithm for 3-SAT Problem
* is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with
* Reference Implementation of Romanov's Polynomial Algorithm for 3-SAT Problem.
* If not, see <http://www.gnu.org/licenses/>.
*/
package com.anjlab.sat3;

import static com.anjlab.sat3.Join2BetweenTiers.canTranspose;
import static com.anjlab.sat3.JoinMethods.endsWith;
import static com.anjlab.sat3.JoinMethods.ensureTheOnlyTierWithVariableExistsAndGetTheTier;
import static com.anjlab.sat3.JoinMethods.ensureTheOnlyTierWithVariablesExistsAndGetTheTier;
import static com.anjlab.sat3.JoinMethods.startsWith;
import cern.colt.list.ObjectArrayList;

public class JoinMethods
{
    private static final IJoinMethod[] joinMethods =
                        new IJoinMethod[]
                        {
                            //  The order matters
                            new Join3AsIs(),
                            new Join3BetweenTiers(),
                            new Join2BetweenTiers(),
                            new Join2Right(),
                            new Join2Left(),
                            new Join1Right(),
                            new Join1Left(),
                            new Join0(),
                        }
   
    public static IJoinMethod[] getMethods()
    {
        return joinMethods;
    }

    public static boolean missingAll(ITabularFormula formula, int varName1, int varName2)
    {
        IPermutation permutation = formula.getPermutation();
       
        return !permutation.contains(varName1)
            && !permutation.contains(varName2);
    }

    public static boolean startsWith(ITabularFormula formula, int varName)
    {
        return formula.getPermutation().get(0) == varName;
    }

    public static boolean startsWith(ITabularFormula formula, int varName1, int varName2)
    {
        IPermutation permutation = formula.getPermutation();

        return permutation.get(0) == varName1
            && permutation.get(1) == varName2;
    }

    public static boolean contains(ITabularFormula formula, int varName)
    {
        return formula.getPermutation().contains(varName);
    }

    public static boolean endsWith(ITabularFormula formula, int varName1, int varName2)
    {
        IPermutation permutation = formula.getPermutation();
       
        int permutationSize = permutation.size();
       
        return permutation.get(permutationSize - 2) == varName1
            && permutation.get(permutationSize - 1) == varName2;
    }

    public static boolean endsWith(ITabularFormula formula, int varName)
    {
        return formula.getPermutation().get(formula.getPermutation().size() - 1) == varName;
    }

    public static ITier ensureTheOnlyTierWithVariableExistsAndGetTheTier(ITabularFormula formula, int varName)
    {
        ObjectArrayList tiers = formula.findTiersFor(varName);
        if (tiers == null)
        {
            return null;
        }
        if (tiers.size() == 1)
        {
            return (ITier) tiers.get(0);
        }
        return null;
    }

    public static ITier ensureTheOnlyTierWithVariablesExistsAndGetTheTier(ITabularFormula formula, int varName1, int varName2)
    {
        ObjectArrayList tiers = formula.findTiersFor(varName1, varName2);
        if (tiers == null)
        {
            return null;
        }
        if (tiers.size() == 1)
        {
            return (ITier) tiers.get(0);
        }
        return null;
    }
   
    public static boolean singleTierExistsForTheVariablesLeft(ITabularFormula formula, int varName1, int varName2)
    {
        ITier tierWithBoth = ensureTheOnlyTierWithVariablesExistsAndGetTheTier(formula, varName1, varName2);
        if (tierWithBoth == null)
        {
            return false;
        }
        ITier tierWithVarName1 = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, varName1);
        if (tierWithVarName1 == null)
        {
            return false;
        }
        ITier tierWithVarName2 = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, varName2);
        if (tierWithVarName2 == null)
        {
            return false;
        }
        return tierWithVarName1 == tierWithVarName2 && startsWith(tierWithVarName1, varName1, varName2);
    }
   
    static boolean startsWith(ITier tier, int varName1, int varName2)
    {
        return tier.getAName() == varName1 && tier.getBName() == varName2;
    }

    public static boolean startsWith(ITier tier, int varName1)
    {
        return tier.getAName() == varName1;
    }

    public static boolean endsWith(ITier tier, int varName1, int varName2)
    {
        return tier.getBName() == varName1 && tier.getCName() == varName2;
    }

    public static boolean endsWith(ITier tier, int varName1)
    {
        return tier.getCName() == varName1;
    }
}

final class Join3AsIs implements IJoinMethod
{
    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        ITier existingTier = formula.findTierFor(tier);
       
        if (existingTier != null)
        {
            formula.unionOrAdd(existingTier);
            return true;
        }

        return false;
    }
}

final class Join3BetweenTiers implements IJoinMethod
{
    private boolean tryJoin2Left1Right(ITabularFormula formula, ITier tier,
            int left1, int left2, int right)
    {
        int left1Index = formula.getPermutation().indexOf(left1);
        int left2Index = formula.getPermutation().indexOf(left2);
        int rightIndex = formula.getPermutation().indexOf(right);
       
        if (left1Index > rightIndex || left2Index > rightIndex)
        {
            return false;
        }
        ITier leftTier = ensureTheOnlyTierWithVariablesExistsAndGetTheTier(formula, left1, left2);
        if (leftTier == null)
        {
            return false;
        }
        ITier rightTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, right);
        if (rightTier == null)
        {
            return false;
        }
        if (leftTier == rightTier)
        {
            return false;
        }
        if (endsWith(leftTier, left1, left2))
        {
            return transposeRightTierAndJoin(formula, tier, right, left2Index, rightIndex, rightTier, left1, left2);
        }
        else if (startsWith(leftTier, left1) && endsWith(leftTier, left2)
                    && canTranspose(formula, leftTier, left1, leftTier.getBName()))
        {
            formula.getPermutation().swap(left1, leftTier.getBName());
            leftTier.swapAB();
            return transposeRightTierAndJoin(formula, tier, right, left2Index, rightIndex, rightTier, left1, left2);
        }
        else if (startsWith(leftTier, left1, left2)
                    && canTranspose(formula, leftTier, left2, leftTier.getCName())
                    && canTranspose(formula, leftTier, left1, left2))
        {
            formula.getPermutation().swap(left1, leftTier.getCName());
            formula.getPermutation().swap(left1, left2);
            leftTier.swapAC();
            leftTier.swapBC();
            return transposeRightTierAndJoin(formula, tier, right, left2Index + 1, rightIndex, rightTier, left1, left2);
        }
       
        return false;
    }

    private static boolean transposeRightTierAndJoin(ITabularFormula formula,
            ITier tier, int right, int leftMostIndex, int rightIndex, ITier rightTier, int left1, int left2)
    {
        IPermutation permutation = formula.getPermutation();
        if (startsWith(rightTier, right))
        {
            if (rightIndex - leftMostIndex != 1)
            {
                ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, formula.getPermutation().get(leftMostIndex));
                if (boundaryTier == null)
                {
                    //  Some tiers exist between left-right indices that adjoined with left or right tier
                    return false;
                }
                int length = permutation.size();
                if (length - rightIndex < rightIndex)
                {
                    permutation.shiftToEnd(leftMostIndex + 1, rightIndex - 1);
                    rightIndex = leftMostIndex + 1;
                }
                else
                {
                    permutation.shiftToStart(leftMostIndex + 1, rightIndex - 1);
                }
            }
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        if (rightTier.getBName() == right
                && canTranspose(formula, rightTier, rightTier.getAName(), rightTier.getBName()))
        {
            rightIndex--;
            if (rightIndex - leftMostIndex != 1)
            {
                ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, formula.getPermutation().get(leftMostIndex));
                if (boundaryTier == null)
                {
                    //  Some tiers exist between left-right indices that adjoined with left or right tier
                    return false;
                }
                int length = permutation.size();
                if (length - rightIndex < rightIndex)
                {
                    permutation.shiftToEnd(leftMostIndex + 1, rightIndex - 1);
                }
                else
                {
                    permutation.shiftToStart(leftMostIndex + 1, rightIndex - 1);
                }
            }
            permutation.swap(rightTier.getAName(), rightTier.getBName());
            rightTier.swapAB();
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        if (rightTier.getCName() == right
                && canTranspose(formula, rightTier, rightTier.getAName(), rightTier.getCName()))
        {
            rightIndex -= 2;
            if (rightIndex - leftMostIndex != 1)
            {
                ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, formula.getPermutation().get(leftMostIndex));
                if (boundaryTier == null)
                {
                    //  Some tiers exist between left-right indices that adjoined with left or right tier
                    return false;
                }
                int length = permutation.size();
                if (length - rightIndex < rightIndex)
                {
                    permutation.shiftToEnd(leftMostIndex + 1, rightIndex - 1);
                }
                else
                {
                    permutation.shiftToStart(leftMostIndex + 1, rightIndex - 1);
                }
            }
            permutation.swap(rightTier.getAName(), rightTier.getCName());
            rightTier.swapAC();
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        return false;
    }
   
    private boolean tryJoin1Left2Right(ITabularFormula formula, ITier tier,
            int left, int right1, int right2)
    {
        int leftIndex = formula.getPermutation().indexOf(left);
        int right1Index = formula.getPermutation().indexOf(right1);
        int right2Index = formula.getPermutation().indexOf(right2);

        if (leftIndex > right1Index || leftIndex > right2Index)
        {
            return false;
        }
        ITier leftTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, left);
        if (leftTier == null)
        {
            return false;
        }
        ITier rightTier = ensureTheOnlyTierWithVariablesExistsAndGetTheTier(formula, right1, right2);
        if (rightTier == null)
        {
            return false;
        }
        if (leftTier == rightTier)
        {
            return false;
        }
        if (endsWith(leftTier, left))
        {
            return transposeRightTierAndJoin2(formula, tier, right1, right2, rightTier,
                    Math.min(right1Index, right2Index), leftIndex, left);
        }
        else if (leftTier.getBName() == left
                && canTranspose(formula, leftTier, left, leftTier.getCName()))
        {
            formula.getPermutation().swap(left, leftTier.getCName());
            leftTier.swapBC();
            return transposeRightTierAndJoin2(formula, tier, right1, right2, rightTier,
                    Math.min(right1Index, right2Index), leftIndex + 1, left);
        }
        else if (startsWith(leftTier, left)
                && canTranspose(formula, leftTier, left, leftTier.getCName()))
        {
            formula.getPermutation().swap(left, leftTier.getCName());
            leftTier.swapAC();
            return transposeRightTierAndJoin2(formula, tier, right1, right2, rightTier,
                    Math.min(right1Index, right2Index), leftIndex + 2, left);
        }
        return false;
    }
   
    private static boolean transposeRightTierAndJoin2(ITabularFormula formula, ITier tier, int right1, int right2,
            ITier rightTier, int rightLeastIndex, int leftIndex, int left)
    {
        IPermutation permutation = formula.getPermutation();
        if (endsWith(rightTier, right1, right2)
                && canTranspose(formula, rightTier, right2, rightTier.getAName())
                && canTranspose(formula, rightTier, right1, right2))
        {
            rightLeastIndex--;
            if (rightLeastIndex - leftIndex != 1)
            {
                ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, formula.getPermutation().get(rightLeastIndex));
                if (boundaryTier == null)
                {
                    //  Some tiers exist between left-right indices that adjoined with left or right tier
                    return false;
                }
                int length = permutation.size();
                if (length - leftIndex < leftIndex)
                {
                    permutation.shiftToEnd(leftIndex + 1, rightLeastIndex - 1);
                }
                else
                {
                    permutation.shiftToStart(leftIndex + 1, rightLeastIndex - 1);
                }
            }
            formula.getPermutation().swap(right2, rightTier.getAName());
            formula.getPermutation().swap(right1, right2);
            rightTier.swapAC();
            rightTier.swapAB();
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (startsWith(rightTier, right1) && endsWith(rightTier, right2)
                    && canTranspose(formula, rightTier, right2, rightTier.getBName()))
        {
            if (rightLeastIndex - leftIndex != 1)
            {
                ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, formula.getPermutation().get(rightLeastIndex));
                if (boundaryTier == null)
                {
                    //  Some tiers exist between left-right indices that adjoined with left or right tier
                    return false;
                }
                int length = permutation.size();
                if (length - leftIndex < leftIndex)
                {
                    permutation.shiftToEnd(leftIndex + 1, rightLeastIndex - 1);
                }
                else
                {
                    permutation.shiftToStart(leftIndex + 1, rightLeastIndex - 1);
                }
            }
            formula.getPermutation().swap(right2, rightTier.getBName());
            rightTier.swapBC();
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (startsWith(rightTier, right1, right2))
        {
            if (rightLeastIndex - leftIndex != 1)
            {
                ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, formula.getPermutation().get(rightLeastIndex));
                if (boundaryTier == null)
                {
                    //  Some tiers exist between left-right indices that adjoined with left or right tier
                    return false;
                }
                int length = permutation.size();
                if (length - leftIndex < leftIndex)
                {
                    permutation.shiftToEnd(leftIndex + 1, rightLeastIndex - 1);
                }
                else
                {
                    permutation.shiftToStart(leftIndex + 1, rightLeastIndex - 1);
                }
            }
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        return false;
    }
   
    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        int a = tier.getAName();
        int b = tier.getBName();
        int c = tier.getCName();

        int aIndex = formula.getPermutation().indexOf(a);
        int bIndex = formula.getPermutation().indexOf(b);
        int cIndex = formula.getPermutation().indexOf(c);
       
        if (aIndex < 0 || bIndex < 0 || cIndex < 0)
        {
            return false;
        }
       
        return tryJoin2Left1Right(formula, tier, a, b, c)
            || tryJoin2Left1Right(formula, tier, a, c, b)
            || tryJoin2Left1Right(formula, tier, b, a, c)
            || tryJoin2Left1Right(formula, tier, b, c, a)
            || tryJoin2Left1Right(formula, tier, c, a, b)
            || tryJoin2Left1Right(formula, tier, c, b, a)
           
            || tryJoin1Left2Right(formula, tier, a, b, c)
            || tryJoin1Left2Right(formula, tier, a, c, b)
            || tryJoin1Left2Right(formula, tier, b, a, c)
            || tryJoin1Left2Right(formula, tier, b, c, a)
            || tryJoin1Left2Right(formula, tier, c, a, b)
            || tryJoin1Left2Right(formula, tier, c, b, a);
    }

}

final class Join2BetweenTiers implements IJoinMethod
{
    public static boolean tryJoin2BetweenTiers(ITabularFormula formula, ITier tier, int left, int right, int middle)
    {
        int leftIndex = formula.getPermutation().indexOf(left);
        int middleIndex = formula.getPermutation().indexOf(middle);
        int rightIndex = formula.getPermutation().indexOf(right);
       
        if (leftIndex > rightIndex || leftIndex < 0 || rightIndex < 0 || middleIndex >= 0)
        {
            return false;
        }
        ITier leftTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, left);
        if (leftTier == null)
        {
            return false;
        }
        ITier rightTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, right);
        if (rightTier == null)
        {
            return false;
        }
        if (leftTier == rightTier)
        {
            return false;
        }
        if (leftTier.getCName() == left)
        {
            return transposeRightTierAndJoin(formula, tier, left, right, middle, leftIndex, rightIndex, leftTier, rightTier);
        }
        else if (leftTier.getBName() == left
                && canTranspose(formula, leftTier, leftTier.getBName(), leftTier.getCName()))
        {
            formula.getPermutation().swap(leftTier.getBName(), leftTier.getCName());
            leftTier.swapBC();
            return transposeRightTierAndJoin(formula, tier, left, right, middle, leftIndex + 1, rightIndex, leftTier, rightTier);
        }
        else if (leftTier.getAName() == left
                && canTranspose(formula, leftTier, leftTier.getAName(), leftTier.getCName()))
        {
            formula.getPermutation().swap(leftTier.getAName(), leftTier.getCName());
            leftTier.swapAC();
            return transposeRightTierAndJoin(formula, tier, left, right, middle, leftIndex + 2, rightIndex, leftTier, rightTier);
        }
           
        return false;
    }

    private static boolean transposeRightTierAndJoin(ITabularFormula formula,
            ITier tier, int left, int right, int middle, int leftIndex,
            int rightIndex, ITier leftTier, ITier rightTier)
    {
        IPermutation permutation = formula.getPermutation();
        if (startsWith(rightTier, right))
        {
            if (rightIndex - leftIndex != 1)
            {
                int length = permutation.size();
                if (length - rightIndex < rightIndex)
                {
                    permutation.shiftToEnd(leftIndex + 1, rightIndex - 1);
                    rightIndex = leftIndex + 1;
                }
                else
                {
                    permutation.shiftToStart(leftIndex + 1, rightIndex - 1);
                }
            }
            permutation.add(rightIndex, middle);
            tier.transposeTo(left, middle, right);
            formula.unionOrAdd(tier);
            return true;
        }
        if (rightTier.getBName() == right
                && canTranspose(formula, rightTier, rightTier.getAName(), rightTier.getBName()))
        {
            rightIndex--;
            if (rightIndex - leftIndex != 1)
            {
                int length = permutation.size();
                if (length - rightIndex < rightIndex)
                {
                    permutation.shiftToEnd(leftIndex + 1, rightIndex - 1);
                    rightIndex = leftIndex + 1;
                }
                else
                {
                    permutation.shiftToStart(leftIndex + 1, rightIndex - 1);
                }
            }
            permutation.add(rightIndex, middle);
            permutation.swap(rightTier.getAName(), rightTier.getBName());
            rightTier.swapAB();
            tier.transposeTo(left, middle, right);
            formula.unionOrAdd(tier);
            return true;
        }
        if (rightTier.getCName() == right
                && canTranspose(formula, rightTier, rightTier.getAName(), rightTier.getCName()))
        {
            rightIndex -= 2;
            if (rightIndex - leftIndex != 1)
            {
                int length = permutation.size();
                if (length - rightIndex < rightIndex)
                {
                    permutation.shiftToEnd(leftIndex + 1, rightIndex - 1);
                    rightIndex = leftIndex + 1;
                }
                else
                {
                    permutation.shiftToStart(leftIndex + 1, rightIndex - 1);
                }
            }
            permutation.add(rightIndex, middle);
            permutation.swap(rightTier.getAName(), rightTier.getCName());
            rightTier.swapAC();
            tier.transposeTo(left, middle, right);
            formula.unionOrAdd(tier);
            return true;
        }
        return false;
    }

    public static boolean canTranspose(ITabularFormula formula, ITier tier, int varName1, int varName2)
    {
        ITier otherTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, varName1);
       
        if (otherTier != tier)
        {
            return false;
        }
        otherTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, varName2);
        if (otherTier != tier)
        {
            return false;
        }
        return true;
    }

    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        int a = tier.getAName();
        int b = tier.getBName();
        int c = tier.getCName();

        return (tryJoin2BetweenTiers(formula, tier, a, b, c))
            || (tryJoin2BetweenTiers(formula, tier, b, a, c))
            || (tryJoin2BetweenTiers(formula, tier, c, b, a))
            || (tryJoin2BetweenTiers(formula, tier, b, c, a))
            || (tryJoin2BetweenTiers(formula, tier, a, c, b))
            || (tryJoin2BetweenTiers(formula, tier, c, a, b));
    }
}

final class Join2Left implements IJoinMethod
{
    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        int a = tier.getAName();
        int b = tier.getBName();
        int c = tier.getCName();

        return tryJoinLeft(formula, tier, a, b, c)
            || tryJoinLeft(formula, tier, a, c, b)
            || tryJoinLeft(formula, tier, b, a, c)
            || tryJoinLeft(formula, tier, b, c, a)
            || tryJoinLeft(formula, tier, c, a, b)
            || tryJoinLeft(formula, tier, c, b, a);
    }

    private boolean tryJoinLeft(ITabularFormula formula, ITier tier, int right1, int right2, int left)
    {
        int right1Index = formula.getPermutation().indexOf(right1);
        int leftIndex = formula.getPermutation().indexOf(left);
       
        if (leftIndex >= 0)
        {
            return false;
        }
        ITier rightTier = ensureTheOnlyTierWithVariablesExistsAndGetTheTier(formula, right1, right2);
        if (rightTier == null)
        {
            return false;
        }
        IPermutation permutation = formula.getPermutation();
        if (startsWith(rightTier, right1, right2))
        {
            ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, right1);
            if (boundaryTier == null)
            {
                return false;
            }
            permutation.add(right1Index, left);
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (startsWith(rightTier, right1)
                && endsWith(rightTier, right2)
                && canTranspose(formula, rightTier, right2, rightTier.getBName()))
        {
            ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, right1);
            if (boundaryTier == null)
            {
                return false;
            }
            permutation.swap(right2, rightTier.getBName());
            rightTier.swapBC();
            permutation.add(right1Index, left);
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (endsWith(rightTier, right1, right2)
                    && canTranspose(formula, rightTier, right1, rightTier.getAName())
                    && canTranspose(formula, rightTier, right1, right2))
        {
            ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, right1);
            if (boundaryTier == null)
            {
                return false;
            }
            permutation.swap(right2, rightTier.getAName());
            permutation.swap(right2, right1);
            rightTier.swapAC();
            rightTier.swapAB();
            right1Index--;
            permutation.add(right1Index, left);
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        return false;
    }
}

final class Join2Right implements IJoinMethod
{
    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        int a = tier.getAName();
        int b = tier.getBName();
        int c = tier.getCName();

        return tryJoinRight(formula, tier, a, b, c)
            || tryJoinRight(formula, tier, a, c, b)
            || tryJoinRight(formula, tier, b, a, c)
            || tryJoinRight(formula, tier, b, c, a)
            || tryJoinRight(formula, tier, c, a, b)
            || tryJoinRight(formula, tier, c, b, a);
    }

    private boolean tryJoinRight(ITabularFormula formula, ITier tier, int left1, int left2, int right)
    {
        int left2Index = formula.getPermutation().indexOf(left2);
        int rightIndex = formula.getPermutation().indexOf(right);
       
        if (rightIndex >= 0)
        {
            return false;
        }
        ITier leftTier = ensureTheOnlyTierWithVariablesExistsAndGetTheTier(formula, left1, left2);
        if (leftTier == null)
        {
            return false;
        }
        IPermutation permutation = formula.getPermutation();
        if (endsWith(leftTier, left1, left2))
        {
            ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, left2);
            if (boundaryTier == null)
            {
                return false;
            }
            permutation.add(left2Index + 1, right);
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (startsWith(leftTier, left1)
                && endsWith(leftTier, left2)
                && canTranspose(formula, leftTier, left1, leftTier.getBName()))
        {
            ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, left2);
            if (boundaryTier == null)
            {
                return false;
            }
            permutation.swap(left1, leftTier.getBName());
            leftTier.swapAB();
            permutation.add(left2Index + 1, right);
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (startsWith(leftTier, left1, left2)
                    && canTranspose(formula, leftTier, left1, leftTier.getCName())
                    && canTranspose(formula, leftTier, left1, left2))
        {
            ITier boundaryTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, left2);
            if (boundaryTier == null)
            {
                return false;
            }
            permutation.swap(left1, leftTier.getCName());
            permutation.swap(left2, left1);
            leftTier.swapAC();
            leftTier.swapBC();
            left2Index++;
            permutation.add(left2Index + 1, right);
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        return false;
    }
}

final class Join1Left implements IJoinMethod
{
    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        int a = tier.getAName();
        int b = tier.getBName();
        int c = tier.getCName();

        return tryJoinLeft(formula, tier, a, b, c)
            || tryJoinLeft(formula, tier, b, a, c)
            || tryJoinLeft(formula, tier, c, a, b);
    }

    private boolean tryJoinLeft(ITabularFormula formula, ITier tier, int right, int left1, int left2)
    {
        int rightIndex = formula.getPermutation().indexOf(right);
        int left1Index = formula.getPermutation().indexOf(left1);
        int left2Index = formula.getPermutation().indexOf(left2);
       
        if (left1Index >= 0 || left2Index >= 0)
        {
            return false;
        }
        ITier rightTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, right);
        if (rightTier == null)
        {
            return false;
        }
        IPermutation permutation = formula.getPermutation();
        if (startsWith(rightTier, right))
        {
            //  TODO Union successive calls to permutation.add(int, int) to a single permutation.add(int, int...)
            permutation.add(rightIndex, left2);
            permutation.add(rightIndex, left1);
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (rightTier.getBName() == right
                && canTranspose(formula, rightTier, right, rightTier.getAName()))
        {
            permutation.swap(right, rightTier.getAName());
            rightTier.swapAB();
            rightIndex--;
            permutation.add(rightIndex, left2);
            permutation.add(rightIndex, left1);
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (endsWith(rightTier, right)
                    && canTranspose(formula, rightTier, right, rightTier.getAName()))
        {
            permutation.swap(right, rightTier.getAName());
            rightTier.swapAC();
            rightIndex -= 2;
            permutation.add(rightIndex, left2);
            permutation.add(rightIndex, left1);
            tier.transposeTo(left1, left2, right);
            formula.unionOrAdd(tier);
            return true;
        }
        return false;
    }
}

final class Join1Right implements IJoinMethod
{
    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        int a = tier.getAName();
        int b = tier.getBName();
        int c = tier.getCName();

        return tryJoinRight(formula, tier, a, b, c)
            || tryJoinRight(formula, tier, b, a, c)
            || tryJoinRight(formula, tier, c, b, a);
    }

    private boolean tryJoinRight(ITabularFormula formula, ITier tier, int left, int right1, int right2)
    {
        int right1Index = formula.getPermutation().indexOf(right1);
        int right2Index = formula.getPermutation().indexOf(right2);
        int leftIndex = formula.getPermutation().indexOf(left);
       
        if (right1Index >= 0 || right2Index >= 0)
        {
            return false;
        }
        ITier leftTier = ensureTheOnlyTierWithVariableExistsAndGetTheTier(formula, left);
        if (leftTier == null)
        {
            return false;
        }
        IPermutation permutation = formula.getPermutation();
        if (endsWith(leftTier, left))
        {
            permutation.add(leftIndex + 1, right2);
            permutation.add(leftIndex + 1, right1);
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (leftTier.getBName() == left
                && canTranspose(formula, leftTier, left, leftTier.getCName()))
        {
            permutation.swap(left, leftTier.getCName());
            leftTier.swapBC();
            leftIndex++;
            permutation.add(leftIndex + 1, right2);
            permutation.add(leftIndex + 1, right1);
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        else if (startsWith(leftTier, left)
                    && canTranspose(formula, leftTier, left, leftTier.getCName()))
        {
            permutation.swap(left, leftTier.getCName());
            leftTier.swapAC();
            leftIndex += 2;
            permutation.add(leftIndex + 1, right2);
            permutation.add(leftIndex + 1, right1);
            tier.transposeTo(left, right1, right2);
            formula.unionOrAdd(tier);
            return true;
        }
        return false;
    }
}

final class Join0 implements IJoinMethod
{
    public boolean tryJoin(ITabularFormula formula, ITier tier)
    {
        IPermutation permutation = formula.getPermutation();
       
        if (!permutation.contains(tier.getAName())
            && !permutation.contains(tier.getBName())
            && !permutation.contains(tier.getCName()))
        {
            formula.unionOrAdd(tier);
            return true;
        }

        return false;
    }
}
TOP

Related Classes of com.anjlab.sat3.Join1Right

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.