partialsolution.java

来自「Java版的SAT求解器」· Java 代码 · 共 411 行

JAVA
411
字号
/** * <p>Title: TBS</p> * <p>Description: TBS</p> * <p>Copyright (c) 2005</p> * <p>Company: Positronic Software</p> * @author Kerry Michael Soileau * @version 1.0 */package positronic.satisfiability.solutions;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Stack;import positronic.math.EquivalenceRelation;import positronic.satisfiability.elements.BooleanLiteral;import positronic.satisfiability.elements.Certificate;import positronic.satisfiability.elements.Conjunction;import positronic.satisfiability.elements.IBooleanLiteral;import positronic.satisfiability.elements.IBooleanVariable;import positronic.satisfiability.elements.ICertificate;import positronic.satisfiability.elements.IClause;import positronic.satisfiability.elements.IProblem;import positronic.satisfiability.elements.Problem;import positronic.satisfiability.exceptions.PartialSolutionException;import positronic.util.ArrayListSet;public class PartialSolution extends Certificate implements ICertificate{  public static Split bestSplit(IProblem prob) throws Exception  {    double bestMeasure=Double.MAX_VALUE;    ArrayList bestSplit=null;    IBooleanVariable bestBoolean=null;    ArrayList vb=prob.getBooleanVariables();    if(vb==null || vb.size()==0)      return null;    for(int i=0;i<vb.size();i++)    {      IBooleanVariable boo=(IBooleanVariable)vb.get(i);      ArrayList split=split(prob,boo);      int a=((ArrayList)split.get(0)).size();      int b=((ArrayList)split.get(1)).size();      int c=((ArrayList)split.get(2)).size();      double measure=a+b+2*c;      if(measure<bestMeasure)      {        bestBoolean=boo;        bestSplit=split;        bestMeasure=measure;      }    }    return new Split(bestBoolean,new Problem((ArrayList)(bestSplit.get(0)))    ,new Problem((ArrayList)(bestSplit.get(1))),new Problem((ArrayList)(bestSplit.get(2))));  }  public static PartialSolution prettyGoodSolver(IProblem problem) throws Exception  {    PartialSolution partialSolution=new PartialSolution(new ArrayListSet(),problem);    PartialSolution partialSolution2=partialSolution.processSingletons();    PartialSolution partialSolution3=partialSolution2.combineSinglyMatchingClauses1Pass();    PartialSolution partialSolution4=partialSolution3.processSingletons();    PartialSolution partialSolution5=partialSolution4.combineSinglyMatchingClauses1Pass();    PartialSolution partialSolution6=partialSolution5.processSingletons();    if(partialSolution6.getProblem()!=null)      partialSolution6.getProblem().sort();    PartialSolution partialSolution7=partialSolution6.processEquivalences();    return partialSolution7;  }  public static PartialSolution singletonSqueezeSolve(IProblem p) throws Exception  {    PartialSolution ps=new PartialSolution(new ArrayListSet(),p);    int oldsize=Integer.MIN_VALUE;    while(oldsize<ps.getBooleanLiterals().size())    {      oldsize=ps.getBooleanLiterals().size();      ps.eliminateSingletons();      if(ps.getProblem()==null) break;      ps.setProblem(ps.getProblem().combineSinglyMatchingClauses());    }//end while    if(ps.getProblem()==null) return ps;    else    {      ps.processEquivalences();      ps.eliminateComplementaryPairClauses();      System.out.println("Presented to divide and conquer:");      System.out.println(ps);      ArrayList v=ps.divideAndConquer();      ArrayList bl=ps.getBooleanLiterals();      for(int i=0;i<v.size();i++)        if(bl!=null)          bl.add((IBooleanLiteral)v.get(i));        else          bl=v;      ps.setProblem(null);      return ps;    }//end else  }  public static IBooleanLiteral[] solve(IProblem prob) throws Exception  {    List l=PartialSolution.solveList(prob);    if(l!=null)    {      IBooleanLiteral[] res=new IBooleanLiteral[l.size()];      for(int i=0;i<l.size();i++)        res[i]=(IBooleanLiteral)l.get(i);      return res;    }    else return null;  }  public static List solveList(IProblem prob) throws Exception  {  	if(prob==null || prob.isEmpty())  		throw new PartialSolutionException("Null or empty IProblem was passed to method solveList.");  	else  	{  		ArrayListSet solution=new ArrayListSet();  		PartialSolution p=new PartialSolution(solution,prob);  		return p.divideAndConquer();  	}  }  public static ArrayList split(IProblem prob,IBooleanVariable b) throws Exception  {    ArrayList occursUnbarred=new ArrayList();    ArrayList occursBarred=new ArrayList();    ArrayList doesNotOccur=new ArrayList();    IBooleanLiteral bUnbarred=BooleanLiteral.getBooleanLiteral(b,false);    IBooleanLiteral bBarred=BooleanLiteral.getBooleanLiteral(b,true);    for(int i=0;i<prob.numberOfClauses();i++)    {      IClause c=prob.getClause(i);      if(c.contains(bUnbarred))      {        occursUnbarred.add(c);        continue;      }      if(c.contains(bBarred))      {        occursBarred.add(c);        continue;      }      doesNotOccur.add(c);    }    ArrayList ret=new ArrayList();    ret.add(occursUnbarred);    ret.add(occursBarred);    ret.add(doesNotOccur);    return ret;  }    private Map equations;  private IProblem problem;  public PartialSolution(ArrayListSet booleanLiterals,IProblem p)  {    super.setBooleanLiterals(booleanLiterals);    this.setProblem(p);  }  public PartialSolution combineSinglyMatchingClauses1Pass() throws Exception  {    if(this.getProblem()!=null)    {      IProblem res=this.getProblem().combineSinglyMatchingClauses();      this.setProblem(res);    }    return this;  }  public ArrayList divideAndConquer() throws Exception  {    ArrayList arl=divideAndConquer1();    this.setBooleanLiterals((ArrayListSet)arl);    return arl;  }    public ArrayList divideAndConquer1() throws Exception  {  	if(this.getProblem()!=null)    {      ProblemStack s=new ProblemStack();      s.push(this);      s.numberOfClauses+=this.getProblem().numberOfClauses();      while(!s.empty())      {        PartialSolution ps=(PartialSolution)(s.pop());        s.numberOfClauses-=ps.getProblem().numberOfClauses();        ArrayList booleanLiterals=(ArrayList)(ps.getBooleanLiterals());        Split split=PartialSolution.bestSplit(ps.getProblem());        if(split!=null)        {          IBooleanVariable splitBooleanVariable=split.getBooleanVariable();          IProblem absentProblem=split.getAbsent();          IProblem unbarred=new Conjunction(split.getUnbarred().substitute(splitBooleanVariable,false),absentProblem);          if(unbarred!=null && !unbarred.containsAnEmptyClause())          {            ArrayListSet v=(ArrayListSet)(booleanLiterals.clone());            v.add(BooleanLiteral.getBooleanLiteral(splitBooleanVariable,true));            if(unbarred.isEmpty())              return v;            else            {              PartialSolution par=new PartialSolution(v,unbarred);              s.push(par);              s.numberOfClauses+=par.getProblem().numberOfClauses();            }          }          IProblem barred=new Conjunction(split.getBarred().substitute(splitBooleanVariable,true),absentProblem);          if(barred!=null && !barred.containsAnEmptyClause())          {            ArrayListSet v=(ArrayListSet)(booleanLiterals.clone());            v.add(BooleanLiteral.getBooleanLiteral(splitBooleanVariable,false));            if(barred.isEmpty())              return v;            else            {              PartialSolution par=new PartialSolution(v,barred);              s.push(par);              s.numberOfClauses+=par.getProblem().numberOfClauses();            }          }        }//end if      }//end while    }    return null;  }  public void eliminateComplementaryPairClauses() throws Exception  {  	this.setProblem(this.getProblem().eliminateComplementaryPairClauses());  }  public PartialSolution eliminateOneSingleton() throws Exception  {    IProblem pp=this.getProblem();    if(pp==null) return this;    ArrayListSet gbl=(ArrayListSet)(super.getBooleanLiterals());    for(int i=0;i<pp.numberOfClauses();i++)    {      IClause c=pp.getClause(i);      if(c.isSingleton())      {        IBooleanLiteral ib=c.getLiteralAt(0);        gbl.add(ib);        IProblem md=pp.substitute(ib.getBooleanVariable(),!ib.isBarred());        return new PartialSolution(gbl,md);      }    }    return this;  }  public void eliminateSingletons() throws Exception  {    int oldsize=Integer.MIN_VALUE;    while(super.getBooleanLiterals().size()>oldsize /*&& this.getProblem()!=null*/)    {      oldsize=super.getBooleanLiterals().size();      PartialSolution res=this.eliminateOneSingleton();      this.setProblem(res.getProblem());      this.setBooleanLiterals(res.getBooleanLiterals());    }  }  public boolean expressEquivalence(IClause c1, IClause c2) throws Exception  {    if(c1==null) return false;    if(c1.size()!=2 || c2.size()!=2) return false;    for(int i=0;i<c1.size();i++)    {      IBooleanLiteral ibl=c1.getLiteralAt(i).complement();      if(!c2.contains(ibl))        return false;    }    return true;  }  public java.util.Map getEquations()  {    return equations;  }  public IProblem getProblem()  {    return this.problem;  }  public PartialSolution processEquivalences() throws Exception  {    IProblem pp=this.getProblem();    if(pp!=null)    {    EquivalenceRelation equiv=new EquivalenceRelation();    for(int i=0;i<pp.numberOfClauses();i++)    {      IClause ci=pp.getClause(i);      for(int j=0;j<pp.numberOfClauses();j++)      {        IClause cj=pp.getClause(j);        if(expressEquivalence(cj,ci))          if(!ci.getLiteralAt(0).equals((IBooleanLiteral)(cj.getLiteralAt(1))))            equiv.add(ci.getLiteralAt(0),cj.getLiteralAt(1));      }//end for    }//end for    Map q=this.getEquations();    if(q==null)      this.setEquations(equiv.toHashMap());    else      q.putAll(equiv.toHashMap());        pp.substitute(this.getEquations());    this.eliminateComplementaryPairClauses();    }    return this;  }  public PartialSolution processSingletons() throws Exception  {    if(this.getProblem()!=null)    {    	if(this.getProblem().size()==0) return this;    	PartialSolution ps;    	while(true)    	{    		int s=this.getProblem().size();    		ps=eliminateOneSingleton();    		if(ps.getProblem()==null) break;    		if(ps.getProblem().size()==s) break;    		this.setProblem(ps.getProblem());    	}    	return ps;    }    return this;  }  public void setEquations(java.util.Map equations)  {    this.equations = equations;  }  public void setProblem(IProblem p)  {    this.problem=p;  }}//end PartialSolution class definitionclass ProblemStack extends Stack{  private static final long serialVersionUID = 1L;  public int numberOfClauses;}class Split{  private static int splitCount;  private IProblem absent;  private IProblem barred;  private IBooleanVariable booleanVariable;  private IProblem unBarred;  public Split(IBooleanVariable booleanVariable,IProblem unBarred,IProblem barred,IProblem absent)  {    this.booleanVariable=booleanVariable;    this.unBarred=unBarred;    this.barred=barred;    this.absent=absent;  }  public IProblem getAbsent()  {    return this.absent;  }  public IProblem getBarred()  {    return this.barred;  }  public IBooleanVariable getBooleanVariable()  {    return this.booleanVariable;  }  public IProblem getUnbarred()  {    return this.unBarred;  }  public String toString()  {    String ret="Split "+ splitCount++ ;    ret+="\nBoolean Variable: "+this.booleanVariable;    ret+="\nunBarred IProblem: "+unBarred;    ret+="\nbarred IProblem: "+barred;    ret+="\nabsent IProblem: "+absent;    return ret;  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?