All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.exigen.ie.constrainer.impl.ArcConsistency_1 Maven / Gradle / Ivy

package com.exigen.ie.constrainer.impl;
import com.exigen.ie.constrainer.Constrainer;
import com.exigen.ie.constrainer.Failure;
import com.exigen.ie.constrainer.Goal;
import com.exigen.ie.constrainer.GoalImpl;
import com.exigen.ie.constrainer.IntExp;
import com.exigen.ie.constrainer.IntExpArray;

///////////////////////////////////////////////////////////////////////////////
/*
 * Copyright Exigen Group 1998, 1999, 2000
 * 320 Amboy Ave., Metuchen, NJ, 08840, USA, www.exigengroup.com
 *
 * The copyright to the computer program(s) herein
 * is the property of Exigen Group, USA. All rights reserved.
 * The program(s) may be used and/or copied only with
 * the written permission of Exigen Group
 * or in accordance with the terms and conditions
 * stipulated in the agreement/contract under which
 * the program(s) have been supplied.
 */
///////////////////////////////////////////////////////////////////////////////

interface ArcConsistency
{
  public void arcConsistency(IntExpArray vars) throws Failure;
}

/**
 * An implementation of the AC-1 algorithm.
 * Experimental release.
 */
public class ArcConsistency_1 implements ArcConsistency
{
  private IntExpArray _vars;
  private Bitset      _domains[];
  private ReviseIJ    _reviseIJ;
  private int         _total_checks;

  public void arcConsistency(IntExpArray vars) throws Failure
  {
    init(vars);
    try
    {
      revise();
    }
    catch(Failure f)
    {
      cleanup();
      throw f;
    }
    cleanup();
  }

  void revise() throws Failure
  {
    long t_start = System.currentTimeMillis();
    int size = _vars.size();
    boolean change;
    do
    {
      change = false;
      for(int I=0; I < size; ++I)
      for(int J=0; J < size; ++J)
      {
        if(I==J) continue;
        change |= _reviseIJ.revise(I,J);
      }
    } while(change);

    long t = System.currentTimeMillis()-t_start;
    long t1 = productInitialSize(_domains), t2 = productSize(_domains);
    if(t1 != t2)
      System.out.println("AC_1: t="+t+"msec checks="+_total_checks+" initial_cards=" + t1+" reduced_cards="+t2);
    else
      System.out.println("AC_1: t="+t+"msec checks="+_total_checks+" initial_cards=" + t1 + " NO reduction");

    reduceDomains();
  }

  private class ReviseIJ extends GoalImpl
  {
    private BitsetIterator _itI = new BitsetIterator();
    private BitsetIterator _itJ = new BitsetIterator();
    private int _I, _i, _J, _j;

    public ReviseIJ(Constrainer c)
    {
      super(c);
    }

    public boolean revise(int I, int J)
    {
      _I = I;
      _J = J;
      int removed = 0;
      _itI.reset(_domains[I]);
      while(_itI.hasNext())
      {
        _i = _itI.next();
        if(!check_i())
        {
          _domains[I].removeValue(_i);
          removed++;
        }
      }
      return removed > 0;
    }

    public boolean check_i()
    {
      _itJ.reset(_domains[_J]);
      while(_itJ.hasNext())
      {
        _j = _itJ.next();
        if(constrainer().execute(this,true))
          return true;
      }
      return false;
    }

    public Goal execute() throws Failure
    {
      _total_checks++;
      _vars.elementAt(_I).setValue(_i);
      _vars.elementAt(_J).setValue(_j);
      return null;
    }

  } // ~ReviseIJ


  void reduceDomains() throws Failure
  {
    for (int I=0; I < _vars.size(); ++I)
    {
      IntExp exp = _vars.elementAt(I);
      for (int i=exp.min(); i <= exp.max(); ++i)
      {
        if(!_domains[I].contains(i))
          exp.removeValue(i);
      }
    }
  }

  void init(IntExpArray vars)
  {
    _vars = vars;
    _domains = createDomains(_vars);
    _reviseIJ = new ReviseIJ(vars.constrainer());
    _total_checks=0;
  }

  void cleanup()
  {
    _vars = null;
    _domains = null;
    _reviseIJ = null;
  }

  static Bitset[] createDomains(IntExpArray vars)
  {
    Bitset[] domains = new Bitset[vars.size()];
    for(int i=0; i < vars.size(); ++i)
    {
      domains[i] = new Bitset(vars.elementAt(i));
    }
    return domains;
  }

  public static long productInitialSize(Bitset[] ary)
  {
    int size = ary.length;
    if(size==0) return 0;

    long total = 1;
    for(int i=0; i < size; ++i)
    {
      total *= ary[i].initialSize();
    }
    return total;
  }

  public static long productSize(Bitset[] ary)
  {
    int size = ary.length;
    if(size==0) return 0;

    long total = 1;
    for(int i=0; i < size; ++i)
    {
      total *= ary[i].size();
    }
    return total;
  }

  /**
   *
   */
  static public final class Bitset
  {
    private boolean[]   _bits;
    private int			    _initial_size;
    private int			    _initial_min;
    private int			    _initial_max;
    private int         _size;
    private int			    _min;
    private int			    _max;

    public Bitset(IntExp exp)
    {
      _max = _initial_max = exp.max();
      _min = _initial_min = exp.min();
      _bits = new boolean[_initial_max - _initial_min + 1];

      _initial_size = 0;
      for(int i = 0; i < _bits.length; ++i)
      {
        if(exp.contains(_initial_min+i))
        {
          _bits[i] = true;
          _initial_size++;
        }
        else
        {
          _bits[i] = false;
        }
      }
      _size = _initial_size;
    }

    public boolean contains(int value)
    {
      if (value < _min || value > _max)
      {
        return false;
      }

      return _bits[value - _initial_min];
    }

    public int next(int value)
    {
      int i = value+1;
      if(i < _min || i > _max)
      {
        return value;
      }

      for(; i <= _max; ++i)
      {
        if(_bits[i - _initial_min])
          return i;
      }

      return value;
    }

    public int size()
    {
      return _size;
    }

    public boolean isEmpty()
    {
      return _size == 0;
    }

    public int initialSize()
    {
      return _initial_size;
    }

    public int max()
    {
      return _max;
    }

    public int min()
    {
      return _min;
    }

    public boolean removeValue(int value)
    {
      if (!contains(value)) return false;

      if (value == _min)
        _min = value + 1;

      if (value == _max)
        _max = value - 1;

      _bits[value - _initial_min] = false;
      --_size;

      return true;
    }

    public String toString()
    {
      return "[" + printIntervals() + "]";
    }

   String printIntervals()
   {
      StringBuffer buf = new StringBuffer();
      for(int i = _min; i <= _max; )
      {
        if (i != _min)
          buf.append(" ");
        int from = i;
        int to = upperBound(from);

        if (to - from == 1)
          buf.append(String.valueOf(from));
        else buf.append(from + ".." + (to - 1));

        i = upperBound(to);
      }

      return buf.toString();
   }


   int upperBound(int i)
   {
      if (i > _max)
        return i;
      boolean sample = _bits[i - _initial_min];

      for(int j = i; ; ++j)
      {
        if (j > _max || _bits[j - _initial_min] != sample)
          return j;
      }
   }

  } // ~Bitset

  /**
   *
   */
  static public final class BitsetIterator
  {
    private Bitset _bits;
    private int _value;

    public BitsetIterator(Bitset bits)
    {
      reset(bits);
    }

    /**
     * Default constructor.
     * Note: default constructor creates the iterator in invalid state.
     * Use reset(Bitset) to make the iterator valid.
     */
    public BitsetIterator()
    {
    }

    public void reset(Bitset bits)
    {
      _bits = bits;
      _value = _bits.min()-1;
    }

    public void reset()
    {
      _value = _bits.min()-1;
    }

    public int next()
    {
      if(!hasNext()) throw new RuntimeException("BitsetIterator.next()");
      _value = _bits.next(_value);
      return _value;
    }

    public boolean hasNext()
    {
      return _bits.next(_value) != _value;
    }

  } // ~BitsetIterator

} // ~ArcConsistency_1




© 2015 - 2024 Weber Informatics LLC | Privacy Policy