001// ***** This file is automatically generated from IntComparisons.java.jpp 002 003package daikon.inv.binary.twoScalar; 004 005import daikon.*; 006import daikon.derive.binary.*; 007import daikon.derive.unary.*; 008import daikon.inv.*; 009import daikon.inv.binary.twoScalar.*; 010import daikon.inv.binary.twoSequence.*; 011import daikon.inv.unary.scalar.*; 012import daikon.inv.unary.sequence.*; 013import daikon.inv.unary.string.*; 014import daikon.suppress.*; 015import java.util.*; 016import java.util.logging.Level; 017import java.util.logging.Logger; 018import org.checkerframework.checker.interning.qual.Interned; 019import org.checkerframework.checker.lock.qual.GuardSatisfied; 020import org.checkerframework.checker.nullness.qual.NonNull; 021import org.checkerframework.checker.nullness.qual.Nullable; 022import org.checkerframework.dataflow.qual.Pure; 023import org.checkerframework.dataflow.qual.SideEffectFree; 024import org.plumelib.util.Intern; 025import typequals.prototype.qual.NonPrototype; 026import typequals.prototype.qual.Prototype; 027 028/** 029 * Represents an invariant of != between two long scalars. Prints as {@code x != y}. 030 */ 031public final class IntNonEqual extends TwoScalar { 032 033 // We are Serializable, so we specify a version to allow changes to 034 // method signatures without breaking serialization. If you add or 035 // remove fields, you should change this number to the current date. 036 static final long serialVersionUID = 20030822L; 037 038 // Variables starting with dkconfig_ should only be set via the 039 // daikon.config.Configuration interface. 040 /** Boolean. True iff IntNonEqual invariants should be considered. */ 041 public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault; 042 043 public static final Logger debug = Logger.getLogger("daikon.inv.binary.twoScalar.IntNonEqual"); 044 045 /** Boolean. True iff IntNonEqual invariants should be considered. */ 046 public static boolean dkconfig_integral_only = true; 047 048 IntNonEqual(PptSlice ppt) { 049 super(ppt); 050 } 051 052 @Prototype IntNonEqual() { 053 super(); 054 } 055 056 private static @Prototype IntNonEqual proto = new @Prototype IntNonEqual(); 057 058 /** Returns the prototype invariant for IntNonEqual */ 059 public static @Prototype IntNonEqual get_proto() { 060 return proto; 061 } 062 063 /** Returns whether or not this invariant is enabled. */ 064 @Override 065 public boolean enabled() { 066 return dkconfig_enabled; 067 } 068 069 /** Returns whether or not the specified var types are valid for IntNonEqual */ 070 @Override 071 public boolean instantiate_ok(VarInfo[] vis) { 072 073 if (!valid_types(vis)) { 074 return false; 075 } 076 077 if (dkconfig_integral_only) { 078 return (vis[0].file_rep_type.isIntegral() 079 && vis[1].file_rep_type.isIntegral()); 080 } 081 return true; 082 } 083 084 /** Instantiate an invariant on the specified slice. */ 085 @Override 086 protected IntNonEqual instantiate_dyn(@Prototype IntNonEqual this, PptSlice slice) { 087 088 // System.out.printf("Instantiating non-equal on %s and %s%n", 089 // slice.var_infos[0], slice.var_infos[1]); 090 091 return new IntNonEqual(slice); 092 } 093 094 @Override 095 protected Invariant resurrect_done_swapped() { 096 097 // we don't care if things swap; we have symmetry 098 return this; 099 } 100 101 @Pure 102 @Override 103 public boolean is_symmetric() { 104 return true; 105 } 106 107 // JHP: this should be removed in favor of checks in PptTopLevel 108 // such as is_equal, is_lessequal, etc. 109 // Look up a previously instantiated IntNonEqual relationship. 110 // Should this implementation be made more efficient? 111 public static @Nullable IntNonEqual find(PptSlice ppt) { 112 assert ppt.arity() == 2; 113 for (Invariant inv : ppt.invs) { 114 if (inv instanceof IntNonEqual) { 115 return (IntNonEqual) inv; 116 } 117 } 118 119 // If the invariant is suppressed, create it 120 if ((suppressions != null) && suppressions.suppressed(ppt)) { 121 IntNonEqual inv = proto.instantiate_dyn(ppt); 122 // System.out.printf("%s is suppressed in ppt %s%n", inv.format(), ppt.name()); 123 return inv; 124 } 125 126 return null; 127 } 128 129 @Override 130 public String repr(@GuardSatisfied IntNonEqual this) { 131 return "IntNonEqual" + varNames(); 132 } 133 134 @SideEffectFree 135 @Override 136 public String format_using(@GuardSatisfied IntNonEqual this, OutputFormat format) { 137 138 String var1name = var1().name_using(format); 139 String var2name = var2().name_using(format); 140 141 if ((format == OutputFormat.DAIKON) || (format == OutputFormat.ESCJAVA)) { 142 String comparator = "!="; 143 return var1name + " " + comparator + " " + var2name; 144 } 145 146 if (format == OutputFormat.CSHARPCONTRACT) { 147 148 String comparator = "!="; 149 return var1name + " " + comparator + " " + var2name; 150 } 151 152 if (format.isJavaFamily()) { 153 154 if ((var1name.indexOf("daikon.Quant.collectObject") != -1) 155 156 || (var2name.indexOf("daikon.Quant.collectObject") != -1)) { 157 return "(warning: it is meaningless to compare hashcodes for values obtained through daikon.Quant.collect... methods:" 158 + var1name + " != " + var2name + ")"; 159 } 160 return var1name + " != " + var2name; 161 } 162 163 if (format == OutputFormat.SIMPLIFY) { 164 165 String comparator = "NEQ"; 166 167 return "(" 168 + comparator 169 + " " 170 + var1().simplifyFixup(var1name) 171 + " " 172 + var2().simplifyFixup(var2name) 173 + ")"; 174 } 175 176 return format_unimplemented(format); 177 } 178 179 @Override 180 public InvariantStatus check_modified(long v1, long v2, int count) { 181 if (!(v1 != v2)) { 182 return InvariantStatus.FALSIFIED; 183 } 184 return InvariantStatus.NO_CHANGE; 185 } 186 187 @Override 188 public InvariantStatus add_modified(long v1, long v2, int count) { 189 if (logDetail() || debug.isLoggable(Level.FINE)) { 190 log( 191 debug, 192 "add_modified (" + v1 + ", " + v2 + ", ppt.num_values = " + ppt.num_values() + ")"); 193 } 194 if ((logOn() || debug.isLoggable(Level.FINE)) 195 && check_modified(v1, v2, count) == InvariantStatus.FALSIFIED) 196 log(debug, "destroy in add_modified (" + v1 + ", " + v2 + ", " + count + ")"); 197 198 return check_modified(v1, v2, count); 199 } 200 201 // This is very tricky, because whether two variables are equal should 202 // presumably be transitive, but it's not guaranteed to be so when using 203 // this method and not dropping out all variables whose values are ever 204 // missing. 205 @Override 206 protected double computeConfidence() { 207 // Should perhaps check number of samples and be unjustified if too few 208 // samples. 209 210 // // The reason for this multiplication is that there might be only a 211 // // very few possible values. Example: towers of hanoi has only 6 212 // // possible (pegA, pegB) pairs. 213 // return 1 - (Math.pow(.5, ppt.num_values()) 214 // * Math.pow(.99, ppt.num_mod_samples())); 215 return 1 - Math.pow(.5, ppt.num_samples()); 216 } 217 218 @Pure 219 @Override 220 public boolean isExact() { 221 222 return false; 223 } 224 225 // // Temporary, for debugging 226 // public void destroy() { 227 // if (debug.isLoggable(Level.FINE)) { 228 // System.out.println("IntNonEqual.destroy(" + ppt.name() + ")"); 229 // System.out.println(repr()); 230 // (new Error()).printStackTrace(); 231 // } 232 // super.destroy(); 233 // } 234 235 @Override 236 public InvariantStatus add( 237 @Interned Object v1, @Interned Object v2, int mod_index, int count) { 238 if (debug.isLoggable(Level.FINE)) { 239 debug.fine( 240 "IntNonEqual" 241 + ppt.varNames() 242 + ".add(" 243 + v1 244 + "," 245 + v2 246 + ", mod_index=" 247 + mod_index 248 + "), count=" 249 + count 250 + ")"); 251 } 252 return super.add(v1, v2, mod_index, count); 253 } 254 255 @Pure 256 @Override 257 public boolean isSameFormula(Invariant other) { 258 return true; 259 } 260 261 @Pure 262 @Override 263 public boolean isExclusiveFormula(Invariant other) { 264 265 // Also ought to check against LinearBinary, etc. 266 267 if (other instanceof IntEqual) { 268 return true; 269 } 270 271 return false; 272 } 273 274 @Override 275 public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) { 276 final VarInfo var1 = vis[0]; 277 final VarInfo var2 = vis[1]; 278 279 if (var1.aux.hasValue(VarInfoAux.MAXIMUM_VALUE) 280 && var2.aux.hasValue(VarInfoAux.MINIMUM_VALUE)) { 281 int maxA = var1.aux.getInt(VarInfoAux.MAXIMUM_VALUE), 282 minB = var2.aux.getInt(VarInfoAux.MINIMUM_VALUE); 283 284 if (maxA < minB) { 285 return new DiscardInfo( 286 this, 287 DiscardCode.obvious, 288 var1.name() + " DISCARD_OP " + var2.name() + " is already known"); 289 } 290 } 291 292 if (var1.aux.hasValue(VarInfoAux.MINIMUM_VALUE) 293 && var2.aux.hasValue(VarInfoAux.MAXIMUM_VALUE)) { 294 int maxB = var2.aux.getInt(VarInfoAux.MAXIMUM_VALUE), 295 minA = var1.aux.getInt(VarInfoAux.MINIMUM_VALUE); 296 297 if (minA > maxB) { 298 return new DiscardInfo( 299 this, 300 DiscardCode.obvious, 301 var1.name() + " DISCARD_OP " + var2.name() + " is already known"); 302 } 303 } 304 305 return super.isObviousStatically(vis); 306 } 307 308 @Pure 309 @Override 310 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 311 312 // JHP: We might consider adding a check over bounds. If 313 // x < c and y > c then we know that x < y. Similarly for 314 // x > c and y < c. We could also substitute oneof for 315 // one or both of the bound checks. 316 317 DiscardInfo super_result = super.isObviousDynamically(vis); 318 if (super_result != null) { 319 return super_result; 320 } 321 322 VarInfo var1 = vis[0]; 323 VarInfo var2 = vis[1]; 324 325 @SuppressWarnings("UnusedVariable") // generated code, variable is sometimes used 326 DiscardInfo di; 327 328 // (A[] no dups) ^ (i != j) ==> a[i] != a[j] 329 di = no_dups_implies(vis); 330 if (di != null) { 331 return di; 332 } 333 334 { // Sequence length tests 335 SequenceLength sl1 = null; 336 if (var1.isDerived() && (var1.derived instanceof SequenceLength)) { 337 sl1 = (SequenceLength) var1.derived; 338 } 339 SequenceLength sl2 = null; 340 if (var2.isDerived() && (var2.derived instanceof SequenceLength)) { 341 sl2 = (SequenceLength) var2.derived; 342 } 343 344 // "size(a)-1 cmp size(b)-1" is never even instantiated; 345 // use "size(a) cmp size(b)" instead. 346 347 // This might never get invoked, as equality is printed out specially. 348 VarInfo s1 = (sl1 == null) ? null : sl1.base; 349 VarInfo s2 = (sl2 == null) ? null : sl2.base; 350 if ((s1 != null) && (s2 != null) && (s1.equalitySet == s2.equalitySet)) { 351 // lengths of equal arrays being compared 352 String n1 = var1.name(); 353 String n2 = var2.name(); 354 return new DiscardInfo( 355 this, 356 DiscardCode.obvious, 357 n1 + " and " + n2 + " are equal arrays, so equal size is implied"); 358 } 359 360 } 361 362 return null; 363 } // isObviousDynamically 364 365 /** 366 * Suppress NonEqual invariants where both variables are subscripts from the same array and the 367 * array has no duplicates: 368 * 369 * <pre>(A[] has no dups) ^ (i != j) ⇒ a[i] != a[j]</pre> 370 */ 371 private @Nullable DiscardInfo no_dups_implies(VarInfo[] vis) { 372 373 // Make sure v1 and v2 are SequenceScalarSubscript from the same array 374 VarInfo v1 = vis[0]; 375 VarInfo v2 = vis[1]; 376 if (!v1.isDerived() || !(v1.derived instanceof SequenceScalarSubscript)) { 377 return null; 378 } 379 if (!v2.isDerived() || !(v2.derived instanceof SequenceScalarSubscript)) { 380 return null; 381 } 382 @NonNull SequenceScalarSubscript der1 = (SequenceScalarSubscript) v1.derived; 383 @NonNull SequenceScalarSubscript der2 = (SequenceScalarSubscript) v2.derived; 384 385 // The sequence vars must be equal (or the same) 386 if (!ppt.parent.is_equal(der1.seqvar().canonicalRep(), 387 der2.seqvar().canonicalRep())) 388 return null; 389 390 // The subscripts must be non_equal 391 DiscardInfo di1 = ppt.parent.check_implied_canonical(this, der1.sclvar(), 392 der2.sclvar(), IntNonEqual.get_proto()); 393 if (di1 == null) { 394 return null; 395 } 396 397 // The array must have no-dups 398 DiscardInfo di2 = ppt.parent.check_implied_canonical(this, der1.seqvar(), 399 NoDuplicates.get_proto()); 400 if (di2 == null) { 401 return null; 402 } 403 404 return new DiscardInfo(this, DiscardCode.obvious, di1.discardString() 405 + " and " + di2.discardString()); 406 } 407 408 /** NI suppressions, initialized in get_ni_suppressions() */ 409 private static @Nullable NISuppressionSet suppressions = null; 410 411 /** Returns the non-instantiating suppressions for this invariant. */ 412 @Pure 413 @Override 414 public NISuppressionSet get_ni_suppressions() { 415 if (suppressions == null) { 416 417 NISuppressee suppressee = new NISuppressee(IntNonEqual.class, 2); 418 419 // suppressor definitions (used in suppressions below) 420 421 NISuppressor v1_gt_v2 = new NISuppressor(0, 1, IntGreaterThan.class); 422 423 NISuppressor v1_lt_v2 = new NISuppressor(0, 1, IntLessThan.class); 424 425 suppressions = 426 new NISuppressionSet( 427 new NISuppression[] { 428 429 // v1 < v2 => v1 != v2 430 new NISuppression(v1_lt_v2, suppressee), 431 // v1 > v2 => v1 != v2 432 new NISuppression(v1_gt_v2, suppressee), 433 434 }); 435 } 436 return suppressions; 437 } 438 439}