001  // #define PAIRWISEINTEQUAL PairwiseStringLessThan
002
003// ***** This file is automatically generated from SeqComparison.java.jpp
004
005package daikon.inv.binary.twoSequence;
006
007import daikon.*;
008import daikon.Quantify.QuantFlags;
009import daikon.derive.binary.*;
010import daikon.inv.*;
011import daikon.suppress.*;
012import java.util.*;
013import java.util.logging.Logger;
014import org.checkerframework.checker.interning.qual.Interned;
015import org.checkerframework.checker.lock.qual.GuardSatisfied;
016import org.checkerframework.checker.nullness.qual.Nullable;
017import org.checkerframework.dataflow.qual.Pure;
018import org.checkerframework.dataflow.qual.SideEffectFree;
019import org.plumelib.util.ArraysPlume;
020import org.plumelib.util.Intern;
021import typequals.prototype.qual.NonPrototype;
022import typequals.prototype.qual.Prototype;
023
024/**
025 * Represents invariants between two sequences of String values. If order matters for each
026 * variable (which it does by default), then the sequences are compared lexically. Prints as
027 * {@code x[] < y[] lexically}.
028 *
029
030 * <p>If the auxiliary information (e.g., order matters) doesn't match between two variables, then
031 * this invariant cannot apply to those variables.
032 */
033public class SeqSeqStringLessThan extends TwoSequenceString
034
035{
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 SeqSeqStringLessThan invariants should be considered. */
041  public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault;
042
043  /** Debugging logger. */
044  static final Logger debug = Logger.getLogger("daikon.inv.binary.twoSequence.SeqSeqStringLessThan");
045
046  static Comparator<String[]> comparator = ArraysPlume.StringArrayComparatorLexical.it;
047
048  boolean orderMatters;
049
050  protected SeqSeqStringLessThan(PptSlice ppt, boolean orderMatters) {
051    super(ppt);
052    this.orderMatters = orderMatters;
053  }
054
055  protected @Prototype SeqSeqStringLessThan(boolean orderMatters) {
056    super();
057    this.orderMatters = orderMatters;
058  }
059
060  protected SeqSeqStringLessThan(SeqSeqStringGreaterThan seq_swap) {
061    super(seq_swap.ppt);
062    orderMatters = seq_swap.orderMatters;
063  }
064
065  private static @Prototype SeqSeqStringLessThan proto = new @Prototype SeqSeqStringLessThan(true);
066
067  /** Returns the prototype invariant for SeqSeqStringLessThan */
068  public static @Prototype SeqSeqStringLessThan get_proto() {
069    return proto;
070  }
071
072  @Override
073  public boolean enabled() {
074    return dkconfig_enabled;
075  }
076
077  @Override
078  public boolean instantiate_ok(VarInfo[] vis) {
079
080    if (!valid_types(vis)) {
081      return false;
082    }
083
084      VarInfo var1 = vis[0];
085      VarInfo var2 = vis[1];
086      ProglangType type1 = var1.type;
087      ProglangType type2 = var2.type;
088
089      // This intentonally checks dimensions(), not pseudoDimensions.
090      boolean only_eq =
091        !((type1.dimensions() == 1)
092          && type1.baseIsString()
093          && (type2.dimensions() == 1)
094          && type2.baseIsString());
095      if (only_eq) {
096        return false;
097      }
098
099      // non equality comparisons don't make sense if the arrays aren't ordered
100      if (!var1.aux.hasOrder() || !var2.aux.hasOrder()) {
101        return false;
102      }
103
104    return true;
105  }
106
107  @Override
108  protected SeqSeqStringLessThan instantiate_dyn(@Prototype SeqSeqStringLessThan this, PptSlice slice) {
109    boolean has_order = slice.var_infos[0].aux.hasOrder() && slice.var_infos[1].aux.hasOrder();
110    return new SeqSeqStringLessThan(slice, has_order);
111  }
112
113  @Override
114  protected Invariant resurrect_done_swapped() {
115
116    return new SeqSeqStringGreaterThan(this);
117  }
118
119  @Override
120  public String repr(@GuardSatisfied SeqSeqStringLessThan this) {
121    return "SeqSeqStringLessThan" + varNames() + ": ,orderMatters=" + orderMatters
122      + ",enoughSamples=" + enoughSamples()
123      ;
124  }
125
126  @SideEffectFree
127  @Override
128  public String format_using(@GuardSatisfied SeqSeqStringLessThan this, OutputFormat format) {
129    // System.out.println("Calling SeqSeqStringLessThan.format for: " + repr());
130
131    if (format == OutputFormat.SIMPLIFY) {
132      return format_simplify();
133    }
134
135    if (format == OutputFormat.DAIKON) {
136      String name1 = var1().name_using(format);
137      String name2 = var2().name_using(format);
138
139      String lexically = (var1().aux.hasOrder() ? " (lexically)" : "");
140      return name1 + " < " + name2 + lexically;
141    }
142
143    if (format == OutputFormat.CSHARPCONTRACT) {
144
145      if (var1().aux.hasOrder()) {
146        String name1 = var1().csharp_collection_string();
147        String name2 = var2().csharp_collection_string();
148        String dbc = "LlexLT".substring(1);
149        return name1 + "." + dbc + "(" + name2 + ")";
150      } else {
151        return "\"SeqComparison.java.jpp: sequence comparison does not apply to unordered collections unimplemented\" != null)"; // interned
152      }
153
154    }
155
156    if (format.isJavaFamily()) {
157      String name1 = var1().name_using(format);
158      String name2 = var2().name_using(format);
159
160      return "daikon.Quant."
161        + (var1().aux.hasOrder() ? "lexLT" : "setEqual" )
162        + "("
163        + name1
164        + ", "
165        + name2
166        + ")";
167
168    }
169
170    return format_unimplemented(format);
171  }
172
173  public String format_simplify(@GuardSatisfied SeqSeqStringLessThan this) {
174    if (Invariant.dkconfig_simplify_define_predicates) {
175      return format_simplify_defined();
176    } else {
177      return format_simplify_explicit();
178    }
179  }
180
181  private String format_simplify_defined(@GuardSatisfied SeqSeqStringLessThan this) {
182    String[] var1_name = var1().simplifyNameAndBounds();
183    String[] var2_name = var2().simplifyNameAndBounds();
184    if (var1_name == null || var2_name == null) {
185      return String.format("%s.format_simplify_defined(%s): var1_name=%s, var2_name=%s, for %s",
186                           getClass().getSimpleName(), this,
187                           Arrays.toString(var1_name), Arrays.toString(var2_name), format());
188    }
189    return "(|lexical-<| "
190      + var1_name[0] + " " + var1_name[1] + " " + var1_name[2] + " "
191      + var2_name[0] + " " + var2_name[1] + " " + var2_name[2] + ")";
192  }
193
194  private String format_simplify_explicit(@GuardSatisfied SeqSeqStringLessThan this) {
195
196      String classname = this.getClass().toString().substring(6);
197      return "warning: method " + classname
198        + ".format_simplify_explicit() needs to be implemented: " + format();
199
200  }
201
202  @Override
203  public InvariantStatus check_modified(
204      String @Interned [] v1, String @Interned [] v2, int count) {
205    /// This does not do the right thing; I really want to avoid comparisons
206    /// if one is missing, but not if one is zero-length.
207    // // Don't make comparisons with empty arrays.
208    // if ((v1.length == 0) || (v2.length == 0)) {
209    //   return;
210    // }
211
212    int comparison = 0;
213    if (orderMatters) {
214      // Standard element wise comparison
215       comparison = comparator.compare(v1, v2);
216    } else {
217      // Do a double subset comparison
218      comparison = (ArraysPlume.isSubset(v1, v2) && ArraysPlume.isSubset( v2, v1)) ? 0 : -1;
219    }
220
221    if (!(comparison < 0) ) {
222      return InvariantStatus.FALSIFIED;
223    }
224    return InvariantStatus.NO_CHANGE;
225  }
226
227  @Override
228  public InvariantStatus add_modified(String @Interned [] v1, String @Interned [] v2, int count) {
229    if (logDetail()) {
230      log("add_modified (%s, %s)", Arrays.toString(v1), Arrays.toString(v2));
231    }
232        return check_modified(v1, v2, count);
233  }
234
235  @Override
236  protected double computeConfidence() {
237
238    return 1 - Math.pow(.5, ppt.num_values());
239  }
240
241  @Pure
242  @Override
243  public boolean isSameFormula(Invariant o) {
244    return true;
245  }
246
247  @Pure
248  @Override
249  public boolean isExclusiveFormula(Invariant o) {
250    return false;
251  }
252
253  /**
254   * Since this invariant can be a postProcessed equality, we have to handle isObvious especially to
255   * avoid circular isObvious relations.
256   */
257  @Pure
258  @Override
259  public @Nullable DiscardInfo isObviousStatically_SomeInEquality() {
260    if (var1().equalitySet == var2().equalitySet) {
261      return isObviousStatically(this.ppt.var_infos);
262    } else {
263      return super.isObviousStatically_SomeInEquality();
264    }
265  }
266
267  /**
268   * Since this invariant can be a postProcessed equality, we have to handle isObvious especially to
269   * avoid circular isObvious relations.
270   */
271  @Pure
272  @Override
273  public @Nullable DiscardInfo isObviousDynamically_SomeInEquality() {
274    if (logOn()) {
275      log("Considering dynamically_someInEquality");
276    }
277    if (var1().equalitySet == var2().equalitySet) {
278      return isObviousDynamically(this.ppt.var_infos);
279    } else {
280      return super.isObviousDynamically_SomeInEquality();
281    }
282  }
283
284  @Pure
285  @Override
286  public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) {
287
288    return super.isObviousStatically(vis);
289  }
290
291  @Pure
292  @Override
293  public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) {
294    DiscardInfo super_result = super.isObviousDynamically(vis);
295    if (super_result != null) {
296      return super_result;
297    }
298    assert ppt != null;
299
300    return null;
301  }
302
303  @Override
304  public void repCheck() {
305    super.repCheck();
306    /*
307      This code is no longer needed now that the can_be_x's are gone
308    if (!(this.can_be_eq || this.can_be_lt || this.can_be_gt)
309        && ppt.num_samples() != 0) {
310      System.err.println(this.repr());
311      System.err.println(this.ppt.num_samples());
312      throw new Error();
313    }
314    */
315  }
316
317  @Pure
318  public boolean isEqual() {
319
320    return false;
321  }
322
323  // Look up a previously instantiated invariant.
324  public static @Nullable SeqSeqStringLessThan find(PptSlice ppt) {
325    assert ppt.arity() == 2;
326    for (Invariant inv : ppt.invs) {
327      if (inv instanceof SeqSeqStringLessThan) {
328        return (SeqSeqStringLessThan) inv;
329      }
330    }
331    return null;
332  }
333
334  /** Returns a list of non-instantiating suppressions for this invariant. */
335  @Pure
336  @Override
337  public @Nullable NISuppressionSet get_ni_suppressions() {
338    return suppressions;
339  }
340
341    private static @Nullable NISuppressionSet suppressions = null;
342
343  @Override
344  public @Nullable @NonPrototype SeqSeqStringLessThan merge(
345      @Prototype SeqSeqStringLessThan this, List<@NonPrototype Invariant> invs, PptSlice parent_ppt) {
346    // Ignore the orderMatters field, because it is always the same (and is always true).
347    return (SeqSeqStringLessThan) super.merge(invs, parent_ppt);
348  }
349}