/* * JFLAP - Formal Languages and Automata Package * * * Susan H. Rodger * Computer Science Department * Duke University * August 27, 2009 * Copyright (c) 2002-2009 * All rights reserved. * JFLAP is open source software. Please see the LICENSE for terms. * */ package pumping; import java.io.Serializable; import java.util.*; import gui.environment.Universe; /** * A ContextFreePumpingLemma is a PumpingLemma that * handles the five string segments that w is broken into, uvxyz. * * @author Jinghui Lim & Chris Morgan * */ public abstract class ContextFreePumpingLemma extends PumpingLemma implements Serializable, Cloneable { /** * The u segment of the w. */ protected String u; /** * The v segment of the w. */ protected String v; /** * The x segment of the w. */ protected String x; /** * The y segment of the w. */ protected String y; /** * The z segment of the w. */ protected String z; /** * Returns segment u of the decomposition. * * @return u of the decomposition */ public String getU() { return u; } /** * Returns segment v of the decomposition. * * @return v of the decomposition */ public String getV() { return v; } /** * Returns segment x of the decomposition. * * @return x of the decomposition */ public String getX() { return x; } /** * Returns segment y of the decomposition. * * @return y of the decomposition */ public String getY() { return y; } /** * Returns segment z of the decomposition. * * @return z of the decomposition */ public String getZ() { return z; } public String getDecompositionAsString() { String[] s = new String[5]; int counter = 0; for (int i=0; i<=3; i++) { s[i] = w.substring(counter, counter + myDecomposition[i]); counter += myDecomposition[i]; } s[4] = w.substring(counter); for (int i=0; ii. * * @see #setDecomposition(int[], int) * @param decomposition the array that contains the length of each part of the decomposition * @return true if this deocmposition is legal, false otherwise */ public boolean setDecomposition(int[] decomposition) { myDecomposition = decomposition; int uLength = decomposition[0]; int vLength = decomposition[1]; int xLength = decomposition[2]; int yLength = decomposition[3]; if(vLength + xLength + yLength > m || vLength + yLength < 1) return false; u = w.substring(0, uLength); v = w.substring(uLength, uLength + vLength); x = w.substring(uLength + vLength, uLength + vLength + xLength); y = w.substring(uLength + vLength + xLength, uLength + vLength + xLength + yLength); z = w.substring(uLength + vLength + xLength + yLength); return true; } /** * Sets i and chooses the decomposition, with the length of * each part of the decomposition in the corresponding space of the * input array. That is, |u| = decomposition[0], * |v| = decomposition[1], * |x| = decomposition[2], * |y| = decomposition[3]. * * @param decomposition the array that contains the length of each part of the decomposition * @param num the number to set i to * @return true if this decomposition is legal and has not been tried * before, false otherwise */ public boolean setDecomposition(int[] decomposition, int num) { i = num; return setDecomposition(decomposition); } /** * Returns the pumped string uvixyiz * according the the decomposition and choice of i. * * @return the pumped string, uvixyiz */ public String createPumpedString() { return u + pumpString(v, getI()) + x + pumpString(y, getI()) + z; } /** * Adds the decomposition to the list that the user has done. If the case is not * a legal decomposition, the it returns -1. If the case has already * been done, it returns the index of the case. If it hasn't been done, it moves * the case to the "done" list and returns its position in the done list. * * @param decomposition the decomposition we wish to add * @return -1 if it is an illegal decomposition, the index of the * decomposition if it has already been done, or a number greater than or equal * to the total number of cases, which can be found by calling * {@link PumpingLemma#numCasesTotal()}. */ public int addCase(int[] decomposition, int num) { /* * addCase(int[]) should only be called after chooseDecomposition(int[]), * so it should be a legal decomposition and uvxyz should have been set. * Nonetheless, we check here. */ if(!setDecomposition(decomposition)) return -1; /* * Check if this case has been done. */ for(int j = 0; j < myDoneCases.size(); j++) { if(((Case)(myDoneCases.get(j))).isCase(v, y)) return j; } /* * Since case has not been done, find the case and put it into the * "done" pile. */ for(int j = 0; j < myAllCases.size(); j++) { Case c = (Case)myAllCases.get(j); if(c.isCase(v, y)) { c.setI(num); c.setUserInput(decomposition); myDoneCases.add(c); return myAllCases.size(); } } System.err.println("BUG FOUND: ContextFreePumpingLemma.addCase(int[], int)"); return -1; } public boolean replaceCase(int[] decomposition, int num, int index) { Case c = (Case)myDoneCases.get(index); if(c.isCase(v, y)) { c.setI(num); c.setUserInput(decomposition); return true; } return false; } /** * Checks to see whether a given v,y decomposition matches a case currently * in myDoneCases. * * @param v segment v of the decomposition * @param y segment y of the decomposition */ /*protected boolean decompMatchesUnusedCase(String v, String y) { Case cAll, cDone; Iterator iAll, iDone; boolean alreadyDone, toReturn; toReturn = false; iAll = myAllCases.iterator(); while (iAll.hasNext()) { alreadyDone = false; cAll = (Case) iAll.next(); if (cAll.isCase(v, y)) { iDone = myDoneCases.iterator(); while (iDone.hasNext()) { cDone = (Case) iDone.next(); if (cDone.isCase(v, y)) alreadyDone = true; } if (!alreadyDone) toReturn = true; } } return toReturn; }*/ /** * For values with cases, chooses a decomposition that corresponds to the first case that * hasn't currently been added to the casePanel */ /* protected void chooseDecompositionWithCases() { String v, x, y; int[] decomp; boolean matchesUnusedCase; int size = w.length(); for (int a=0; a= 1) { matchesUnusedCase = decompMatchesUnusedCase(v, y); if (matchesUnusedCase) { decomp = new int[] {a, b-a, c-b, d-c}; setDecomposition(decomp); return; } } } }*/ /** * Chooses a random decomposition, with it randomly spread over the string. * |vy| >= 1 && |vxy| <= m; */ private void chooseDecompositionWithoutCases() { int temp, counter; int[] decomp = new int[4]; counter = 0; temp = 0; //Some ugly code... decomp[0] = LemmaMath.fetchRandInt(0, w.length() - 1); counter += decomp[0]; temp = Math.min(w.length() - counter, m); decomp[1] = LemmaMath.fetchRandInt(0, temp); if (decomp[1] == w.length() - counter) { decomp[2] = 0; decomp[3] = 0; } else { counter += decomp[1]; temp = Math.min(w.length() - counter - 1, m-1); decomp[2] = LemmaMath.fetchRandInt(0, temp); counter += decomp[2]; temp = Math.min(w.length() - counter, m - decomp[2]); if (decomp[1] > 0) decomp[3] = LemmaMath.fetchRandInt(0, temp); else decomp[3] = LemmaMath.fetchRandInt(1, temp); } setDecomposition(decomp); } /** * Chooses a random context-free decomposition, ignoring cases. */ public void chooseDecomposition() { // Currently just chooses a decomposition without cases. The code for choosing it // with cases is currently commented out, but can be added if desired. chooseDecompositionWithoutCases(); } }