001// ***** This file is automatically generated from SubSet.java.jpp
002
003package daikon.inv.binary.twoSequence;
004
005import daikon.*;
006import daikon.inv.*;
007import daikon.suppress.*;
008import java.util.*;
009import java.util.logging.Level;
010import java.util.logging.Logger;
011import org.checkerframework.checker.lock.qual.GuardSatisfied;
012import org.checkerframework.checker.nullness.qual.NonNull;
013import org.checkerframework.checker.nullness.qual.Nullable;
014import org.checkerframework.dataflow.qual.Pure;
015import org.checkerframework.dataflow.qual.SideEffectFree;
016import org.plumelib.util.ArraysPlume;
017import typequals.prototype.qual.NonPrototype;
018import typequals.prototype.qual.Prototype;
019
020/**
021 * Represents two sequences of long values where one of the sequences is a subset of the other; that
022 * is each element of one sequence appears in the other. Prints as either
023 * {@code x[] is a subset of y[]} or as {@code x[] is a superset of y[]}.
024 */
025public class SuperSet extends TwoSequence {
026  static final long serialVersionUID = 20031024L;
027
028  private static final Logger debug =
029    Logger.getLogger("daikon.inv.binary.twoSequence.SuperSet");
030
031  // Variables starting with dkconfig_ should only be set via the
032  // daikon.config.Configuration interface.
033  /** Boolean. True iff SubSet invariants should be considered. */
034  public static boolean dkconfig_enabled = false;
035
036  protected SuperSet(PptSlice ppt) {
037    super(ppt);
038  }
039
040  protected @Prototype SuperSet() {
041    super();
042  }
043
044  private static @Prototype SuperSet proto = new @Prototype SuperSet();
045
046  /** Returns the prototype invariant for SuperSet */
047  public static @Prototype SuperSet get_proto() {
048    return proto;
049  }
050
051  @Override
052  public boolean enabled() {
053    return dkconfig_enabled;
054  }
055
056  @Override
057  public boolean instantiate_ok(VarInfo[] vis) {
058
059    if (!valid_types(vis)) {
060      return false;
061    }
062
063    return true;
064  }
065
066  @Override
067  public SuperSet instantiate_dyn(@Prototype SuperSet this, PptSlice slice) {
068    return new SuperSet(slice);
069  }
070
071  @Override
072  protected Invariant resurrect_done_swapped() {
073    return new SubSet(ppt);
074  }
075
076  @Override
077  public String repr(@GuardSatisfied SuperSet this) {
078    return "SuperSet" + varNames() + ": ,falsified=" + falsified;
079  }
080
081  @SideEffectFree
082  @Override
083  public String format_using(@GuardSatisfied SuperSet this, OutputFormat format) {
084    if (format == OutputFormat.DAIKON) {
085      return format();
086    }
087    if (format == OutputFormat.ESCJAVA) {
088      return format_esc();
089    }
090    if (format == OutputFormat.SIMPLIFY) {
091      return format_simplify();
092    }
093    if (format == OutputFormat.CSHARPCONTRACT) {
094      return format_csharp_contract();
095    }
096    if (format.isJavaFamily()) {
097      return format_java_family(format);
098    }
099
100    return format_unimplemented(format);
101  }
102
103  @SideEffectFree
104  @Override
105  public String format(@GuardSatisfied SuperSet this) {
106    String v1 = var1().name();
107    String v2 = var2().name();
108
109    return v1 + " is a superset of " + v2;
110  }
111
112  public String format_csharp_contract(@GuardSatisfied SuperSet this) {
113    String v1 = var1().csharp_collection_string();
114    String v2 = var2().csharp_collection_string();
115
116    return "Contract.ForAll(" + v2 + ", i => " + v1 + ".Contains(i))";
117  }
118
119  public String format_esc(@GuardSatisfied SuperSet this) {
120    String classname = this.getClass().toString().substring(6); // remove leading "class"
121    return "warning: method " + classname + ".format_esc() needs to be implemented: " + format();
122  }
123
124  public String format_simplify(@GuardSatisfied SuperSet this) {
125    if (Invariant.dkconfig_simplify_define_predicates) {
126      return format_simplify_defined();
127    } else {
128      return format_simplify_explicit();
129    }
130  }
131
132  private String format_simplify_defined(@GuardSatisfied SuperSet this) {
133
134    VarInfo subvar = var2();
135    VarInfo supervar = var1();
136
137    String[] sub_name = subvar.simplifyNameAndBounds();
138    String[] super_name = supervar.simplifyNameAndBounds();
139
140    if (sub_name == null || super_name == null) {
141      return String.format("%s.format_simplify_defined(%s): sub_name=%s, super_name=%s, for %s",
142                           getClass().getSimpleName(), this,
143                           Arrays.toString(sub_name), Arrays.toString(super_name), format());
144    }
145
146    return "(subset "
147      + sub_name[0] + " " + sub_name[1] + " " + sub_name[2] + " "
148      + super_name[0] + " " + super_name[1] + " " + super_name[2] + ")";
149  }
150
151  private String format_simplify_explicit(@GuardSatisfied SuperSet this) {
152
153    VarInfo subvar = var2();
154    VarInfo supervar = var1();
155
156    String[] sub_name = subvar.simplifyNameAndBounds();
157    String[] super_name = supervar.simplifyNameAndBounds();
158
159    if (sub_name == null || super_name == null) {
160      return String.format("%s.format_simplify_explicit(%s): sub_name=%s, super_name=%s, for %s",
161                           getClass().getSimpleName(), this,
162                           Arrays.toString(sub_name), Arrays.toString(super_name), format());
163    }
164
165    String indices[] = VarInfo.get_simplify_free_indices(subvar, supervar);
166
167    // (FORALL (a i j b ip jp)
168    //    (IFF (subset a i j b ip jp)
169    //         (FORALL (x)
170    //           (IMPLIES
171    //              (AND (<= i x) (<= x j))
172    //              (EXISTS (y)
173    //                  (AND (<= ip y) (<= y jp)
174    //                        (EQ (select (select elems a) x)
175    //                            (select (select elems b) y))))))))
176
177    return "(FORALL (" + indices[0] + ") (IMPLIES (AND (<= " + sub_name[1]
178      + " " + indices[0] + ") (<= " + indices[0] + " " + sub_name[2] + "))"
179      + "(EXISTS (" + indices[1] + ")(AND (<= " + super_name[1] + " "
180      + indices[1] + ") (<= " + indices[1] + " " + super_name[2]+ ")"
181      + "(EQ (select (select elems " + sub_name[0] + ") " + indices[0] + ") "
182      + "(select (select elems " + super_name[0] +") " + indices[1] + "))))))";
183
184  }
185
186  public String format_java_family(@GuardSatisfied SuperSet this, OutputFormat format) {
187
188    String v1 = var1().name_using(format);
189    String v2 = var2().name_using(format);
190
191    return "daikon.Quant.subsetOf(" + v2 + ", " + v1 + ")";
192  }
193
194  @Override
195  public InvariantStatus check_modified(long[] a1, long[] a2, int count) {
196
197    if (!ArraysPlume.isSubset(a2, a1)) {
198
199      return InvariantStatus.FALSIFIED;
200    } else {
201      return InvariantStatus.NO_CHANGE;
202    }
203
204  }
205
206  @Override
207  public InvariantStatus add_modified(long[] a1, long[] a2, int count) {
208    if (debug.isLoggable(Level.FINE)) {
209      debug.fine(Arrays.toString(a1));
210      debug.fine(Arrays.toString(a2));
211    }
212    return check_modified(a1, a2, count);
213  }
214
215  @Override
216  protected double computeConfidence() {
217    return Invariant.CONFIDENCE_JUSTIFIED;
218  }
219
220  // Convenience name to make this easier to find.
221  @Pure
222  public static @Nullable DiscardInfo isObviousSubSet(Invariant inv, VarInfo subvar, VarInfo supervar) {
223    return SubSequence.isObviousSubSequence(inv, subvar, supervar);
224  }
225
226  @Pure
227  @Override
228  public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) {
229    VarInfo var1 = vis[0];
230    VarInfo var2 = vis[1];
231
232    DiscardInfo di;
233    di = SuperSet.isObviousSubSet(this, var1, var2);
234    if (di == null) {
235      di = SuperSet.isObviousSubSet(this, var2, var1);
236    }
237    if (di != null) {
238      return di;
239    }
240
241    VarInfo subvar, supervar;
242
243    subvar = var2;
244    supervar = var2;
245
246    // Uninteresting if this is of the form x[0..i] subsequence
247    // x[0..j].  Not necessarily obvious.
248    VarInfo subvar_super = subvar.isDerivedSubSequenceOf();
249    if (subvar_super == supervar) {
250      debug.fine("  returning true because subvar_super == supervar");
251      return new DiscardInfo(this, DiscardCode.obvious, "x[0..i] subsequence of x[0..j] is uninteresting");
252    }
253
254    VarInfo supervar_super = supervar.isDerivedSubSequenceOf();
255    if (subvar_super != null && subvar_super == supervar_super) {
256      debug.fine("  returning true because subvar_super == supervar_super");
257      return new DiscardInfo(this, DiscardCode.obvious, "x[0..i] subsequence of x[0..j] is uninteresting");
258    }
259
260    di = SubSequence.isObviousSubSequence(this, var1, var2);
261    if (di == null) {
262      di = SubSequence.isObviousSubSequence(this, var2, var1);
263    }
264    if (di != null) {
265      return di;
266    }
267    return super.isObviousStatically(vis);
268  }
269
270  // Look up a previously instantiated SubSet relationship.
271  public static @Nullable SuperSet find(PptSlice ppt) {
272    assert ppt.arity() == 2;
273    for (Invariant inv : ppt.invs) {
274      if (inv instanceof SuperSet) {
275        return (SuperSet) inv;
276      }
277    }
278    return null;
279  }
280
281  @Pure
282  @Override
283  public boolean isSameFormula(Invariant other) {
284    assert other instanceof SuperSet;
285    return true;
286  }
287
288  /** NI suppressions, initialized in get_ni_suppressions() */
289  private static @Nullable NISuppressionSet suppressions = null;
290
291  /** returns the ni-suppressions for SuperSet */
292  @Pure
293  @Override
294  public NISuppressionSet get_ni_suppressions() {
295    if (suppressions == null) {
296      NISuppressee suppressee = new NISuppressee(SuperSet.class, 2);
297
298      // suppressor definitions (used in suppressions below)
299      NISuppressor v1_eq_v2 = new NISuppressor(0, 1, SeqSeqIntEqual.class);
300      NISuppressor v1_pw_eq_v2 = new NISuppressor(0, 1, PairwiseIntEqual.class);
301
302      // sub/super set suppressions.  We have both SeqSeq and Pairwise
303      // as suppressions because each can be enabled separately.
304      suppressions = new NISuppressionSet(
305          new NISuppression[] {
306              // a[] == b[] ==> a[] sub/superset b[]
307              new NISuppression(v1_eq_v2, suppressee),
308              // a[] == b[] ==> a[] sub/superset b[]
309              new NISuppression(v1_pw_eq_v2, suppressee),
310          });
311    }
312
313    return suppressions;
314  }
315}