/**********************************************************
*This program is part of Chen (2014) "Probabilistic *
*Selection of Input in Morphophonological Acquisition". *
*The algorithm is introduced in Ch.4 of the above work *
*and intends to model the diachronic reduction of Tone 3 *
*in Standard Mandarin as a result of morphophonological *
*acquisition. *
*This source code can be modified without permission, but*
*it is necessary to include the citation of the above *
*work in the modified code. *
* Tsung-Ying Chen Jul 23rd, 2014 *
*********************************************************/
import java.util.Random;
import java.util.HashSet;
import java.util.Set;
public class TaiwanMan
{
//Collection of output types and types that are exceptions to the two unnatural constraints
protected static Set OutputType1 = new HashSet(),
OutputType2 = new HashSet(),
ExcepUnCon1 = new HashSet(),
ExcepUnCon2 = new HashSet();
//Number of learning generations
public static final int Generation = 10, SimulationNum = 10;
//Longest Sentence Length
public static final int S_L = 5, P_Inv = 100, M_Inv = 1000;
public static final int learnCycP = 10000, learnCycM = 100000;
public final double decay = 0.0005;
//Input sentence template
public String InputPhr[] = new String[S_L];
public String ChildPhr[] = new String[S_L];
public String Word_Seq[] = new String[S_L];
public String Stage = "";
public static String ResultInd = "", ResultFinal = "", PrintMode = "Yes";
//The probability of eighteen T3 words in Non-Final position
public static double NonFinal18[] =
{0.6, 0.3, 2.6, 0.3, 0.4, 0.3, 1.6, 7.7, 2.5, 0.3, 0.5,
1.1, 7.3, 2.2, 1.3, 10.1, 25.4, 32.8};
//The probability of eighteen T3 words in Final position
public static double Final18[] =
{8.3, 2.6, 17.9, 16.2, 2, 1.3, 5.3, 25.2, 7.6, 1, 1.3,
2.6, 2.6, 0.7, 0.3, 1.7, 2, 1.3};
//Probabilities of each tone to be selected in each slot: 55, 24, 214, 51
//Type frequency see Zhang & Lai (2010)
public static double T_InvenProb[] = {16.7,18.4,14.8,42.5,7.6};
//Tonal Inventory, 224 stands for misperceived T3, 234 stands for T2 changed
//from T3 after third tone sandhi rule.
public final String T_Inven[] = {"T1","T2","T3","T4","T0"};
//Learner's lexical frequency of the 18 words in non-final positions
public static double FreqNonFinal18[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//Learner's lexical frequency of the 18 words in final positions
public static double FreqFinal18[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//Learners's experience of each allomorph (214, 21, 234) of the 18 words
public static double allomorphFreq[][] =
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //214
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //21
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; //234
//Learner's error productions using an allomorph of the 18 words
public static double allomorphER[][] =
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //214
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //21
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; //234
//Learner's target productions using an allomorph of the 18 words
public static double allomorphTarget[][] =
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //214
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //21
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; //234
//Learner's Inefficiency of Target Production using an allomorph of the 18 words
public static double allomorphIEP[][] =
{{0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001}, //214
{0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001}, //21
{0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001}}; //234
//Learner's SP of each allomorph of the 18 words
public static double allomorphSP[][] =
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //214
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //21
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; //234
public static double AdultSP[][] =
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //214
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //21
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; //234
//T3 selection probability: 214, 21, 234
public static double Adult_T3Prob[] = {100,0,0};
public static double Child_T3Prob[] = {0,0,0};
public static double temp_T3Prob[] = {0,0,0};
//T2 selection probability: 24, 224
// public static double Adult_T2Prob[] = {100,0};
// public static double Child_T2Prob[] = {0,0};
//Misperception of T3 as T2 probability (%)
// public final double misperProb = 40, alphaLevel = 0.05;
//Constraint set: *NonFinalMLH, *LAPSE, *OCP-MLH >> *MLH >> IdentMLH->H|HL >> IdentMLH->MH >> IdentMLH->ML; MH->ML, MH|ML->MLH
public static double CON[] = {100,100,100,95,10,5,0,0,0};
public static double AdultCON[] = {0,0,0,0,0,0,0,0,0};
public static boolean UnCon[] = {false, false};
//Averaged zone for printing results
//Average Results
public static double AverageSP[][][] = new double[Generation][allomorphFreq.length][allomorphFreq[0].length];
public static double AverageIndSP[][][] = new double[learnCycM/M_Inv][allomorphFreq.length][allomorphFreq[0].length];
public static double AverageIEP[][][] = new double[Generation][allomorphFreq.length][allomorphFreq[0].length];
public static double AverageIndIEP[][][] = new double[learnCycM/M_Inv][allomorphFreq.length][allomorphFreq[0].length];
//Averaged constraints value at the P and M stages
public static double AveragePCON[][] = new double[Generation][CON.length];
public static double AverageIndPCON[][] = new double[learnCycP/P_Inv][CON.length];
public static double AverageMCON[][] = new double[Generation][CON.length];
public static double AverageIndMCON[][] = new double[learnCycM/M_Inv][CON.length];
public static double AverageOutputNum[][][] = new double[Generation][allomorphFreq.length][allomorphFreq[0].length];
//Averaged number of output types and exceptions
public static double AverageOutputandExcep[][] = new double[Generation][4];
//Empty Violation Profile: There are four phonological processes, and thus 16 possible
//outputs (faithful, Optimal, 1234, 123, 124, 134, 234, 12, 13, 14, 23, 24, 34, 1, 2, 3, 4)
public static int VIO[][] = {{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0}};
public static int testFinal18 = 0;
public static void main(String[] args)
{
TaiwanMan tm = new TaiwanMan();
RichLexiconFile rlf = new RichLexiconFile();
//Initialize Average Variables
for(int i=0;i();
OutputType2 = new HashSet();
ExcepUnCon1 = new HashSet();
ExcepUnCon2 = new HashSet();
}
//Average the results by the end of each generation
for(int j=0;j100)
{
random = 100;
}
else if(random<0)
{
random = 0;
}
//Select a tonal category.
for(int k=0;k99.99)
{
temp = 100.000000001;
}
//If the randomly generated probability is smaller than the
//current accumulated probability, make the decision of
//selecting the tonal category from the random ordering.
if(random100)
{
random = 100;
}
else if(random<0)
{
random = 0;
}
//Select which word to produce first according to the distributional
//probability of T3 words
for(int k=0;k99.99)
{
temp = 100.000000001;
}
if(random100)
{
random = 100;
}
else if(random<0)
{
random = 0;
}
//Select a tonal category.
for(int k=0;k99.99)
{
temp = 100.000000001;
}
//If the randomly generated probability is smaller than the
//current accumulated probability, make the decision of
//selecting the tonal category from the random ordering.
if(random100)
{
random = 100;
}
else if(random<0)
{
random = 0;
}
//Select a tonal category.
for(int k=0;k99.99)
{
temp = 100.000000001;
}
//If the randomly generated probability is smaller than the
//current accumulated probability, make the decision of
//selecting the tonal category from the random ordering.
if(random100)
{
random = 100;
}
else if(random<0)
{
random = 0;
}
//Since there are 3 allotones for T3, the random ordering
//process is more complicated, which is identical to that
//of randomly selecting a tonal category above.
for(int k=0;k<3;k++)
{
//Change: Use adult's SP to determine the selection of T3 allotones
random2 = rn.nextInt(3);
if(rnChks.indexOf(","+random2+",")<0)
{
rnChks += ","+random2+",";
rnChk[k] = random2;
}
else
{
k--;
}
}
for(int k=0;k99.99)
{
temp = 100.000000001;
}
//Insert the T3 allomorph of a word.
if(random-1)
{
//Identify which T3 word it is
for(int l=0;l-1)
{
switch(Integer.parseInt(InputPhr[k]))
{
case 214:
allomorphFreq[0][l]++;
break;
case 21:
allomorphFreq[1][l]++;
break;
case 24:
allomorphFreq[2][l]++;
break;
}
//Update SP after the change in frequency
allomorphSP[0][l] = 100*allomorphFreq[0][l]/allomorphIEP[0][l]/(allomorphFreq[0][l]/allomorphIEP[0][l]+allomorphFreq[1][l]/allomorphIEP[1][l]+allomorphFreq[2][l]/allomorphIEP[2][l]);
allomorphSP[1][l] = 100*allomorphFreq[1][l]/allomorphIEP[1][l]/(allomorphFreq[0][l]/allomorphIEP[0][l]+allomorphFreq[1][l]/allomorphIEP[1][l]+allomorphFreq[2][l]/allomorphIEP[2][l]);
allomorphSP[2][l] = 100*allomorphFreq[2][l]/allomorphIEP[2][l]/(allomorphFreq[0][l]/allomorphIEP[0][l]+allomorphFreq[1][l]/allomorphIEP[1][l]+allomorphFreq[2][l]/allomorphIEP[2][l]);
//Replace the T3 word with an allotone based on learner's SP
//Since there are 3 allotones for T3, the random ordering
//process is more complicated, which is identical to that
//of randomly selecting a tonal category above.
for(int m=0;m<3;m++)
{
//Change: Use adult's SP to determine the selection of T3 allotones
random2 = rn.nextInt(3);
if(rnChks.indexOf(","+random2+",")<0)
{
rnChks += ","+random2+",";
rnChk[m] = random2;
}
else
{
m--;
}
}
random = rn.nextInt(100)+rn.nextGaussian();
if(random>100)
{
random = 100;
}
else if(random<0)
{
random = 0;
}
for(int m=0;m<3;m++)
{
temp += allomorphSP[rnChk[m]][l];
if(temp>99.99)
{
temp = 100.000000001;
}
//Insert the T3 allomorph of a word.
if(randomML
if(OptOut[i]=="21" && UR[i]=="214")
{
LocalVIO[0][6]++;
URequalOpt = false;
}
//Change from 214 to 24 violates IdentMLH->MH
if(OptOut[i]=="24" && UR[i]=="214")
{
LocalVIO[0][5]++;
URequalOpt = false;
}
//For any other unfaithful IO-correspondence
if(OptOut[i]!=UR[i])
{
LocalVIO[0][4]++;
URequalOpt = false;
}
//Any 214 in the output violates *MLH
if(OptOut[i]=="214")
{
LocalVIO[0][3]++;
}
//If the two unnatural constraints are created, also evaluate their violations
//for the optimal output
if(UnCon[0]==true | UnCon[1]==true)
{
if(UnCon[0]==true && i=maxVAL)
{
//Remember the constraint weight and the
//constraint.
maxVAL = CONtemp[j];
maxCON = j;
}
}
//Assign a transferred value to replace the original
//constraint value, which is 10000000 divided by
//10's power of i
if(maxVAL!=preMaxVAL)
{
conRank[maxCON] = 100000000/Math.pow(10.0, 1.0*i);
evenMax = 0;
}
else
{
evenMax++;
conRank[maxCON] = 100000000/Math.pow(10.0, 1.0*(i-evenMax));
}
preMaxVAL = maxVAL;
//Set the constraint value of the ranked constraint
//to negative, so it won't be ranked again.
CONtemp[maxCON] = -100000000;
//Reset the current highest value.
maxVAL = -100000000;
}
//Decide the violation value
for(int i=0;i1 && conVio[i]==0)
{
conVio[i]=100000000;
}
//Search for the optimal output that has the
//least violation (values).
if(conVio[i]vioCancel[1][i])
{
//Cancel the violation marks
vioCancel[0][i] -= vioCancel[1][i];
vioCancel[1][i] = 0;
}
else if(vioCancel[0][i]0)
{
HarBounded = false;
}
}
//Generate the optimal output string
for(int i=0;i0)
{
OptString[i] = "214";
}
//If UR is 214 in any position and IdentMLH->H|HL is violated,
//214 must surface as 55 (or 51) in this winning output
else if(UR[i]=="214" && LocalVIO[leastVioCAND][4]>0)
{
OptString[i] = "55";
}
//If UR is 214 in any position and IdentMLH->MH is violated
//214 must surface 24 in this winning output
else if(UR[i]=="214" && LocalVIO[leastVioCAND][5]>0)
{
OptString[i] = "24";
}
//If UR is 214 in any position and IdentMLH->ML is violated
//214 must surface as 24 in this winning output
else if(UR[i]=="214" && LocalVIO[leastVioCAND][6]>0)
{
OptString[i] = "21";
}
//If UR is 24 in any position and MH->ML is violated
//24 must surface as 21 via the unnatural alternation in this winning output
else if(UR[i]=="24" && LocalVIO[leastVioCAND][7]>0)
{
OptString[i] = "21";
}
//If UR is 24 or 21 in the final position and MH|ML->MLH is violated
//24 or 21 must surface as 214 via the unnatural alternation in this winning output
else if((UR[i]=="24" | UR[i]=="21") && i==PhrLn-1 && LocalVIO[leastVioCAND][8]>0)
{
OptString[i] = "214";
}
else
{
OptString[i] = UR[i];
}
}
//Check the number of winner-preferring constraints and
//the number of loser-preferring constraints
for(int i=0;i0)
{
numOfWinP++;
if(CONtemp2[i]>=maxWinP)
{
maxWinP = CONtemp2[i];
}
}
}
for(int i=0;i0)
{
if(CONtemp2[i]>maxWinP)
{
numOfUndLosP++;
}
else
{
vioCancel[0][i]=0;
}
}
}
//Update Error Penalty
if(LearnStage=="M")
{
//Scan for mismatch between the optimal output and the target output
for(int i=0;i-1 && OptString[i]!=OptOut[i])
{
for(int j=0;j-1)
{
//Encode errors for different allotone
switch(Integer.parseInt(UR[i]))
{
case 214:
allomorphER[0][j]++;
allomorphIEP[0][j] = (allomorphER[0][j]+0.5)/(allomorphER[0][j]+allomorphTarget[0][j]+1);
break;
case 21:
allomorphER[1][j]++;
allomorphIEP[1][j] = (allomorphER[1][j]+0.5)/(allomorphER[1][j]+allomorphTarget[1][j]+1);
break;
case 24:
allomorphER[2][j]++;
allomorphIEP[2][j] = (allomorphER[2][j]+0.5)/(allomorphER[2][j]+allomorphTarget[2][j]+1);
break;
}
break;
}
}
}
}
}
//Change the original constraint weights after Mark
//Cancellation.
for(int i=0;i=1)
{
if(!HarBounded)
{
CON[i] -= plasticity;
//Maintain Intrinsic Ranking between *NonFinalMLH >> *MLH
if(i==0)
{
if(CON[0]-CON[3]<5)
{
CON[3] -= plasticity;
}
}
//Maintain Intrinsic Ranking between Ident Constraints
if(i>3 && i<7)
{
if(i==4 && CON[i]-CON[i+1]<5)
{
CON[i+1] -= plasticity;
if(CON[i+1]-CON[i+2]<5)
{
CON[i+2] -= plasticity;
}
}
if(i==5 && CON[i]-CON[i+1]<5)
{
CON[i+1] -= plasticity;
}
}
}
}
//Increase the constraint value that prefers the winner.
if(vioCancel[1][i]>=1)
{
if(!HarBounded)
{
CON[i] += plasticity*(numOfUndLosP/(numOfWinP+1));
//Maintain Intrinsic Ranking between *NonFinalMLH >> *MLH
if(i==3)
{
if(CON[0]-CON[3]<5)
{
CON[0] += plasticity*(numOfUndLosP/(numOfWinP+1));
}
}
//Maintain Intrinsic Ranking between Ident Constraints
if(i>3 && i<7)
{
if(i==6 && CON[i-1]-CON[i]<5)
{
CON[i-1] += plasticity*(numOfUndLosP/(numOfWinP+1));
if(CON[i-2]-CON[i-1]<5)
{
CON[i-2] += plasticity*(numOfUndLosP/(numOfWinP+1));
}
}
if(i==5 && CON[i-1]-CON[i]<5)
{
CON[i-1] += plasticity*(numOfUndLosP/(numOfWinP+1));
}
}
}
}
}
}
//If the target output is generated...accumulate the number of targets...
else
{
if(LearnStage=="M")
{
//Scan for T3 words to accumulate the number of target outputs
//generated by selected allomorphs
for(int i=0;i-1)
{
for(int j=0;j-1)
{
//Encode errors for different allotone and Update IEP
switch(Integer.parseInt(UR[i]))
{
case 214:
allomorphTarget[0][j]++;
allomorphIEP[0][j] = (allomorphER[0][j]+0.5)/(allomorphER[0][j]+allomorphTarget[0][j]+1);
break;
case 21:
allomorphTarget[1][j]++;
allomorphIEP[1][j] = (allomorphER[1][j]+0.5)/(allomorphER[1][j]+allomorphTarget[1][j]+1);
break;
case 24:
allomorphTarget[2][j]++;
allomorphIEP[2][j] = (allomorphER[2][j]+0.5)/(allomorphER[2][j]+allomorphTarget[2][j]+1);
break;
}
break;
}
}
}
}
}
}
//Scan the output types
for(int i=0;i1)
{
OutputType1.add(temp);
}
OutputType2.add(temp);
temp = "";
}
//Evaluate whether unnatural constraints are created
if(ExcepUnCon1.size()<(OutputType1.size()/Math.log(OutputType1.size())))
{
UnCon[0] = true;
}
else
{
UnCon[0] = false;
}
if(ExcepUnCon2.size()<(OutputType2.size()/Math.log(OutputType2.size())))
{
UnCon[1] = true;
}
else
{
UnCon[1] = false;
}
//Reset Violation Profiles
for(int i=0;i(LocalCON[4]+2*rn.nextGaussian()) |
(LocalCON[3]+2*rn.nextGaussian())>(LocalCON[4]+2*rn.nextGaussian()))
{
input[i]="21";
}
}
else
{
if((LocalCON[3]+2*rn.nextGaussian())>(LocalCON[4]+2*rn.nextGaussian()))
{
input[i]="21";
}
}
}
//Third-Tone Sandhi
for(int i=0;i(LocalCON[4]+2*rn.nextGaussian()))
input[i]="24";
}
}
//Unnatural phrasal final rising. If the difference in the constraint value
//between FinalRising and Ident-T is more than 5, change phrase-final 21 to
//214.
if(input[PhrLn-1]=="24" && UnCon[0]==true)
{
if((LocalCON[7]+2*rn.nextGaussian())>(LocalCON[5]+2*rn.nextGaussian()))
{
input[PhrLn-1]="21";
}
}
if(input[PhrLn-1]=="24" && UnCon[1]==true)
{
if((LocalCON[8]+2*rn.nextGaussian())>(LocalCON[6]+2*rn.nextGaussian()))
{
input[PhrLn-1]="214";
}
}
if(input[PhrLn-1]=="21" && UnCon[1]==true)
{
if((LocalCON[8]+2*rn.nextGaussian())>(LocalCON[7]+2*rn.nextGaussian()))
{
input[PhrLn-1]="214";
}
}
}
return input;
}
//Simulated Elicitation Task
public void Production(double[][] T3_SP, double[] LocalCON, int Genre)
{
int OutputNumber[][] = new int[T3_SP.length][T3_SP[0].length];
int random2 = 0, Chk[] = new int[3];
String Chks = "", UR = "";
Random rn = new Random();
double random = 0, temp = 0;
for(int i=0;i100)
{
random = 100;
}
for(int k=0;k<3;k++)
{
//Change: Use adult's SP to determine the selection of T3 allotones
random2 = rn.nextInt(3);
if(Chks.indexOf(","+random2+",")<0)
{
Chks += ","+random2+",";
Chk[k] = random2;
}
else
{
k--;
}
}
for(int k=0;k99.99)
{
temp = 100.000000001;
}
if(randomML dominates *MLH,
//UR 214 surfaces as 214, otherwise 21
if(UR=="214")
{
if((LocalCON[6]+2*rn.nextGaussian())>(LocalCON[3]+2*rn.nextGaussian()))
{
OutputNumber[0][i]++;
}
else
{
OutputNumber[1][i]++;
}
}
//Final Concave, in a final position, if FinalConcave dominates IdentMLH->ML
//UR 21 surface as 214, otherwise 21
if(UR=="21")
{
if(UnCon[0] && (LocalCON[7]+2*rn.nextGaussian())>(LocalCON[6]+2*rn.nextGaussian()))
{
OutputNumber[0][i]++;
}
else
{
OutputNumber[1][i]++;
}
}
//Final Concave, in a final position, if FinalConcave dominates IdentMLH->MH
//UR 24 surface as 214, otherwise 24
if(UR=="24")
{
if(UnCon[1] && (LocalCON[7]+2*rn.nextGaussian())>(LocalCON[5]+2*rn.nextGaussian()))
{
OutputNumber[0][i]++;
}
else
{
OutputNumber[2][i]++;
}
}
}
}
for(int i=0;i