-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGodot_Grams.gd
157 lines (129 loc) · 3.57 KB
/
Godot_Grams.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
extends TileMap
export (int, 0, 500) var source_width
export (int, 0, 1000) var width
export (int, 0, 100) var height
export (int, 0, 10) var rows
export (int, 1, 500) var n
export (bool) var random
var source:Array = []
var feats:Array = []
var grams:Trie = null
var probs:Dictionary = {}
const START:int = -1
const END:int = -2
### The Overal Process
func _unhandled_input(event):
if event.is_action_pressed("reload"):
clear()
populate(random)
func _ready():
source = parse_source()
feats = parse_feats()
grams = parse_grams()
probs = generate_probs()
populate(random)
### Setting and Getting Cells
func apply_feat(x:int, feat:Dictionary):
var elem = feat.val
for y in range(0, height):
set_cell(x, y, elem[y])
func parse_source():
var source = []
for row in range(0, rows):
source.append([])
for x in range(0, source_width):
source[row].append([])
for y in range(0, height):
source[row][x].append(get_cell(x, y + row*height))
set_cell(x, y, -1)
return source
### Vocabulary Parsing
func parse_feats() -> Array:
# Generate Feats Trie
var trie = Trie.new()
for row in range(rows):
var src_len = source[row].size()
for idx in range(src_len):
var elem:Array = source[row][idx]
trie.insert(elem, {"row":row, "idx":idx})
return generate_feats(trie)
func generate_feats(trie:Trie) -> Array:
# Generate Feats Dictionary
var set = trie.traverse()
var all_feats = []
for row in range(rows):
var feats = []
all_feats.append(feats)
var src_len = source[row].size()
feats.resize(src_len+2)
feats[0] = START
feats[src_len+1] = END
for idx in range(set.size()):
var elem = set[idx]
var srcs = trie.search(elem)
var feat = {"val":elem, "srcs":srcs}
for src in srcs:
all_feats[src.row][src.idx+1] = feat
return all_feats
### N-Gram Creation and Probability Assignment
func parse_grams() -> Trie:
# Generate Grams Trie
var grams:Trie = Trie.new()
for row in range(rows):
var src_len:int = feats[row].size()
for i in range(src_len):
for j in range(i, src_len+1):
var src = {"row":row, "idx":i}
grams.insert(feats[row].slice(i, j), src)
return grams
func generate_probs() -> Dictionary:
var n_grams:Array = grams.traverse_n(n)
var probs:Dictionary = {}
for n_gram in n_grams:
var n_count:float = grams.count_key(n_gram)
var m_count:float = grams.count_key(n_gram.slice(0, n_gram.size()-2))
probs[n_gram] = (n_count/m_count)
return probs
### N-Gram Level Generation
func select_n_gram(key:Array):
var keys:Array = grams.traverse_n_key(n, key)
var max_key:Array
var max_prob:float = -INF
for key in keys:
if probs[key] > max_prob:
max_key = key
max_prob = probs[key]
return max_key
func select_rand_n_gram(key:Array):
var keys:Array = grams.traverse_n_key(n, key)
var wrand:WRandom = WRandom.new()
for key in keys:
wrand.add_weight(key, probs[key])
wrand.init_probabilities()
return wrand.pick()
func n_gram_start(n_gram):
if n_gram == null: return false
var front = n_gram.front()
return front is int and front == START
func n_gram_end(n_gram):
if n_gram == null: return false
var back = n_gram.back()
return back is int and back == END
func populate(rand:bool=false):
var key = [START]
for xi in range(0, width):
var n_gram
if rand:
while ((xi < width-n and n_gram_end(n_gram)) or n_gram == null):
n_gram = select_rand_n_gram(key)
else:
n_gram = select_n_gram(key)
key = n_gram.slice(1, n_gram.size()-1)
if n_gram_start(n_gram):
for xj in range(1, n):
var x = xi + xj
apply_feat(x, n_gram[xj])
elif n_gram_end(n_gram):
break
else:
apply_feat(xi+(n-1), n_gram[(n-1)])