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