如何使用变量和标记实现马尔可夫算法?
How can I implement Markov's algorithm with variables and markers?
我一直在尝试实现马尔可夫算法,但只取得了部分成功。该算法相当简单,可以找到here。
但是,我的项目有一个额外的困难,我必须使用包含标记和变量的规则。
变量代表字母表中的任何字母,而标记只是用作移动变量的参考的字符(它没有实际值)。
此示例复制字符串中的每个字符:
Alphabet: {a,b,c}
Markers: {M}
Variables: {x}
Rule 1: Mx -> xxM
Rule 2: xM -> x
Rule 3: x -> Mx
input: abc
abc //We apply rule 3
Mabc //We apply rule 1
aaMbc //We apply rule 1
aabbMc //We apply rule 1
aabbccM //We apply rule 2
aabbcc
这是我的递归函数,它实现了仅适用于字符串输入的马尔可夫算法,例如:规则 1:"apple" -> "orange",输入:"apple".
public static String markov(String input, LinkedList<Rule> rules) {
for (Rule rule : rules) {
if (!input.equals(input.replace(rule.getFrom(), rule.getTo()))) { //If the rule matches a substring
if (rule.isTerminating()) { //If the rule is terminating
input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
System.out.println(input); //Replace the first instance
return input; //return and end the cycle
} else {
input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
System.out.println(input);
return markov(input, rules); //Start looking again for matching rules
}
}
}
return input;
}
我不知道如何在这个逻辑中实现变量和标记,也许有人可以教我实现这个逻辑的最佳方法?欢迎任何建议。
如果问题不符合 SO 准则,请在评论中告诉我原因,这样我就不会重蹈覆辙。
谢谢!
我认为最简单的方法是使用 Java 正则表达式。一旦您了解了这些,那么以下规则应该适用于您的示例:
Rule 1: "M([a-c])" -> "M"
Rule 2: "([a-c])M" -> "" (terminating)
Rule 3: "([a-c])" -> "M"
请注意,您需要对当前方法进行一些调整才能使此工作...
replace
将文字字符串作为第一个参数,而 replaceFirst
使用正则表达式,因此:
replace: if (!input.equals(input.replace(rule.getFrom(), rule.getTo()))) {
with: if (!input.equals(input.replaceFirst(rule.getFrom(), rule.getTo()))) {
您正在引用 rule.getFrom()
字符串,它不适用于正则表达式,因此:
replace: input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
with: input = input.replaceFirst(rule.getFrom(), rule.getTo());
那时,您在两次调用 replaceFirst
的代码中有一些重复,因此您可以在第一次将其粘贴到临时变量中并重新使用它:
String next = input.replace(rule.getFrom(), rule.getTo());
if (!input.equals(next)) {
...
input = next;
...
}
由于您目前正在引用整个 rule.getFrom()
字符串,我猜您之前在正则表达式特殊字符方面遇到过问题。如果是这样,您需要在创建规则时单独解决它们。我真的不想在这里讨论正则表达式,因为它是一个很大的领域,并且与马尔可夫算法完全分开,所以如果您遇到这些问题,请在线进行一些研究(例如 Regular Expressions and Capturing Groups),或在此处提出一个单独的问题,重点关注正则表达式的特定问题。
请注意,您仍然可以将这些与正常规则结合使用(将标记字符从 M
更改为 #
以允许在字母表中使用 M
),这些规则:
"A" -> "apple"
"B" -> "bag"
"S" -> "shop"
"T" -> "the"
"the shop" -> "my brother"
"#([a-zA-Z .])" -> "#"
"([a-zA-Z .])#" -> "" (terminating)
"([a-zA-Z .])" -> "#"
将转换:
from: I bought a B of As from T S.
to: II bboouugghhtt aa bbaagg ooff aapppplleess ffrroomm mmyy bbrrootthheerr..
希望这对您有所帮助。
我一直在尝试实现马尔可夫算法,但只取得了部分成功。该算法相当简单,可以找到here。
但是,我的项目有一个额外的困难,我必须使用包含标记和变量的规则。
变量代表字母表中的任何字母,而标记只是用作移动变量的参考的字符(它没有实际值)。
此示例复制字符串中的每个字符:
Alphabet: {a,b,c}
Markers: {M}
Variables: {x}
Rule 1: Mx -> xxM
Rule 2: xM -> x
Rule 3: x -> Mx
input: abc
abc //We apply rule 3
Mabc //We apply rule 1
aaMbc //We apply rule 1
aabbMc //We apply rule 1
aabbccM //We apply rule 2
aabbcc
这是我的递归函数,它实现了仅适用于字符串输入的马尔可夫算法,例如:规则 1:"apple" -> "orange",输入:"apple".
public static String markov(String input, LinkedList<Rule> rules) {
for (Rule rule : rules) {
if (!input.equals(input.replace(rule.getFrom(), rule.getTo()))) { //If the rule matches a substring
if (rule.isTerminating()) { //If the rule is terminating
input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
System.out.println(input); //Replace the first instance
return input; //return and end the cycle
} else {
input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
System.out.println(input);
return markov(input, rules); //Start looking again for matching rules
}
}
}
return input;
}
我不知道如何在这个逻辑中实现变量和标记,也许有人可以教我实现这个逻辑的最佳方法?欢迎任何建议。
如果问题不符合 SO 准则,请在评论中告诉我原因,这样我就不会重蹈覆辙。
谢谢!
我认为最简单的方法是使用 Java 正则表达式。一旦您了解了这些,那么以下规则应该适用于您的示例:
Rule 1: "M([a-c])" -> "M"
Rule 2: "([a-c])M" -> "" (terminating)
Rule 3: "([a-c])" -> "M"
请注意,您需要对当前方法进行一些调整才能使此工作...
replace
将文字字符串作为第一个参数,而 replaceFirst
使用正则表达式,因此:
replace: if (!input.equals(input.replace(rule.getFrom(), rule.getTo()))) {
with: if (!input.equals(input.replaceFirst(rule.getFrom(), rule.getTo()))) {
您正在引用 rule.getFrom()
字符串,它不适用于正则表达式,因此:
replace: input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
with: input = input.replaceFirst(rule.getFrom(), rule.getTo());
那时,您在两次调用 replaceFirst
的代码中有一些重复,因此您可以在第一次将其粘贴到临时变量中并重新使用它:
String next = input.replace(rule.getFrom(), rule.getTo());
if (!input.equals(next)) {
...
input = next;
...
}
由于您目前正在引用整个 rule.getFrom()
字符串,我猜您之前在正则表达式特殊字符方面遇到过问题。如果是这样,您需要在创建规则时单独解决它们。我真的不想在这里讨论正则表达式,因为它是一个很大的领域,并且与马尔可夫算法完全分开,所以如果您遇到这些问题,请在线进行一些研究(例如 Regular Expressions and Capturing Groups),或在此处提出一个单独的问题,重点关注正则表达式的特定问题。
请注意,您仍然可以将这些与正常规则结合使用(将标记字符从 M
更改为 #
以允许在字母表中使用 M
),这些规则:
"A" -> "apple"
"B" -> "bag"
"S" -> "shop"
"T" -> "the"
"the shop" -> "my brother"
"#([a-zA-Z .])" -> "#"
"([a-zA-Z .])#" -> "" (terminating)
"([a-zA-Z .])" -> "#"
将转换:
from: I bought a B of As from T S.
to: II bboouugghhtt aa bbaagg ooff aapppplleess ffrroomm mmyy bbrrootthheerr..
希望这对您有所帮助。