00001 /* 00002 * (c) copyright 2008, Technische Universitaet Graz and Technische Universitaet Wien 00003 * 00004 * This file is part of jdiagengine. 00005 * 00006 * jdiagengine is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * jdiagengine is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * You should have received a copy of the GNU General Public License 00016 * along with jdiagengine. If not, see <http://www.gnu.org/licenses/>. 00017 * 00018 * Authors: Joerg Weber, Franz Wotawa 00019 * Contact: jweber@ist.tugraz.at (preferred), or fwotawa@ist.tugraz.at 00020 * 00021 */ 00022 00023 00024 package dfengine; 00025 00026 import java.util.*; 00027 00028 import utils.*; 00029 00030 00031 public final class DENode extends DoubleLinkedDAGNode { 00032 00033 public static final int TYPE_ALPHA = 0; 00034 public static final int TYPE_BETA = 1; 00035 00036 public static final int STATUS_FALSE = 0; 00037 public static final int STATUS_TRUE = 1; 00038 public static final int STATUS_UNKNOWN = -1; 00039 00040 // either TYPE_ALPHA or TYPE_BETA 00041 protected int type; 00042 00043 // The root of the tree. 00044 protected DENode rootNode; 00045 00046 /* 00047 * The length of the path between rootNode and this node. 00048 * 00049 * Note: distanceToRoot is an upper limit for the length of the longest DF-chain in the mode assignment. 00050 */ 00051 protected int distanceToRoot; 00052 00053 protected ModeAssignment ma; 00054 00055 /* 00056 * Contains Mode objects indicating which modes must not change in descendants of this node. 00057 * 00058 * The meaning of a Mode m is different for alpha and beta nodes: 00059 * 00060 * For alpha nodes, m.type = Mode.MODE_IF and this.ma contains m. Furthermore, for all descendants n of 00061 * this node: n.ma contains m. 00062 * 00063 * For beta nodes: m.type = Mode.MODE_DF, and this.ma must not contain m. The same holds for all 00064 * descendants of this node. 00065 * 00066 * Released by DiagnosisEnvironments when no longer needed (see method DENode.releaseConstCompModes()). 00067 * No longer needed after expanded AND consistency checked. 00068 */ 00069 protected TreeSet constCompModes; 00070 00071 // also stored in a ConflictSets instance => this member variable does not need much additional memory 00072 protected ConflictSet cs = null; 00073 00074 protected boolean expandedAlpha = false; 00075 00076 protected boolean expandedBeta = false; 00077 00078 protected int consistent = STATUS_UNKNOWN; 00079 00080 // true if a conflict set exists which proves that all descendants of this node are inconsistent 00081 protected boolean descInconsistent = false; 00082 00083 protected int numIF = -1; 00084 00085 protected int minNumIF = -1; 00086 00087 protected int minimal = STATUS_UNKNOWN; 00088 00089 00090 public DENode(int type, DENode rootNode, int distanceToRoot, ModeAssignment ma, 00091 TreeSet constCompModes) { 00092 00093 this.type = type; 00094 if (rootNode == null) { 00095 this.rootNode = this; 00096 } else { 00097 this.rootNode = rootNode; 00098 } 00099 this.distanceToRoot = distanceToRoot; 00100 this.ma = ma; 00101 this.constCompModes = constCompModes; 00102 } 00103 00104 public int getType() { 00105 return type; 00106 } 00107 00108 public int getDistanceToRoot() { 00109 return distanceToRoot; 00110 } 00111 00112 public String getTypeAsString() { 00113 if (type == TYPE_ALPHA) return "ALPHA"; 00114 else if (type == TYPE_BETA) return "BETA"; 00115 else { 00116 assert(false); 00117 return null; 00118 } 00119 } 00120 00121 public DENode getRootNode() { 00122 return rootNode; 00123 } 00124 00125 public ModeAssignment getModeAssignment() { 00126 return ma; 00127 } 00128 00129 public void setConflictSet(ConflictSet cs) { 00130 this.cs = cs; 00131 } 00132 00133 public ConflictSet getConflictSet() { 00134 return cs; 00135 } 00136 00137 public void setDescInconsistent() { 00138 descInconsistent = true; 00139 } 00140 00141 public boolean descInconsistent() { 00142 return descInconsistent; 00143 } 00144 00145 /* 00146 * In order to safe memory: dereference constCompModes (=> can be destroyed by garbage collector now) 00147 */ 00148 public void releaseConstCompModes() { 00149 constCompModes = null; 00150 } 00151 00152 public TreeSet getConstCompModes() { 00153 return constCompModes; 00154 } 00155 00156 public void setConsistent(int status) { 00157 consistent = status; 00158 } 00159 00160 public int consistent() { 00161 return consistent; 00162 } 00163 00164 public void setMinimal(int status) { 00165 minimal = status; 00166 } 00167 00168 public int minimal() { 00169 return minimal; 00170 } 00171 00172 public void setExpanded(int expansionType) { 00173 if (expansionType == TYPE_ALPHA) 00174 { 00175 assert(this.type == TYPE_ALPHA); 00176 expandedAlpha = true; 00177 } else 00178 { 00179 assert(expansionType == TYPE_BETA); 00180 expandedBeta = true; 00181 } 00182 } 00183 00184 public boolean expanded(int expansionType) { 00185 if (expansionType == TYPE_ALPHA) 00186 { 00187 return expandedAlpha; 00188 } 00189 else { 00190 assert(expansionType == TYPE_BETA); 00191 return expandedBeta; 00192 } 00193 } 00194 00195 public int getNumIF() { 00196 00197 // lazy evaluation 00198 if (numIF == -1) numIF = ma.getNumPFCs(); 00199 return numIF; 00200 } 00201 00202 public void setMinNumIF(int minNumIF) { 00203 this.minNumIF = minNumIF; 00204 } 00205 00206 // This method is only relevant for alpha nodes. 00207 public int getMinNumIF() { 00208 return minNumIF; 00209 } 00210 00211 /* 00212 * For debugging. 00213 */ 00214 public String toStringShort() { 00215 StringBuffer result = new StringBuffer(); 00216 00217 result.append(Integer.toString(id)); 00218 result.append(": "); 00219 00220 if (type == TYPE_ALPHA) result.append("ALPHA node: "); 00221 else result.append("BETA node: "); 00222 00223 /* 00224 result.append("ROOT_DISTANCE: "); 00225 result.append(Integer.toString(distanceToRoot)); 00226 result.append(" "); 00227 */ 00228 00229 result.append(ma.toStringShort()); 00230 00231 result.append(" ["); 00232 if (type == TYPE_ALPHA) { 00233 result.append("expanded ALPHA: " + expandedAlpha + "; "); 00234 } 00235 result.append("expanded BETA: " + expandedBeta); 00236 result.append("; cons.: " + statusToStr(consistent)); 00237 result.append("; minimal: " + statusToStr(minimal)); 00238 result.append("; #<=IF: " + minNumIF); 00239 if (descInconsistent) result.append("; DESC. INC."); 00240 00241 if (constCompModes != null) { 00242 result.append("; CCM: {"); 00243 00244 Iterator itCCM = constCompModes.iterator(); 00245 while (itCCM.hasNext()) { 00246 Mode m = (Mode)itCCM.next(); 00247 result.append(m.toString()); 00248 if (itCCM.hasNext()) { 00249 result.append(", "); 00250 } 00251 } 00252 00253 result.append("}"); 00254 } 00255 00256 result.append("]"); 00257 00258 return result.toString(); 00259 } 00260 00261 protected String statusToStr(int status) { 00262 switch (status) { 00263 case STATUS_TRUE: return "true"; 00264 case STATUS_FALSE: return "false"; 00265 default: return "?"; 00266 } 00267 } 00268 00269 protected boolean invariant() { 00270 00271 // for all DF(c, c_i) in ma: c_i must be IF or DF 00272 00273 Iterator itModes = ma.getModeIterator(Mode.MODE_DF); 00274 while (itModes.hasNext()) { 00275 Mode m = (Mode)itModes.next(); 00276 Mode parM = ma.getMode(m.getComponent()); 00277 if ((parM.getType() != Mode.MODE_IF) 00278 && (parM.getType() != Mode.MODE_DF)) { 00279 00280 System.out.println("ERROR: DENode.invariant() failed: " + 1); 00281 return false; 00282 } 00283 } 00284 00285 // if this node is BETA: all children must be BETA as well 00286 00287 if (type == TYPE_BETA) { 00288 Iterator itChildren = getChildrenIterator(); 00289 while (itChildren.hasNext()) { 00290 DENode child = (DENode)itChildren.next(); 00291 if (child.getType() != TYPE_BETA) { 00292 00293 System.out.println("ERROR: DENode.invariant() failed: " + 2); 00294 return false; 00295 } 00296 } 00297 } 00298 00299 // mode assignment must not contain any NAB 00300 00301 if (ma.hasMode(Mode.MODE_NAB)) { 00302 System.out.println("ERROR: DENode.invariant() failed: " + 3); 00303 return false; 00304 } 00305 00306 // See constCompModes. Checks if constCompModes contains modes of the "right" type 00307 // and compares constCompModes with ma. 00308 00309 if (constCompModes != null) { 00310 00311 // ALPHA 00312 if (type == TYPE_ALPHA) { 00313 Iterator itCCM = constCompModes.iterator(); 00314 while (itCCM.hasNext()) { 00315 Mode m = (Mode)itCCM.next(); 00316 if ((m.getType() != Mode.MODE_IF) || (ma.getMode(m.getComponent()) == null)) { 00317 System.out.println("ERROR: DENode.invariant() failed: " + 4); 00318 return false; 00319 } 00320 } 00321 00322 } else { // BETA 00323 Iterator itCCM = constCompModes.iterator(); 00324 while (itCCM.hasNext()) { 00325 Mode m = (Mode)itCCM.next(); 00326 if ((m.getType() != Mode.MODE_DF) || (ma.getMode(m.getComponent()) == m)) { 00327 System.out.println("ERROR: DENode.invariant() failed: " + 5); 00328 return false; 00329 } 00330 } 00331 } 00332 } 00333 00334 // minNumIF must be less or equal to numIF 00335 00336 if ((numIF > 0) && (minNumIF > numIF)) { 00337 System.out.println("ERROR: DENode.invariant() failed: " + 6); 00338 return false; 00339 } 00340 00341 // for all children: child.minNumIF >= this.minNumIF 00342 00343 Iterator itChildren = getChildrenIterator(); 00344 while (itChildren.hasNext()) { 00345 DENode child = (DENode)itChildren.next(); 00346 if ((minNumIF > 0) && (child.minNumIF > 0) && (child.minNumIF < this.minNumIF)) { 00347 System.out.println("ERROR: DENode.invariant() failed: " + 7); 00348 return false; 00349 } 00350 } 00351 00352 // children must have the same root node as this node 00353 00354 if (rootNode == null) { 00355 System.out.println("ERROR: DENode.invariant() failed: " + 8); 00356 return false; 00357 } 00358 itChildren = getChildrenIterator(); 00359 while (itChildren.hasNext()) { 00360 DENode child = (DENode)itChildren.next(); 00361 if ((child.getRootNode() == null) || (child.getRootNode() != rootNode)) { 00362 System.out.println("ERROR: DENode.invariant() failed: " + 9); 00363 return false; 00364 } 00365 } 00366 00367 // this is a root node <=> no parents 00368 00369 if ((rootNode != this) && (parents.size() == 0) 00370 || (rootNode == this) && (parents.size() != 0)) { 00371 00372 System.out.println("ERROR: DENode.invariant() failed: " + 10); 00373 return false; 00374 } 00375 00376 // #parents <= 1 00377 00378 if (parents.size() > 1) { 00379 System.out.println("ERROR: DENode.invariant() failed: " + 11); 00380 return false; 00381 } 00382 00383 // if marked as "desc. inconsistent": the same must hold for children 00384 // furthermore: must be marked as inconsistent 00385 if (descInconsistent) { 00386 if (consistent == STATUS_TRUE) { 00387 System.out.println("ERROR: DENode.invariant() failed: " + 12); 00388 return false; 00389 } 00390 itChildren = getChildrenIterator(); 00391 while (itChildren.hasNext()) { 00392 DENode child = (DENode)itChildren.next(); 00393 if (!child.descInconsistent) { 00394 System.out.println("ERROR: DENode.invariant() failed: " + 13); 00395 return false; 00396 } 00397 } 00398 } 00399 00400 // if expanded == false: must not have children 00401 if (!expandedAlpha && !expandedBeta && hasChildren()) { 00402 System.out.println("ERROR: DENode.invariant() failed: " + 15); 00403 return false; 00404 } 00405 00406 // if minimal: must be consistent 00407 if ((minimal == STATUS_TRUE) && (consistent != STATUS_TRUE)) { 00408 System.out.println("ERROR: DENode.invariant() failed: " + 16); 00409 return false; 00410 } 00411 00412 // if impliedByRC: the consistency of this node is not checked 00413 /*if (impliedByRC && (consistent != STATUS_UNKNOWN)) { 00414 System.out.println("ERROR: DENode.invariant() failed: " + 17); 00415 return false; 00416 }*/ 00417 00418 return true; 00419 00420 } // invariant 00421 00422 }