-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
205 lines (175 loc) · 7.93 KB
/
main.py
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import graphviz
import cv2
import os
nrRandare = 0
f = graphviz.Digraph(directory='imagini', filename=f'{nrRandare}', format="png")
f.attr(rankdir='LR', size='20', ratio="1")
def stareFinala(stare):
stari = generare(stare)
ok = 1
for valoare in stari:
# if the state is composed of a final state, it will be circled 2 times
if stariFinale[valoare] == 1:
return 1
# if the state does not have any final state in its component, we will circle it only once
return 0
# the function transforms a set into a string in the form of a sorted list for naming the new composed states
def denumire(lista):
lista = list(set(lista))
lista.sort()
return str(lista)
# the function transforms a sorted list string into a list
def generare(cuvant):
cuvant = cuvant[1:-1]
if cuvant:
cuvant = [int(x) for x in cuvant.split(", ")]
return cuvant
# the function determines the path that starts from the Current state and has the property that it has identical
# transitions, the lambda is treated differently from the rest of the transitions because for the lambda the Current
# state is also taken into account, unlike the others where only the state where you can reach matters
def parcurgere(stareCurenta, simbol, vizitat, drum):
vizitat[stareCurenta] = 1 # Record the visit of the state so as not to go through the same state several times
if simbol == '#':
drum.add(stareCurenta)
if stareCurenta in automat and simbol in automat[stareCurenta]:
for stare in automat[stareCurenta][simbol]:
if simbol != '#':
drum.add(stare)
if vizitat[stare] == 0:
parcurgere(stare, simbol, vizitat, drum)
# the function constructs the DFA
def dfs(stareCurenta):
global nrRandare
if stareCurenta == stareInitialaDfa:
if stareFinala(stareCurenta):
f.attr('node', shape='doublecircle')
else:
f.attr('node', shape='circle')
f.node(stareCurenta)
f.attr('node', shape='none')
f.node('')
f.edge('', f'{stareCurenta}')
f.render(filename=f'{nrRandare}')
nrRandare += 1
else:
if stareFinala(stareCurenta):
f.attr('node', shape='doublecircle')
else:
f.attr('node', shape='circle')
f.node(stareCurenta)
# I add the Current state to the verificare to make sure I don't get into an infinite loop later
verificare.append(stareCurenta)
# I go through the list of possible transitions
for tranzitie in simbolTranzitii:
# The current state is transmitted as a string parameter. I use the generare function to turn it into a list
stareCurenta = generare(stareCurenta)
stareNoua = set()
# take each state component of the Current state
for stare in stareCurenta:
if stare in automat and tranzitie in automat[stare]:
# determine the union the states that belong to the path generated by a specific transition for
# all the component states
stareNoua = stareNoua.union(lambdaInchideri[stare][tranzitie])
test = stareNoua
for subStare in stareNoua:
# traverse the component states of the New state and find the union of the states that belong to the path
# generated by the lambda (the lambda closure)
if subStare in lambdaInchideri and '#' in lambdaInchideri[subStare]:
test = test.union(lambdaInchideri[subStare]['#'])
stareNoua = test
# transform New state and Current state from lists to strings (preparing the parameter)
stareNoua = denumire(list(stareNoua))
stareCurenta = denumire(stareCurenta)
# Update the transitions for Current state
if stareCurenta not in stariDfa:
stariDfa[stareCurenta] = {tranzitie: stareNoua}
else:
stariDfa[stareCurenta][tranzitie] = stareNoua
# If the state has not been generated before, we call the dfs function
if stareFinala(stareNoua):
f.attr('node', shape='doublecircle')
else:
f.attr('node', shape='circle')
f.edge(stareCurenta, stareNoua, label=tranzitie)
f.render(filename=f'{nrRandare}')
nrRandare += 1
if stareNoua not in verificare:
dfs(stareNoua)
fisier = open("date.in", "r")
continutFisier = fisier.read().split("\n")
# Determine the values of n and m
valori = continutFisier[0].split()
n = int(valori[0])
m = int(valori[1])
# We create a distionary like this
# automaton = {state: {character: [states in which it is possible to go through the respective transition]}}
automat = {}
# transitions
simbolTranzitii = set()
for index1 in range(1, m + 1):
valori = continutFisier[index1].split()
simbolTranzitii.add(valori[2]) # All possible transitions
if int(valori[0]) in automat: # check if the current state exists in the automaton
if valori[2] in automat[int(valori[0])]: # check if the transition exists for the current state
automat[int(valori[0])][valori[2]].append(int(valori[1]))
else:
automat[int(valori[0])][valori[2]] = [int(valori[1])]
else:
automat[int(valori[0])] = {valori[2]: [int(valori[1])]}
# Initial state index
stareInitiala = int(continutFisier[m + 1])
valori = [int(element) for element in continutFisier[m + 2].split()]
# Memorize the number of final states
nrStariFinale = valori[0]
# Building a list in which we will record the existence of end states
stariFinale = [0 for index2 in range(n + 1)]
for element in valori[1:]:
stariFinale[element] = 1
# a dictionary in which I will memorize for each node the path starting from it with a specific transition
lambdaInchideri = dict()
simbolTranzitii = list(simbolTranzitii)
# for each possible transition, I take all the states from the automaton and, if the transition appears in the
# automat[state], I generate for that state a path with the specific transition
for tranzitie in simbolTranzitii:
for stare in automat:
if tranzitie in automat[stare]:
vizitat = [0 for x in range(n + 1)]
drum = set()
parcurgere(stare, tranzitie, vizitat, drum)
if stare in lambdaInchideri:
lambdaInchideri[stare][tranzitie] = list(drum)
else:
lambdaInchideri[stare] = {tranzitie: list(drum)}
# if there is no lambda transition from that state, we must still have that state
elif tranzitie == '#':
if stare in lambdaInchideri:
lambdaInchideri[stare][tranzitie] = [stare]
else:
lambdaInchideri[stare] = {tranzitie: [stare]}
# the initial state of the final automaton consists of the lambda states of the closing of the initial state
stareInitialaDfa = denumire(lambdaInchideri[stareInitiala]['#'])
# the final automaton
stariDfa = {stareInitialaDfa: dict()}
# in verificare I will add all the generated states
verificare = list()
# the lambda disappears at this moment of the generation of the final automaton
simbolTranzitii.remove('#')
dfs(stareInitialaDfa)
imagini = [f for f in os.listdir('./imagini') if f.endswith('.png')]
imagini.sort(key=lambda x: int(x.split('.')[0]))
fps = 1
dimensiune = None
for imagine in imagini:
img = cv2.imread('./imagini/' + imagine)
dimensiune = img.shape[1], img.shape[0]
format = "XVID"
fourcc = cv2.VideoWriter_fourcc(*format)
videoclip = None
for imagine in imagini:
img = cv2.imread('./imagini/' + imagine)
if videoclip is None:
videoclip = cv2.VideoWriter('videoclip.avi', fourcc, fps, dimensiune)
if dimensiune[0] != img.shape[1] and dimensiune[1] != img.shape[0]:
img = cv2.resize(img, dimensiune)
videoclip.write(img)
videoclip.release()