/*
* 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();
}
}