001// ***** This file is automatically generated from CommonSequence.java.jpp 002 003package daikon.inv.unary.sequence; 004 005import daikon.*; 006import daikon.inv.*; 007import java.util.Arrays; 008import org.checkerframework.checker.interning.qual.Interned; 009import org.checkerframework.checker.lock.qual.GuardSatisfied; 010import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 011import org.checkerframework.dataflow.qual.Pure; 012import org.checkerframework.dataflow.qual.SideEffectFree; 013import org.plumelib.util.ArraysPlume; 014import org.plumelib.util.Intern; 015import typequals.prototype.qual.NonPrototype; 016import typequals.prototype.qual.Prototype; 017 018/** 019 * Represents sequences of double values that contain a common subset. Prints as 020 * {@code {e1, e2, e3, ...} subset of x[]}. 021 */ 022 023public class CommonFloatSequence extends SingleFloatSequence { 024 // We are Serializable, so we specify a version to allow changes to 025 // method signatures without breaking serialization. If you add or 026 // remove fields, you should change this number to the current date. 027 static final long serialVersionUID = 20030822L; 028 029 // Variables starting with dkconfig_ should only be set via the 030 // daikon.config.Configuration interface. 031 /** Boolean. True iff CommonSequence invariants should be considered. */ 032 public static boolean dkconfig_enabled = false; 033 034 /** Boolean. Set to true to consider common sequences over hashcodes (pointers). */ 035 public static boolean dkconfig_hashcode_seqs = false; 036 037 static final boolean debugCommonSequence = false; 038 039 private int elts = 0; 040 041 /** 042 * Null means no samples have been seen yet. 043 * Empty array means intersection is empty. 044 */ 045 private double @MonotonicNonNull [] intersect = null; 046 047 protected CommonFloatSequence(PptSlice ppt) { 048 super(ppt); 049 } 050 051 protected @Prototype CommonFloatSequence() { 052 super(); 053 } 054 055 private static @Prototype CommonFloatSequence proto = new @Prototype CommonFloatSequence(); 056 057 /** Returns the prototype invariant for CommonFloatSequence */ 058 public static @Prototype CommonFloatSequence get_proto() { 059 return proto; 060 } 061 062 /** returns whether or not this invariant is enabled */ 063 @Override 064 public boolean enabled() { 065 return dkconfig_enabled; 066 } 067 068 /** Sequences of hashcode values won't be consistent and are thus not printed by default. */ 069 @Override 070 public boolean instantiate_ok(VarInfo[] vis) { 071 072 if (!valid_types(vis)) { 073 return false; 074 } 075 076 return dkconfig_hashcode_seqs || vis[0].file_rep_type.baseIsFloat(); 077 } 078 079 /** instantiate an invariant on the specified slice */ 080 @Override 081 protected CommonFloatSequence instantiate_dyn(@Prototype CommonFloatSequence this, PptSlice slice) { 082 return new CommonFloatSequence(slice); 083 } 084 085 // this.intersect is read-only, so don't clone it 086 // public Object clone(); 087 088 @Override 089 public String repr(@GuardSatisfied CommonFloatSequence this) { 090 return "CommonFloatSequence " + varNames() + ": elts=\"" + elts; 091 } 092 093 private String printIntersect(@GuardSatisfied CommonFloatSequence this) { 094 if (intersect == null) { 095 return "{}"; 096 } 097 098 String result = "{"; 099 for (int i = 0; i < intersect.length; i++) { 100 result += intersect[i]; 101 if (i != intersect.length - 1) { 102 result += ", "; 103 } 104 } 105 result += "}"; 106 return result; 107 } 108 109 @SideEffectFree 110 @Override 111 public String format_using(@GuardSatisfied CommonFloatSequence this, OutputFormat format) { 112 if (format == OutputFormat.DAIKON) { 113 return format_daikon(); 114 } 115 if (format == OutputFormat.CSHARPCONTRACT) { 116 return format_csharp_contract(); 117 } 118 if (format == OutputFormat.SIMPLIFY) { 119 return format_simplify(); 120 } 121 122 return format_unimplemented(format); 123 } 124 125 public String format_daikon(@GuardSatisfied CommonFloatSequence this) { 126 return printIntersect() + " subset of " + var().name(); 127 } 128 129 public String format_csharp_contract(@GuardSatisfied CommonFloatSequence this) { 130 if (intersect == null) { 131 return "()"; 132 } 133 134 if (intersect.length == 1) { 135 String collection = var().csharp_collection_string(); 136 return collection + ".Contains(" + intersect[0] + ")"; 137 } 138 139 String exp = "("; 140 for (int i = 0; i < intersect.length; i++) { 141 exp += " " + intersect[i] + " "; 142 if (i != intersect.length - 1) { 143 exp += ","; 144 } 145 } 146 exp += ")"; 147 148 String[] split = var().csharp_array_split(); 149 return "Contract.ForAll(" + split[0] + ", x => x" + split[1] + ".OneOf" + exp + ")"; 150 } 151 152 private String format_simplify(@GuardSatisfied CommonFloatSequence this) { 153 if (intersect == null || intersect.length == 0) { 154 return "(AND)"; 155 } 156 String[] name = var().simplifyNameAndBounds(); 157 if (name == null) { 158 return format_unimplemented(OutputFormat.SIMPLIFY); 159 } 160 String idx; 161 if (!name[0].equals("|i|")) { 162 idx = "i"; 163 } else { 164 idx = "j"; 165 } 166 StringBuilder pre_buf = new StringBuilder(""); 167 StringBuilder end_buf = new StringBuilder(""); 168 for (int i = 0; i < intersect.length; i++) { 169 pre_buf.append("(EXISTS ("+idx + i + ") (AND "); 170 pre_buf.append("(>= "+idx + i + " " + name[1] + ") "); 171 pre_buf.append("(<= "+idx + i + " " + name[2] + ") "); 172 173 // Based on the class name, I originally wrote this method as if 174 // the invariant represented a common subsequence between two 175 // sequences (i.e. where the match was required to be in 176 // order). In case an invariant like that is added in the 177 // future, use the following: 178// if (i == 0) 179// pre_buf.append("(>= "+idx + i + " 0) "); 180// else if (i > 0) 181// pre_buf.append("(> "+idx + i + " "+idx+(i-1) +") "); 182// if (i == intersect.length - 1) 183// pre_buf.append("(< "+idx + i + " (select arrayLength " + name[0] + ")) "); 184 pre_buf.append("(EQ (select (select elems " + name[0] + ") "+idx + i + ") " 185 + simplify_format_double(intersect[i]) + ")"); 186 if (i == intersect.length - 1) { 187 pre_buf.append(" "); 188 } 189 end_buf.append("))"); 190 } 191 pre_buf.append(end_buf); 192 return pre_buf.toString(); 193 } 194 195 @Override 196 public InvariantStatus check_modified(double @Interned [] a, int count) { 197 if (a == null) { 198 return InvariantStatus.FALSIFIED; 199 } else if (intersect == null) { 200 return InvariantStatus.NO_CHANGE; 201 } else { 202 for (int i = 0; i < a.length; i++) { 203 if (Global.fuzzy.indexOf(intersect, a[i]) != -1) { 204 return InvariantStatus.NO_CHANGE; 205 } 206 } 207 return InvariantStatus.FALSIFIED; 208 } 209 } 210 211 @Override 212 public InvariantStatus add_modified(double @Interned [] a, int count) { 213 // System.out.println ("common: " + Arrays.toString (a)); 214 if (a == null) { 215 return InvariantStatus.FALSIFIED; 216 } else if (intersect == null) { 217 intersect = a; 218 return InvariantStatus.NO_CHANGE; 219 } 220 221 double[] tmp = new double[intersect.length]; 222 int size = 0; 223 for (int i = 0; i < a.length; i++) { 224 // if (a[i] in intersect) && !(a[i] in tmp), add a[i] to tmp 225 int ii = Global.fuzzy.indexOf(intersect, a[i]); 226 if ((ii != -1) 227 && (Global.fuzzy.indexOf(ArraysPlume.subarray(tmp,0,size), a[i]) == -1)) { 228 // System.out.println ("adding " + intersect[ii] + " at " + size); 229 230 // Carefully add the existing intersect value and not a[i]. These 231 // are not necessarily the same when fuzzy floating point 232 // comparisons are active. 233 tmp[size++] = intersect[ii]; 234 } 235 } 236 if (size == 0) { 237 return InvariantStatus.FALSIFIED; 238 } 239 240 intersect = ArraysPlume.subarray(tmp, 0, size); 241 242 intersect = Intern.intern(intersect); 243 elts++; 244 return InvariantStatus.NO_CHANGE; 245 } 246 247 @Override 248 protected double computeConfidence() { 249 return 1 - Math.pow(.9, elts); 250 } 251 252 @Pure 253 @Override 254 public boolean isSameFormula(Invariant other) { 255 assert other instanceof CommonFloatSequence; 256 return true; 257 } 258}