Olá!
Alguém tem alguma idéia de algoritmo para realizar o seguinte problema.
Preciso gerar frases randômicas a partir de uma lista de regras de uma linguagem livre de contexto.
S -> NP VP
Ou seja, uma regra S vira uma regra NP e uma regra VP, porém estas regras possuem probabilidades, pois são construídas assim:
S -> NP VP 0.4
S -> PP VP 0.6
Ou seja a primeira regra S tem 40% de chance de acontecer e a segunda 60%, preciso de um algoritmo para escolher a melhor e continuar derivando as regras até chegarem no fim.
A gramática é a seguinte:
[ S ] > [ PES ] [ OBJ ] ;1
[ PES ] > [ SUJ ] [ VER ] ;0.3
[ PES ] > [ SUJ ] [ COMP ] ;0.4
[ PES ] > [ PES ] [ VER ] ;0.3
[ OBJ ] > [ PREP ] [ SUJ ] ;0.3
[ OBJ ] > [ NOM ] [ QUANT ] ;0.1
[ OBJ ] > [ PRON ] [ NOM ] ;0.1
[ OBJ ] > [ NOM ] [ ADV ] ;0.4
[ OBJ ] > [ PREP ] [ NOM ] ;0.1
[ LIG ] > [ VER ] [ ART ] ;1
[ NOM ] > [ ART ] [ NOM ] ;0.2
[ COMP ] > [ CON ] [ SUJ ] ;1
[ VER ] > [ NEG ] [ VER ] ;0.14
Só para exemplificar. As regras são vetores, [0] equivale ao primeiro valor, [1] e [2] ao segundo e terceiro respectivamente o [4] possui o valor da probabilidade.
Se alguém puder ajudar obrigado!
Se precisarem que eu esclareça mais, por favor.
Vou dar um exemplo. Digamos que você tenha 3 resultados possíveis, um (A) com probabillidade de 0.2, outro (B) com probabilidade de 0.7 e o terceiro © com probabilidade de 0.1. (O total é 1.0, conforme você deve ter entendido).
Gere um número aleatório de 0.0 até 1.0. Se ele estiver entre 0 e 0.2, então escolha A; se ele estiver entre 0.2 e 0.9 (note que 0.9 = 0.2 + 0.7) então escolha B; e se ele estiver entre 0.9 e 1.0 (note que 1.0 = 0.2 + 0.7 + 0.1) escolha C.
A partir disso, você que é bem esperto pode gerar suas frases aleatórias. (A palavra em português é “aleatório”, embora eu ache que a palavra “randômico” possa ser encontrada no Aurélio - não tenho o dicionário aqui comigo para conferir.)
[quote=entanglement]Vou dar um exemplo. Digamos que você tenha 3 resultados possíveis, um (A) com probabillidade de 0.2, outro (B) com probabilidade de 0.7 e o terceiro © com probabilidade de 0.1. (O total é 1.0, conforme você deve ter entendido).
Gere um número aleatório de 0.0 até 1.0. Se ele estiver entre 0 e 0.2, então escolha A; se ele estiver entre 0.2 e 0.9 (note que 0.9 = 0.2 + 0.7) então escolha B; e se ele estiver entre 0.9 e 1.0 (note que 1.0 = 0.2 + 0.7 + 0.1) escolha C.
A partir disso, você que é bem esperto pode gerar suas frases aleatórias. (A palavra em português é “aleatório”, embora eu ache que a palavra “randômico” possa ser encontrada no Aurélio - não tenho o dicionário aqui comigo para conferir.)
[/quote]
Sim sim, essa parte já tenho montada na minha cabeça, só preciso montar a estrutura toda, acho que uma árvore binária é o que eu preciso já que todas produções das regras são de 2 ou 1 resultado.
Alguma outra idéia?
Obrigado!
Alguém?
Algum exemplo de montagem de árvore binária baseada em probabilidades?
Obrigado!
Até agora consegui isto:
[code]package parser;
import java.util.ArrayList;
class no extends Parseador {
no noEsq;
no noDir;
String valor;
String[][] regras;
public void setRegras(String[][] regras) {
this.regras = regras;
}
public no(String regra, String[][] regrasPai) {
setRegras(regrasPai);
valor = regra;
System.out.println("Nó " + valor + " criado.");
ArrayList<Integer> regrasUtilizadas = new ArrayList<Integer>();
for (int i = 0; i < regras.length; i++) {
if (regras[i][0].equalsIgnoreCase(valor)) {
regrasUtilizadas.add(i);
}
}
if (regrasUtilizadas == null)
{
System.out.println(valor);
}
else {
constroiProbabilidades(regrasUtilizadas);
}
}
public void constroiProbabilidades(ArrayList<Integer> regrasUtilizadas) {
ArrayList<Double> prob = new ArrayList<Double>();
double aux = 0;
for (int i = regrasUtilizadas.get(0); i <= regrasUtilizadas.size(); i++) {
aux = aux + Double.parseDouble(regras[i][3]);
prob.add(aux);
}
double random = Math.random();
System.out.println(random);
int regraEscolhida = regrasUtilizadas.get(0);
for (int j = 0; j < regrasUtilizadas.size(); j++) {
if (j == 0 && random <= prob.get(0)) {
geraNos(regraEscolhida, regrasUtilizadas);
} else if (random > prob.get(j) && random <= prob.get(j + 1)) {
regraEscolhida = regrasUtilizadas.get(j);
geraNos(regraEscolhida, regrasUtilizadas);
}
}
}
public void ImprimeValor() {
if (noDir == null) {
System.out.println(valor);
} else {
noEsq.ImprimeValor();
noDir.ImprimeValor();
}
}
public void geraNos(int regraEscolhida, ArrayList<Integer> regrasUtilizadas) {
String esq = regras[regrasUtilizadas.get(regraEscolhida)][1];
String dir = regras[regrasUtilizadas.get(regraEscolhida)][2];
System.out.println(esq);
System.out.println(dir);
noEsq = new no(esq, regras);
if (regras[regrasUtilizadas.get(regraEscolhida)][2].equals("")) {
System.out.println("teste");
noDir = null;
} else {
System.out.println("teste");
noDir = new no(dir, regras);
}
}
}
[/code]
Mas a árvore fica criando nós recursivamente a esquerda :\