package OT; import java.util.*; /** * Gen-eval algorithm. * @version 1999-04-03 * @author Andrea Heiberg, University of Arizona */ public class GenEval { //Each "good" candidate constructed is added to allCandidates (for duplicate checking) private RepresentationSet allCandidates = new RepresentationSet(); //keys for the new candidates that are created are temporarily stored in newCandidates private Vector newCandidates = new Vector(); //keys for optimal candidates are stored in optimalCandidates private Vector optimalCandidates = new Vector(); private Debug debug; private Gen gen; private Hierarchy currentConstraintHierarchy = new Hierarchy(null); private Hierarchy constraintHierarchy; private int attemptedCounter = 1; private int duplicateCounter = 0; private int createdCounter = 1; private int gappedCounter = 0; private int logicCounter = 0; private int ocpCounter = 0; private int passCounter = 1; private int totalCounter = 1; private Representation input; private Single applet; public GenEval(Debug debug, Gen gen, Hierarchy constraintHierarchy, Representation input, Single applet) { this.constraintHierarchy = constraintHierarchy; this.applet = applet; this.debug = debug; this.gen = gen; this.input = input; } //end constructor public RepresentationSet eval(long c, long t) { //print out information on the constraint hierarchy StringBuffer sb = new StringBuffer(); sb.append("Constraint hierarchy (" + constraintHierarchy.size() + " constraints):\n"); int constraintCounter = 1; for (Enumeration e = constraintHierarchy.elements(); e.hasMoreElements();) { Constraint b = (Constraint)e.nextElement(); sb.append(" " + constraintCounter + ": " + b.toString() + "\n"); constraintCounter++; } //end for debug.write(sb.toString()); sb = null; //put input in relevant sets Integer inputNum = new Integer(totalCounter++); String inputKey = input.getKey(); allCandidates.put(inputNum, inputKey, input); optimalCandidates.addElement(inputKey); //while there are more constraints Enumeration h = constraintHierarchy.elements(); while (h.hasMoreElements()) { debug.write("TOP OF LOOP, PASS " + passCounter); //get the next constraint Constraint constraint = (Constraint)h.nextElement(); debug.write(" Current constraint: " + constraint.toString()); currentConstraintHierarchy.addElement(constraint); //evaluate optimalCandidates on the current constraint for (Enumeration w = optimalCandidates.elements(); w.hasMoreElements();) { String key = (String)w.nextElement(); Representation candidate = (Representation)allCandidates.get(key); candidate.putViolations(constraint, constraint.evaluate(candidate, input)); } //end for if (optimalCandidates.size()>1) { //cull the optimalCandidates set on the current constraint only //(we've already culled the optimalCandidates on the higher ranked constraints) cullOptimalCandidates(constraint); } //end if if (gen.size()>0) { //try to create some more candidates //get the set of GEN operations relevant to this constraint Vector relevantOperations = gen.getByFeatureType(constraint.featureType1, constraint.featureType2); //create candidates from optimalCandidates and GEN operations newCandidates = createCandidates(optimalCandidates, relevantOperations, constraint.global); if (newCandidates.size() > 0) { //add newCandidates to optimalCandidates for (Enumeration k = newCandidates.elements(); k.hasMoreElements();) { String key = (String)k.nextElement(); Representation rep = (Representation)allCandidates.get(key); optimalCandidates.addElement(key); } //end for //evaluate the candidates we just created on the current constraint hierarchy for (Enumeration i = currentConstraintHierarchy.elements(); i.hasMoreElements();) { Constraint b = (Constraint)i.nextElement(); for (Enumeration k = newCandidates.elements(); k.hasMoreElements();) { String key = (String)k.nextElement(); Representation candidate = (Representation)allCandidates.get(key); if (optimalCandidates.contains(key)) { if (candidate.getViolations(b).intValue()==-1) { //haven't done this evaluation yet candidate.putViolations(b, b.evaluate(candidate, input)); } //end if } //end if } //end for //cull optimalCandidates cullOptimalCandidates(b); } //end for //reset newCandidates newCandidates.removeAllElements(); } //end if //cull GEN operations for this constraint gen = constraint.cullGen(gen); } //end if passCounter++; } //end while totalCounter--; sb = new StringBuffer(); sb.append("\n" + "all candidates:\n"); int sorted[] = allCandidates.sort(); for (int i = 0; i <= sorted.length-1; i++) { int key = sorted[i]; Representation rep = (Representation)allCandidates.get(new Integer(key)); sb.append(rep.printViolations(constraintHierarchy) + " c" + key + " " + rep.toOrthography() + "\n"); } //end for /* sb.append("\n" + "maximum # of candidates to attempt = " + t + "\n"); int p1 = new Float((new Float(attemptedCounter).floatValue()/new Float(t).floatValue())*100).intValue(); sb.append("actual # of candidates attempted = " + attemptedCounter + ", " + p1 + "%" + "\n"); sb.append("# of attempted candidates rejected due to logic = " + logicCounter + "\n"); */ sb.append("# of candidates created = " + createdCounter + "\n"); sb.append("# of created candidates rejected due to OCP = " + ocpCounter + "\n"); sb.append("# of created candidates rejected due to gapping = " + gappedCounter + "\n"); sb.append("# of created candidates rejected due to duplication = " + duplicateCounter + "\n"); int p2 = new Float((new Float(totalCounter).floatValue()/new Float(c).floatValue())*100).intValue(); sb.append("# of candidates evaluated = " + totalCounter + " (" + c + " possible, " + p2 + "%)" + "\n"); sb.append("# of optimal candidates = " + optimalCandidates.size() + "\n"); for (Enumeration e = optimalCandidates.elements(); e.hasMoreElements();) { String key = (String)e.nextElement(); Integer num = allCandidates.getNum(key); Representation rep = (Representation)allCandidates.get(key); sb.append(" c" + num + " " + rep.toOrthography() + ":\n" + rep.toString()); rep.isOptimal = true; } //end for debug.write(sb.toString()); sb = null; return allCandidates; } //end eval private boolean globalDone (Vector operations) { boolean enough = true; //determine minPasses Enumeration z=operations.elements(); Operation op = (Operation)z.nextElement(); NodeSet anchors = input.getAnchors(op.featureType.anchor); int minPasses = anchors.size(); Enumeration e=operations.elements(); while ((e.hasMoreElements()) && (enough)) { Operation o = (Operation)e.nextElement(); if (o.appliedCounter < minPasses) { enough = false; } //end if } //end while return enough; } //end globalDone private Vector createCandidates(Vector seeds, Vector operations, boolean global) { //make new candidates from seeds boolean duplicate; Vector created = new Vector(); long osize = operations.size(); long ssize = seeds.size(); debug.write(" " + osize + " operations * " + ssize + " candidates = " + osize*ssize + " potential new candidates"); for (Enumeration k = seeds.elements(); k.hasMoreElements();) { String key = (String)k.nextElement(); Representation rep = (Representation)allCandidates.get(key); Integer num = allCandidates.getNum(key); int count = 1; //try each GEN operation on each candidate for (Enumeration e = operations.elements(); e.hasMoreElements();) { StringBuffer sb = new StringBuffer(); Operation operation = (Operation)e.nextElement(); String os = operation.toString(); sb.append(" trying " + count + " " + os + " on c" + num + "\n"); count++; attemptedCounter++; if (!(rep.operationsTried.contains(os))) { //we haven't already tried this operation on this representation rep.operationsTried.addElement(os); if (operation.test(rep)) { //we will be able to apply operation to candidate Representation candidate = rep.copy(); //make a new candidate from rep operation.apply(candidate); createdCounter++; if (operation.canCreateGaps && candidate.gapped(operation)) { gappedCounter++; sb.append(" candidate is gapped\n"); } else { //new candidate is not gapped; continue if (operation.canCreateOCPViolation && candidate.ocp(operation.feature)) { //OCP violation ocpCounter++; sb.append(" candidate violates OCP\n"); } else { //new candidate does not violate OCP; continue //check to see if we have already made this candidate String newKey = candidate.getKey(); Representation d = (Representation)allCandidates.get(newKey); if (d==null) { //not a duplicate; add this candidate to the set Integer newNum = new Integer(totalCounter++); created.addElement(newKey); allCandidates.put(newNum, newKey, candidate.copy()); operation.appliedCounter++; String o = candidate.toOrthography(); sb.append(" added c" + newNum + " " + o + ":\n" + candidate.toString() + "\n"); applet.message("added c" + newNum + " " + o); } else { Integer dupNum = allCandidates.getNum(d.getKey()); sb.append(" duplicate of c" + dupNum + "\n"); } //end if } //end if } //end if } else { logicCounter++; sb.append(" couldn't apply operation to c" + num + "\n"); } //end if } else { sb.append(" already tried operation on c" + num + "\n"); } //end if debug.write(sb.toString()); } //end for } //end for debug.write("Created " + created.size() + " new candidates"); if (global) { //constraint is global if (created.size() > 0) { //we did make some new candidates this round if (!globalDone(operations)) { //we haven't applied all operations enough times debug.write("global constraint, trying operations on " + created.size() + " candidates just created"); Vector next = createCandidates(created, operations, global); for (Enumeration e=next.elements(); e.hasMoreElements();) { String key = (String)e.nextElement(); created.addElement(key); } //end for } //end if } //end if } //end if created.trimToSize(); return created; } //end createCandidates private void cullOptimalCandidates(Constraint constraint) { StringBuffer sb = new StringBuffer(); sb.append(" Culling candidates on " + constraint + "\n " + optimalCandidates.size() + " original optimalCandidates\n"); //find the optimalCandidates optimalCandidates = constraint.getOptimalCandidates(optimalCandidates, allCandidates); sb.append(" " + optimalCandidates.size() + " new optimalCandidates\n"); debug.write(sb.toString()); sb = null; } //end cullOptimalCandidates }