1#!/bin/sh
2# -*- coding: utf-8 -*-
3# Copyright (C) 2009, 2010, 2012, 2014-2021 Laboratoire de
4# Recherche et Développement de l'Epita (LRDE).
5# Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
6# département Systèmes Répartis Coopératifs (SRC), Université Pierre
7# et Marie Curie.
8#
9# This file is part of Spot, a model checking library.
10#
11# Spot is free software; you can redistribute it and/or modify it
12# under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 3 of the License, or
14# (at your option) any later version.
15#
16# Spot is distributed in the hope that it will be useful, but WITHOUT
17# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19# License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
24
25. ./defs
26
27set -e
28
29cat >input <<\EOF
30HOA: v1
31States: 3
32Start: 0
33AP: 3 "a" "b" "F\\G"
34acc-name: generalized-Buchi 2
35Acceptance: 2 Inf(0)&Inf(1)
36properties: trans-labels explicit-labels state-acc deterministic
37--BODY--
38State: 0 {0 1}
39[0&!1] 1
40State: 1 {0}
41[2] 2
42State: 2
43[t] 0
44--END--
45EOF
46
47run 0 autfilt --hoa input > stdout
48diff stdout input
49
50test `autfilt -c --is-weak input` = 0
51
52autfilt -H1.1 -v --is-weak input | grep properties: | tee props
53cat >expected.props <<EOF
54properties: trans-labels explicit-labels state-acc !complete
55properties: deterministic !weak
56EOF
57diff expected.props props
58
59
60# Transition merging
61cat >input <<\EOF
62HOA: v1
63States: 2
64Start: 0
65AP: 2 "a" "b"
66acc-name: Buchi
67Acceptance: 1 Inf(0)
68properties: trans-labels explicit-labels trans-acc
69--BODY--
70State: 0
71[0&1] 1 {0}
72[!1] 1
73[0&!1] 1 {0}
74State: 1
75[!1] 0
76[1&0] 0 {0}
77[0&!1] 0 {0}
78--END--
79EOF
80
81cat >expected <<\EOF
82HOA: v1
83States: 2
84Start: 0
85AP: 2 "a" "b"
86acc-name: Buchi
87Acceptance: 1 Inf(0)
88properties: trans-labels explicit-labels trans-acc
89--BODY--
90State: 0
91[!1] 1
92[0] 1 {0}
93State: 1
94[!1] 0
95[0] 0 {0}
96--END--
97EOF
98
99run 0 autfilt --merge-transitions --hoa input > stdout
100cat stdout
101run 0 autfilt -F stdout --isomorph expected
102
103# Likewise, with a randomly generated TGBA.
104run 0 randaut -Q 20 a b -e 0.2 -a 0.2 -A 2 --hoa | tee input
105
106# the first read-write can renumber the states
107run 0 autfilt --hoa --merge-transitions input > stdout
108run 0 autfilt -F input --isomorph stdout
109
110# But this second output should be the same as the first
111run 0 autfilt --hoa stdout > stdout2
112diff stdout stdout2
113
114# Find formula that can be translated into a 3-state automaton, and
115# exercise both %M and %m.  The nonexistant file should never be
116# open, because the input stream is infinite and autfilt should
117# stop after 10 automata.
118randltl -n -1 a b | ltl2tgba |
119    autfilt -F - -F nonexistant --states=3 --edges=..10 --acc-sets=1.. \
120	     --name='%M, %S states' --stats='<%m>, %e, %a' -n 10 > output
121cat >expected <<EOF
122<F(b | Ga), 3 states>, 5, 1
123<F(!b & G(!b | G!a)), 3 states>, 5, 1
124<XF!b, 3 states>, 4, 1
125<G!b | Gb, 3 states>, 4, 1
126<XFb, 3 states>, 4, 1
127<F(b W a), 3 states>, 6, 1
128<(a & !b & (b | (!b M F!a))) | (!a & (b | (!b & (b W Ga)))), 3 states>, 5, 1
129<(a & (a U !b)) | (!a & (!a R b)), 3 states>, 5, 1
130<a | G((a & GFa) | (!a & FG!a)), 3 states>, 4, 1
131<XXG(!a & (Fa W Gb)), 3 states>, 3, 1
132EOF
133diff output expected
134
135
136cat >input <<EOF
137HOA: v1
138States: 10
139Start: 0
140AP: 1 "a"
141acc-name: generalized-Buchi 3
142Acceptance: 3 Inf(0)&Inf(1)&Inf(2)
143properties: trans-labels explicit-labels trans-acc
144--BODY--
145State: 0
146[t] 0 {0}
147[!0] 1 {0}
148[!0] 2 {0}
149[0] 3 {0}
150[0] 3 {0 2}
151[!0] 2 {0 2}
152[!0] 4 {1}
153[!0] 5 {1}
154[!0] 6 {1}
155[!0] 6 {1 2}
156[!0] 7 {1}
157[!0] 8 {1}
158[!0] 9 {1}
159[!0] 9 {1 2}
160[!0] 4 {0 1}
161[!0] 5 {0 1}
162[!0] 6 {0 1}
163[!0] 6 {0 1 2}
164[!0] 7 {0 1}
165[!0] 8 {0 1}
166[!0] 9 {0 1}
167[!0] 9 {0 1 2}
168State: 1
169[0] 3 {0 2}
170State: 2
171[!0] 2 {0 2}
172[!0] 6 {1 2}
173[!0] 9 {1 2}
174[!0] 6 {0 1 2}
175[!0] 9 {0 1 2}
176State: 3
177[!0] 1 {0 2}
178[!0] 2 {0}
179[0] 3 {0 2}
180[!0] 2 {0 2}
181[!0] 5 {1 2}
182[!0] 6 {1}
183[!0] 6 {1 2}
184[!0] 8 {1 2}
185[!0] 9 {1}
186[!0] 9 {1 2}
187[!0] 5 {0 1 2}
188[!0] 6 {0 1}
189[!0] 6 {0 1 2}
190[!0] 8 {0 1 2}
191[!0] 9 {0 1}
192[!0] 9 {0 1 2}
193State: 4
194[!0] 4 {1}
195[!0] 5 {1}
196[!0] 6 {1}
197[!0] 6 {1 2}
198[!0] 7
199[!0] 8
200[!0] 9
201[!0] 9 {2}
202[!0] 7 {1}
203[!0] 8 {1}
204[!0] 9 {1}
205[!0] 9 {1 2}
206State: 5
207State: 6
208[!0] 6 {1 2}
209[!0] 9 {2}
210[!0] 9 {1 2}
211State: 7
212[0] 0 {0}
213[0] 3 {0}
214[0] 3 {0 2}
215State: 8
216[0] 3 {0 2}
217State: 9
218--END--
219EOF
220
221cat >expected <<EOF
222HOA: v1
223name: "63->32 edges, 64->33 transitions"
224States: 10
225Start: 0
226AP: 1 "a"
227acc-name: generalized-Buchi 3
228Acceptance: 3 Inf(0)&Inf(1)&Inf(2)
229properties: trans-labels explicit-labels
230--BODY--
231State: 0
232[t] 0 {0}
233[!0] 1 {0}
234[!0] 2 {0 2}
235[0] 3 {0 2}
236[!0] 4 {0 1}
237[!0] 5 {0 1}
238[!0] 6 {0 1 2}
239[!0] 7 {0 1}
240[!0] 8 {0 1}
241[!0] 9 {0 1 2}
242State: 1 {0 2}
243[0] 3
244State: 2
245[!0] 2 {0 2}
246[!0] 6 {0 1 2}
247[!0] 9 {0 1 2}
248State: 3
249[!0] 1 {0 2}
250[!0] 2 {0 2}
251[0] 3 {0 2}
252[!0] 5 {0 1 2}
253[!0] 6 {0 1 2}
254[!0] 8 {0 1 2}
255[!0] 9 {0 1 2}
256State: 4
257[!0] 4 {1}
258[!0] 5 {1}
259[!0] 6 {1 2}
260[!0] 7 {1}
261[!0] 8 {1}
262[!0] 9 {1 2}
263State: 5
264State: 6 {1 2}
265[!0] 6
266[!0] 9
267State: 7
268[0] 0 {0}
269[0] 3 {0 2}
270State: 8 {0 2}
271[0] 3
272State: 9
273--END--
274EOF
275
276autfilt --merge -Hm input --name="%E->%e edges, %T->%t transitions" > output
277diff output expected
278
279
280ltl2tgba -x degen-lskip=1 --ba > tmp.hoa <<EOF
281a U b
282false
283!b && Xb && GFa
284EOF
285autfilt <tmp.hoa --stats='"%M","%w"' > output
286cat >expected <<EOF
287"a U b","cycle{b}"
288"0",""
289"!b & X(b & GFa)","!b; cycle{a & b}"
290EOF
291diff output expected
292
293
294cat >input <<EOF
295HOA: v1
296States: 4
297Start: 2
298Start: 3
299AP: 2 "a" "b"
300acc-name: Buchi
301Acceptance: 1 Inf(0)
302properties: trans-labels explicit-labels state-acc
303--BODY--
304State: 0 "s0" {0}
305[1] 0
306State: 1 "s1" {0}
307[0] 1
308State: 2 "s2"
309[1] 0
310State: 3 "s3"
311[0] 1
312--END--
313EOF
314
315autfilt -H input |
316    SPOT_DEFAULT_FORMAT=dot \
317    SPOT_DOTDEFAULT=vcsnaAi \
318    SPOT_DOTEXTRA='/* hello world */' \
319    autfilt >output
320
321cat >expected <<EOF
322digraph "" {
323  node [shape="circle"]
324  node [id="S\N"]
325  /* hello world */
326  I [label="", style=invis, height=0]
327  I -> 3
328  subgraph cluster_0 {
329  color=green
330  id="SCC0"
331  1 [label="s1", peripheries=2]
332  }
333  subgraph cluster_1 {
334  color=green
335  id="SCC1"
336  0 [label="s0", peripheries=2]
337  }
338  subgraph cluster_2 {
339  color=black
340  id="SCC2"
341  3 [label="s3"]
342  }
343  0 -> 0 [label="b", id="E1", tooltip="\\\\E\n#1"]
344  1 -> 1 [label="a", id="E2", tooltip="\\\\E\n#2"]
345  2 [label="s2"]
346  2 -> 0 [label="b", id="E3", tooltip="\\\\E\n#3"]
347  3 -> 1 [label="a", id="E4", tooltip="\\\\E\n#4"]
348  3 -> 0 [label="b", id="E5", tooltip="\\\\E\n#5"]
349}
350EOF
351
352diff output expected
353
354test 1 = `autfilt -H input --complete | autfilt --is-complete --count`
355
356
357# The SPOT_DEFAULT_FORMAT envvar should be ignored if --dot is given.
358# --dot=k should be ignored when not applicable.
359SPOT_DEFAULT_FORMAT=hoa ltl2tgba --dot=ak 'GFa & GFb' >output
360cat output
361cat >expected <<EOF
362digraph "G(Fa & Fb)" {
363  rankdir=LR
364  label="Inf(0)&Inf(1)\n[gen. Büchi 2]"
365  labelloc="t"
366  node [shape="circle"]
367  I [label="", style=invis, width=0]
368  I -> 0
369  0 [label="0"]
370  0 -> 0 [label="!a & !b"]
371  0 -> 0 [label="a & !b\n{0}"]
372  0 -> 0 [label="!a & b\n{1}"]
373  0 -> 0 [label="a & b\n{0,1}"]
374}
375EOF
376diff output expected
377
378ltl2tgba -d'bani(foo)' 'GFa & GFb' >output
379cat output
380cat >expected <<EOF
381digraph "G(Fa & Fb)" {
382  rankdir=LR
383  label="G(Fa & Fb)\nInf(⓿)&Inf(❶)\n[gen. Büchi 2]"
384  labelloc="t"
385  node [shape="circle"]
386  id="foo"
387  node [id="S\N"]
388  I [label="", style=invis, width=0]
389  I -> 0
390  0 [label="0"]
391  0 -> 0 [label="!a & !b", id="E1", tooltip="\\\\E\n#1"]
392  0 -> 0 [label="a & !b\n⓿", id="E2", tooltip="\\\\E\n#2"]
393  0 -> 0 [label="!a & b\n❶", id="E3", tooltip="\\\\E\n#3"]
394  0 -> 0 [label="a & b\n⓿❶", id="E4", tooltip="\\\\E\n#4"]
395}
396EOF
397diff output expected
398
399ltl2tgba -dbang 'GFa & GFb' >output
400cat output
401cat >expected <<EOF
402digraph "G(Fa & Fb)" {
403  rankdir=LR
404  label="G(Fa & Fb)\nInf(⓿)&Inf(❶)\n[gen. Büchi 2]"
405  labelloc="t"
406  node [shape="circle"]
407  I [label="", style=invis, width=0]
408  I -> 0
409  0 [label="0"]
410  0 -> 0 [label=""]
411  0 -> 0 [label="⓿"]
412  0 -> 0 [label="❶"]
413  0 -> 0 [label="⓿❶"]
414}
415EOF
416diff output expected
417
418
419SPOT_DOTDEFAULT=bra ltl2tgba --dot='Ae.f(Lato)' 'GFa & GFb' >output
420cat output
421
422zero='<font color="#1F78B4">⓿</font>'
423one='<font color="#FF4DA0">❶</font>'
424cat >expected <<EOF
425digraph "G(Fa & Fb)" {
426  rankdir=LR
427  label=<Inf($zero)&amp;Inf($one)<br/>[gen. Büchi 2]>
428  labelloc="t"
429  node [shape="ellipse",width="0.5",height="0.5"]
430  fontname="Lato"
431  node [fontname="Lato"]
432  edge [fontname="Lato"]
433  I [label="", style=invis, width=0]
434  I -> 0
435  0 [label=<0>]
436  0 -> 0 [label=<!a &amp; !b>]
437  0 -> 0 [label=<a &amp; !b<br/>$zero>]
438  0 -> 0 [label=<!a &amp; b<br/>$one>]
439  0 -> 0 [label=<a &amp; b<br/>$zero$one>]
440}
441EOF
442diff output expected
443
444
445cat >in <<EOF
446HOA: v1
447States: 10
448Start: 0
449AP: 2 "a" "b"
450Acceptance: 4 Fin(0) | (Fin(1) & Inf(2)) | Fin(3)
451--BODY--
452State: 0
453[!0&!1] 1
454[0&!1] 2
455[!0&1] 3
456[0&1] 4
457State: 1 "test me" {0 3}
458[!0&!1] 1
459[0&!1] 2
460[!0&1] 6
461[0&1] 7
462State: 2 {0 2 3}
463[!0&!1] 1
464[0&!1] 2
465[!0&1] 6
466[0&1] 7
467State: 3 {3}
468[t] 5
469State: 4 "hihi" {2 3}
470[t] 5
471State: 5 {1 3}
472[t] 5
473State: 6 {0}
474[!0&!1] 8
475[!0&1] 6
476[0&!1] 9
477[0&1] 7
478State: 7 {0 2}
479[!0&!1] 8
480[!0&1] 6
481[0&!1] 9
482[0&1] 7
483State: 8 {0 3}
484[!0&!1] 8
485[!0&1] 6
486[0&!1] 9
487[0&1] 7
488State: 9 {0 2 3}
489[!0&!1] 8
490[!0&1] 6
491[0&!1] 9
492[0&1] 7
493--END--
494EOF
495
496cat >expected <<EOF
497digraph "" {
498  rankdir=LR
499  label="(Fin(⓿)|Fin(❸)) | (Fin(❶) & Inf(❷))\n[gen. Rabin 3]"
500  labelloc="t"
501  node [shape="box",style="rounded",width="0.5"]
502  I [label="", style=invis, width=0]
503  I -> 0
504  0 [label="0"]
505  0 -> 1 [label="!a & !b", taillabel="0"]
506  0 -> 2 [label="a & !b", taillabel="1"]
507  0 -> 3 [label="!a & b", taillabel="2"]
508  0 -> 4 [label="a & b", taillabel="3"]
509  1 [label="test me\n⓿❸"]
510  1 -> 1 [label="!a & !b", taillabel="0"]
511  1 -> 2 [label="a & !b", taillabel="1"]
512  1 -> 6 [label="!a & b", taillabel="2"]
513  1 -> 7 [label="a & b", taillabel="3"]
514  2 [label="2\n⓿❷❸"]
515  2 -> 1 [label="!a & !b", taillabel="0"]
516  2 -> 2 [label="a & !b", taillabel="1"]
517  2 -> 6 [label="!a & b", taillabel="2"]
518  2 -> 7 [label="a & b", taillabel="3"]
519  3 [label="3\n❸"]
520  3 -> 5 [label="1", taillabel="0"]
521  4 [label="hihi\n❷❸"]
522  4 -> 5 [label="1", taillabel="0"]
523  5 [label="5\n❶❸"]
524  5 -> 5 [label="1", taillabel="0"]
525  6 [label="6\n⓿"]
526  6 -> 8 [label="!a & !b", taillabel="0"]
527  6 -> 6 [label="!a & b", taillabel="1"]
528  6 -> 9 [label="a & !b", taillabel="2"]
529  6 -> 7 [label="a & b", taillabel="3"]
530  7 [label="7\n⓿❷"]
531  7 -> 8 [label="!a & !b", taillabel="0"]
532  7 -> 6 [label="!a & b", taillabel="1"]
533  7 -> 9 [label="a & !b", taillabel="2"]
534  7 -> 7 [label="a & b", taillabel="3"]
535  8 [label="8\n⓿❸"]
536  8 -> 8 [label="!a & !b", taillabel="0"]
537  8 -> 6 [label="!a & b", taillabel="1"]
538  8 -> 9 [label="a & !b", taillabel="2"]
539  8 -> 7 [label="a & b", taillabel="3"]
540  9 [label="9\n⓿❷❸"]
541  9 -> 8 [label="!a & !b", taillabel="0"]
542  9 -> 6 [label="!a & b", taillabel="1"]
543  9 -> 9 [label="a & !b", taillabel="2"]
544  9 -> 7 [label="a & b", taillabel="3"]
545}
546EOF
547
548autfilt --dot=bao in >out
549diff out expected
550
551cat >expected2 <<EOF
552digraph "" {
553  rankdir=LR
554  label="(Fin(⓿)|Fin(❸)) | (Fin(❶) & Inf(❷))\n[gen. Rabin 3]"
555  labelloc="t"
556  node [shape="box",style="rounded",width="0.5"]
557  I [label="", style=invis, width=0]
558  0 [label="0"]
559  1 [label="1\n⓿❸", tooltip="test me"]
560  2 [label="2\n⓿❷❸"]
561  3 [label="3\n❸"]
562  4 [label="4\n❷❸", tooltip="hihi"]
563  5 [label="5\n❶❸"]
564  6 [label="6\n⓿"]
565  7 [label="7\n⓿❷"]
566  8 [label="8\n⓿❸"]
567  9 [label="9\n⓿❷❸"]
568}
569EOF
570
571# This should remove the state names, and automatically use circled
572# states.
573autfilt --dot=bao1 in | grep -v '>' >out
574diff out expected2
575
576cat >expected3 <<EOF
577digraph "" {
578  rankdir=LR
579  node [shape="ellipse",width="0.5",height="0.5"]
580  I [label="", style=invis, width=0]
581  0 [label="6", peripheries=2]
582  u0 [label="...", shape=none, width=0, height=0, tooltip="hidden successors"]
583  1 [label="0", peripheries=2]
584  2 [label="1", peripheries=2]
585  3 [label="2", peripheries=2]
586  4 [label="3", peripheries=2]
587}
588EOF
589
590# States should be circled even if <5 causes all states to be named,
591# because the names are smaller then 2 characters anyway.
592ltl2tgba --det 'Ga | Gb | Gc' -d'A<5' | grep -v '>' >out
593diff out expected3
594
595# Let's pretend that this is some used supplied input, as discussed in
596# the comments of https://github.com/adl/hoaf/issues/39
597
598cat >input <<EOF
599HOA: v1
600States: 7
601Start: 1
602AP: 2 "p0" "p1"
603acc-name: all
604Acceptance: 0 t
605properties: trans-labels explicit-labels state-acc
606--BODY--
607State: 1
608[!0&1] 0
609[!0&!1] 4
610State: 3
611[!0&!1] 2
612State: 4
613[0&1] 6
614[0&1] 5
615[0&1] 2
616[!0&1] 3
617State: 6
618[!0&!1] 1
619[!0&!1] 3
620[0&1] 7
621--END--
622EOF
623
624# autfilt should complain about the input (we only check the exit
625# status here, because the actual error messages are tested in
626# parseaut.test) and produce a valid output with the number of states
627# fixed, and the missing state definitions.
628autfilt -H input >output1 && exit 1
629
630cat >expect1 <<EOF
631HOA: v1
632States: 8
633Start: 1
634AP: 2 "p0" "p1"
635acc-name: all
636Acceptance: 0 t
637properties: trans-labels explicit-labels state-acc
638--BODY--
639State: 0
640State: 1
641[!0&1] 0
642[!0&!1] 4
643State: 2
644State: 3
645[!0&!1] 2
646State: 4
647[0&1] 6
648[0&1] 5
649[0&1] 2
650[!0&1] 3
651State: 5
652State: 6
653[!0&!1] 1
654[!0&!1] 3
655[0&1] 7
656State: 7
657--END--
658EOF
659
660diff output1 expect1
661# Make sure the output is valid.
662autfilt -H output1 > output1b
663diff output1 output1b
664
665# Here is the scenario where the undefined states are actually states
666# we wanted to remove.  So we tell autfilt to fix the automaton using
667# --remove-dead-states
668SPOT_DEFAULT_FORMAT=hoa autfilt --remove-dead input >output2 && exit 1
669
670cat >expect2 <<EOF
671HOA: v1
672States: 3
673Start: 0
674AP: 2 "p0" "p1"
675acc-name: all
676Acceptance: 0 t
677properties: trans-labels explicit-labels state-acc deterministic
678--BODY--
679State: 0
680[!0&!1] 1
681State: 1
682[0&1] 2
683State: 2
684[!0&!1] 0
685--END--
686EOF
687
688diff output2 expect2
689
690SPOT_DEFAULT_FORMAT=hoa=k autfilt expect2 >output2b
691
692cat >expect2b <<EOF
693HOA: v1
694States: 3
695Start: 0
696AP: 2 "p0" "p1"
697acc-name: all
698Acceptance: 0 t
699properties: state-labels explicit-labels state-acc deterministic
700--BODY--
701State: [!0&!1] 0
7021
703State: [0&1] 1
7042
705State: [!0&!1] 2
7060
707--END--
708EOF
709
710diff output2b expect2b
711
712# Check the difference between --remove-unreach and --remove-dead
713cat >input <<EOF
714HOA: v1
715States: 6
716Start: 0
717AP: 2 "p0" "p1"
718acc-name: all
719Acceptance: 0 t
720--BODY--
721State: 0
722[!0&!1] 1
723State: 1
724[0&1] 2
725State: 2
726[!0&!1] 0
727[t] 5
728State: 3
729[t] 4
730State: 4
731[t] 3
732State: 5
733--END--
734EOF
735
736autfilt -H --remove-unreach input >output3
737autfilt -H --remove-dead input >>output3
738
739cat >expect3 <<EOF
740HOA: v1
741States: 4
742Start: 0
743AP: 2 "p0" "p1"
744acc-name: all
745Acceptance: 0 t
746properties: trans-labels explicit-labels state-acc
747--BODY--
748State: 0
749[!0&!1] 1
750State: 1
751[0&1] 2
752State: 2
753[!0&!1] 0
754[t] 3
755State: 3
756--END--
757HOA: v1
758States: 3
759Start: 0
760AP: 2 "p0" "p1"
761acc-name: all
762Acceptance: 0 t
763properties: trans-labels explicit-labels state-acc deterministic
764--BODY--
765State: 0
766[!0&!1] 1
767State: 1
768[0&1] 2
769State: 2
770[!0&!1] 0
771--END--
772EOF
773
774diff output3 expect3
775
776
777autfilt -Hz input 2>stderr && exit 1
778grep 'print_hoa.*z' stderr
779
780cat >input4 <<EOF
781HOA: v1
782States: 3
783Start: 0
784AP: 2 "a" "b"
785Acceptance: 2 Inf(0) & Inf(1)
786--BODY--
787State: 0 {0}   [0] 1
788State: 1 {1}   [1] 2
789State: 2 {0 1} [0] 2
790--END--
791EOF
792
793test `autfilt --is-weak -c input4` = 1
794test `autfilt --is-inherently-weak -c input4` = 1
795test `autfilt --is-terminal -c input4` = 0
796
797autfilt -H --small --high input4 >output4
798autfilt -H --small input4 >output4b
799autfilt -H --high input4 >output4c
800cat output4
801
802cat >expect4<<EOF
803HOA: v1
804States: 3
805Start: 1
806AP: 2 "a" "b"
807acc-name: Buchi
808Acceptance: 1 Inf(0)
809properties: trans-labels explicit-labels state-acc deterministic
810properties: very-weak
811--BODY--
812State: 0
813[1] 2
814State: 1
815[0] 0
816State: 2 {0}
817[0] 2
818--END--
819EOF
820
821diff output4 expect4
822diff output4b expect4
823diff output4c expect4
824
825autfilt -Hv --small input4 >output5
826test `autfilt --is-weak -c output4` = 1
827test `autfilt --is-terminal -c output4` = 0
828
829sed 's/\[0\]/[t]/g' expect4 > output4d
830test `autfilt --is-terminal -c output4d` = 1
831
832
833cat >expect5<<EOF
834HOA: v1
835States: 3
836Start: 1
837AP: 2 "a" "b"
838acc-name: Buchi
839Acceptance: 1 Inf(0)
840properties: trans-labels explicit-labels state-acc deterministic
841properties: no-univ-branch unambiguous semi-deterministic very-weak
842properties: weak inherently-weak
843--BODY--
844State: 0
845[1] 2
846State: 1
847[0] 0
848State: 2 {0}
849[0] 2
850--END--
851EOF
852diff output5 expect5
853
854cat >input6 <<EOF
855HOA: v1
856States: 3
857Start: 1
858AP: 2 "a" "b"
859acc-name: Buchi
860Acceptance: 1 Inf(0)
861properties: no-univ-branch trans-labels explicit-labels state-acc
862--BODY--
863State: 0
864[1] 2
865[1] 1
866[1] 1
867State: 1
868[0] 0
869[0] 1
870State: 2 {0}
871[0] 2
872[0] 0
873[0] 1
874--END--
875EOF
876
877run 0 autfilt -Hk input6 >output6
878cat >expect6 <<EOF
879HOA: v1
880States: 3
881Start: 1
882AP: 2 "a" "b"
883acc-name: Buchi
884Acceptance: 1 Inf(0)
885properties: state-labels explicit-labels state-acc
886--BODY--
887State: [1] 0
8882 1 1
889State: [0] 1
8900 1
891State: [0] 2 {0}
8922 0 1
893--END--
894EOF
895
896diff output6 expect6
897
898run 0 autfilt -dAk input6 >output6d
899cat >expect6d <<EOF
900digraph "" {
901  rankdir=LR
902  node [shape="box",style="rounded",width="0.5"]
903  I [label="", style=invis, width=0]
904  I -> 1
905  0 [label="0\nb"]
906  0 -> 2 [label=""]
907  0 -> 1 [label=""]
908  0 -> 1 [label=""]
909  1 [label="1\na"]
910  1 -> 0 [label=""]
911  1 -> 1 [label=""]
912  2 [label="2\na", peripheries=2]
913  2 -> 2 [label=""]
914  2 -> 0 [label=""]
915  2 -> 1 [label=""]
916}
917EOF
918diff output6d expect6d
919
920run 0 autfilt -dbark input6 >output6d2
921cat >expect6d2 <<EOF
922digraph "" {
923  rankdir=LR
924  label=<Inf(<font color="#1F78B4">⓿</font>)<br/>[Büchi]>
925  labelloc="t"
926  node [shape="box",style="rounded",width="0.5"]
927  I [label="", style=invis, width=0]
928  I -> 1
929  0 [label=<0<br/>b>]
930  0 -> 2 [label=<>]
931  0 -> 1 [label=<>]
932  0 -> 1 [label=<>]
933  1 [label=<1<br/>a>]
934  1 -> 0 [label=<>]
935  1 -> 1 [label=<>]
936  2 [label=<2<br/><font color="#1F78B4">⓿</font><br/>a>]
937  2 -> 2 [label=<>]
938  2 -> 0 [label=<>]
939  2 -> 1 [label=<>]
940}
941EOF
942diff output6d2 expect6d2
943
944cat >input7 <<EOF
945HOA: v1
946States: 3
947Start: 1
948AP: 0
949acc-name: Buchi
950Acceptance: 2 Inf(0) & Inf(1)
951--BODY--
952State: 0
953[t] 1 {0}
954[t] 0 {0 1}
955State: 1
956[t] 0 {1}
957[t] 1 {0 1}
958--END--
959EOF
960test `autfilt -c --is-inherently-weak input7` = 1
961test `autfilt -c --is-weak input7` = 0
962test `autfilt -c --is-stutter-invariant input7` = 1
963autfilt --check input7 -H >output7
964cat >expected7 <<EOF
965HOA: v1
966States: 3
967Start: 1
968AP: 0
969acc-name: generalized-Buchi 2
970Acceptance: 2 Inf(0)&Inf(1)
971properties: trans-labels explicit-labels trans-acc stutter-invariant
972properties: inherently-weak
973--BODY--
974State: 0
975[t] 1 {0}
976[t] 0 {0 1}
977State: 1
978[t] 0 {1}
979[t] 1 {0 1}
980State: 2
981--END--
982EOF
983diff output7 expected7
984
985cat >input8 <<EOF
986HOA: v1
987States: 3
988Start: 1
989AP: 0
990acc-name: Buchi
991Acceptance: 2 Inf(0) & Inf(1)
992--BODY--
993State: 0
994[t] 1 {0}
995[t] 0 {0 1}
996State: 1
997[t] 0 {1}
998[t] 1 {0}
999--END--
1000EOF
1001test `autfilt -c --is-inherently-weak input8` = 0
1002test `autfilt -c --is-weak input8` = 0
1003
1004autfilt input8 -Hl >oneline.hoa
1005autfilt input8 --stats='%h' >oneline2.hoa
1006autfilt input8 --stats='%H' >oneline3.hoa
1007autfilt input8 --randomize --stats='%h' >oneline4.hoa
1008autfilt input8 --randomize --stats='%H' >oneline5.hoa
1009diff oneline.hoa oneline2.hoa
1010diff oneline.hoa oneline3.hoa
1011diff oneline.hoa oneline4.hoa && exit 1
1012diff oneline.hoa oneline5.hoa
1013
1014
1015cat >input9 <<EOF
1016HOA: v1
1017name: "a U (b U c)"
1018States: 3
1019Start: 2
1020AP: 3 "a" "b" "c"
1021acc-name: Buchi
1022Acceptance: 1 Inf(0)
1023properties: trans-labels explicit-labels state-acc deterministic
1024properties: stutter-invariant terminal
1025spot.highlight.edges: 3 0 1 1 4 3 2 2
1026spot.highlight.states: 0 0 2 3
1027--BODY--
1028State: 1  /* Defined before State 0 on purpose */
1029[2] 0     /* because it affects the edge numbering */
1030[1&!2] 1  /* used in spot.highlight.edges */
1031State: 0 {0}
1032[t] 0
1033State: 2 "new
1034line"
1035[2] 0
1036[!0&1&!2] 1
1037[0&!2] 2
1038--END--
1039EOF
1040autfilt -dA input9 > output9
1041cat >expected9 <<EOF
1042digraph "a U (b U c)" {
1043  rankdir=LR
1044  node [shape="box",style="rounded",width="0.5"]
1045  I [label="", style=invis, width=0]
1046  I -> 2
1047  0 [label="0", peripheries=2, style="bold,rounded", color="#1F78B4"]
1048  0 -> 0 [label="1", style=bold, color="#1F78B4"]
1049  1 [label="1"]
1050  1 -> 0 [label="c", style=bold, color="#FF4DA0"]
1051  1 -> 1 [label="b & !c", style=bold, color="#FF7F00"]
1052  2 [label="new\nline", style="bold,rounded", color="#6A3D9A"]
1053  2 -> 0 [label="c", style=bold, color="#6A3D9A"]
1054  2 -> 1 [label="!a & b & !c"]
1055  2 -> 2 [label="a & !c"]
1056}
1057EOF
1058diff output9 expected9
1059autfilt -dbar input9 > output9a
1060style=', style="bold,rounded", color="#1F78B4"'
1061cat >expected9a <<EOF
1062digraph "a U (b U c)" {
1063  rankdir=LR
1064  label=<Inf(<font color="#1F78B4">⓿</font>)<br/>[Büchi]>
1065  labelloc="t"
1066  node [shape="box",style="rounded",width="0.5"]
1067  I [label="", style=invis, width=0]
1068  I -> 2
1069  0 [label=<0<br/><font color="#1F78B4">⓿</font>>$style]
1070  0 -> 0 [label=<1>, style=bold, color="#1F78B4"]
1071  1 [label=<1>]
1072  1 -> 0 [label=<c>, style=bold, color="#FF4DA0"]
1073  1 -> 1 [label=<b &amp; !c>, style=bold, color="#FF7F00"]
1074  2 [label=<new<br/>line>, style="bold,rounded", color="#6A3D9A"]
1075  2 -> 0 [label=<c>, style=bold, color="#6A3D9A"]
1076  2 -> 1 [label=<!a &amp; b &amp; !c>]
1077  2 -> 2 [label=<a &amp; !c>]
1078}
1079EOF
1080diff output9a expected9a
1081
1082# spot.hightlight.edges and spot.hightlight.states are not valid HOA
1083# v1 output, so they should only but output for HOA 1.1
1084autfilt input9 -H1 | autfilt -H1  | grep highlight && exit 1
1085autfilt input9 -H1 | autfilt -H1.1 | grep highlight && exit 1
1086autfilt -H1.1 input9 | autfilt -H1.1 | grep highlight
1087autfilt -H1.1 input9 | autfilt -dA > output9b
1088diff output9 output9b
1089
1090test 2 = `ltl2tgba 'GFa' 'a U b' 'a U b U c'| autfilt --ap=2..3 --count`
1091
1092# reading CSV with embedded automata
1093test 2 = `genltl --dac=1..3 | ltl2tgba --stats='%e,"%h",%s' |
1094          dstar2tgba -F-/2 --stats='%<,%>,"%h"' |
1095          autfilt --states=2..3 -F-/3 --stats='%<,"%h"' | wc -l`
1096
1097# --dot=d
1098ltl2tgba 'GF(a <-> Fb)' | autfilt -B --dot=dA | grep ' (' >out
1099cat >expected <<EOF
1100  0 [label="0 (0)", peripheries=2]
1101  1 [label="1 (0)"]
1102  2 [label="2 (1)", peripheries=2]
1103  3 [label="3 (2)"]
1104  4 [label="4 (1)"]
1105EOF
1106diff out expected
1107# --dot=d should also not use circles
1108ltl2tgba 'a U b' | autfilt --remove-ap=b=0 --name=%M --dot=dA >out
1109cat >expected <<EOF
1110digraph "a U b" {
1111  rankdir=LR
1112  node [shape="box",style="rounded",width="0.5"]
1113  I [label="", style=invis, width=0]
1114  I -> 0
1115  0 [label="0 (1)"]
1116  0 -> 0 [label="a"]
1117}
1118EOF
1119diff out expected
1120
1121# Issue #392.
1122test 2 = `genltl --rv-counter-carry-linear=7|ltl2tgba -d'<10' |grep -c hidden`
1123
1124f="{{!a;!b}:{{c <-> d} && {e xor f} && {m | {l && {k | {j <-> {i xor {g && h}"
1125f="$f}}}}} && {{n && o} | {!n && p}} && {q -> {r <-> s}}}:{[*0..1];t}}[]-> u"
1126ltl2tgba -f "$f" --dot=bar > out.dot
1127grep 'label too long' out.dot
1128
1129
1130# genltl --and-fg=32 | ltlfilt --relabel=abc | ltldo ltl3ba produces a
1131# few edges equivalent to a lot of transitions.  The code used to
1132# count those transitions used to be very inefficient.
1133cat >andfg32.hoa <<EOF
1134HOA: v1
1135States: 2
1136Start: 0
1137AP: 32 "a" "ab" "b" "bb" "c" "cb" "d" "db" "e" "eb" "f" "fb" "g" "h"
1138"i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
1139acc-name: Buchi
1140Acceptance: 1 Inf(0)
1141properties: trans-labels explicit-labels state-acc
1142--BODY--
1143State: 0
1144[t] 0
1145[0&1&2&3&4&5&6&7&8&9&10&11&12&13&14&15&16&17
1146&18&19&20&21&22&23&24&25&26&27&28&29&30&31] 1
1147State: 1 {0}
1148[0&1&2&3&4&5&6&7&8&9&10&11&12&13&14&15&16&17
1149&18&19&20&21&22&23&24&25&26&27&28&29&30&31] 1
1150--END--
1151EOF
1152test `autfilt andfg32.hoa --stats=%t` = 4294967298 # 2^32 + 2
1153