Package com.anjlab.sat3

Source Code of com.anjlab.sat3.VarPairsIndexFactory

/*
* Copyright (c) 2010, 2011 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cern.colt.function.LongObjectProcedure;
import cern.colt.list.LongArrayList;
import cern.colt.list.ObjectArrayList;
import cern.colt.map.OpenIntObjectHashMap;
import cern.colt.map.OpenLongObjectHashMap;

public class VarPairsIndexFactory
{
    private static final Logger LOGGER = LoggerFactory.getLogger(VarPairsIndexFactory.class);
   
    private static VarPairsIndexFactory instance = new VarPairsIndexFactory();
   
    private OpenIntObjectHashMap indexCache = new OpenIntObjectHashMap();
   
    public static VarPairsIndexFactory getInstance()
    {
        return instance;
    }
   
    public void clear()
    {
        indexCache.clear();
    }
   
    public class VarPairsIndex
    {
        private OpenLongObjectHashMap pairsToTiersIndex = new OpenLongObjectHashMap();
        private OpenIntObjectHashMap varNameToPairsIndex = new OpenIntObjectHashMap();
        private VarPairsIndex fullIndex;
       
        public VarPairsIndex(VarPairsIndex fullIndex)
        {
            this.fullIndex = fullIndex;
        }
       
        public VarPairsIndex()
        {
        }
       
        /**
         *
         * @param varName1
         * @param varName2
         * @param formulaIndex Index of formula which tier is adding.
         * @param tierIndex Index of tier, containing varName1 and varName2 in the formula.
         * @param cts List of CTS. Used when {@link Helper#EnableAssertions} is <code>true</code>.
         */
        public void addTier(int varName1, int varName2, int formulaIndex, int tierIndex, ObjectArrayList cts)
        {
            long key = varName1 < varName2 ? (long)varName1 << 21 | varName2 : (long)varName2 << 21 | varName1;
            long formulaAndTierIndices = (long)formulaIndex << 32 | (long)tierIndex;
           
            if (Helper.EnableAssertions)
            {
                int varName1_ = (int) (key >> 21);
                int varName2_ = (int) (key & 0x1FFFFF);
       
                if (((varName1 != varName1_) && (varName1 != varName2_))
                        || ((varName2 != varName1_) && (varName2 != varName2_)))
                {
                    throw new AssertionError("Bad hash");
                }
            }

            //  List of formulaAndTierIndices
            LongArrayList tiers = (LongArrayList) pairsToTiersIndex.get(key);
           
            if (tiers == null)
            {
                tiers = new LongArrayList(new long[] {formulaAndTierIndices});
                pairsToTiersIndex.put(key, tiers);
            }
            else
            {
                if (Helper.EnableAssertions)
                {
                    ITier tier = ((ICompactTripletsStructureHolder) cts.get(formulaIndex)).getCTS().getTier(tierIndex);
                    if (!tier.hasVariable(varName1) || !tier.hasVariable(varName2))
                    {
                        throw new IllegalStateException();
                    }
                }
               
                //  Ensure tier will be added only once
                if (tiers.indexOf(formulaAndTierIndices) < 0)
                {
                    tiers.add(formulaAndTierIndices);
                }
            }
        }

        /**
         * Remove pairs from index that only belong to single CTS
         */
        public void purge()
        {
            final LongArrayList toBeRemoved = new LongArrayList();
           
            pairsToTiersIndex.forEachPair(new LongObjectProcedure()
            {
                public boolean apply(long key, Object value)
                {
                    //  List of formulaAndTierIndices
                    LongArrayList tiers = (LongArrayList) value;
                    int tiersCount = tiers.size();
                    if (tiersCount < 2)
                    {
                        toBeRemoved.add(key);
                    }
                    else
                    {
                        long formulaAndTierIndex = tiers.getQuick(0);
                        long formulaIndexPart = formulaAndTierIndex & 0xFFFFFFFF00000000L;
                        for (int i = 1; i < tiersCount; i++)
                        {
                            long formulaAndTierIndex2 = tiers.getQuick(i);
                            long formulaIndexPart2 = formulaAndTierIndex2 & 0xFFFFFFFF00000000L;
                            if (formulaIndexPart != formulaIndexPart2)
                            {
                                //  Found distinct formulas
                               
                                //  See VarPairsIndex#addTier() for details of key construction
                                int varName1 = (int) (key >> 21);
                                int varName2 = (int) (key & 0x1FFFFF);
                               
                                addVarNamePair(varName1, key);
                                addVarNamePair(varName2, key);
                               
                                return true;
                            }
                        }
                        //  All triplets are from the same formula
                        toBeRemoved.add(key);
                    }
                    return true;
                }

                private void addVarNamePair(int varName1, long key)
                {
                    LongArrayList pairs = (LongArrayList) varNameToPairsIndex.get(varName1);
                    if (pairs == null)
                    {
                        pairs = new LongArrayList(new long[]{ key });
                        varNameToPairsIndex.put(varName1, pairs);
                    }
                    else
                    {
                        pairs.add(key);
                    }
                }
            });
           
            int size = toBeRemoved.size();
            for (int i = 0; i < size; i++)
            {
                long key = toBeRemoved.getQuick(i);
                pairsToTiersIndex.removeKey(key);
            }
            LOGGER.debug("Removed {} triplet permutations from index", size);
        }

        public void forEachPair(LongObjectProcedure procedure)
        {
            pairsToTiersIndex.forEachPair(procedure);
        }

        public LongArrayList pairs()
        {
            return pairsToTiersIndex.keys();
        }

        public LongArrayList getPairs(int varName)
        {
            return (LongArrayList) varNameToPairsIndex.get(varName);
        }

        public void rebuildIndex(ObjectArrayList cts, ICompactTripletsStructureHolder formula, int fromTier, int toTier)
        {
            for (int j = fromTier; j <= toTier; j++)
            {
                ITier tier = formula.getCTS().getTier(j);
               
                addVarName(tier.getAName());
                addVarName(tier.getBName());
                addVarName(tier.getCName());
            }
        }

        private void addVarName(int varName)
        {
            LongArrayList pairs = fullIndex.getPairs(varName);
           
            if (pairs == null)
            {
                //  There is no any pairs that contain this varName.
                //  No need to add it to the index.
                return;
            }
           
            for (int i = 0; i < pairs.size(); i++)
            {
                long key = pairs.getQuick(i);
                if (!pairsToTiersIndex.containsKey(key))
                {
                    pairsToTiersIndex.put(key, fullIndex.pairsToTiersIndex.get(key));
                }
            }
        }
    }
   
    /**
     * 
     *
     * @param cts
     * @param formula
     * @param fromTier Index of start tier in the formula
     * @param toTier Index of end tier in the formula
     * @return
     */
    public VarPairsIndex buildPartialIndex(final ObjectArrayList cts, ICompactTripletsStructureHolder formula, int fromTier, int toTier)
    {
        int cacheKey = getCacheKey(cts);
       
        VarPairsIndex fullIndex = (VarPairsIndex) indexCache.get(cacheKey);
       
        if (fullIndex == null)
        {
            throw new IllegalStateException("Full index should be built first");
        }
       
        VarPairsIndex index = new VarPairsIndex(fullIndex);
       
        index.rebuildIndex(cts, formula, fromTier, toTier);
       
        return index;
    }
   
    /**
     *
     * @param cts List of {@link ICompactTripletsStructureHolder}
     * @return
     * @throws EmptyStructureException
     */
    public VarPairsIndex buildIndex(final ObjectArrayList cts) throws EmptyStructureException
    {
        VarPairsIndex index;
       
        int cacheKey = getCacheKey(cts);
       
        boolean creatingNewIndex = !indexCache.containsKey(cacheKey);
       
        if (creatingNewIndex)
        {
            index = new VarPairsIndex();
           
            LOGGER.debug("Building pairs index...");
           
            int tierCount = ((ICompactTripletsStructureHolder) cts.get(0)).getCTS().getPermutation().size() - 2;
            int ctsCount = cts.size();
           
            for(int i = 0; i < ctsCount; i++)
            {
                ITabularFormula s = ((ICompactTripletsStructureHolder) cts.getQuick(i)).getCTS();
                if(s.isEmpty())
                {
                    throw new EmptyStructureException(s);
                }
               
                Object[] tierElements = s.getTiers().elements();
               
                for (int j = 0; j < tierCount; j++)
                {
                    ITier tier = (ITier) tierElements[j];
                   
                    index.addTier(tier.getAName(), tier.getBName(), i, j, cts);
                    index.addTier(tier.getAName(), tier.getCName(), i, j, cts);
                    index.addTier(tier.getBName(), tier.getCName(), i, j, cts);
                }
            }
           
            indexCache.put(cacheKey, index);
           
            index.purge();
        }
        else
        {
            int ctsCount = cts.size();
           
            for(int i = 0; i < ctsCount; i++)
            {
                ITabularFormula s = ((ICompactTripletsStructureHolder) cts.getQuick(i)).getCTS();
                if(s.isEmpty())
                {
                    throw new EmptyStructureException(s);
                }
            }
           
            index = (VarPairsIndex) indexCache.get(cacheKey);
        }
       
        return index;
    }

    private int getCacheKey(ObjectArrayList cts)
    {
        int result = 1;
        for (int i = 0; i < cts.size(); i++)
        {
            IPermutation permutation = ((ICompactTripletsStructureHolder) cts.get(i)).getCTS().getPermutation();
            //  See Arrays.hashCode(int[])
            result = 31 * result + permutation.elementsHash();
        }
        return result;
    }

}
TOP

Related Classes of com.anjlab.sat3.VarPairsIndexFactory

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.