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