001// ***** This file is automatically generated from SubSequence.java.jpp 002 003package daikon.inv.binary.twoSequence; 004 005import daikon.*; 006import daikon.derive.*; 007import daikon.derive.binary.*; 008import daikon.derive.ternary.*; 009import daikon.inv.*; 010import daikon.inv.unary.sequence.*; 011import daikon.suppress.*; 012import java.util.*; 013import java.util.logging.Level; 014import java.util.logging.Logger; 015import org.checkerframework.checker.lock.qual.GuardSatisfied; 016import org.checkerframework.checker.nullness.qual.NonNull; 017import org.checkerframework.checker.nullness.qual.Nullable; 018import org.checkerframework.dataflow.qual.Pure; 019import org.checkerframework.dataflow.qual.SideEffectFree; 020import org.plumelib.util.ArraysPlume; 021import org.plumelib.util.IPair; 022import org.plumelib.util.UtilPlume; 023import typequals.prototype.qual.NonPrototype; 024import typequals.prototype.qual.Prototype; 025 026/** 027 * Represents two sequences of double values where one sequence is a subsequence of the 028 * other. Prints as {@code x[] is a subsequence of y[]}. 029 */ 030 031public class SubSequenceFloat extends TwoSequenceFloat { 032 // We are Serializable, so we specify a version to allow changes to 033 // method signatures without breaking serialization. If you add or 034 // remove fields, you should change this number to the current date. 035 static final long serialVersionUID = 20031024L; 036 037 private static final Logger debug = 038 Logger.getLogger("daikon.inv.binary.twoSequence.SubSequenceFloat"); 039 040 // Variables starting with dkconfig_ should only be set via the 041 // daikon.config.Configuration interface. 042 /** Boolean. True iff SubSequence invariants should be considered. */ 043 public static boolean dkconfig_enabled = false; 044 045 protected SubSequenceFloat(PptSlice ppt) { 046 super(ppt); 047 } 048 049 protected @Prototype SubSequenceFloat() { 050 super(); 051 } 052 053 private static @Prototype SubSequenceFloat proto = new @Prototype SubSequenceFloat(); 054 055 /** Returns the prototype invariant for SubSequenceFloat */ 056 public static @Prototype SubSequenceFloat get_proto() { 057 return proto; 058 } 059 060 /** returns whether or not this invariant is enabled */ 061 @Override 062 public boolean enabled() { 063 return dkconfig_enabled; 064 } 065 066 /** instantiates the invariant on the specified slice */ 067 @Override 068 protected SubSequenceFloat instantiate_dyn(@Prototype SubSequenceFloat this, PptSlice slice) { 069 return new SubSequenceFloat(slice); 070 } 071 072 @Override 073 protected Invariant resurrect_done_swapped() { 074 return new SuperSequenceFloat(ppt); 075 } 076 077 @SideEffectFree 078 @Override 079 public String format_using(@GuardSatisfied SubSequenceFloat this, OutputFormat format) { 080 if (format == OutputFormat.DAIKON) { 081 return format_daikon(); 082 } 083 if (format == OutputFormat.SIMPLIFY) { 084 return format_simplify(); 085 } 086 if (format == OutputFormat.CSHARPCONTRACT) { 087 return format_csharp_contract(); 088 } 089 if (format.isJavaFamily()) { 090 return format_unimplemented(format); 091 } 092 093 return format_unimplemented(format); 094 } 095 096 public String format_daikon(@GuardSatisfied SubSequenceFloat this) { 097 String v1 = var1().name(); 098 String v2 = var2().name(); 099 return v1 + " is a subsequence of " + v2; 100 } 101 102 public String format_csharp_contract(@GuardSatisfied SubSequenceFloat this) { 103 String v1 = var1().csharp_collection_string(); 104 String v2 = var2().csharp_collection_string(); 105 return v1 + ".IsSubsequence(" + v2 + ")"; 106 } 107 108 public String format_simplify(@GuardSatisfied SubSequenceFloat this) { 109 if (Invariant.dkconfig_simplify_define_predicates) { 110 return format_simplify_defined(); 111 } else { 112 return format_simplify_explicit(); 113 } 114 } 115 116 private String format_simplify_defined(@GuardSatisfied SubSequenceFloat this) { 117 String[] sub_name = var1().simplifyNameAndBounds(); 118 String[] super_name = var2().simplifyNameAndBounds(); 119 120 if (sub_name == null || super_name == null) { 121 return String.format("%s.format_simplify_defined(%s): sub_name=%s, super_name=%s, for %s", 122 getClass().getSimpleName(), this, 123 Arrays.toString(sub_name), Arrays.toString(super_name), format()); 124 } 125 126 return "(subsequence " 127 + sub_name[0] + " " + sub_name[1] + " " + sub_name[2] + " " 128 + super_name[0] + " " + super_name[1] + " " + super_name[2] + ")"; 129 } 130 131 // This is apparently broken somehow, though from the logs it's not 132 // clear how. -- smcc 133 private String format_simplify_explicit(@GuardSatisfied SubSequenceFloat this) { 134 return "format_simplify disabled"; 135 136 /* Since this doesn't work (since at least april 2003) 137 and it uses quant in complex ways, 138 its just commented out (jhp 8/3/2006) 139 140 // (exists k s.t. (forall i, j; (i bounds & j bounds & (i = j + k)) ==> ...)) 141 142 QuantifyReturn qret = QuantHelper.quantify(new VarInfoName[] 143 { var1().name, var2().name} ); 144 assert qret.bound_vars.size() == 2; 145 assert qret.root_primes.length == 2; 146 147 // These variables are, in order: Example element, free Index 148 // variable, Lower bound, Upper bound, Span 149 String aE, aI, aL, aH, aS; // a = subsequence 150 String bE, bI, bL, bH, bS; // b = supersequence 151 { 152 VarInfoName[] boundv; 153 154 boundv = qret.bound_vars.get(0); 155 aE = qret.root_primes[0].simplify_name(); 156 aI = boundv[0].simplify_name(); 157 aL = boundv[1].simplify_name(); 158 aH = boundv[2].simplify_name(); 159 aS = "(+ (- " + aH + " " + aL + ") 1)"; 160 161 boundv = qret.bound_vars.get(1); 162 bE = qret.root_primes[1].simplify_name(); 163 bI = boundv[0].simplify_name(); 164 bL = boundv[1].simplify_name(); 165 bH = boundv[2].simplify_name(); 166 bS = "(+ (- " + bH + " " + bL + ") 1)"; 167 } 168 169 // This invariant would not have been given data if a value was 170 // missing - for example, if a slice had a negative length. We 171 // must predicate this invariant on the values being sensible. 172 173 String sensible = "(AND (>= " + aS + " 0) (>= " + bS + " 0))"; 174 175 // This invariant would have been falsified if the subsequence A 176 // length was ever zero. Also, this invariant would have been 177 // falsified if the subsequence A was ever longer than the 178 // supersequence B. 179 180 String length_stmt = "(AND (NEQ " + aS + " 0) (>= " + bS + " " + aS + "))"; 181 182 // Subsequence means that there exists an offset in supersequence 183 // B, where (1) the offset is non-negative, (2) the offset doesn't 184 // cause the matching to push past the end of B, and (3) for all 185 // indices less than the span of subsequence A, (4) the elements 186 // starting from A_low and B_low+offset are equal. 187 188 String index = "|__index|"; 189 String shift = "|__shift|"; 190 String subseq_stmt = 191 "(EXISTS (" + shift + ") (AND " 192 + "(<= 0 " + shift + ") " // 1 193 + "(<= (+ " + shift + " " + aS + ") " + bS + ") " // 2 194 + "(FORALL (" + index + ") (IMPLIES (AND (<= 0 " + index + ") (< " + index + " " + aS + ")) " // 3 195 + "(EQ " 196 + aE.replace(aI, "(+ " + aL + " " + index + ")") + " " 197 + bE.replace(bI, "(+ (+ " + bL + " " + index + ") " + shift + ")") + ")))))"; 198 199 // So, when this in sensible, we know that both the length and 200 // subseq statements hold. 201 202 String result = "(IMPLIES " + sensible + " (AND " + length_stmt + " " + subseq_stmt + "))"; 203 return result; 204 */ 205 } 206 207 @Override 208 public InvariantStatus check_modified(double[] a1, double[] a2, 209 int count) { 210 if ((a1 == null) || (a2 == null)) { 211 return InvariantStatus.FALSIFIED; 212 } 213 214 int result = Global.fuzzy.indexOf(a2, a1); 215 216 if (result == -1) { 217 return InvariantStatus.FALSIFIED; 218 } else { 219 return InvariantStatus.NO_CHANGE; 220 } 221 } 222 223 @Override 224 public InvariantStatus add_modified(double[] a1, double[] a2, 225 int count) { 226 InvariantStatus is = check_modified(a1, a2, count); 227 if ((is == InvariantStatus.FALSIFIED) && Debug.logOn()) { 228 log("%s destroyed by %s %s", 229 format(), Debug.toString(a1), 230 Debug.toString(a2)); 231 } 232 return is; 233 } 234 235 @Override 236 protected double computeConfidence() { 237 return Invariant.CONFIDENCE_JUSTIFIED; 238 } 239 240 /** Returns a DiscardInfo, or null if the Invariant is not an obvious subsequence. 241@return a DiscardInfo, or null if the Invariant is not an obvious subsequence */ 242 @Pure 243 public static @Nullable DiscardInfo isObviousSubSequence(Invariant inv, VarInfo subvar, VarInfo supervar) { 244 IPair<DiscardCode,String> pcds = isObviousSubSequence(subvar, supervar); 245 if (pcds == null) { 246 return null; 247 } else { 248 return new DiscardInfo(inv, pcds.first, pcds.second); 249 } 250 } 251 252 /** 253 * Returns a IPair of a DiscardCode and a discardReason string, or null if the Invariant is not an 254 * obvious subsequence. 255 * @return a IPair of a DiscardCode and a discardReason string, or null if the Invariant is not an 256 * obvious subsequence 257 */ 258 @Pure 259 public static @Nullable IPair<DiscardCode,String> isObviousSubSequence(VarInfo subvar, VarInfo supervar) { 260 // Must typecheck since this could be called with non-sequence variables in 261 // some methods. 262 ProglangType rep1 = subvar.rep_type; 263 ProglangType rep2 = supervar.rep_type; 264 if (!(((rep1 == ProglangType.INT_ARRAY) 265 && (rep2 == ProglangType.INT_ARRAY)) 266 || ((rep1 == ProglangType.DOUBLE_ARRAY) 267 && (rep2 == ProglangType.DOUBLE_ARRAY)) 268 || ((rep1 == ProglangType.STRING_ARRAY) 269 && (rep2 == ProglangType.STRING_ARRAY)) 270 )) { 271 return null; 272 } 273 274 if (debug.isLoggable(Level.FINE)) { 275 debug.fine("isObviousSubSequence " 276 + subvar.name() + " in " + supervar.name()); 277 } 278 279 // Standard discard reason/string 280 DiscardCode discardCode = DiscardCode.obvious; 281 String discardString = subvar.name()+" obvious subset/subsequence of "+supervar.name(); 282 283 // For unions and intersections, it probably doesn't make sense to 284 // do subsequence or subset detection. This is mainly to prevent 285 // invariants of the form (x subset of union(x, y)) but this means 286 // we also miss those of the form (z subset of union(x,y)) which 287 // might be useful. Subsequence, however, seems totally useless 288 // on unions and intersections. 289 if (supervar.derived instanceof SequenceFloatIntersection 290 || supervar.derived instanceof SequenceFloatUnion 291 || subvar.derived instanceof SequenceFloatIntersection 292 || subvar.derived instanceof SequenceFloatUnion) { 293 discardCode = DiscardCode.obvious; 294 discardString = "Invariants involving subsets/subsequences of unions/intersections are suppressed"; 295 debug.fine(" returning true because of union or intersection"); 296 return IPair.<DiscardCode,String>of(discardCode, discardString); 297 } 298 299 if (subvar.derived instanceof SequencesPredicateFloat) { 300 // It's not useful that predicate(x[], b[]) is a subsequence or subset 301 // of x[] 302 SequencesPredicateFloat derived = (SequencesPredicateFloat) subvar.derived; 303 if (derived.var1().equals(supervar)) { 304 discardCode = DiscardCode.obvious; 305 discardString = subvar.name()+" is derived from "+supervar.name(); 306 debug.fine(" returning true because of predicate slicing"); 307 return IPair.of(discardCode, discardString + " [pred slicing]"); 308 } 309 } 310 311 VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); 312 if (subvar_super == null) { 313 // If it's not a union, intersection or a subsequence, it's not obvious 314 debug.fine(" returning false because subvar_super == null"); 315 return null; 316 } 317 318 if (subvar_super == supervar) { 319 // System.out.println("SubSequence.isObviousDerived(" + subvar.name() + ", " + supervar.name + ") = true"); 320 // System.out.println(" details: subvar_super=" + subvar_super.name + "; supervar_super=" + supervar.isDerivedSubSequenceOf() == null ? "null" : supervar.isDerivedSubSequenceOf().name); 321 discardCode = DiscardCode.obvious; 322 discardString = subvar.name()+"=="+supervar.name(); 323 debug.fine(" returning true because subvar_super == supervar"); 324 return IPair.of(discardCode, 325 discardString + " [subvar_super == supervar]"); 326 } 327 328 // a[i+a..j+b] cmp a[i+c..j+d] 329 VarInfo supervar_super = supervar.isDerivedSubSequenceOf(); 330 // we know subvar_super != null due to check above 331 if (subvar_super == supervar_super) { 332 // both sequences are derived from the same supersequence 333 if ((subvar.derived instanceof SequenceFloatSubsequence 334 || subvar.derived instanceof SequenceFloatArbitrarySubsequence) 335 && (supervar.derived instanceof SequenceFloatSubsequence 336 || supervar.derived instanceof SequenceFloatArbitrarySubsequence)) { 337 // In "A[i..j] subseq B[k..l]": i=sub_left_var, j=sub_right_var, 338 // k=super_left_var, l=super_right_var. 339 VarInfo sub_left_var = null, sub_right_var = null, 340 super_left_var = null, super_right_var = null; 341 // I'm careful not to access foo_shift unless foo_var has been set 342 // to a non-null value, but Java is too stupid to recognize that. 343 int sub_left_shift = 42, sub_right_shift = 69, super_left_shift = 1492, 344 super_right_shift = 1776; 345 if (subvar.derived instanceof SequenceFloatSubsequence) { 346 SequenceFloatSubsequence sub = (SequenceFloatSubsequence)subvar.derived; 347 if (sub.from_start) { 348 sub_right_var = sub.sclvar(); 349 sub_right_shift = sub.index_shift; 350 } else { 351 sub_left_var = sub.sclvar(); 352 sub_left_shift = sub.index_shift; 353 } 354 } else if (subvar.derived instanceof SequenceFloatArbitrarySubsequence) { 355 SequenceFloatArbitrarySubsequence sub = (SequenceFloatArbitrarySubsequence)subvar.derived; 356 sub_left_var = sub.startvar(); 357 sub_left_shift = (sub.left_closed ? 0 : 1); 358 sub_right_var = sub.endvar(); 359 sub_right_shift = (sub.right_closed ? 0 : -1); 360 } else { 361 throw new Error(); 362 } 363 if (supervar.derived instanceof SequenceFloatSubsequence) { 364 SequenceFloatSubsequence super_ = (SequenceFloatSubsequence)supervar.derived; 365 if (super_.from_start) { 366 super_right_var = super_.sclvar(); 367 super_right_shift = super_.index_shift; 368 } else { 369 super_left_var = super_.sclvar(); 370 super_left_shift = super_.index_shift; 371 } 372 } else if (supervar.derived instanceof SequenceFloatArbitrarySubsequence) { 373 SequenceFloatArbitrarySubsequence super_ = (SequenceFloatArbitrarySubsequence)supervar.derived; 374 super_left_var = super_.startvar(); 375 super_left_shift = (super_.left_closed ? 0 : 1); 376 super_right_var = super_.endvar(); 377 super_right_shift = (super_.right_closed ? 0 : -1); 378 } else { 379 throw new Error(); 380 } 381 boolean left_included = false, right_included = false; 382 if (super_left_var == null) { 383 left_included = true; 384 } 385 if (super_left_var == sub_left_var) { 386 if (super_left_shift < sub_left_shift) left_included = true; 387 } 388 if (super_right_var == null) { 389 right_included = true; 390 } 391 if (super_right_var == sub_right_var) { 392 if (super_right_shift > sub_right_shift) right_included = true; 393 } 394 if (left_included && right_included) { 395 discardCode = DiscardCode.obvious; 396 discardString = subvar.name()+" obvious subset/subsequence of "+supervar.name(); 397 return IPair.of(discardCode, discardString + " [obvious]") 398; 399 } 400 } else if ((subvar.derived instanceof SequenceStringSubsequence) 401 && (supervar.derived instanceof SequenceStringSubsequence)) { 402 // Copied from (an old version) just above 403 // XXX I think this code is dead; why isn't it just produced 404 // from the above by macro expansion? -smcc 405 SequenceStringSubsequence sss1 = (SequenceStringSubsequence) subvar.derived; 406 SequenceStringSubsequence sss2 = (SequenceStringSubsequence) supervar.derived; 407 VarInfo index1 = sss1.sclvar(); 408 int shift1 = sss1.index_shift; 409 boolean start1 = sss1.from_start; 410 VarInfo index2 = sss2.sclvar(); 411 int shift2 = sss2.index_shift; 412 boolean start2 = sss2.from_start; 413 if (index1 == index2) { 414 if (start1 == true && start2 == true) { 415 if (shift1 <= shift2) { 416 return IPair.of(discardCode, discardString + " [shift1]"); 417 } 418 } else if (start1 == false && start2 == false) { 419 if (shift1 >= shift2) { 420 return IPair.of(discardCode, discardString + " [shift2]"); 421 } 422 } 423 } 424 } else { 425 throw new Error("how can this happen? " + subvar.name() 426 + " " + (subvar.derived == null 427 ? "(not derived)" 428 : subvar.derived.getClass()) 429 + " " + supervar.name() 430 + " " + (supervar.derived == null 431 ? "(not derived)" 432 : supervar.derived.getClass())); 433 } 434 } 435 436 return null; 437 } 438 439 // Look up a previously instantiated SubSequence relationship. 440 public static @Nullable SubSequenceFloat find(PptSlice ppt) { 441 assert ppt.arity() == 2; 442 for (Invariant inv : ppt.invs) { 443 if (inv instanceof SubSequenceFloat) { 444 return (SubSequenceFloat) inv; 445 } 446 } 447 return null; 448 } 449 450 @Pure 451 @Override 452 public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) { 453 454 VarInfo subvar = var1(vis); 455 VarInfo supervar = var2(vis); 456 457 // check for x[i..j] subsequence of x[] 458 VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); 459 if (subvar_super == supervar) { 460 debug.fine(" returning true because subvar_super == supervar"); 461 return new DiscardInfo(this, DiscardCode.obvious, 462 "x[i..j] subsequence of x[] is obvious"); 463 } 464 465 DiscardInfo di = SubSequenceFloat.isObviousSubSequence(this, subvar, supervar); 466 if (di != null) { 467 return di; 468 } 469 470 // JHP: This is not a valid obvious check, since it doesn't imply that 471 // the invariant is true. 472 if (!subvar.aux.hasOrder() 473 || !supervar.aux.hasOrder()) { 474 // Doesn't make sense to consider subsequence if order doens't matter 475 return new DiscardInfo(this, DiscardCode.obvious, 476 "Order doesn't matter, so subsequence is meaningless"); 477 } 478 479 return super.isObviousStatically(vis); 480 } 481 482 // Two ways to go about this: 483 // * look at all subseq relationships, see if one is over a variable of 484 // interest 485 // * look at all variables derived from the 486 487 // (Seems overkill to check for other transitive relationships. 488 // Eventually that is probably the right thing, however.) 489 @Pure 490 @Override 491 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 492 493 // System.out.println("checking isObviousImplied for: " + format()); 494 if (debug.isLoggable(Level.FINE)) { 495 debug.fine("isObviousDynamically: checking " + vis[0].name() + " in " + vis[1].name()); 496 } 497 498 DiscardInfo super_result = super.isObviousDynamically(vis); 499 if (super_result != null) { 500 return super_result; 501 } 502 503 VarInfo subvar = var1(vis); 504 VarInfo supervar = var2(vis); 505 506 // JHP: The next check is an un-interesting check, not 507 // an obvious check. We need to figure out how to resolve this. 508 509 // Uninteresting if this is of the form x[0..i] subsequence 510 // x[0..j]. Not necessarily obvious. 511 VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); 512 VarInfo supervar_super = supervar.isDerivedSubSequenceOf(); 513 if (subvar_super != null && subvar_super == supervar_super) { 514 debug.fine(" returning true because subvar_super == supervar_super"); 515 return new DiscardInfo(this, DiscardCode.obvious, 516 "x[0..i] subsequence of x[0..j] is uninteresting"); 517 } 518 519 if (isObviousSubSequenceDynamically(this, subvar, supervar)) { 520 return new DiscardInfo(this, DiscardCode.obvious, subvar.name() 521 + " is an obvious subsequence of " 522 + supervar.name()); 523 } 524 return null; 525 } 526 527 /** 528 * Returns true if the two original variables are related in a way that makes subsequence or 529 * subset detection not informative. 530 */ 531 public static boolean isObviousSubSequenceDynamically(Invariant inv, 532 VarInfo subvar, VarInfo supervar) { 533 534 VarInfo [] vis = {subvar, supervar}; 535 536 ProglangType rep1 = subvar.rep_type; 537 ProglangType rep2 = supervar.rep_type; 538 if (!(((rep1 == ProglangType.INT_ARRAY) 539 && (rep2 == ProglangType.INT_ARRAY)) 540 || ((rep1 == ProglangType.DOUBLE_ARRAY) 541 && (rep2 == ProglangType.DOUBLE_ARRAY)) 542 || ((rep1 == ProglangType.STRING_ARRAY) 543 && (rep2 == ProglangType.STRING_ARRAY)) 544 )) { 545 return false; 546 } 547 548 if (debug.isLoggable(Level.FINE)) { 549 debug.fine("Checking isObviousSubSequenceDynamically " 550 + subvar.name() + " in " + supervar.name()); 551 } 552 553 DiscardInfo di = isObviousSubSequence(inv, subvar, supervar); 554 if (di != null) { 555 inv.log("ObvSubSeq- true from isObviousSubSequence: %s", di.discardString()); 556 return true; 557 } 558 debug.fine(" not isObviousSubSequence(statically)"); 559 560 PptTopLevel ppt_parent = subvar.ppt; 561 562 // If the elements of supervar are always the same (EltOneOf), 563 // we aren't going to learn anything new from this invariant, 564 // since each sequence should have an EltOneOf over it. 565 if (false) { 566 PptSlice1 slice = ppt_parent.findSlice(supervar); 567 if (slice == null) { 568 System.out.println("No slice: parent =" + ppt_parent); 569 } else { 570 System.out.println("Slice var =" + slice.var_infos[0]); 571 for (Invariant superinv : slice.invs) { 572 System.out.println("Inv = " + superinv); 573 if (superinv instanceof EltOneOfFloat) { 574 EltOneOfFloat eltinv = (EltOneOfFloat) superinv; 575 if (eltinv.num_elts() > 0) { 576 inv.log(" obvious because of %s", eltinv.format()); 577 return true; 578 } 579 } 580 } 581 } 582 } 583 584 // Obvious if subvar is always just [] 585 if (true) { 586 PptSlice1 slice = ppt_parent.findSlice(subvar); 587 if (slice != null) { 588 for (Invariant subinv : slice.invs) { 589 if (subinv instanceof OneOfFloatSequence) { 590 OneOfFloatSequence seqinv = (OneOfFloatSequence) subinv; 591 if (seqinv.num_elts() == 1) { 592 Object elt = seqinv.elt(); 593 if (elt instanceof long[] && ((long[]) elt).length == 0) { 594 Debug.log(debug, inv.getClass(), inv.ppt, vis, 595 "ObvSubSeq- True from subvar being []"); 596 return true; 597 } 598 if (elt instanceof double[] && ((double[]) elt).length == 0) { 599 inv.log("ObvSubSeq- True from subvar being []"); 600 return true; 601 } 602 } 603 } 604 } 605 } 606 } 607 608 // Check for a[0..i] subseq a[0..j] but i < j. 609 VarInfo subvar_super = subvar.isDerivedSubSequenceOf(); 610 VarInfo supervar_super = supervar.isDerivedSubSequenceOf(); 611 612 if (subvar_super != null && subvar_super == supervar_super) { 613 // both sequences are derived from the same supersequence 614 if ((subvar.derived instanceof SequenceFloatSubsequence 615 || subvar.derived instanceof SequenceFloatArbitrarySubsequence) 616 && (supervar.derived instanceof SequenceFloatSubsequence 617 || supervar.derived instanceof SequenceFloatArbitrarySubsequence)) { 618 VarInfo sub_left_var = null, sub_right_var = null, 619 super_left_var = null, super_right_var = null; 620 // I'm careful not to access foo_shift unless foo_var has been set 621 // to a non-null value, but Java is too stupid to recognize that. 622 int sub_left_shift = 42, sub_right_shift = 69, super_left_shift = 1492, 623 super_right_shift = 1776; 624 if (subvar.derived instanceof SequenceFloatSubsequence) { 625 SequenceFloatSubsequence sub = (SequenceFloatSubsequence)subvar.derived; 626 if (sub.from_start) { 627 sub_right_var = sub.sclvar(); 628 sub_right_shift = sub.index_shift; 629 } else { 630 sub_left_var = sub.sclvar(); 631 sub_left_shift = sub.index_shift; 632 } 633 } else if (subvar.derived instanceof SequenceFloatArbitrarySubsequence) { 634 SequenceFloatArbitrarySubsequence sub = (SequenceFloatArbitrarySubsequence)subvar.derived; 635 sub_left_var = sub.startvar(); 636 sub_left_shift = (sub.left_closed ? 0 : 1); 637 sub_right_var = sub.endvar(); 638 sub_right_shift = (sub.right_closed ? 0 : -1); 639 } else { 640 throw new Error(); 641 } 642 if (supervar.derived instanceof SequenceFloatSubsequence) { 643 SequenceFloatSubsequence super_ = (SequenceFloatSubsequence)supervar.derived; 644 if (super_.from_start) { 645 super_right_var = super_.sclvar(); 646 super_right_shift = super_.index_shift; 647 } else { 648 super_left_var = super_.sclvar(); 649 super_left_shift = super_.index_shift; 650 } 651 } else if (supervar.derived instanceof SequenceFloatArbitrarySubsequence) { 652 SequenceFloatArbitrarySubsequence super_ = (SequenceFloatArbitrarySubsequence)supervar.derived; 653 super_left_var = super_.startvar(); 654 super_left_shift = (super_.left_closed ? 0 : 1); 655 super_right_var = super_.endvar(); 656 super_right_shift = (super_.right_closed ? 0 : -1); 657 } else { 658 throw new Error(); 659 } 660 boolean left_included, right_included; 661 if (super_left_var == null) { 662 left_included = true; 663 } else if (sub_left_var == null) // we know super_left_var != null here 664 left_included = false; 665 else { 666 left_included = 667 VarInfo.compare_vars(super_left_var, super_left_shift, 668 sub_left_var, sub_left_shift, 669 true /* <= */); 670 } 671 if (super_right_var == null) { 672 right_included = true; 673 } else if (sub_right_var == null) // we know super_right_var != null here 674 right_included = false; 675 else { 676 right_included = 677 VarInfo.compare_vars(super_right_var, super_right_shift, 678 sub_right_var, sub_right_shift, 679 false /* >= */); 680 } 681// System.out.println("Is " + subvar.name() + " contained in " 682// + supervar.name() 683// + "? left: " + left_included + ", right: " 684// + right_included); 685 if (left_included && right_included) { 686 inv.log("ObvSubSeq- True a[0..i] subseq a[0..j] and i < j"); 687 return true; 688 } 689 } else if ((subvar.derived instanceof SequenceStringSubsequence) 690 && (supervar.derived instanceof SequenceStringSubsequence)) { 691 // Copied from just above 692 SequenceStringSubsequence sss1 = (SequenceStringSubsequence) subvar.derived; 693 SequenceStringSubsequence sss2 = (SequenceStringSubsequence) supervar.derived; 694 VarInfo index1 = sss1.sclvar(); 695 int shift1 = sss1.index_shift; 696 boolean start1 = sss1.from_start; 697 VarInfo index2 = sss2.sclvar(); 698 int shift2 = sss2.index_shift; 699 boolean start2 = sss2.from_start; 700 if (start1 == start2) { 701 if (VarInfo.compare_vars(index1, shift1, index2, shift2, start1)) { 702 inv.log("True from comparing indices"); 703 return true; 704 } 705 } 706 } else { 707 throw new Error("how can this happen? " + subvar.name() 708 + " " + (subvar.derived == null 709 ? "(not derived)" 710 : subvar.derived.getClass()) 711 + " " + supervar.name() 712 + " " + (supervar.derived == null 713 ? "(not derived)" 714 : supervar.derived.getClass())); 715 } 716 717 } 718 719 // Also need to check A[0..i] subseq A[0..j] via compare_vars. 720 721 // A subseq B[0..n] => A subseq B 722 723 List<Derivation> derivees = supervar.derivees(); 724 // For each variable derived from supervar ("B") 725 for (Derivation der : derivees) { 726 // System.out.println(" ... der = " + der.getVarInfo().name() + " " + der); 727 if (der instanceof SequenceFloatSubsequence) { 728 // If that variable is "B[0..n]" 729 VarInfo supervar_part = der.getVarInfo(); 730 // Get the canonical version; being equal to it is good enough. 731 if (supervar_part.get_equalitySet_leader() == subvar) { 732 Debug.log(debug, inv.getClass(), inv.ppt, vis, 733 "ObvSubSeq- True from canonical leader"); 734 return true; 735 } 736 737 if (supervar_part.isCanonical()) { 738 if (subvar == supervar_part) { 739 System.err.println("Error: variables " 740 + subvar.name() 741 + " and " 742 + supervar_part.name() 743 + " are identical. Canonical"); 744 System.err.println(subvar.isCanonical()); 745 System.err.println(supervar_part.isCanonical()); 746 throw new Error(); 747 } 748 749 // Check to see if there is a subsequence over the supervar 750 if (ppt_parent.is_subsequence(subvar, supervar_part)) { 751 if (Debug.logOn()) { 752 inv.log("ObvSubSeq- true from A subseq B[0..n] %s/%s", 753 subvar.name(), supervar_part.name()); 754 } 755 return true; 756 } 757 } 758 } 759 } 760 return false; 761 } 762 763 @Pure 764 @Override 765 public boolean isSameFormula(Invariant inv) { 766 assert inv instanceof SubSequenceFloat; 767 return true; 768 } 769 770 /** returns the ni-suppressions for SubSequence */ 771 @Pure 772 @Override 773 public NISuppressionSet get_ni_suppressions() { 774 return suppressions; 775 } 776 777 /** definition of this invariant (the suppressee) */ 778 private static NISuppressee suppressee = new NISuppressee(SubSequenceFloat.class, 2); 779 780 // suppressor definitions (used in suppressions below) 781 private static NISuppressor v1_eq_v2 = new NISuppressor(0, 1, SeqSeqFloatEqual.class); 782 private static NISuppressor v1_pw_eq_v2 = new NISuppressor(0, 1, PairwiseFloatEqual.class); 783 784 // sub/super sequence suppressions. We have both SeqSeq and Pairwise 785 // as suppressions because each can be enabled separately. 786 private static NISuppressionSet suppressions = 787 new NISuppressionSet( 788 new NISuppression[] { 789 // a[] == b[] ==> a[] sub/superset b[] 790 new NISuppression(v1_eq_v2, suppressee), 791 // a[] == b[] ==> a[] sub/superset b[] 792 new NISuppression(v1_pw_eq_v2, suppressee), 793 }); 794 795}