001// ***** This file is automatically generated from SeqComparison.java.jpp 002 003package daikon.inv.binary.twoSequence; 004 005import daikon.*; 006import daikon.Quantify.QuantFlags; 007import daikon.derive.binary.*; 008import daikon.inv.*; 009import daikon.suppress.*; 010import java.util.*; 011import java.util.logging.Logger; 012import org.checkerframework.checker.interning.qual.Interned; 013import org.checkerframework.checker.lock.qual.GuardSatisfied; 014import org.checkerframework.checker.nullness.qual.Nullable; 015import org.checkerframework.dataflow.qual.Pure; 016import org.checkerframework.dataflow.qual.SideEffectFree; 017import org.plumelib.util.ArraysPlume; 018import org.plumelib.util.Intern; 019import typequals.prototype.qual.NonPrototype; 020import typequals.prototype.qual.Prototype; 021 022/** 023 * Represents invariants between two sequences of double values. If order matters for each 024 * variable (which it does by default), then the sequences are compared lexically. Prints as 025 * {@code x[] <= y[] lexically}. 026 * 027 028 * <p>If the auxiliary information (e.g., order matters) doesn't match between two variables, then 029 * this invariant cannot apply to those variables. 030 */ 031public class SeqSeqFloatLessEqual extends TwoSequenceFloat 032 033{ 034 // We are Serializable, so we specify a version to allow changes to 035 // method signatures without breaking serialization. If you add or 036 // remove fields, you should change this number to the current date. 037 static final long serialVersionUID = 20030822L; 038 039 // Variables starting with dkconfig_ should only be set via the 040 // daikon.config.Configuration interface. 041 /** Boolean. True iff SeqSeqFloatLessEqual invariants should be considered. */ 042 public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault; 043 044 /** Debugging logger. */ 045 static final Logger debug = Logger.getLogger("daikon.inv.binary.twoSequence.SeqSeqFloatLessEqual"); 046 047 static Comparator<double[]> comparator = Global.fuzzy.new DoubleArrayComparatorLexical(); 048 049 boolean orderMatters; 050 051 protected SeqSeqFloatLessEqual(PptSlice ppt, boolean order) { 052 super(ppt); 053 orderMatters = order; 054 } 055 056 protected @Prototype SeqSeqFloatLessEqual(boolean order) { 057 super(); 058 orderMatters = order; 059 } 060 061 protected SeqSeqFloatLessEqual(SeqSeqFloatGreaterEqual seq_swap) { 062 super(seq_swap.ppt); 063 orderMatters = seq_swap.orderMatters; 064 } 065 066 private static @Prototype SeqSeqFloatLessEqual proto = new @Prototype SeqSeqFloatLessEqual(true); 067 068 /** Returns the prototype invariant for SeqSeqFloatLessEqual */ 069 public static @Prototype SeqSeqFloatLessEqual get_proto() { 070 return proto; 071 } 072 073 /** Returns whether or not this invariant is enabled. */ 074 @Override 075 public boolean enabled() { 076 return dkconfig_enabled; 077 } 078 079 /** Non-Equal SeqComparison is only valid on integral types. */ 080 @Override 081 public boolean instantiate_ok(VarInfo[] vis) { 082 083 if (!valid_types(vis)) { 084 return false; 085 } 086 087 VarInfo var1 = vis[0]; 088 VarInfo var2 = vis[1]; 089 ProglangType type1 = var1.type; 090 ProglangType type2 = var2.type; 091 092 // This intentonally checks dimensions(), not pseudoDimensions. 093 boolean only_eq = 094 !((type1.dimensions() == 1) 095 && type1.baseIsFloat() 096 && (type2.dimensions() == 1) 097 && type2.baseIsFloat()); 098 if (only_eq) { 099 return false; 100 } 101 102 // non equality comparisons don't make sense if the arrays aren't ordered 103 if (!var1.aux.hasOrder() || !var2.aux.hasOrder()) { 104 return false; 105 } 106 107 return true; 108 } 109 110 /** Instantiates the invariant on the specified slice. */ 111 @Override 112 protected SeqSeqFloatLessEqual instantiate_dyn(@Prototype SeqSeqFloatLessEqual this, PptSlice slice) { 113 boolean has_order = slice.var_infos[0].aux.hasOrder() && slice.var_infos[1].aux.hasOrder(); 114 return new SeqSeqFloatLessEqual(slice, has_order); 115 } 116 117 @Override 118 protected Invariant resurrect_done_swapped() { 119 120 return new SeqSeqFloatGreaterEqual(this); 121 } 122 123 @Override 124 public String repr(@GuardSatisfied SeqSeqFloatLessEqual this) { 125 return "SeqSeqFloatLessEqual" + varNames() + ": ,orderMatters=" + orderMatters 126 + ",enoughSamples=" + enoughSamples() 127 ; 128 } 129 130 @SideEffectFree 131 @Override 132 public String format_using(@GuardSatisfied SeqSeqFloatLessEqual this, OutputFormat format) { 133 // System.out.println("Calling SeqSeqFloatLessEqual.format for: " + repr()); 134 135 if (format == OutputFormat.SIMPLIFY) { 136 return format_simplify(); 137 } 138 139 if (format == OutputFormat.DAIKON) { 140 String name1 = var1().name_using(format); 141 String name2 = var2().name_using(format); 142 143 String lexically = (var1().aux.hasOrder() ? " (lexically)" : ""); 144 return name1 + " <= " + name2 + lexically; 145 } 146 147 if (format == OutputFormat.CSHARPCONTRACT) { 148 149 if (var1().aux.hasOrder()) { 150 String name1 = var1().csharp_collection_string(); 151 String name2 = var2().csharp_collection_string(); 152 String dbc = "LlexLTE".substring(1); 153 return name1 + "." + dbc + "(" + name2 + ")"; 154 } else { 155 return "\"SeqComparison.java.jpp: sequence comparison does not apply to unordered collections unimplemented\" != null)"; // interned 156 } 157 158 } 159 160 if (format.isJavaFamily()) { 161 String name1 = var1().name_using(format); 162 String name2 = var2().name_using(format); 163 164 return "daikon.Quant." 165 + (var1().aux.hasOrder() ? "lexLTE" : "setEqual" ) 166 + "(" 167 + name1 168 + ", " 169 + name2 170 + ")"; 171 172 } 173 174 return format_unimplemented(format); 175 } 176 177 public String format_simplify(@GuardSatisfied SeqSeqFloatLessEqual this) { 178 if (Invariant.dkconfig_simplify_define_predicates) { 179 return format_simplify_defined(); 180 } else { 181 return format_simplify_explicit(); 182 } 183 } 184 185 private String format_simplify_defined(@GuardSatisfied SeqSeqFloatLessEqual this) { 186 String[] var1_name = var1().simplifyNameAndBounds(); 187 String[] var2_name = var2().simplifyNameAndBounds(); 188 if (var1_name == null || var2_name == null) { 189 return String.format("%s.format_simplify_defined(%s): var1_name=%s, var2_name=%s, for %s", 190 getClass().getSimpleName(), this, 191 Arrays.toString(var1_name), Arrays.toString(var2_name), format()); 192 } 193 return "(|lexical-<=| " 194 + var1_name[0] + " " + var1_name[1] + " " + var1_name[2] + " " 195 + var2_name[0] + " " + var2_name[1] + " " + var2_name[2] + ")"; 196 } 197 198 private String format_simplify_explicit(@GuardSatisfied SeqSeqFloatLessEqual this) { 199 200 String classname = this.getClass().toString().substring(6); 201 return "warning: method " + classname 202 + ".format_simplify_explicit() needs to be implemented: " + format(); 203 204 } 205 206 @Override 207 public InvariantStatus check_modified( 208 double @Interned [] v1, double @Interned [] v2, int count) { 209 /// This does not do the right thing; I really want to avoid comparisons 210 /// if one is missing, but not if one is zero-length. 211 // // Don't make comparisons with empty arrays. 212 // if ((v1.length == 0) || (v2.length == 0)) { 213 // return; 214 // } 215 216 int comparison = 0; 217 if (orderMatters) { 218 // Standard element wise comparison 219 comparison = comparator.compare(v1, v2); 220 } else { 221 // Do a double subset comparison 222 comparison = Global.fuzzy.isElemMatch(v1, v2) ? 0 : -1; 223 } 224 225 if (!(comparison <= 0) ) { 226 return InvariantStatus.FALSIFIED; 227 } 228 return InvariantStatus.NO_CHANGE; 229 } 230 231 @Override 232 public InvariantStatus add_modified(double @Interned [] v1, double @Interned [] v2, int count) { 233 if (logDetail()) { 234 log("add_modified (%s, %s)", Arrays.toString(v1), Arrays.toString(v2)); 235 } 236 return check_modified(v1, v2, count); 237 } 238 239 @Override 240 protected double computeConfidence() { 241 242 return 1 - Math.pow(.5, ppt.num_values()); 243 } 244 245 @Pure 246 @Override 247 public boolean isSameFormula(Invariant o) { 248 return true; 249 } 250 251 @Pure 252 @Override 253 public boolean isExclusiveFormula(Invariant o) { 254 return false; 255 } 256 257 /** 258 * Since this invariant can be a postProcessed equality, we have to handle isObvious especially to 259 * avoid circular isObvious relations. 260 */ 261 @Pure 262 @Override 263 public @Nullable DiscardInfo isObviousStatically_SomeInEquality() { 264 if (var1().equalitySet == var2().equalitySet) { 265 return isObviousStatically(this.ppt.var_infos); 266 } else { 267 return super.isObviousStatically_SomeInEquality(); 268 } 269 } 270 271 /** 272 * Since this invariant can be a postProcessed equality, we have to handle isObvious especially to 273 * avoid circular isObvious relations. 274 */ 275 @Pure 276 @Override 277 public @Nullable DiscardInfo isObviousDynamically_SomeInEquality() { 278 if (logOn()) { 279 log("Considering dynamically_someInEquality"); 280 } 281 if (var1().equalitySet == var2().equalitySet) { 282 return isObviousDynamically(this.ppt.var_infos); 283 } else { 284 return super.isObviousDynamically_SomeInEquality(); 285 } 286 } 287 288 @Pure 289 @Override 290 public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) { 291 292 VarInfo var1 = vis[0]; 293 VarInfo var2 = vis[1]; 294 DiscardInfo di; 295 di = SubSequenceFloat.isObviousSubSequence(this, var1, var2); 296 if (di == null) { 297 di = SubSequenceFloat.isObviousSubSequence(this, var2, var1); 298 } 299 if (di != null) { 300 return di; 301 } 302 303 return super.isObviousStatically(vis); 304 } 305 306 @Pure 307 @Override 308 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 309 DiscardInfo super_result = super.isObviousDynamically(vis); 310 if (super_result != null) { 311 return super_result; 312 } 313 assert ppt != null; 314 315 Debug debug = new Debug(getClass(), ppt, vis); 316 317 if (logOn()) { 318 debug.log("Checking IsObviousDynamically"); 319 } 320 321 // Check to see if the same Pairwise invariant exists 322 DiscardInfo di = new DiscardInfo(this, DiscardCode.obvious, ""); 323 if (ppt.parent.check_implied(di, vis[0], vis[1], PairwiseFloatLessEqual.get_proto())) { 324 di.add_implied_vis(vis); 325 return di; 326 } 327 328 // If either variable is a subsequence and the original arrays 329 // are related elementwise this isn't interesting 330 VarInfo v1 = vis[0]; 331 VarInfo v2 = vis[1]; 332 VarInfo arr1 = v1; 333 VarInfo arr2 = v2; 334 if (v1.derived instanceof SequenceFloatSubsequence) { 335 arr1 = ((SequenceFloatSubsequence) v1.derived).seqvar(); 336 } 337 if (v2.derived instanceof SequenceFloatSubsequence) { 338 arr2 = ((SequenceFloatSubsequence) v2.derived).seqvar(); 339 } 340 if (!isEqual() && ((arr1 != v1) || (arr2 != v2))) { 341 VarInfo[] avis = new VarInfo [] {arr1, arr2}; 342 PptSlice slice = this.ppt.parent.findSlice_unordered(avis); 343 if (slice != null) { 344 PairwiseFloatEqual picEQ = PairwiseFloatEqual.find(slice); 345 if (picEQ != null) { 346 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + picEQ.format()); 347 } 348 PairwiseFloatLessThan picLT = PairwiseFloatLessThan.find(slice); 349 if (picLT != null) { 350 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + picLT.format()); 351 } 352 PairwiseFloatGreaterThan picGT = PairwiseFloatGreaterThan.find(slice); 353 if (picGT != null) { 354 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + picGT.format()); 355 } 356 PairwiseFloatLessEqual picLE = PairwiseFloatLessEqual.find(slice); 357 if (picLE != null) { 358 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + picLE.format()); 359 } 360 PairwiseFloatGreaterEqual picGE = PairwiseFloatGreaterEqual.find(slice); 361 if (picGE != null) { 362 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + picGE.format()); 363 } 364 } 365 } 366 367 // Similarly, if either variable is a subsequence and the original 368 // arrays are related lexically this isn't interesting 369 if ((arr1 != v1) || (arr2 != v2)) { 370 if (arr1 == arr2) { 371 debug.log("Obvious Dynamic- subsequence from same array"); 372 return new DiscardInfo(this, DiscardCode.obvious, "Supersequences are related lexically"); 373 } 374 VarInfo[] avis = {arr1, arr2}; 375 debug.log("looking for " + avis[0].name() + " " + avis[1].name()); 376 PptSlice slice = this.ppt.parent.findSlice_unordered(avis); 377 debug.log("Found ppt " + slice); 378 if (slice != null) { 379 for (Invariant inv : slice.invs) { 380 debug.log("-- invariant " + inv.format()); 381 } 382 Invariant inv; 383 inv = SeqSeqFloatEqual.find(slice); 384 if (inv != null) { 385 if (logOn()) { 386 debug.log("Obvious Dynamic from " + inv.format() + "(" + inv.getClass() + ")"); 387 } 388 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + inv.format()); 389 } 390 inv = SeqSeqFloatLessThan.find(slice); 391 if (inv != null) { 392 if (logOn()) { 393 debug.log("Obvious Dynamic from " + inv.format() + "(" + inv.getClass() + ")"); 394 } 395 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + inv.format()); 396 } 397 inv = SeqSeqFloatGreaterThan.find(slice); 398 if (inv != null) { 399 if (logOn()) { 400 debug.log("Obvious Dynamic from " + inv.format() + "(" + inv.getClass() + ")"); 401 } 402 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + inv.format()); 403 } 404 inv = SeqSeqFloatLessEqual.find(slice); 405 if (inv != null) { 406 if (logOn()) { 407 debug.log("Obvious Dynamic from " + inv.format() + "(" + inv.getClass() + ")"); 408 } 409 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + inv.format()); 410 } 411 inv = SeqSeqFloatGreaterEqual.find(slice); 412 if (inv != null) { 413 if (logOn()) { 414 debug.log("Obvious Dynamic from " + inv.format() + "(" + inv.getClass() + ")"); 415 } 416 return new DiscardInfo(this, DiscardCode.obvious, "Implied by " + inv.format()); 417 } 418 } 419 } 420 421 // Check to see if these variables are obviously related 422 if (v1.isDerived() || v2.isDerived()) { 423 if (SubSequenceFloat.isObviousSubSequenceDynamically(this, v1, v2) 424 || SubSequenceFloat.isObviousSubSequenceDynamically(this, v2, v1)) { 425 if (logOn()) { 426 debug.log("Obvious SubSequence Dynamically"); 427 } 428 assert ppt != null; 429 return new DiscardInfo( 430 this, 431 DiscardCode.obvious, 432 "Both vars are derived and one is a subsequence of the other"); 433 } 434 } 435 436 return null; 437 } 438 439 @Override 440 public void repCheck() { 441 super.repCheck(); 442 /* 443 This code is no longer needed now that the can_be_x's are gone 444 if (!(this.can_be_eq || this.can_be_lt || this.can_be_gt) 445 && ppt.num_samples() != 0) { 446 System.err.println(this.repr()); 447 System.err.println(this.ppt.num_samples()); 448 throw new Error(); 449 } 450 */ 451 } 452 453 @Pure 454 public boolean isEqual() { 455 456 return false; 457 } 458 459 // Look up a previously instantiated invariant. 460 public static @Nullable SeqSeqFloatLessEqual find(PptSlice ppt) { 461 assert ppt.arity() == 2; 462 for (Invariant inv : ppt.invs) { 463 if (inv instanceof SeqSeqFloatLessEqual) { 464 return (SeqSeqFloatLessEqual) inv; 465 } 466 } 467 return null; 468 } 469 470 /** Returns a list of non-instantiating suppressions for this invariant. */ 471 @Pure 472 @Override 473 public @Nullable NISuppressionSet get_ni_suppressions() { 474 return suppressions; 475 } 476 477 /** Definition of this invariant (the suppressee) */ 478 private static NISuppressee suppressee = new NISuppressee(SeqSeqFloatLessEqual.class, 2); 479 480 // Suppressor definitions (used in suppressions below) 481 private static NISuppressor v1_pw_v2 = new NISuppressor(0, 1, PairwiseFloatLessEqual.class); 482 483 private static NISuppressionSet suppressions = 484 new NISuppressionSet( 485 new NISuppression[] { 486 // pairwise => lexical 487 new NISuppression(v1_pw_v2, suppressee), 488 }); 489 490}