Commit a4b63e8e authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

dot: heuristic to switch between circles and ellipses

* src/twaalgos/dotty.cc: Add an option (e) to force elliptic shape, and
a heuristic to choose between circle and ellipse by default.
* src/bin/common_aoutput.cc, src/bin/dstar2tgba.cc: Document 'e'.
* src/taalgos/dotty.cc: Ignore 'e'.
* wrap/python/spot.py (setup): Do not force circular states.  The
default should be fine.
* src/tests/det.test, src/tests/dstar.test, src/tests/monitor.test,
src/tests/neverclaimread.test, src/tests/readsave.test,
src/tests/sccdot.test, src/tests/tgbagraph.test: Adjust expected
results.
* NEWS: Adjust.
parent 8aa88c29
......@@ -187,10 +187,12 @@ New in spot 1.99b (not yet released)
sugar for [:*1..], and corresponds to the operator ⊕ introduced
by Dax et al. (ATVA'09).
- GraphViz output now uses an horizontal layout by default. The
--dot option of the various command-line tools takes an optional
parameter to fine-tune the GraphViz output (including vertical
layout, round states, named automata, SCC informations, ordered
- GraphViz output now uses an horizontal layout by default, and
also use circular states (unless the automaton has more than 100
states, or uses named-states). The --dot option of the various
command-line tools takes an optional parameter to fine-tune the
GraphViz output (including vertical layout, forced circular or
elliptic states, named automata, SCC information, ordered
transitions, and different ways to colorize the acceptance
sets). The environment variables SPOT_DOTDEFAULT and
SPOT_DOTEXTRA can also be used to respectively provide a default
......
......@@ -51,13 +51,14 @@ static const argp_option options[] =
{
/**************************************************/
{ 0, 0, 0, 0, "Output format:", 3 },
{ "dot", OPT_DOT, "1|a|b|B|c|f(FONT)|h|n|N|o|r|R|s|t|v",
{ "dot", OPT_DOT, "1|a|b|B|c|e|f(FONT)|h|n|N|o|r|R|s|t|v",
OPTION_ARG_OPTIONAL,
"GraphViz's format (default). Add letters for "
"(1) force numbered states, "
"(a) acceptance display, (b) acceptance sets as bullets, "
"(B) bullets except for Büchi/co-Büchi automata, "
"(c) circular nodes, (f(FONT)) use FONT, (h) horizontal layout, "
"(c) force circular nodes, (e) force elliptic nodes, "
"(f(FONT)) use FONT, (h) horizontal layout, "
"(v) vertical layout, (n) with name, (N) without name, "
"(o) ordered transitions, "
"(r) rainbow colors for acceptance sets, "
......
......@@ -73,13 +73,14 @@ static const argp_option options[] =
"of the given property)", 0 },
/**************************************************/
{ 0, 0, 0, 0, "Output format:", 3 },
{ "dot", OPT_DOT, "1|a|b|B|c|f(FONT)|h|n|N|o|r|R|s|t|v",
{ "dot", OPT_DOT, "1|a|b|B|c|e|f(FONT)|h|n|N|o|r|R|s|t|v",
OPTION_ARG_OPTIONAL,
"GraphViz's format (default). Add letters for "
"(1) force numbered states, "
"(a) acceptance display, (b) acceptance sets as bullets, "
"(B) bullets except for Büchi automata, "
"(c) circular nodes, (f(FONT)) use FONT, (h) horizontal layout, "
"(B) bullets except for Büchi/co-Büchi automata, "
"(c) force circular nodes, (e) force elliptic nodes, "
"(f(FONT)) use FONT, (h) horizontal layout, "
"(v) vertical layout, (n) with name, (N) without name, "
"(o) ordered transitions, "
"(r) rainbow colors for acceptance sets, "
......
......@@ -88,6 +88,7 @@ namespace spot
case 'a':
case 'b':
case 'B':
case 'e':
case 'n':
case 'N':
case 'o':
......
......@@ -118,6 +118,7 @@ run 0 ../ltl2tgba -x -DC 'GFa & XGFb' > out.tgba
cat >ex.tgba <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......
......@@ -61,6 +61,7 @@ run 0 ../ltl2tgba -XD dra.dstar | tee stdout
cat >expected <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -82,6 +83,7 @@ run 0 ../ltl2tgba -XDD dra.dstar | tee stdout
cat >expected <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -126,6 +128,7 @@ run 0 ../ltl2tgba -XDB dsa.dstar | tee stdout
cat >expected <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -215,6 +218,7 @@ run 0 ../ltl2tgba -XDD dra.dstar | tee stdout
cat >expected <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -264,6 +268,7 @@ digraph G {
rankdir=LR
label="aut.dsa"
labelloc="t"
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......
......@@ -34,6 +34,7 @@ expect()
expect ../../bin/ltl2tgba --monitor a <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 1
0 [label="0"]
......
......@@ -134,6 +134,7 @@ run 0 ../ltl2tgba -XN input > stdout
cat >expected <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
......
......@@ -349,6 +349,7 @@ digraph G {
rankdir=LR
label="Inf(0)&Inf(1)"
labelloc="t"
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -367,6 +368,7 @@ digraph G {
rankdir=LR
label="G(Fa & Fb)\nInf(⓿)&Inf(❶)"
labelloc="t"
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -379,7 +381,7 @@ EOF
diff output expected
SPOT_DOTDEFAULT=bra $ltl2tgba --dot='c.f(Lato)' 'GFa & GFb' >output
SPOT_DOTDEFAULT=bra $ltl2tgba --dot='e.f(Lato)' 'GFa & GFb' >output
cat output
zero='<font color="#5DA5DA">⓿</font>'
......@@ -389,7 +391,6 @@ digraph G {
rankdir=LR
label=<Inf($zero)&amp;Inf($one)>
labelloc="t"
node [shape="circle"]
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
......@@ -515,6 +516,7 @@ digraph G {
rankdir=LR
label="Fin(⓿) | (Fin(❶) & Inf(❷)) | Fin(❸)"
labelloc="t"
node [shape="circle"]
I [label="", style=invis, width=0]
0 [label="0"]
1 [label="1\n⓿❸"]
......@@ -529,7 +531,8 @@ digraph G {
}
EOF
# This should remove the state names
# This should remove the state names, and automatically use circled
# states.
$autfilt --dot=bao1 in | grep -v '>' >out
diff out expected2
......
......@@ -76,6 +76,7 @@ digraph G {
rankdir=LR
label="Fin(2) & (Inf(0)&Inf(1))"
labelloc="t"
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 1
subgraph cluster_0 {
......
#!/bin/sh
# -*- coding: utf-8 -*-
# Copyright (C) 2014 Laboratoire de Recherche et Développement de
# l'Epita (LRDE).
# Copyright (C) 2014, 2015 Laboratoire de Recherche et Développement
# de l'Epita (LRDE).
#
# This file is part of Spot, a model checking library.
#
......@@ -35,6 +35,7 @@ run 0 ../tgbagraph | tee stdout
cat >expected <<EOF
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -50,6 +51,7 @@ digraph G {
}
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -63,6 +65,7 @@ digraph G {
}
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -75,6 +78,7 @@ digraph G {
}
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......@@ -90,6 +94,7 @@ digraph G {
}
digraph G {
rankdir=LR
node [shape="circle"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
......
......@@ -47,7 +47,8 @@ namespace spot
bool opt_force_acc_trans_ = false;
bool opt_horizontal_ = true;
bool opt_name_ = false;
bool opt_circles_ = false;
enum { ShapeAuto = 0, ShapeCircle, ShapeEllipse }
opt_shape_ = ShapeAuto;
bool opt_show_acc_ = false;
bool mark_states_ = false;
bool opt_scc_ = false;
......@@ -123,10 +124,10 @@ namespace spot
opt_bullet_but_buchi = true;
break;
case 'c':
opt_circles_ = true;
opt_shape_ = ShapeCircle;
break;
case 'h':
opt_horizontal_ = true;
case 'e':
opt_shape_ = ShapeEllipse;
break;
case 'f':
if (*options != '(')
......@@ -141,6 +142,9 @@ namespace spot
options = end + 1;
}
break;
case 'h':
opt_horizontal_ = true;
break;
case 'n':
opt_name_ = true;
break;
......@@ -275,7 +279,6 @@ namespace spot
aut_->get_acceptance().used_inf_fin_sets();
if (opt_bullet && aut_->acc().num_sets() <= MAX_BULLET)
opt_all_bullets = true;
os_ << "digraph G {\n";
if (opt_horizontal_)
os_ << " rankdir=LR\n";
......@@ -317,8 +320,18 @@ namespace spot
}
os_ << " labelloc=\"t\"\n";
}
if (opt_circles_)
os_ << " node [shape=\"circle\"]\n";
switch (opt_shape_)
{
case ShapeCircle:
os_ << " node [shape=\"circle\"]\n";
break;
case ShapeEllipse:
// Do not print anything. Ellipse is
// the default shape used by GraphViz.
break;
case ShapeAuto:
SPOT_UNREACHABLE();
}
if (!opt_font_.empty())
os_ << " fontname=\"" << opt_font_
<< "\"\n node [fontname=\"" << opt_font_
......@@ -452,8 +465,16 @@ namespace spot
if (opt_name_)
name_ = aut_->get_named_prop<std::string>("automaton-name");
mark_states_ = !opt_force_acc_trans_ && aut_->has_state_based_acc();
if (opt_shape_ == ShapeAuto)
{
if (sn_ || aut->num_states() > 100)
opt_shape_ = ShapeEllipse;
else
opt_shape_ = ShapeCircle;
}
auto si =
std::unique_ptr<scc_info>(opt_scc_ ? new scc_info(aut) : nullptr);
start();
if (si)
{
......
......@@ -48,7 +48,7 @@ def setup(**kwargs):
kwargs.get('fillcolor', '#ffffaa'))
bullets = 'B' if kwargs.get('bullets', True) else ''
d = 'rcf({})'.format(kwargs.get('font', 'Lato')) + bullets
d = 'rf({})'.format(kwargs.get('font', 'Lato')) + bullets
os.environ['SPOT_DOTDEFAULT'] = d
# Global BDD dict so that we do not have to create one in user code.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment