package de.FeatureModellingTool.PLModelChecker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import de.FeatureModellingTool.Customize.Customization;
import de.FeatureModellingTool.Customize.CustomizationModel;
import de.FeatureModellingTool.Customize.CustomizationVersion;
import de.FeatureModellingTool.FeatureModel.CFRModifier;
import de.FeatureModellingTool.FeatureModel.CompositeConstraint;
import de.FeatureModellingTool.FeatureModel.CompositeConstraintPortType;
import de.FeatureModellingTool.FeatureModel.CompositeConstraintType;
import de.FeatureModellingTool.FeatureModel.ConstraintModel;
import de.FeatureModellingTool.FeatureModel.Feature;
import de.FeatureModellingTool.FeatureModel.FeatureModel;
import de.FeatureModellingTool.FeatureModel.FeatureRelation;
import de.FeatureModellingTool.FeatureModel.GroupConstraint;
import de.FeatureModellingTool.FeatureModel.GroupConstraintType;
import de.FeatureModellingTool.FeatureModel.VPConstraint;
import de.FeatureModellingTool.FeatureModel.VPConstraintType;
import de.FeatureModellingTool.PLModelChecker.RelationAnalysis.ConstraintRelationDiagram;
import de.FeatureModellingTool.PLModelChecker.RelationAnalysis.FeatureReorder;
public class FMBDD {
private boolean optimized = false;
public FMBDD(FeatureModel featureModel , boolean optimized){
this.featureModel = featureModel;
this.include = featureModel.getAllFeatureRelation(FeatureRelation.DECOMPOSE);
this.dimensionValue = featureModel.getAllFeatureRelation(FeatureRelation.ATTRIBUTE);
this.require = featureModel.getAllFeatureRelation(FeatureRelation.REQUIRE);
this.mutex = featureModel.getAllFeatureRelation(FeatureRelation.EXCLUDE);
if(include == null)
include = new TreeMap();
if(dimensionValue == null)
dimensionValue = new TreeMap();
if(require == null)
require = new TreeMap();
if(mutex == null)
mutex = new TreeMap();
this.optimized = optimized;
}
/* ����bdd*/
public void build(FeatureModel featureModel, AtomSet atomSet, ConstraintModel constraintModel, CustomizationModel customizationModel){
this.featureModel = featureModel;
this.atomSet = atomSet;
this.constraintModel = constraintModel;
this.allAtomedFeatures = atomSet.getAllAtomedFeatures();
this.customizationModel = customizationModel;
/* �������̣�
* 1����ʼ��bdd
* 2��������ȵ�˳����bdd�IJ�������
* 3��������ȵ�˳��Ϊ����ģ�͵�������������Χ��ֵ����ϵ����bdd
* 4�������û�����ָ����������ϵ
* 5������һ�Զ�ĸ���Լ��
* 6�������Զ�ĸ���Լ��
*/
bdd = new MyBDD(3000, 10000);
List<Feature> featureOrder = null;
if (this.optimized) {
featureOrder = this.getOptimizedFeatureOrder();
} else {
featureOrder = this.getDepthVisitFeatureOrder();
}
createBoolVar(featureOrder);
build_Restrict();
build_CompositeConstraint();
build_GroupConstraint();
build_VPConstraint();
}
private void createBoolVar(){
// System.out.println("\n*****************\nCREATEBOOLVAR");
Set<Feature> roots = atomSet.getRoots();
//�����״̬��������BddVar=1��ɾ��������BddVar=0��
Iterator e = allAtomedFeatures.keySet().iterator();
CustomizationVersion curCustomizationVersion = customizationModel.getCurrentCustomizationVersion();
if(curCustomizationVersion != null)
{
while(e.hasNext()){
AtomedFeature cur = (AtomedFeature)allAtomedFeatures.get(e.next());
if(curCustomizationVersion.getFinalCustomizationById(cur.feature.getID()) == Customization.Undecided)
continue;
if(curCustomizationVersion.getFinalCustomizationById(cur.feature.getID()) == Customization.Selected)
cur.BddVar = 1;
if(curCustomizationVersion.getFinalCustomizationById(cur.feature.getID()) == Customization.Unselected)
cur.BddVar = 0;
Iterator i = allAtomedFeatures.keySet().iterator();
while(i.hasNext()){
AtomedFeature t = (AtomedFeature)allAtomedFeatures.get(i.next());
if( t.atomSetNum == cur.atomSetNum)
t.BddVar = cur.BddVar;
}
System.out.println(cur.feature.getName()+" "+cur.BddVar);
}
}
e = roots.iterator();
while(e.hasNext()){
AtomedFeature root = (AtomedFeature)allAtomedFeatures.get(e.next());
if(root.feature.getVariability().equals(de.FeatureModellingTool.FeatureModel.Variability.Mandatory)){
root.BddVar = 1;
Iterator i = allAtomedFeatures.keySet().iterator();
while(i.hasNext()){
AtomedFeature cur = (AtomedFeature)allAtomedFeatures.get(i.next());
if (cur.atomSetNum == root.atomSetNum)
cur.BddVar = 1;
}
}
}
/*test
e = allAtomedFeatures.keySet().iterator();
while(e.hasNext()){
AtomedFeature cur = (AtomedFeature)allAtomedFeatures.get(e.next());
if (cur.BddVar == 1)
System.out.println(cur.feature.getName()+" "+cur.atomSetNum+roots.contains(cur.feature));
}*/
if (this.optimized) {
ConstraintRelationDiagram crd = new ConstraintRelationDiagram(featureModel , constraintModel , null);
Collection<ConstraintRelationDiagram.NGraph> graphs = crd.getGraph().getConnectedGraph();
List<Feature> rootList = new ArrayList<Feature>();
for (Iterator<ConstraintRelationDiagram.NGraph> itGraph=graphs.iterator() ; itGraph.hasNext() ; ) {
ConstraintRelationDiagram.NGraph graph = itGraph.next();
for (Iterator<Feature> itFeature=roots.iterator() ; itFeature.hasNext() ; ) {
Feature feature = itFeature.next();
if (graph.nodes.containsKey(feature)) {
rootList.add(feature);
}
}
}
e = rootList.iterator();
while(e.hasNext()){
depthVisitCreateVar((Feature)e.next());
}
} else {
e = roots.iterator();
while(e.hasNext()){
depthVisitCreateVar((Feature)e.next());
}
}
/* e = allAtomedFeatures.keySet().iterator();
while(e.hasNext()){
AtomedFeature cur = allAtomedFeatures.get(e.next());
System.out.println( cur.feature.getName() + " " +
cur.atomSetNum + " " +
cur.BddVar);
}
System.out.println("\n********************\n");*/
/* ����������ȵر���ԭ�Ӽ���
ÿ��ԭ�Ӽ������ҽ���һ��Ԫ�ر�������BDD������BddVar��
����һ�δ��뽫ԭ�Ӽ�������Ԫ�ص�BddVar�����ó����BDD������
�Ա���ԭ�Ӽ�������Ԫ�ص�ͬ����
*/
e = allAtomedFeatures.keySet().iterator();
while(e.hasNext()){
AtomedFeature cur = (AtomedFeature)allAtomedFeatures.get(e.next());
if(cur.BddVar != AtomedFeature.UNDEFINED)
continue;
// System.out.println( cur.feature.getName() + " " +
// cur.atomSetNum + " " +
// cur.BddVar);
Iterator i = allAtomedFeatures.keySet().iterator();
while(i.hasNext()){
AtomedFeature t = (AtomedFeature)allAtomedFeatures.get(i.next());
if( t.atomSetNum == cur.atomSetNum
&&
t.BddVar != AtomedFeature.UNDEFINED){
cur.BddVar = t.BddVar;
break;
}
}
if(cur.BddVar == AtomedFeature.UNDEFINED)
cur.createBddVar(bdd);
// System.out.println( cur.feature.getName() + " " +
// cur.atomSetNum + " " +
// cur.BddVar);
}
/* System.out.println("\n********************\n");
e = allAtomedFeatures.keySet().iterator();
while(e.hasNext()){
AtomedFeature cur = allAtomedFeatures.get(e.next());
System.out.println( cur.feature.getName() + " " +
cur.atomSetNum + " " +
cur.BddVar);
}*/
}
private void depthVisitCreateVar(Feature father){
AtomedFeature fatherAtomedFeature = allAtomedFeatures.get(father);
if(!fatherAtomedFeature.createBddVar(bdd)) return;
// Map include = featureModel.getAllFeatureRelation(FeatureRelation.DECOMPOSE);
// Map dimensionValue = featureModel.getAllFeatureRelation(FeatureRelation.ATTRIBUTE);
// Map require = featureModel.getAllFeatureRelation(FeatureRelation.REQUIRE);
Iterator e = null;
Feature child = null;
FeatureRelation r = null;
AtomedFeature startAtomedFeature = null,
endAtomedFeature = null;
e = include.keySet().iterator();
while(e.hasNext()){
r = (FeatureRelation)include.get(e.next());
// ��������ϵ��������������������Ϊend��
// ��������ϵ�б���������Ϊstart��ȡ���ǵ�ԭ�Ӽ�
startAtomedFeature = allAtomedFeatures.get(r.getStartFeature());
endAtomedFeature = allAtomedFeatures.get(r.getEndFeature());
// ֻ��start��father��ͬһԭ�Ӽ��ڣ�
// ��end��start����ͬһԭ�Ӽ��ڣ�
// ��˵�����������ϵ����Ч��
if ( startAtomedFeature.atomSetNum == fatherAtomedFeature.atomSetNum
&&
startAtomedFeature.atomSetNum != endAtomedFeature.atomSetNum){
child = r.getEndFeature();
depthVisitCreateVar(child);
}
}
e = dimensionValue.keySet().iterator();
while(e.hasNext()){
r = (FeatureRelation)dimensionValue.get(e.next());
// ��������ϵ��������������������Ϊend��
// ��������ϵ�б���������Ϊstart��ȡ���ǵ�ԭ�Ӽ�
startAtomedFeature = allAtomedFeatures.get(r.getStartFeature());
endAtomedFeature = allAtomedFeatures.get(r.getEndFeature());
// ֻ��start��father��ͬһԭ�Ӽ��ڣ�
// ��end��start����ͬһԭ�Ӽ��ڣ�
// ��˵�����������ϵ����Ч��
if ( startAtomedFeature.atomSetNum == fatherAtomedFeature.atomSetNum
&&
startAtomedFeature.atomSetNum != endAtomedFeature.atomSetNum){
child = r.getEndFeature();
depthVisitCreateVar(child);
}
}
e = require.keySet().iterator();
while(e.hasNext()){
r = (FeatureRelation)require.get(e.next());
// ��������ϵ��������������������Ϊstart��
// ��������ϵ�б���������Ϊend��ȡ���ǵ�ԭ�Ӽ�
startAtomedFeature = allAtomedFeatures.get(r.getStartFeature());
endAtomedFeature = allAtomedFeatures.get(r.getEndFeature());
// ֻ��start��father��ͬһԭ�Ӽ��ڣ�
// ��end��start����ͬһԭ�Ӽ��ڣ�
// ��˵�����������ϵ����Ч��
if ( endAtomedFeature.atomSetNum == fatherAtomedFeature.atomSetNum
&&
endAtomedFeature.atomSetNum != startAtomedFeature.atomSetNum){
child = r.getStartFeature();
depthVisitCreateVar(child);
}
}
}
private List<Feature> getDepthVisitFeatureOrder() {
List<Feature> result = new ArrayList<Feature>();
Set<Feature> roots = atomSet.getRoots();
for (Iterator<Feature> itFeature=roots.iterator() ; itFeature.hasNext() ; ) {
getDepthVisitFeatureOrder(itFeature.next() , result);
}
return result;
}
private void getDepthVisitFeatureOrder(Feature father, List<Feature> result) {
if (result.contains(father)) {
return;
}
result.add(father);
AtomedFeature fatherAtomedFeature = allAtomedFeatures.get(father);
Iterator e = null;
Feature child = null;
FeatureRelation r = null;
AtomedFeature startAtomedFeature = null, endAtomedFeature = null;
e = include.keySet().iterator();
while (e.hasNext()) {
r = (FeatureRelation) include.get(e.next());
if (r.getStartFeature().equals(father)) {
getDepthVisitFeatureOrder(r.getEndFeature() , result);
}
}
e = dimensionValue.keySet().iterator();
while (e.hasNext()) {
r = (FeatureRelation) dimensionValue.get(e.next());
if (r.getStartFeature().equals(father)) {
getDepthVisitFeatureOrder(r.getEndFeature() , result);
}
}
e = require.keySet().iterator();
while (e.hasNext()) {
r = (FeatureRelation) require.get(e.next());
if (r.getStartFeature().equals(father)) {
getDepthVisitFeatureOrder(r.getEndFeature() , result);
}
}
}
private List<Feature> getOptimizedFeatureOrder() {
FeatureReorder order = new FeatureReorder(featureModel , constraintModel);
List<Feature> result = order.getFeatureOrder();
for (int i=0 ; i<result.size() ; i++) {
System.out.println(result.get(i).getName());
}
return result;
}
private void createBoolVar(List<Feature> featureOrder) {
Set<Feature> roots = atomSet.getRoots();
//�����״̬��������BddVar=1��ɾ��������BddVar=0��
Iterator<Feature> e = allAtomedFeatures.keySet().iterator();
CustomizationVersion curCustomizationVersion = customizationModel.getCurrentCustomizationVersion();
if(curCustomizationVersion != null)
{
while(e.hasNext()){
AtomedFeature cur = (AtomedFeature)allAtomedFeatures.get(e.next());
if(curCustomizationVersion.getFinalCustomizationById(cur.feature.getID()) == Customization.Undecided)
continue;
if(curCustomizationVersion.getFinalCustomizationById(cur.feature.getID()) == Customization.Selected)
cur.BddVar = 1;
if(curCustomizationVersion.getFinalCustomizationById(cur.feature.getID()) == Customization.Unselected)
cur.BddVar = 0;
for (Iterator<AtomedFeature> itFeature=allAtomedFeatures.values().iterator() ; itFeature.hasNext() ; ) {
AtomedFeature newFeature = itFeature.next();
if (newFeature.atomSetNum==cur.atomSetNum) {
newFeature.BddVar = cur.BddVar;
}
}
System.out.println(cur.feature.getName()+" "+cur.BddVar);
}
}
e = roots.iterator();
while(e.hasNext()){
AtomedFeature root = (AtomedFeature)allAtomedFeatures.get(e.next());
if(root.feature.getVariability().equals(de.FeatureModellingTool.FeatureModel.Variability.Mandatory)){
root.BddVar = 1;
for (Iterator<AtomedFeature> itFeature=allAtomedFeatures.values().iterator() ; itFeature.hasNext() ; ) {
AtomedFeature newFeature = itFeature.next();
if (newFeature.atomSetNum==root.atomSetNum) {
newFeature.BddVar = root.BddVar;
}
}
}
}
for (int i=0 ; i<featureOrder.size() ; i++) {
Feature feature = featureOrder.get(i);
AtomedFeature aFeature = allAtomedFeatures.get(feature);
if (aFeature.BddVar==AtomedFeature.UNDEFINED) {
aFeature.createBddVar(bdd);
for (Iterator<AtomedFeature> itFeature=allAtomedFeatures.values().iterator() ; itFeature.hasNext() ; ) {
AtomedFeature newFeature = itFeature.next();
if (newFeature.atomSetNum==aFeature.atomSetNum) {
newFeature.BddVar = aFeature.BddVar;
}
}
}
}
}
private void build_Restrict(){
// System.out.println("\n*************\nBuilding_Restrict");
Set<Feature> roots = atomSet.getRoots();
// Map<Feature, AtomedFeature> allAtomedFeatures = atomSet.getAllAtomedFeatures();
// Map include = featureModel.getAllFeatureRelation(FeatureRelation.DECOMPOSE);
// Map dimensionValue = featureModel.getAllFeatureRelation(FeatureRelation.ATTRIBUTE);
// Map require = featureModel.getAllFeatureRelation(FeatureRelation.REQUIRE);
Iterator x = include.keySet().iterator();
/* while(x.hasNext()){
FeatureRelation rr = (FeatureRelation)include.get(x.next());
AtomedFeature sa = allAtomedFeatures.get(rr.getStartFeature()),
ea = allAtomedFeatures.get(rr.getEndFeature());
System.out.println( ea.feature.getName() + " "+
"-> " +
sa.feature.getName() + ": "+
ea.atomSetNum + " " +
"-> " +
sa.atomSetNum + "�� "+
ea.BddVar + " " +
"-> " +
sa.BddVar);
}
x = dimensionValue.keySet().iterator();
while(x.hasNext()){
FeatureRelation rr = (FeatureRelation)dimensionValue.get(x.next());
AtomedFeature sa = allAtomedFeatures.get(rr.getStartFeature()),
ea = allAtomedFeatures.get(rr.getEndFeature());
System.out.println( ea.feature.getName() + " "+
"-> " +
sa.feature.getName() + ": "+
ea.atomSetNum + " " +
"-> " +
sa.atomSetNum + "�� "+
ea.BddVar + " " +
"-> " +
sa.BddVar);
}
x = require.keySet().iterator();
while(x.hasNext()){
FeatureRelation rr = (FeatureRelation)require.get(x.next());
AtomedFeature sa = allAtomedFeatures.get(rr.getStartFeature()),
ea = allAtomedFeatures.get(rr.getEndFeature());
System.out.println( ea.feature.getName() + " "+
"-> " +
sa.feature.getName() + ": "+
ea.atomSetNum + " " +
"-> " +
sa.atomSetNum + "�� "+
ea.BddVar + " " +
"-> " +
sa.BddVar);
}
x = mutex.keySet().iterator();
while(x.hasNext()){
FeatureRelation rr = (FeatureRelation)mutex.get(x.next());
AtomedFeature sa = allAtomedFeatures.get(rr.getStartFeature()),
ea = allAtomedFeatures.get(rr.getEndFeature());
System.out.println( ea.feature.getName() + " "+
"<-x-> " +
sa.feature.getName() + ": "+
ea.atomSetNum + " " +
"<-x-> " +
sa.atomSetNum + "�� "+
ea.BddVar + " " +
"<-x-> " +
sa.BddVar);
}
System.out.println("\n***********************\n");
*/
LinkedList<Feature> list = new LinkedList<Feature>();
list.clear();
Iterator e = roots.iterator();
while(e.hasNext()){
list.add((Feature)e.next());
while(!list.isEmpty()){
Iterator i = null;
FeatureRelation r = null;
AtomedFeature startAtomedFeature = null,
endAtomedFeature = null,
fatherAtomedFeature = null;
Feature father = list.getFirst();
list.removeFirst();
fatherAtomedFeature = allAtomedFeatures.get(father);
i = include.keySet().iterator();
while(i.hasNext()){
Object key = (Object)i.next();
r = (FeatureRelation)include.get(key);
// ��������ϵ��������������������Ϊend��
// ��������ϵ�б���������Ϊstart��ȡ���ǵ�ԭ�Ӽ�
startAtomedFeature = allAtomedFeatures.get(r.getStartFeature());
endAtomedFeature = allAtomedFeatures.get(r.getEndFeature());
// ֻ��start��father��ͬһԭ�Ӽ��ڣ�
// ��end��start����ͬһԭ�Ӽ��ڣ�
// ��˵�����������ϵ����Ч��
if ( startAtomedFeature.atomSetNum == fatherAtomedFeature.atomSetNum
&&
startAtomedFeature.atomSetNum != endAtomedFeature.atomSetNum){
int temp = bdd.ref(
bdd.imp(endAtomedFeature.BddVar
,startAtomedFeature.BddVar)
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
/* System.out.println( endAtomedFeature.feature.getName() + " "+
"-> " +
startAtomedFeature.feature.getName() + ": "+
endAtomedFeature.atomSetNum + " " +
"-> " +
startAtomedFeature.atomSetNum + "�� "+
endAtomedFeature.BddVar + " " +
"-> " +
startAtomedFeature.BddVar);*/
i.remove();
include.remove(key);
list.addLast(endAtomedFeature.feature);
}//end if
else if(startAtomedFeature.atomSetNum == endAtomedFeature.atomSetNum){
i.remove();
require.remove(key);
}
}//end while
i = dimensionValue.keySet().iterator();
while(i.hasNext()){
Object key = (Object)i.next();
r = (FeatureRelation)dimensionValue.get(key);
// ��������ϵ��������������������Ϊend��
// ��������ϵ�б���������Ϊstart��ȡ���ǵ�ԭ�Ӽ�
startAtomedFeature = allAtomedFeatures.get(r.getStartFeature());
endAtomedFeature = allAtomedFeatures.get(r.getEndFeature());
// ֻ��start��father��ͬһԭ�Ӽ��ڣ�
// ��end��start����ͬһԭ�Ӽ��ڣ�
// ��˵�����������ϵ����Ч��
if ( startAtomedFeature.atomSetNum == fatherAtomedFeature.atomSetNum
&&
startAtomedFeature.atomSetNum != endAtomedFeature.atomSetNum){
//list.addLast(r.getEndFeature());
int temp = bdd.ref(
bdd.imp(endAtomedFeature.BddVar
,startAtomedFeature.BddVar)
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
/* System.out.println( endAtomedFeature.feature.getName() + " "+
"-> " +
startAtomedFeature.feature.getName() + ": "+
endAtomedFeature.atomSetNum + " " +
"-> " +
startAtomedFeature.atomSetNum + "�� "+
endAtomedFeature.BddVar + " " +
"-> " +
startAtomedFeature.BddVar);*/
i.remove();
dimensionValue.remove(key);
list.addLast(endAtomedFeature.feature);
}//end if
else if(startAtomedFeature.atomSetNum == endAtomedFeature.atomSetNum){
i.remove();
require.remove(key);
}
}//end while
//!!!!!!!!!!!require��dimensionValue��include��ͬ���ر�Ҫע�⣺
//require��start->end
//dimensionValue��include��end->start
i = require.keySet().iterator();
while(i.hasNext()){
Object key = (Object)i.next();
r = (FeatureRelation)require.get(key);
// ��������ϵ��������������������Ϊstart��
// ��������ϵ�б���������Ϊend��ȡ���ǵ�ԭ�Ӽ�
startAtomedFeature = allAtomedFeatures.get(r.getStartFeature());
endAtomedFeature = allAtomedFeatures.get(r.getEndFeature());
// ֻ��start��father��ͬһԭ�Ӽ��ڣ�
// ��end��start����ͬһԭ�Ӽ��ڣ�
// ��˵�����������ϵ����Ч��
if ( startAtomedFeature.atomSetNum == fatherAtomedFeature.atomSetNum
&&
startAtomedFeature.atomSetNum != endAtomedFeature.atomSetNum){
//list.addLast(r.getEndFeature());
int temp = bdd.ref(
bdd.imp(startAtomedFeature.BddVar
,endAtomedFeature.BddVar)
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
/* System.out.println( startAtomedFeature.feature.getName() + " "+
"-> " +
endAtomedFeature.feature.getName() + ": "+
startAtomedFeature.atomSetNum + " " +
"-> " +
endAtomedFeature.atomSetNum + "�� "+
startAtomedFeature.BddVar + " " +
"-> " +
endAtomedFeature.BddVar);*/
i.remove();
require.remove(key);
list.addLast(startAtomedFeature.feature);
}//end if
else if(startAtomedFeature.atomSetNum == endAtomedFeature.atomSetNum){
i.remove();
require.remove(key);
}
}//end while
}//end while
}//end while
/* System.out.println("\nRestrict_building completed***********************\n");
if(!include.isEmpty() || !dimensionValue.isEmpty() || !require.isEmpty())
System.out.println("FATAL!!/n/n");
else
System.out.println("PASS/n/n");*/
x = mutex.keySet().iterator();
while(x.hasNext()){
FeatureRelation r = (FeatureRelation)mutex.get(x.next());
// ��������ϵ��������������������Ϊstart��
// ��������ϵ�б���������Ϊend��ȡ���ǵ�ԭ�Ӽ�
AtomedFeature startAtomedFeature = allAtomedFeatures.get(r.getStartFeature());
AtomedFeature endAtomedFeature = allAtomedFeatures.get(r.getEndFeature());
if (startAtomedFeature.atomSetNum != endAtomedFeature.atomSetNum){
//list.addLast(r.getEndFeature());
int temp = bdd.ref(
bdd.or(bdd.not(startAtomedFeature.BddVar)
, bdd.not(endAtomedFeature.BddVar))
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
/*
int temp1 = bdd.ref(
bdd.imp(startAtomedFeature.BddVar
,bdd.not(endAtomedFeature.BddVar))
);
int temp2 = bdd.ref(
bdd.imp(endAtomedFeature.BddVar
,bdd.not(startAtomedFeature.BddVar))
);
int temp = bdd.ref(bdd.and(temp1, temp2));
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
bdd.deref(temp1);
bdd.deref(temp2);*/
/* System.out.println( startAtomedFeature.feature.getName() + " "+
"<-x-> " +
endAtomedFeature.feature.getName() + ": "+
startAtomedFeature.atomSetNum + " " +
"<-x-> " +
endAtomedFeature.atomSetNum + "�� "+
startAtomedFeature.BddVar + " " +
"<-x-> " +
endAtomedFeature.BddVar);*/
}//end if
else{
// System.out.println("\n\nConflict detected!!!\nmutex relation in same atom set\n\n");
bdd.bddRoot = bdd.andTo(bdd.bddRoot, 0);
}
}
/* int t1 = bdd.createVar();
int t2 = bdd.createVar();
// int temp = bdd.ref(bdd.imp(t1, t2));
int temp = bdd.ref(bdd.or(bdd.not(t1), t2));
// int temp2 = bdd.ref(bdd.imp(t1, bdd.not(t2)));
int temp2 = bdd.ref(bdd.or(bdd.not(t1), bdd.not(t2)));
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp2);
System.out.println("ROOT = "+bdd.bddRoot);*/
}
//(a,b,c)->(x,y,z)
private void build_CompositeConstraint(){
// System.out.println("\n*************\nBuilding_CompositeConstraint");
// Map<Feature, AtomedFeature> allAtomedFeature = atomSet.getAllAtomedFeatures();
Map compositeConstraint = constraintModel.getAllCompositeConstraint();
Iterator e = compositeConstraint.keySet().iterator();
while(e.hasNext()){
// System.out.println("*************Building_CompositeConstraint");
CompositeConstraint c = (CompositeConstraint)compositeConstraint.get(e.next());
Set sourceFeature = c.getSourceFeatureSet();
Set sinkFeature = c.getSinkFeatureSet();
if(sourceFeature.isEmpty() || sinkFeature.isEmpty())
continue;
CompositeConstraintType type = c.getPLType();
int tempBddi = -1,
tempBddj = -1;
// ����source��BDD
if (c.getSourceType() == CompositeConstraintPortType.All){
tempBddi = 1;
Iterator i = sourceFeature.iterator();
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
if (constraintModel.getCFRelation(x.feature, c, true).getModifier().equals(CFRModifier.Affirmation))
tempBddi = bdd.andTo(tempBddi, x.BddVar);
else
tempBddi = bdd.andTo(tempBddi, bdd.not(x.BddVar));
}
}
else if (c.getSourceType() == CompositeConstraintPortType.Multi){
/* if(type == CompositeConstraintType.Mutex)
tempBddi = 0;
else
tempBddi = 1;*/
tempBddi = 0;
Iterator i = sourceFeature.iterator();
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
if (constraintModel.getCFRelation(x.feature, c, true).getModifier().equals(CFRModifier.Affirmation))
tempBddi = bdd.orTo(tempBddi, x.BddVar);
else
tempBddi = bdd.orTo(tempBddi, bdd.not(x.BddVar));
}
}
else if (c.getSourceType() == CompositeConstraintPortType.Single){
Iterator i = sourceFeature.iterator();
tempBddi = 0;
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
int temp;
if (constraintModel.getCFRelation(x.feature, c, true).getModifier().equals(CFRModifier.Affirmation))
temp = x.BddVar;
else
temp = bdd.not(x.BddVar);
Iterator j = sourceFeature.iterator();
while(j.hasNext()){
AtomedFeature y = allAtomedFeatures.get((Feature)j.next());
if(x == y) continue;
if (constraintModel.getCFRelation(y.feature, c, true).getModifier().equals(CFRModifier.Affirmation))
temp = bdd.andTo(temp, bdd.not(y.BddVar));
else
temp = bdd.andTo(temp, y.BddVar);
}
tempBddi = bdd.orTo(tempBddi, temp);
}
}//end if
// ����sink��BDD
if (c.getSinkType() == CompositeConstraintPortType.All){
tempBddj = 1;
Iterator i = sinkFeature.iterator();
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
tempBddj = bdd.andTo(tempBddj, x.BddVar);
else
tempBddj = bdd.andTo(tempBddj, bdd.not(x.BddVar));
}
}
else if (c.getSinkType() == CompositeConstraintPortType.Multi){
/* if(type == CompositeConstraintType.Mutex)
tempBddj = 0;
else
tempBddj = 1;*/
tempBddj = 0;
Iterator i = sinkFeature.iterator();
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
tempBddj = bdd.orTo(tempBddj, x.BddVar);
else
tempBddj = bdd.orTo(tempBddj, bdd.not(x.BddVar));
}
}
else if (c.getSinkType() == CompositeConstraintPortType.Single){
Iterator i = sinkFeature.iterator();
tempBddj = 0;
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
int temp;
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
temp = x.BddVar;
else
temp = bdd.not(x.BddVar);
Iterator j = sinkFeature.iterator();
while(j.hasNext()){
AtomedFeature y = allAtomedFeatures.get((Feature)j.next());
if(x == y) continue;
if (constraintModel.getCFRelation(y.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
temp = bdd.andTo(temp, bdd.not(y.BddVar));
else
temp = bdd.andTo(temp, y.BddVar);
}
tempBddj = bdd.orTo(tempBddj, temp);
}
}//end if
// ����source��sink��type��ϵ�µ�BDD
if (type == CompositeConstraintType.L2R_Implication){
int temp = bdd.ref(
bdd.imp(tempBddi, tempBddj)
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
}
else if (type == CompositeConstraintType.R2L_Implication){
int temp = bdd.ref(
bdd.imp(tempBddj, tempBddi)
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
}
else if (type == CompositeConstraintType.Mutex){
int temp = bdd.ref(
bdd.or(bdd.not(tempBddi)
, bdd.not(tempBddj))
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
/* int temp1 = bdd.ref(
bdd.imp(tempBddi, bdd.not(tempBddj))
);
int temp2 = bdd.ref(
bdd.imp(tempBddj, bdd.not(tempBddi))
);
int temp = bdd.ref(
bdd.and(temp1, temp2)
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
bdd.deref(temp1);
bdd.deref(temp2);*/
}
else if (type == CompositeConstraintType.Equivalence){
int temp = bdd.ref(
bdd.biimp(tempBddi, tempBddj)
);
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
}//end if
bdd.deref(tempBddi);
bdd.deref(tempBddj);
/* if(bdd.bddRoot == 0){
System.out.println(sourceFeature);
System.out.println(sinkFeature);
System.out.println(type);
bdd.bddRoot = 1;
}*/
}//end while
}
//(a,b,c)
private void build_GroupConstraint(){
// System.out.println("\n*************\nBuilding_GroupConstraint");
// Map<Feature, AtomedFeature> allAtomedFeature = atomSet.getAllAtomedFeatures();
Map groupConstraint = constraintModel.getAllGroupConstraint();
Iterator e = groupConstraint.keySet().iterator();
while(e.hasNext()){
// System.out.println("**********Building_GroupConstraint");
GroupConstraint c = (GroupConstraint)groupConstraint.get(e.next());
Set featureSet = c.getFeatureSet();
if(featureSet.isEmpty())
continue;
GroupConstraintType type = c.getType();
int tempBdd = 1;
if (type == GroupConstraintType.AllGroup){
Iterator i = featureSet.iterator();
tempBdd = 1;
int tempBdd2 = 1;
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation)){
tempBdd = bdd.andTo(tempBdd, x.BddVar);
tempBdd2 = bdd.andTo(tempBdd2 , bdd.not(x.BddVar));
}
else{
tempBdd = bdd.andTo(tempBdd, bdd.not(x.BddVar));
tempBdd2 = bdd.andTo(tempBdd2 , x.BddVar);
}
}
tempBdd = bdd.orTo(tempBdd , tempBdd2);
bdd.deref(tempBdd2);
}
else if (type == GroupConstraintType.MultiGroup){
// tempBdd = 1;
/* do nothing for multi-group
Iterator i = featureSet.iterator();
tempBdd = 0;
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
tempBdd = bdd.orTo(tempBdd, x.BddVar);
}
*/
}
else if (type == GroupConstraintType.SingleGroup){
Iterator i = featureSet.iterator();
tempBdd = 0;
int tempBdd2 = 1;
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
int temp;
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
temp = x.BddVar;
else
temp = bdd.not(x.BddVar);
Iterator j = featureSet.iterator();
while(j.hasNext()){
AtomedFeature y = allAtomedFeatures.get((Feature)j.next());
if(x == y) continue;
/*System.out.println(y.feature.getName()+"*");
System.out.println(y.BddVar);
bdd.not(y.BddVar);*/
if (constraintModel.getCFRelation(y.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
temp = bdd.andTo(temp, bdd.not(y.BddVar));
else
temp = bdd.andTo(temp, y.BddVar);
}
tempBdd = bdd.orTo(tempBdd, temp);
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
tempBdd2 = bdd.andTo(tempBdd2 , bdd.not(x.BddVar));
else
tempBdd2 = bdd.andTo(tempBdd2 , x.BddVar);
}
tempBdd = bdd.orTo(tempBdd , tempBdd2);
bdd.deref(tempBdd2);
}//end if
bdd.bddRoot = bdd.andTo(bdd.bddRoot, tempBdd);
bdd.deref(tempBdd);
}//end while
}
//x->(a,b,c)
private void build_VPConstraint(){
// System.out.println("\n*************\nBuilding_VPConstraint");
// Map<Feature, AtomedFeature> allAtomedFeature = atomSet.getAllAtomedFeatures();
Map vpConstraint = constraintModel.getAllVPConstraint();
Iterator e = vpConstraint.keySet().iterator();
while(e.hasNext()){
// System.out.println("************Building_VPConstraint");
VPConstraint c = (VPConstraint)vpConstraint.get(e.next());
if(c.getSourceFeatureSet().isEmpty() || c.getSinkFeatureSet().isEmpty())
continue;
Feature sourceFeature = c.getSourceFeatureSet().iterator().next();
AtomedFeature sourceAtomedFeature = allAtomedFeatures.get(sourceFeature);
Set sinkFeature = c.getSinkFeatureSet();
VPConstraintType type = c.getType();
int tempBdd = -1;
// ����sink��BDD
if (type == VPConstraintType.AllVP){
Iterator i = sinkFeature.iterator();
tempBdd = 1;
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
tempBdd = bdd.andTo(tempBdd, x.BddVar);
else
tempBdd = bdd.andTo(tempBdd, bdd.not(x.BddVar));
}
}
else if (type == VPConstraintType.MultiVP){
// tempBdd = 1;
Iterator i = sinkFeature.iterator();
tempBdd = 0;
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
tempBdd = bdd.orTo(tempBdd, x.BddVar);
else
tempBdd = bdd.orTo(tempBdd, bdd.not(x.BddVar));
}
}
else if (type == VPConstraintType.SingleVP){
Iterator i = sinkFeature.iterator();
while(i.hasNext()){
AtomedFeature x = allAtomedFeatures.get((Feature)i.next());
tempBdd = 0;
int temp;
if (constraintModel.getCFRelation(x.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
temp = x.BddVar;
else
temp = bdd.not(x.BddVar);
Iterator j = sinkFeature.iterator();
while(j.hasNext()){
AtomedFeature y = allAtomedFeatures.get((Feature)j.next());
if(x == y) continue;
if (constraintModel.getCFRelation(y.feature, c, false).getModifier().equals(CFRModifier.Affirmation))
temp = bdd.andTo(temp, bdd.not(y.BddVar));
else
temp = bdd.andTo(temp, y.BddVar);
}
tempBdd = bdd.orTo(tempBdd, temp);
}
}//end if
int temp;
if (constraintModel.getCFRelation(sourceAtomedFeature.feature, c, true).getModifier().equals(CFRModifier.Affirmation))
temp = bdd.imp(tempBdd, sourceAtomedFeature.BddVar);
else
temp = bdd.imp(tempBdd, bdd.not(sourceAtomedFeature.BddVar));
bdd.bddRoot = bdd.andTo(bdd.bddRoot, temp);
bdd.deref(temp);
bdd.deref(tempBdd);
}//end while
}
public boolean check(){
if(bdd.bddRoot == 0) return false;
return true;
}
/* public void printBddTable(){
System.out.println("Node-table:");
for(int i = 0; i<2100; ++i)
System.out.println("" + i + "\t" + bdd.getVar(i) + "\t" + bdd.getLow(i) + "\t" + bdd.getHigh(i) + "\t: " + bdd.getRef(i) );
System.out.println("" + bdd.bddRoot + "\t" + bdd.getVar(bdd.bddRoot) + "\t" + bdd.getLow(bdd.bddRoot) + "\t" + bdd.getHigh(bdd.bddRoot) + "\t: " + bdd.getRef(bdd.bddRoot) );
}
*/
public boolean checkRule2and3(){
boolean result = true;
disobeyrule23Feature = "";
Set<Integer> row = new LinkedHashSet<Integer>();
Set<Integer> add = new LinkedHashSet<Integer>();
row.add(Integer.valueOf(bdd.bddRoot));
// ������Bdd���
for(int i = bdd.getVar(bdd.bddRoot); i < bdd.getVar(0); ++i){
Iterator e = row.iterator();
add.clear();
int tag = 1; //����Ƿ��н��������
// System.out.print(i+"* ");
while(e.hasNext()){
Object cur = e.next();
int curInt = ((Integer)cur).intValue();
//����С�ڱ���Ľ�㽫����չ
// System.out.print(cur + ":" +bdd.getHigh(curInt)+","+bdd.getLow(curInt)+";"+ bdd.getVar(curInt) + " ");
if(bdd.getVar(curInt) < i){
int high = bdd.getHigh(curInt);
int low = bdd.getLow(curInt);
// if ( high == 0 || high == 1
// || low == 0 || low == 1)
// return true;
if (bdd.getVar(high) != i && high != 0)
tag = 0;
if (bdd.getVar(low) != i && low != 0)
tag = 0;
add.add(Integer.valueOf(high));
add.add(Integer.valueOf(low));
e.remove();
// row.remove(cur);
}
else if(bdd.getVar(curInt) > i && curInt != 0)
tag = 0;
}
row.addAll(add);
// System.out.println();
//��������Bdd���
if (tag == 1){
e = row.iterator();
int t1 = 1;
int t2 = 1;
while(e.hasNext()){
int curInt = ((Integer)e.next()).intValue();
if(bdd.getHigh(curInt) != 0)
t1 = 0;
if(bdd.getLow(curInt) != 0)
t2 = 0;
if(t1 == 0 && t2 == 0)
break;
}
if(t1 == 1 || t2 == 1){
Iterator it = allAtomedFeatures.keySet().iterator();
while(it.hasNext()){
AtomedFeature x = allAtomedFeatures.get(it.next());
if(x.BddVar == i * 2 + 2 && !x.feature.getVariability().equals(de.FeatureModellingTool.FeatureModel.Variability.Mandatory)){
// System.out.println("Conflict detected:rule 2 and 3 \n" + x.feature.getName() + "\n");
if(disobeyrule23Feature == "")
disobeyrule23Feature = x.feature.getName();
else
disobeyrule23Feature = disobeyrule23Feature + " �� " + x.feature.getName();
}
}
// System.out.println("Conflict:" + i);
result = false;
}
}
}
// if(!result) System.out.println("no Conflict");
return result;
}
public MyBDD getBdd(){
return bdd;
}
public void clear(){
bdd.cleanup();
}
protected MyBDD bdd = null;
private FeatureModel featureModel = null;
private ConstraintModel constraintModel = null;
private AtomSet atomSet = null;
private CustomizationModel customizationModel = null;
private Map<Feature, AtomedFeature> allAtomedFeatures = null;
private Map include = null;
private Map dimensionValue = null;
private Map require = null;
private Map mutex = null;
protected String disobeyrule23Feature = "";
}