* NEWS: Mention this. * COPYING: Replace by GPL v3. * src/sanity/style.test: Check files with the wrong license, in case we forgot to update it during a merge. * Makefile.am, bench/Makefile.am, bench/emptchk/Makefile.am, bench/emptchk/defs.in, bench/emptchk/ltl-human.sh, bench/emptchk/ltl-random.sh, bench/emptchk/pml-clserv.sh, bench/emptchk/pml-eeaean.sh, bench/emptchk/pml2tgba.pl, bench/ltl2tgba/big, bench/ltl2tgba/defs.in, bench/ltl2tgba/known, bench/ltl2tgba/lbtt2csv.pl, bench/ltl2tgba/ltl2baw.in, bench/ltl2tgba/parseout.pl, bench/ltl2tgba/small, bench/ltlclasses/Makefile.am, bench/ltlclasses/defs.in, bench/ltlclasses/run, bench/ltlcounter/Makefile.am, bench/ltlcounter/defs.in, bench/ltlcounter/run, bench/scc-stats/Makefile.am, bench/scc-stats/stats.cc, bench/split-product/Makefile.am, bench/split-product/cutscc.cc, bench/split-product/pml2tgba.pl, bench/wdba/Makefile.am, bench/wdba/defs.in, bench/wdba/run, configure.ac, doc/Makefile.am, doc/dot.in, doc/tl/Makefile.am, iface/Makefile.am, iface/dve2/Makefile.am, iface/dve2/defs.in, iface/dve2/dve2.cc, iface/dve2/dve2.hh, iface/dve2/dve2check.cc, iface/dve2/dve2check.test, iface/dve2/finite.test, iface/dve2/kripke.test, iface/gspn/Makefile.am, iface/gspn/common.cc, iface/gspn/common.hh, iface/gspn/dcswave.test, iface/gspn/dcswaveeltl.test, iface/gspn/dcswavefm.test, iface/gspn/dcswaveltl.test, iface/gspn/dottygspn.cc, iface/gspn/dottyssp.cc, iface/gspn/gspn.cc, iface/gspn/gspn.hh, iface/gspn/ltlgspn.cc, iface/gspn/simple.test, iface/gspn/ssp.cc, iface/gspn/ssp.hh, iface/gspn/udcsefm.test, iface/gspn/udcseltl.test, iface/gspn/udcsfm.test, iface/gspn/udcsltl.test, src/Makefile.am, src/bin/Makefile.am, src/bin/common_cout.cc, src/bin/common_cout.hh, src/bin/common_finput.cc, src/bin/common_finput.hh, src/bin/common_output.cc, src/bin/common_output.hh, src/bin/common_post.cc, src/bin/common_post.hh, src/bin/common_r.cc, src/bin/common_r.hh, src/bin/common_range.cc, src/bin/common_range.hh, src/bin/common_setup.cc, src/bin/common_setup.hh, src/bin/common_sys.hh, src/bin/genltl.cc, src/bin/ltl2tgba.cc, src/bin/ltl2tgta.cc, src/bin/ltlfilt.cc, src/bin/man/Makefile.am, src/bin/randltl.cc, src/eltlparse/Makefile.am, src/eltlparse/eltlparse.yy, src/eltlparse/eltlscan.ll, src/eltlparse/fmterror.cc, src/eltlparse/parsedecl.hh, src/eltlparse/public.hh, src/eltltest/Makefile.am, src/eltltest/acc.cc, src/eltltest/acc.test, src/eltltest/defs.in, src/eltltest/nfa.cc, src/eltltest/nfa.test, src/evtgba/Makefile.am, src/evtgba/evtgba.cc, src/evtgba/evtgba.hh, src/evtgba/evtgbaiter.hh, src/evtgba/explicit.cc, src/evtgba/explicit.hh, src/evtgba/product.cc, src/evtgba/product.hh, src/evtgba/symbol.cc, src/evtgba/symbol.hh, src/evtgbaalgos/Makefile.am, src/evtgbaalgos/dotty.cc, src/evtgbaalgos/dotty.hh, src/evtgbaalgos/reachiter.cc, src/evtgbaalgos/reachiter.hh, src/evtgbaalgos/save.cc, src/evtgbaalgos/save.hh, src/evtgbaalgos/tgba2evtgba.cc, src/evtgbaalgos/tgba2evtgba.hh, src/evtgbaparse/Makefile.am, src/evtgbaparse/evtgbaparse.yy, src/evtgbaparse/evtgbascan.ll, src/evtgbaparse/fmterror.cc, src/evtgbaparse/parsedecl.hh, src/evtgbaparse/public.hh, src/evtgbatest/Makefile.am, src/evtgbatest/defs.in, src/evtgbatest/explicit.cc, src/evtgbatest/explicit.test, src/evtgbatest/ltl2evtgba.cc, src/evtgbatest/ltl2evtgba.test, src/evtgbatest/product.cc, src/evtgbatest/product.test, src/evtgbatest/readsave.cc, src/evtgbatest/readsave.test, src/kripke/Makefile.am, src/kripke/fairkripke.cc, src/kripke/fairkripke.hh, src/kripke/kripke.cc, src/kripke/kripke.hh, src/kripke/kripkeexplicit.cc, src/kripke/kripkeexplicit.hh, src/kripke/kripkeprint.cc, src/kripke/kripkeprint.hh, src/kripkeparse/Makefile.am, src/kripkeparse/fmterror.cc, src/kripkeparse/kripkeparse.yy, src/kripkeparse/kripkescan.ll, src/kripkeparse/parsedecl.hh, src/kripkeparse/public.hh, src/kripkeparse/scankripke.ll, src/kripketest/Makefile.am, src/kripketest/bad_parsing.test, src/kripketest/defs.in, src/kripketest/kripke.test, src/kripketest/parse_print_test.cc, src/ltlast/Makefile.am, src/ltlast/allnodes.hh, src/ltlast/atomic_prop.cc, src/ltlast/atomic_prop.hh, src/ltlast/automatop.cc, src/ltlast/automatop.hh, src/ltlast/binop.cc, src/ltlast/binop.hh, src/ltlast/bunop.cc, src/ltlast/bunop.hh, src/ltlast/constant.cc, src/ltlast/constant.hh, src/ltlast/formula.cc, src/ltlast/formula.hh, src/ltlast/formula_tree.cc, src/ltlast/formula_tree.hh, src/ltlast/multop.cc, src/ltlast/multop.hh, src/ltlast/nfa.cc, src/ltlast/nfa.hh, src/ltlast/predecl.hh, src/ltlast/refformula.cc, src/ltlast/refformula.hh, src/ltlast/unop.cc, src/ltlast/unop.hh, src/ltlast/visitor.hh, src/ltlenv/Makefile.am, src/ltlenv/declenv.cc, src/ltlenv/declenv.hh, src/ltlenv/defaultenv.cc, src/ltlenv/defaultenv.hh, src/ltlenv/environment.hh, src/ltlparse/Makefile.am, src/ltlparse/fmterror.cc, src/ltlparse/ltlfile.cc, src/ltlparse/ltlfile.hh, src/ltlparse/ltlparse.yy, src/ltlparse/ltlscan.ll, src/ltlparse/parsedecl.hh, src/ltlparse/public.hh, src/ltltest/Makefile.am, src/ltltest/consterm.cc, src/ltltest/consterm.test, src/ltltest/defs.in, src/ltltest/equals.cc, src/ltltest/equals.test, src/ltltest/kind.cc, src/ltltest/kind.test, src/ltltest/length.cc, src/ltltest/length.test, src/ltltest/lunabbrev.test, src/ltltest/nenoform.test, src/ltltest/parse.test, src/ltltest/parseerr.test, src/ltltest/readltl.cc, src/ltltest/reduc.cc, src/ltltest/reduc.test, src/ltltest/reduccmp.test, src/ltltest/reducpsl.test, src/ltltest/syntimpl.cc, src/ltltest/syntimpl.test, src/ltltest/tostring.cc, src/ltltest/tostring.test, src/ltltest/tunabbrev.test, src/ltltest/tunenoform.test, src/ltltest/utf8.test, src/ltltest/uwrm.test, src/ltlvisit/Makefile.am, src/ltlvisit/apcollect.cc, src/ltlvisit/apcollect.hh, src/ltlvisit/clone.cc, src/ltlvisit/clone.hh, src/ltlvisit/contain.cc, src/ltlvisit/contain.hh, src/ltlvisit/destroy.cc, src/ltlvisit/destroy.hh, src/ltlvisit/dotty.cc, src/ltlvisit/dotty.hh, src/ltlvisit/dump.cc, src/ltlvisit/dump.hh, src/ltlvisit/lbt.cc, src/ltlvisit/lbt.hh, src/ltlvisit/length.cc, src/ltlvisit/length.hh, src/ltlvisit/lunabbrev.cc, src/ltlvisit/lunabbrev.hh, src/ltlvisit/mark.cc, src/ltlvisit/mark.hh, src/ltlvisit/nenoform.cc, src/ltlvisit/nenoform.hh, src/ltlvisit/postfix.cc, src/ltlvisit/postfix.hh, src/ltlvisit/randomltl.cc, src/ltlvisit/randomltl.hh, src/ltlvisit/reduce.cc, src/ltlvisit/reduce.hh, src/ltlvisit/relabel.cc, src/ltlvisit/relabel.hh, src/ltlvisit/simpfg.cc, src/ltlvisit/simpfg.hh, src/ltlvisit/simplify.cc, src/ltlvisit/simplify.hh, src/ltlvisit/snf.cc, src/ltlvisit/snf.hh, src/ltlvisit/tostring.cc, src/ltlvisit/tostring.hh, src/ltlvisit/tunabbrev.cc, src/ltlvisit/tunabbrev.hh, src/ltlvisit/wmunabbrev.cc, src/ltlvisit/wmunabbrev.hh, src/misc/Makefile.am, src/misc/acccompl.cc, src/misc/acccompl.hh, src/misc/accconv.cc, src/misc/accconv.hh, src/misc/bareword.cc, src/misc/bareword.hh, src/misc/bddalloc.cc, src/misc/bddalloc.hh, src/misc/bddlt.hh, src/misc/bddop.cc, src/misc/bddop.hh, src/misc/casts.hh, src/misc/escape.cc, src/misc/escape.hh, src/misc/fixpool.hh, src/misc/freelist.cc, src/misc/freelist.hh, src/misc/hash.hh, src/misc/hashfunc.hh, src/misc/intvcmp2.cc, src/misc/intvcmp2.hh, src/misc/intvcomp.cc, src/misc/intvcomp.hh, src/misc/ltstr.hh, src/misc/memusage.cc, src/misc/memusage.hh, src/misc/minato.cc, src/misc/minato.hh, src/misc/modgray.cc, src/misc/modgray.hh, src/misc/mspool.hh, src/misc/optionmap.cc, src/misc/optionmap.hh, src/misc/random.cc, src/misc/random.hh, src/misc/timer.cc, src/misc/timer.hh, src/misc/unique_ptr.hh, src/misc/version.cc, src/misc/version.hh, src/neverparse/Makefile.am, src/neverparse/fmterror.cc, src/neverparse/neverclaimparse.yy, src/neverparse/neverclaimscan.ll, src/neverparse/parsedecl.hh, src/neverparse/public.hh, src/saba/Makefile.am, src/saba/explicitstateconjunction.cc, src/saba/explicitstateconjunction.hh, src/saba/saba.cc, src/saba/saba.hh, src/saba/sabacomplementtgba.cc, src/saba/sabacomplementtgba.hh, src/saba/sabastate.hh, src/saba/sabasucciter.hh, src/sabaalgos/Makefile.am, src/sabaalgos/sabadotty.cc, src/sabaalgos/sabadotty.hh, src/sabaalgos/sabareachiter.cc, src/sabaalgos/sabareachiter.hh, src/sabatest/Makefile.am, src/sabatest/defs.in, src/sabatest/sabacomplementtgba.cc, src/sanity/Makefile.am, src/sanity/readme.test, src/sanity/style.test, src/ta/Makefile.am, src/ta/ta.cc, src/ta/ta.hh, src/ta/taexplicit.cc, src/ta/taexplicit.hh, src/ta/taproduct.cc, src/ta/taproduct.hh, src/ta/tgta.cc, src/ta/tgta.hh, src/ta/tgtaexplicit.cc, src/ta/tgtaexplicit.hh, src/ta/tgtaproduct.cc, src/ta/tgtaproduct.hh, src/taalgos/Makefile.am, src/taalgos/dotty.cc, src/taalgos/dotty.hh, src/taalgos/emptinessta.cc, src/taalgos/emptinessta.hh, src/taalgos/minimize.cc, src/taalgos/minimize.hh, src/taalgos/reachiter.cc, src/taalgos/reachiter.hh, src/taalgos/statessetbuilder.cc, src/taalgos/statessetbuilder.hh, src/taalgos/stats.cc, src/taalgos/stats.hh, src/taalgos/tgba2ta.cc, src/taalgos/tgba2ta.hh, src/tgba/Makefile.am, src/tgba/bdddict.cc, src/tgba/bdddict.hh, src/tgba/bddprint.cc, src/tgba/bddprint.hh, src/tgba/formula2bdd.cc, src/tgba/formula2bdd.hh, src/tgba/futurecondcol.cc, src/tgba/futurecondcol.hh, src/tgba/public.hh, src/tgba/sba.hh, src/tgba/state.hh, src/tgba/statebdd.cc, src/tgba/statebdd.hh, src/tgba/succiter.hh, src/tgba/succiterconcrete.cc, src/tgba/succiterconcrete.hh, src/tgba/taatgba.cc, src/tgba/taatgba.hh, src/tgba/tgba.cc, src/tgba/tgba.hh, src/tgba/tgbabddconcrete.cc, src/tgba/tgbabddconcrete.hh, src/tgba/tgbabddconcretefactory.cc, src/tgba/tgbabddconcretefactory.hh, src/tgba/tgbabddconcreteproduct.cc, src/tgba/tgbabddconcreteproduct.hh, src/tgba/tgbabddcoredata.cc, src/tgba/tgbabddcoredata.hh, src/tgba/tgbabddfactory.hh, src/tgba/tgbaexplicit.cc, src/tgba/tgbaexplicit.hh, src/tgba/tgbakvcomplement.cc, src/tgba/tgbakvcomplement.hh, src/tgba/tgbaproduct.cc, src/tgba/tgbaproduct.hh, src/tgba/tgbasafracomplement.cc, src/tgba/tgbasafracomplement.hh, src/tgba/tgbascc.cc, src/tgba/tgbascc.hh, src/tgba/tgbasgba.cc, src/tgba/tgbasgba.hh, src/tgba/tgbatba.cc, src/tgba/tgbatba.hh, src/tgba/tgbaunion.cc, src/tgba/tgbaunion.hh, src/tgba/wdbacomp.cc, src/tgba/wdbacomp.hh, src/tgbaalgos/Makefile.am, src/tgbaalgos/bfssteps.cc, src/tgbaalgos/bfssteps.hh, src/tgbaalgos/cutscc.cc, src/tgbaalgos/cutscc.hh, src/tgbaalgos/cycles.cc, src/tgbaalgos/cycles.hh, src/tgbaalgos/degen.cc, src/tgbaalgos/degen.hh, src/tgbaalgos/dotty.cc, src/tgbaalgos/dotty.hh, src/tgbaalgos/dottydec.cc, src/tgbaalgos/dottydec.hh, src/tgbaalgos/dupexp.cc, src/tgbaalgos/dupexp.hh, src/tgbaalgos/eltl2tgba_lacim.cc, src/tgbaalgos/eltl2tgba_lacim.hh, src/tgbaalgos/emptiness.cc, src/tgbaalgos/emptiness.hh, src/tgbaalgos/emptiness_stats.hh, src/tgbaalgos/gtec/Makefile.am, src/tgbaalgos/gtec/ce.cc, src/tgbaalgos/gtec/ce.hh, src/tgbaalgos/gtec/explscc.cc, src/tgbaalgos/gtec/explscc.hh, src/tgbaalgos/gtec/gtec.cc, src/tgbaalgos/gtec/gtec.hh, src/tgbaalgos/gtec/nsheap.cc, src/tgbaalgos/gtec/nsheap.hh, src/tgbaalgos/gtec/sccstack.cc, src/tgbaalgos/gtec/sccstack.hh, src/tgbaalgos/gtec/status.cc, src/tgbaalgos/gtec/status.hh, src/tgbaalgos/gv04.cc, src/tgbaalgos/gv04.hh, src/tgbaalgos/isdet.cc, src/tgbaalgos/isdet.hh, src/tgbaalgos/isweakscc.cc, src/tgbaalgos/isweakscc.hh, src/tgbaalgos/lbtt.cc, src/tgbaalgos/lbtt.hh, src/tgbaalgos/ltl2taa.cc, src/tgbaalgos/ltl2taa.hh, src/tgbaalgos/ltl2tgba_fm.cc, src/tgbaalgos/ltl2tgba_fm.hh, src/tgbaalgos/ltl2tgba_lacim.cc, src/tgbaalgos/ltl2tgba_lacim.hh, src/tgbaalgos/magic.cc, src/tgbaalgos/magic.hh, src/tgbaalgos/minimize.cc, src/tgbaalgos/minimize.hh, src/tgbaalgos/ndfs_result.hxx, src/tgbaalgos/neverclaim.cc, src/tgbaalgos/neverclaim.hh, src/tgbaalgos/postproc.cc, src/tgbaalgos/postproc.hh, src/tgbaalgos/powerset.cc, src/tgbaalgos/powerset.hh, src/tgbaalgos/projrun.cc, src/tgbaalgos/projrun.hh, src/tgbaalgos/randomgraph.cc, src/tgbaalgos/randomgraph.hh, src/tgbaalgos/reachiter.cc, src/tgbaalgos/reachiter.hh, src/tgbaalgos/reducerun.cc, src/tgbaalgos/reducerun.hh, src/tgbaalgos/reductgba_sim.cc, src/tgbaalgos/reductgba_sim.hh, src/tgbaalgos/replayrun.cc, src/tgbaalgos/replayrun.hh, src/tgbaalgos/rundotdec.cc, src/tgbaalgos/rundotdec.hh, src/tgbaalgos/safety.cc, src/tgbaalgos/safety.hh, src/tgbaalgos/save.cc, src/tgbaalgos/save.hh, src/tgbaalgos/scc.cc, src/tgbaalgos/scc.hh, src/tgbaalgos/sccfilter.cc, src/tgbaalgos/sccfilter.hh, src/tgbaalgos/se05.cc, src/tgbaalgos/se05.hh, src/tgbaalgos/simulation.cc, src/tgbaalgos/simulation.hh, src/tgbaalgos/stats.cc, src/tgbaalgos/stats.hh, src/tgbaalgos/tau03.cc, src/tgbaalgos/tau03.hh, src/tgbaalgos/tau03opt.cc, src/tgbaalgos/tau03opt.hh, src/tgbaalgos/weight.cc, src/tgbaalgos/weight.hh, src/tgbaparse/Makefile.am, src/tgbaparse/fmterror.cc, src/tgbaparse/parsedecl.hh, src/tgbaparse/public.hh, src/tgbaparse/tgbaparse.yy, src/tgbaparse/tgbascan.ll, src/tgbatest/Makefile.am, src/tgbatest/babiak.test, src/tgbatest/bddprod.test, src/tgbatest/complementation.cc, src/tgbatest/complementation.test, src/tgbatest/cycles.test, src/tgbatest/defs.in, src/tgbatest/degendet.test, src/tgbatest/degenid.test, src/tgbatest/dfs.test, src/tgbatest/dupexp.test, src/tgbatest/eltl2tgba.test, src/tgbatest/emptchk.test, src/tgbatest/emptchke.test, src/tgbatest/emptchkr.test, src/tgbatest/explicit.cc, src/tgbatest/explicit.test, src/tgbatest/explicit2.cc, src/tgbatest/explicit2.test, src/tgbatest/explpro2.test, src/tgbatest/explpro3.test, src/tgbatest/explpro4.test, src/tgbatest/explprod.cc, src/tgbatest/explprod.test, src/tgbatest/intvcmp2.cc, src/tgbatest/intvcomp.cc, src/tgbatest/intvcomp.test, src/tgbatest/kv.test, src/tgbatest/ltl2neverclaim.test, src/tgbatest/ltl2ta.test, src/tgbatest/ltl2tgba.cc, src/tgbatest/ltl2tgba.test, src/tgbatest/ltlcounter.test, src/tgbatest/ltlprod.cc, src/tgbatest/ltlprod.test, src/tgbatest/mixprod.cc, src/tgbatest/mixprod.test, src/tgbatest/neverclaimread.test, src/tgbatest/nondet.test, src/tgbatest/obligation.test, src/tgbatest/powerset.cc, src/tgbatest/randpsl.test, src/tgbatest/randtgba.cc, src/tgbatest/randtgba.test, src/tgbatest/readsave.test, src/tgbatest/renault.test, src/tgbatest/scc.test, src/tgbatest/sccsimpl.test, src/tgbatest/spotlbtt.test, src/tgbatest/spotlbtt2.test, src/tgbatest/taatgba.cc, src/tgbatest/taatgba.test, src/tgbatest/tgbaread.cc, src/tgbatest/tgbaread.test, src/tgbatest/tripprod.cc, src/tgbatest/tripprod.test, src/tgbatest/wdba.test, src/tgbatest/wdba2.test, wrap/Makefile.am, wrap/python/Makefile.am, wrap/python/ajax/Makefile.am, wrap/python/ajax/spot.in, wrap/python/buddy.i, wrap/python/spot.i, wrap/python/tests/Makefile.am, wrap/python/tests/alarm.py, wrap/python/tests/bddnqueen.py, wrap/python/tests/implies.py, wrap/python/tests/interdep.py, wrap/python/tests/ltl2tgba.py, wrap/python/tests/ltl2tgba.test, wrap/python/tests/ltlparse.py, wrap/python/tests/ltlsimple.py, wrap/python/tests/minato.py, wrap/python/tests/modgray.py, wrap/python/tests/optionmap.py, wrap/python/tests/parsetgba.py, wrap/python/tests/run.in, wrap/python/tests/setxor.py: Update licence version, and replace the FSF address by a URL.
1361 lines
31 KiB
C++
1361 lines
31 KiB
C++
// Copyright (C) 2008, 2011 Laboratoire de Recherche et Developpement
|
|
// de l'Epita (LRDE).
|
|
// Copyright (C) 2003, 2004, 2005, 2006, 2007 Laboratoire
|
|
// d'Informatique de Paris 6 (LIP6), département Systèmes Répartis
|
|
// Coopératifs (SRC), Université Pierre et Marie Curie.
|
|
//
|
|
// This file is part of Spot, a model checking library.
|
|
//
|
|
// Spot is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
// License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#include <cstring>
|
|
#include <map>
|
|
#include <cassert>
|
|
#include <gspnlib.h>
|
|
#include "ssp.hh"
|
|
#include "misc/bddlt.hh"
|
|
#include "misc/hash.hh"
|
|
#include <bdd.h>
|
|
#include "tgbaalgos/gtec/explscc.hh"
|
|
#include "tgbaalgos/gtec/nsheap.hh"
|
|
|
|
namespace spot
|
|
{
|
|
|
|
namespace
|
|
{
|
|
static bdd*
|
|
bdd_realloc(bdd* t, int size, int new_size)
|
|
{
|
|
assert(new_size);
|
|
bdd* tmp = new bdd[new_size];
|
|
|
|
for (int i = 0; i < size; i++)
|
|
tmp[i] = t[i];
|
|
|
|
delete[] t;
|
|
return tmp;
|
|
}
|
|
|
|
static bool doublehash;
|
|
static bool pushfront;
|
|
}
|
|
|
|
// state_gspn_ssp
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
class state_gspn_ssp: public state
|
|
{
|
|
public:
|
|
state_gspn_ssp(State left, const state* right)
|
|
: left_(left), right_(right)
|
|
{
|
|
}
|
|
|
|
virtual
|
|
~state_gspn_ssp()
|
|
{
|
|
right_->destroy();
|
|
}
|
|
|
|
virtual int
|
|
compare(const state* other) const
|
|
{
|
|
const state_gspn_ssp* o = down_cast<const state_gspn_ssp*>(other);
|
|
assert(o);
|
|
if (o->left() == left())
|
|
return right_->compare(o->right());
|
|
if (o->left() < left())
|
|
return -1;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
virtual size_t
|
|
hash() const
|
|
{
|
|
return ((reinterpret_cast<char*>(left())
|
|
- static_cast<char*>(0)) << 10) + right_->hash();
|
|
}
|
|
|
|
virtual state_gspn_ssp* clone() const
|
|
{
|
|
return new state_gspn_ssp(left(), right()->clone());
|
|
}
|
|
|
|
State
|
|
left() const
|
|
{
|
|
return left_;
|
|
}
|
|
|
|
const state*
|
|
right() const
|
|
{
|
|
return right_;
|
|
}
|
|
|
|
private:
|
|
State left_;
|
|
const state* right_;
|
|
}; // state_gspn_ssp
|
|
|
|
// tgba_gspn_ssp_private_
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
struct tgba_gspn_ssp_private_
|
|
{
|
|
int refs; // reference count
|
|
|
|
bdd_dict* dict;
|
|
typedef std::map<int, AtomicProp> prop_map;
|
|
prop_map prop_dict;
|
|
|
|
signed char* all_props;
|
|
|
|
size_t prop_count;
|
|
const tgba* operand;
|
|
|
|
tgba_gspn_ssp_private_(bdd_dict* dict,
|
|
const ltl::declarative_environment& env,
|
|
const tgba* operand)
|
|
: refs(1), dict(dict), all_props(0),
|
|
operand(operand)
|
|
{
|
|
const ltl::declarative_environment::prop_map& p = env.get_prop_map();
|
|
|
|
try
|
|
{
|
|
AtomicProp max_prop = 0;
|
|
|
|
for (ltl::declarative_environment::prop_map::const_iterator i
|
|
= p.begin(); i != p.end(); ++i)
|
|
{
|
|
int var = dict->register_proposition(i->second, this);
|
|
AtomicProp index;
|
|
int err = prop_index(i->first.c_str(), &index);
|
|
if (err)
|
|
throw gspn_exception("prop_index(" + i->first + ")", err);
|
|
|
|
prop_dict[var] = index;
|
|
|
|
max_prop = std::max(max_prop, index);
|
|
}
|
|
prop_count = 1 + max_prop;
|
|
all_props = new signed char[prop_count];
|
|
}
|
|
catch (...)
|
|
{
|
|
// If an exception occurs during the loop, we need to clean
|
|
// all BDD variables which have been registered so far.
|
|
dict->unregister_all_my_variables(this);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
~tgba_gspn_ssp_private_()
|
|
{
|
|
dict->unregister_all_my_variables(this);
|
|
delete[] all_props;
|
|
}
|
|
};
|
|
|
|
|
|
// tgba_succ_iterator_gspn_ssp
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
class tgba_succ_iterator_gspn_ssp: public tgba_succ_iterator
|
|
{
|
|
public:
|
|
tgba_succ_iterator_gspn_ssp(Succ_* succ_tgba,
|
|
size_t size_tgba,
|
|
bdd* bdd_array,
|
|
state** state_array,
|
|
size_t size_states,
|
|
Props_* prop,
|
|
int size_prop)
|
|
: successors_(succ_tgba),
|
|
size_succ_(size_tgba),
|
|
current_succ_(0),
|
|
bdd_array_(bdd_array),
|
|
state_array_(state_array),
|
|
size_states_(size_states),
|
|
props_(prop),
|
|
size_prop_(size_prop)
|
|
{
|
|
}
|
|
|
|
virtual
|
|
~tgba_succ_iterator_gspn_ssp()
|
|
{
|
|
|
|
for (size_t i = 0; i < size_states_; i++)
|
|
state_array_[i]->destroy();
|
|
|
|
delete[] bdd_array_;
|
|
free(state_array_);
|
|
|
|
if (props_)
|
|
{
|
|
for (int i = 0; i < size_prop_; i++)
|
|
free(props_[i].arc);
|
|
free(props_);
|
|
}
|
|
|
|
if (size_succ_ != 0)
|
|
succ_free(successors_);
|
|
|
|
}
|
|
|
|
virtual void
|
|
first()
|
|
{
|
|
if (!successors_)
|
|
return;
|
|
current_succ_=0;
|
|
}
|
|
|
|
virtual void
|
|
next()
|
|
{
|
|
++current_succ_;
|
|
}
|
|
|
|
virtual bool
|
|
done() const
|
|
{
|
|
return current_succ_ + 1 > size_succ_;
|
|
}
|
|
|
|
virtual state*
|
|
current_state() const
|
|
{
|
|
state_gspn_ssp* s =
|
|
new state_gspn_ssp(successors_[current_succ_].succ_,
|
|
(state_array_[successors_[current_succ_]
|
|
.arc->curr_state])->clone());
|
|
return s;
|
|
}
|
|
|
|
virtual bdd
|
|
current_condition() const
|
|
{
|
|
return bddtrue;
|
|
}
|
|
|
|
virtual bdd
|
|
current_acceptance_conditions() const
|
|
{
|
|
// There is no acceptance conditions in GSPN systems, so we just
|
|
// return those from operand_.
|
|
return bdd_array_[successors_[current_succ_].arc->curr_acc_conds];
|
|
}
|
|
private:
|
|
|
|
// All successors of STATE matching a selection conjunctions from
|
|
// ALL_CONDS.
|
|
Succ_* successors_; /// array of successors
|
|
size_t size_succ_; /// size of successors_
|
|
size_t current_succ_; /// current position in successors_
|
|
|
|
bdd * bdd_array_;
|
|
state** state_array_;
|
|
size_t size_states_;
|
|
Props_* props_;
|
|
int size_prop_;
|
|
}; // tgba_succ_iterator_gspn_ssp
|
|
|
|
|
|
// tgba_gspn_ssp
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
class tgba_gspn_ssp: public tgba
|
|
{
|
|
public:
|
|
tgba_gspn_ssp(bdd_dict* dict, const ltl::declarative_environment& env,
|
|
const tgba* operand);
|
|
tgba_gspn_ssp(const tgba_gspn_ssp& other);
|
|
tgba_gspn_ssp& operator=(const tgba_gspn_ssp& other);
|
|
virtual ~tgba_gspn_ssp();
|
|
virtual state* get_init_state() const;
|
|
virtual tgba_succ_iterator*
|
|
succ_iter(const state* local_state,
|
|
const state* global_state = 0,
|
|
const tgba* global_automaton = 0) const;
|
|
virtual bdd_dict* get_dict() const;
|
|
virtual std::string format_state(const state* state) const;
|
|
virtual state* project_state(const state* s, const tgba* t) const;
|
|
virtual bdd all_acceptance_conditions() const;
|
|
virtual bdd neg_acceptance_conditions() const;
|
|
protected:
|
|
virtual bdd compute_support_conditions(const spot::state* state) const;
|
|
virtual bdd compute_support_variables(const spot::state* state) const;
|
|
private:
|
|
tgba_gspn_ssp_private_* data_;
|
|
};
|
|
|
|
tgba_gspn_ssp::tgba_gspn_ssp(bdd_dict* dict,
|
|
const ltl::declarative_environment& env,
|
|
const tgba* operand)
|
|
{
|
|
data_ = new tgba_gspn_ssp_private_(dict, env, operand);
|
|
}
|
|
|
|
tgba_gspn_ssp::tgba_gspn_ssp(const tgba_gspn_ssp& other)
|
|
: tgba()
|
|
{
|
|
data_ = other.data_;
|
|
++data_->refs;
|
|
}
|
|
|
|
tgba_gspn_ssp::~tgba_gspn_ssp()
|
|
{
|
|
if (--data_->refs == 0)
|
|
delete data_;
|
|
}
|
|
|
|
tgba_gspn_ssp&
|
|
tgba_gspn_ssp::operator=(const tgba_gspn_ssp& other)
|
|
{
|
|
if (&other == this)
|
|
return *this;
|
|
this->~tgba_gspn_ssp();
|
|
new (this) tgba_gspn_ssp(other);
|
|
return *this;
|
|
}
|
|
|
|
state* tgba_gspn_ssp::get_init_state() const
|
|
{
|
|
// Use 0 as initial state for the SSP side. State 0 does not
|
|
// exists, but when passed to succ() it will produce the list
|
|
// of initial states.
|
|
return new state_gspn_ssp(0, data_->operand->get_init_state());
|
|
}
|
|
|
|
tgba_succ_iterator*
|
|
tgba_gspn_ssp::succ_iter(const state* state_,
|
|
const state* global_state,
|
|
const tgba* global_automaton) const
|
|
{
|
|
const state_gspn_ssp* s = down_cast<const state_gspn_ssp*>(state_);
|
|
assert(s);
|
|
(void) global_state;
|
|
(void) global_automaton;
|
|
|
|
bdd all_conds_;
|
|
bdd outside_;
|
|
bdd cond;
|
|
|
|
Props_* props_ = 0;
|
|
int nb_arc_props = 0;
|
|
bdd* bdd_array = 0;
|
|
int size_bdd = 0;
|
|
state** state_array = 0;
|
|
size_t size_states = 0;
|
|
|
|
tgba_succ_iterator* i = data_->operand->succ_iter(s->right());
|
|
|
|
for (i->first(); !i->done(); i->next())
|
|
{
|
|
all_conds_ = i->current_condition();
|
|
outside_ = !all_conds_;
|
|
|
|
if (all_conds_ != bddfalse)
|
|
{
|
|
props_ = (Props_*) realloc(props_,
|
|
(nb_arc_props + 1) * sizeof(Props_));
|
|
|
|
props_[nb_arc_props].nb_conj = 0;
|
|
props_[nb_arc_props].prop = 0;
|
|
props_[nb_arc_props].arc =
|
|
(Arc_Ident_*) malloc(sizeof(Arc_Ident_));
|
|
|
|
bdd_array = bdd_realloc(bdd_array, size_bdd, size_bdd + 1);
|
|
bdd_array[size_bdd] = i->current_acceptance_conditions();
|
|
props_[nb_arc_props].arc->curr_acc_conds = size_bdd;
|
|
++size_bdd;
|
|
|
|
state_array =
|
|
(state**) realloc(state_array,
|
|
(size_states + 1) * sizeof(state*));
|
|
state_array[size_states] = i->current_state();
|
|
props_[nb_arc_props].arc->curr_state = size_states;
|
|
++size_states;
|
|
|
|
while (all_conds_ != bddfalse)
|
|
{
|
|
cond = bdd_satone(all_conds_);
|
|
cond = bdd_simplify(cond, cond | outside_);
|
|
all_conds_ -= cond;
|
|
|
|
props_[nb_arc_props].prop =
|
|
(signed char **) realloc(props_[nb_arc_props].prop,
|
|
(props_[nb_arc_props].nb_conj + 1)
|
|
* sizeof(signed char *));
|
|
|
|
props_[nb_arc_props].prop[props_[nb_arc_props].nb_conj]
|
|
= (signed char*) calloc(data_->prop_count,
|
|
sizeof(signed char));
|
|
memset(props_[nb_arc_props].prop[props_[nb_arc_props].nb_conj],
|
|
-1, data_->prop_count);
|
|
|
|
while (cond != bddtrue)
|
|
{
|
|
int var = bdd_var(cond);
|
|
bdd high = bdd_high(cond);
|
|
int res;
|
|
|
|
if (high == bddfalse)
|
|
{
|
|
cond = bdd_low(cond);
|
|
res = 0;
|
|
}
|
|
else
|
|
{
|
|
cond = high;
|
|
res = 1;
|
|
}
|
|
|
|
tgba_gspn_ssp_private_::prop_map::iterator k
|
|
= data_->prop_dict.find(var);
|
|
|
|
if (k != data_->prop_dict.end())
|
|
props_[nb_arc_props]
|
|
.prop[props_[nb_arc_props].nb_conj][k->second] = res;
|
|
|
|
assert(cond != bddfalse);
|
|
}
|
|
++props_[nb_arc_props].nb_conj;
|
|
}
|
|
++nb_arc_props;
|
|
}
|
|
}
|
|
Succ_* succ_tgba_ = 0;
|
|
size_t size_tgba_ = 0;
|
|
int j, conj;
|
|
|
|
succ(s->left(), props_, nb_arc_props, &succ_tgba_, &size_tgba_);
|
|
|
|
for (j = 0; j < nb_arc_props; j++)
|
|
{
|
|
for (conj = 0; conj < props_[j].nb_conj; conj++)
|
|
free(props_[j].prop[conj]);
|
|
free(props_[j].prop);
|
|
}
|
|
|
|
delete i;
|
|
return new tgba_succ_iterator_gspn_ssp(succ_tgba_, size_tgba_,
|
|
bdd_array, state_array,
|
|
size_states, props_,
|
|
nb_arc_props);
|
|
}
|
|
|
|
bdd
|
|
tgba_gspn_ssp::compute_support_conditions(const spot::state* state) const
|
|
{
|
|
(void) state;
|
|
return bddtrue;
|
|
}
|
|
|
|
bdd
|
|
tgba_gspn_ssp::compute_support_variables(const spot::state* state) const
|
|
{
|
|
(void) state;
|
|
return bddtrue;
|
|
}
|
|
|
|
bdd_dict*
|
|
tgba_gspn_ssp::get_dict() const
|
|
{
|
|
return data_->dict;
|
|
}
|
|
|
|
std::string
|
|
tgba_gspn_ssp::format_state(const state* state) const
|
|
{
|
|
const state_gspn_ssp* s = down_cast<const state_gspn_ssp*>(state);
|
|
assert(s);
|
|
char* str;
|
|
State gs = s->left();
|
|
if (gs)
|
|
{
|
|
int err = print_state(gs, &str);
|
|
if (err)
|
|
throw gspn_exception("print_state()", err);
|
|
// Strip trailing \n...
|
|
unsigned len = strlen(str);
|
|
while (str[--len] == '\n')
|
|
str[len] = 0;
|
|
}
|
|
else
|
|
{
|
|
str = strdup("-1");
|
|
}
|
|
|
|
std::string res(str);
|
|
free(str);
|
|
return res + " * " + data_->operand->format_state(s->right());
|
|
}
|
|
|
|
state*
|
|
tgba_gspn_ssp::project_state(const state* s, const tgba* t) const
|
|
{
|
|
const state_gspn_ssp* s2 = down_cast<const state_gspn_ssp*>(s);
|
|
assert(s2);
|
|
if (t == this)
|
|
return s2->clone();
|
|
return data_->operand->project_state(s2->right(), t);
|
|
}
|
|
|
|
bdd
|
|
tgba_gspn_ssp::all_acceptance_conditions() const
|
|
{
|
|
// There is no acceptance conditions in GSPN systems, they all
|
|
// come from the operand automaton.
|
|
return data_->operand->all_acceptance_conditions();
|
|
}
|
|
|
|
bdd
|
|
tgba_gspn_ssp::neg_acceptance_conditions() const
|
|
{
|
|
// There is no acceptance conditions in GSPN systems, they all
|
|
// come from the operand automaton.
|
|
return data_->operand->neg_acceptance_conditions();
|
|
}
|
|
|
|
// gspn_ssp_interface
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
gspn_ssp_interface::gspn_ssp_interface(int argc, char **argv,
|
|
bdd_dict* dict,
|
|
const
|
|
ltl::declarative_environment& env,
|
|
bool inclusion,
|
|
bool doublehash_,
|
|
bool pushfront_)
|
|
: dict_(dict), env_(env)
|
|
{
|
|
doublehash = doublehash_;
|
|
pushfront = pushfront_;
|
|
if (inclusion)
|
|
inclusion_version();
|
|
|
|
int res = initialize(argc, argv);
|
|
if (res)
|
|
throw gspn_exception("initialize()", res);
|
|
}
|
|
|
|
gspn_ssp_interface::~gspn_ssp_interface()
|
|
{
|
|
int res = finalize();
|
|
if (res)
|
|
throw gspn_exception("finalize()", res);
|
|
}
|
|
|
|
tgba*
|
|
gspn_ssp_interface::automaton(const tgba* operand) const
|
|
{
|
|
return new tgba_gspn_ssp(dict_, env_, operand);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
class connected_component_ssp: public explicit_connected_component
|
|
{
|
|
public:
|
|
virtual
|
|
~connected_component_ssp()
|
|
{
|
|
}
|
|
|
|
virtual const state*
|
|
has_state(const state* s) const
|
|
{
|
|
set_type::const_iterator i;
|
|
|
|
for (i = states.begin(); i != states.end(); ++i)
|
|
{
|
|
const state_gspn_ssp* old_state = (const state_gspn_ssp*)(*i);
|
|
const state_gspn_ssp* new_state = (const state_gspn_ssp*)(s);
|
|
|
|
if ((old_state->right())->compare(new_state->right()) == 0
|
|
&& old_state->left()
|
|
&& new_state->left())
|
|
if (spot_inclusion(new_state->left(), old_state->left()))
|
|
{
|
|
if (*i != s)
|
|
s->destroy();
|
|
return *i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
virtual void
|
|
insert(const state* s)
|
|
{
|
|
states.insert(s);
|
|
}
|
|
|
|
protected:
|
|
typedef Sgi::hash_set<const state*,
|
|
state_ptr_hash, state_ptr_equal> set_type;
|
|
set_type states;
|
|
};
|
|
|
|
class connected_component_ssp_factory :
|
|
public explicit_connected_component_factory
|
|
{
|
|
public:
|
|
virtual connected_component_ssp*
|
|
build() const
|
|
{
|
|
return new connected_component_ssp();
|
|
}
|
|
|
|
/// Get the unique instance of this class.
|
|
static const connected_component_ssp_factory*
|
|
instance()
|
|
{
|
|
static connected_component_ssp_factory f;
|
|
return &f;
|
|
}
|
|
|
|
protected:
|
|
virtual
|
|
~connected_component_ssp_factory()
|
|
{
|
|
}
|
|
/// Construction is forbiden.
|
|
connected_component_ssp_factory()
|
|
{
|
|
}
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
namespace
|
|
{
|
|
inline void*
|
|
container_(const State s)
|
|
{
|
|
return doublehash ? container(s) : 0;
|
|
}
|
|
}
|
|
|
|
class numbered_state_heap_ssp_semi : public numbered_state_heap
|
|
{
|
|
public:
|
|
numbered_state_heap_ssp_semi()
|
|
: numbered_state_heap(), inclusions(0)
|
|
{
|
|
}
|
|
|
|
virtual
|
|
~numbered_state_heap_ssp_semi()
|
|
{
|
|
// Free keys in H.
|
|
hash_type::iterator i = h.begin();
|
|
while (i != h.end())
|
|
{
|
|
// Advance the iterator before deleting the key.
|
|
const state* s = i->first;
|
|
++i;
|
|
s->destroy();
|
|
}
|
|
}
|
|
|
|
virtual numbered_state_heap::state_index
|
|
find(const state* s) const
|
|
{
|
|
const state_gspn_ssp* s_ = down_cast<const state_gspn_ssp*>(s);
|
|
const void* cont = container_(s_->left());
|
|
contained_map::const_iterator i = contained.find(cont);
|
|
if (i != contained.end())
|
|
{
|
|
f_map::const_iterator k = i->second.find(s_->right());
|
|
if (k != i->second.end())
|
|
{
|
|
const state_list& l = k->second;
|
|
|
|
state_list::const_iterator j;
|
|
for (j = l.begin(); j != l.end(); ++j)
|
|
{
|
|
const state_gspn_ssp* old_state =
|
|
down_cast<const state_gspn_ssp*>(*j);
|
|
const state_gspn_ssp* new_state =
|
|
down_cast<const state_gspn_ssp*>(s);
|
|
assert(old_state);
|
|
assert(new_state);
|
|
|
|
if (old_state->left() == new_state->left())
|
|
break;
|
|
|
|
if (old_state->left()
|
|
&& new_state->left()
|
|
&& spot_inclusion(new_state->left(), old_state->left()))
|
|
{
|
|
++inclusions;
|
|
break;
|
|
}
|
|
}
|
|
if (j != l.end())
|
|
{
|
|
if (s != *j)
|
|
{
|
|
s->destroy();
|
|
s = *j;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
|
|
state_index res;
|
|
|
|
if (s == 0)
|
|
{
|
|
res.first = 0;
|
|
res.second = 0;
|
|
}
|
|
else
|
|
{
|
|
hash_type::const_iterator i = h.find(s);
|
|
assert(i != h.end());
|
|
assert(s == i->first);
|
|
res.first = i->first;
|
|
res.second = i->second;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
virtual numbered_state_heap::state_index_p
|
|
find(const state* s)
|
|
{
|
|
const state_gspn_ssp* s_ = down_cast<const state_gspn_ssp*>(s);
|
|
const void* cont = container_(s_->left());
|
|
contained_map::const_iterator i = contained.find(cont);
|
|
if (i != contained.end())
|
|
{
|
|
f_map::const_iterator k = i->second.find(s_->right());
|
|
if (k != i->second.end())
|
|
{
|
|
const state_list& l = k->second;
|
|
|
|
state_list::const_iterator j;
|
|
for (j = l.begin(); j != l.end(); ++j)
|
|
{
|
|
const state_gspn_ssp* old_state =
|
|
down_cast<const state_gspn_ssp*>(*j);
|
|
const state_gspn_ssp* new_state =
|
|
down_cast<const state_gspn_ssp*>(s);
|
|
assert(old_state);
|
|
assert(new_state);
|
|
|
|
if (old_state->left() == new_state->left())
|
|
break;
|
|
|
|
if (old_state->left()
|
|
&& new_state->left()
|
|
&& spot_inclusion(new_state->left(), old_state->left()))
|
|
{
|
|
++inclusions;
|
|
break;
|
|
}
|
|
}
|
|
if (j != l.end())
|
|
{
|
|
if (s != *j)
|
|
{
|
|
s->destroy();
|
|
s = *j;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
|
|
state_index_p res;
|
|
|
|
if (s == 0)
|
|
{
|
|
res.first = 0;
|
|
res.second = 0;
|
|
}
|
|
else
|
|
{
|
|
hash_type::iterator i = h.find(s);
|
|
assert(i != h.end());
|
|
assert(s == i->first);
|
|
res.first = i->first;
|
|
res.second = &i->second;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
virtual numbered_state_heap::state_index
|
|
index(const state* s) const
|
|
{
|
|
state_index res;
|
|
hash_type::const_iterator i = h.find(s);
|
|
if (i == h.end())
|
|
{
|
|
res.first = 0;
|
|
res.second = 0;
|
|
}
|
|
else
|
|
{
|
|
res.first = i->first;
|
|
res.second = i->second;
|
|
|
|
if (s != i->first)
|
|
s->destroy();
|
|
}
|
|
return res;
|
|
}
|
|
|
|
virtual numbered_state_heap::state_index_p
|
|
index(const state* s)
|
|
{
|
|
state_index_p res;
|
|
hash_type::iterator i = h.find(s);
|
|
if (i == h.end())
|
|
{
|
|
res.first = 0;
|
|
res.second = 0;
|
|
}
|
|
else
|
|
{
|
|
res.first = i->first;
|
|
res.second = &i->second;
|
|
|
|
if (s != i->first)
|
|
s->destroy();
|
|
}
|
|
return res;
|
|
}
|
|
|
|
virtual void
|
|
insert(const state* s, int index)
|
|
{
|
|
h[s] = index;
|
|
|
|
const state_gspn_ssp* s_ = down_cast<const state_gspn_ssp*>(s);
|
|
State sg = s_->left();
|
|
if (sg)
|
|
{
|
|
const void* cont = container_(sg);
|
|
if (pushfront)
|
|
contained[cont][s_->right()].push_front(s);
|
|
else
|
|
contained[cont][s_->right()].push_back(s);
|
|
}
|
|
}
|
|
|
|
virtual int
|
|
size() const
|
|
{
|
|
return h.size();
|
|
}
|
|
|
|
virtual numbered_state_heap_const_iterator* iterator() const;
|
|
|
|
protected:
|
|
typedef Sgi::hash_map<const state*, int,
|
|
state_ptr_hash, state_ptr_equal> hash_type;
|
|
hash_type h; ///< Map of visited states.
|
|
|
|
typedef std::list<const state*> state_list;
|
|
typedef Sgi::hash_map<const state*, state_list,
|
|
state_ptr_hash, state_ptr_equal> f_map;
|
|
typedef Sgi::hash_map<const void*, f_map,
|
|
ptr_hash<void> > contained_map;
|
|
contained_map contained;
|
|
|
|
friend class numbered_state_heap_ssp_const_iterator;
|
|
friend class couvreur99_check_shy_ssp;
|
|
friend class couvreur99_check_shy_semi_ssp;
|
|
|
|
mutable unsigned inclusions;
|
|
};
|
|
|
|
|
|
class numbered_state_heap_ssp_const_iterator :
|
|
public numbered_state_heap_const_iterator
|
|
{
|
|
public:
|
|
numbered_state_heap_ssp_const_iterator
|
|
(const numbered_state_heap_ssp_semi::hash_type& h)
|
|
: numbered_state_heap_const_iterator(), h(h)
|
|
{
|
|
}
|
|
|
|
~numbered_state_heap_ssp_const_iterator()
|
|
{
|
|
}
|
|
|
|
virtual void
|
|
first()
|
|
{
|
|
i = h.begin();
|
|
}
|
|
|
|
virtual void
|
|
next()
|
|
{
|
|
++i;
|
|
}
|
|
|
|
virtual bool
|
|
done() const
|
|
{
|
|
return i == h.end();
|
|
}
|
|
|
|
virtual const state*
|
|
get_state() const
|
|
{
|
|
return i->first;
|
|
}
|
|
|
|
virtual int
|
|
get_index() const
|
|
{
|
|
return i->second;
|
|
}
|
|
|
|
private:
|
|
numbered_state_heap_ssp_semi::hash_type::const_iterator i;
|
|
const numbered_state_heap_ssp_semi::hash_type& h;
|
|
};
|
|
|
|
|
|
numbered_state_heap_const_iterator*
|
|
numbered_state_heap_ssp_semi::iterator() const
|
|
{
|
|
return new numbered_state_heap_ssp_const_iterator(h);
|
|
}
|
|
|
|
|
|
/// \brief Factory for numbered_state_heap_ssp_semi
|
|
///
|
|
/// This class is a singleton. Retrieve the instance using instance().
|
|
class numbered_state_heap_ssp_factory_semi:
|
|
public numbered_state_heap_factory
|
|
{
|
|
public:
|
|
virtual numbered_state_heap_ssp_semi*
|
|
build() const
|
|
{
|
|
return new numbered_state_heap_ssp_semi();
|
|
}
|
|
|
|
/// Get the unique instance of this class.
|
|
static const numbered_state_heap_ssp_factory_semi*
|
|
instance()
|
|
{
|
|
static numbered_state_heap_ssp_factory_semi f;
|
|
return &f;
|
|
}
|
|
|
|
protected:
|
|
virtual
|
|
~numbered_state_heap_ssp_factory_semi()
|
|
{
|
|
}
|
|
|
|
numbered_state_heap_ssp_factory_semi()
|
|
{
|
|
}
|
|
};
|
|
|
|
|
|
class couvreur99_check_shy_ssp : public couvreur99_check_shy
|
|
{
|
|
public:
|
|
couvreur99_check_shy_ssp(const tgba* a, bool stack_inclusion,
|
|
bool double_inclusion,
|
|
bool reversed_double_inclusion,
|
|
bool no_decomp)
|
|
: couvreur99_check_shy(a,
|
|
option_map(),
|
|
numbered_state_heap_ssp_factory_semi::instance()),
|
|
inclusion_count_heap(0),
|
|
inclusion_count_stack(0),
|
|
stack_inclusion(stack_inclusion),
|
|
double_inclusion(double_inclusion),
|
|
reversed_double_inclusion(reversed_double_inclusion),
|
|
no_decomp(no_decomp)
|
|
{
|
|
onepass_ = true;
|
|
|
|
stats["inclusion count heap"] =
|
|
static_cast<spot::unsigned_statistics::unsigned_fun>
|
|
(&couvreur99_check_shy_ssp::get_inclusion_count_heap);
|
|
stats["inclusion count stack"] =
|
|
static_cast<spot::unsigned_statistics::unsigned_fun>
|
|
(&couvreur99_check_shy_ssp::get_inclusion_count_stack);
|
|
stats["contained map size"] =
|
|
static_cast<spot::unsigned_statistics::unsigned_fun>
|
|
(&couvreur99_check_shy_ssp::get_contained_map_size);
|
|
}
|
|
|
|
private:
|
|
unsigned inclusion_count_heap;
|
|
unsigned inclusion_count_stack;
|
|
bool stack_inclusion;
|
|
bool double_inclusion;
|
|
bool reversed_double_inclusion;
|
|
bool no_decomp;
|
|
|
|
protected:
|
|
unsigned
|
|
get_inclusion_count_heap() const
|
|
{
|
|
return inclusion_count_heap;
|
|
};
|
|
unsigned
|
|
get_inclusion_count_stack() const
|
|
{
|
|
return inclusion_count_stack;
|
|
};
|
|
unsigned
|
|
get_contained_map_size() const
|
|
{
|
|
return
|
|
down_cast<numbered_state_heap_ssp_semi*>(ecs_->h)->contained.size();
|
|
}
|
|
|
|
// If a new state includes an older state, we may have to add new
|
|
// children to the list of children of that older state. We cannot
|
|
// to this by sub-classing numbered_state_heap since TODO is not
|
|
// available. So we override find_state() instead.
|
|
virtual numbered_state_heap::state_index_p
|
|
find_state(const state* s)
|
|
{
|
|
typedef numbered_state_heap_ssp_semi::hash_type hash_type;
|
|
hash_type& h = down_cast<numbered_state_heap_ssp_semi*>(ecs_->h)->h;
|
|
typedef numbered_state_heap_ssp_semi::contained_map contained_map;
|
|
typedef numbered_state_heap_ssp_semi::f_map f_map;
|
|
typedef numbered_state_heap_ssp_semi::state_list state_list;
|
|
const contained_map& contained =
|
|
down_cast<numbered_state_heap_ssp_semi*>(ecs_->h)->contained;
|
|
|
|
const state_gspn_ssp* s_ = down_cast<const state_gspn_ssp*>(s);
|
|
const void* cont = container_(s_->left());
|
|
contained_map::const_iterator i = contained.find(cont);
|
|
|
|
if (i != contained.end())
|
|
{
|
|
f_map::const_iterator k = i->second.find(s_->right());
|
|
if (k != i->second.end())
|
|
{
|
|
const state_list& l = k->second;
|
|
state_list::const_iterator j;
|
|
|
|
// Make a first pass looking for identical states.
|
|
for (j = l.begin(); j != l.end(); ++j)
|
|
{
|
|
const state_gspn_ssp* old_state =
|
|
down_cast<const state_gspn_ssp*>(*j);
|
|
const state_gspn_ssp* new_state =
|
|
down_cast<const state_gspn_ssp*>(s);
|
|
assert(old_state);
|
|
assert(new_state);
|
|
|
|
if (old_state->left() == new_state->left())
|
|
goto found_match;
|
|
}
|
|
|
|
// Now, check for inclusions.
|
|
for (j = l.begin(); j != l.end(); ++j)
|
|
{
|
|
const state_gspn_ssp* old_state =
|
|
down_cast<const state_gspn_ssp*>(*j);
|
|
const state_gspn_ssp* new_state =
|
|
down_cast<const state_gspn_ssp*>(s);
|
|
assert(old_state);
|
|
assert(new_state);
|
|
|
|
if (old_state->left() && new_state->left())
|
|
{
|
|
hash_type::const_iterator i = h.find(*j);
|
|
assert(i != h.end());
|
|
if (i->second == -1)
|
|
{
|
|
if (spot_inclusion(new_state->left(),
|
|
old_state->left()))
|
|
{
|
|
++inclusion_count_heap;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (stack_inclusion
|
|
&& double_inclusion
|
|
&& !reversed_double_inclusion
|
|
&& spot_inclusion(new_state->left(),
|
|
old_state->left()))
|
|
break;
|
|
if (stack_inclusion
|
|
&& spot_inclusion(old_state->left(),
|
|
new_state->left()))
|
|
{
|
|
++inclusion_count_stack;
|
|
|
|
succ_queue& queue = todo.back().q;
|
|
succ_queue::iterator old;
|
|
if (pos == queue.end())
|
|
old = queue.begin();
|
|
else
|
|
{
|
|
old = pos;
|
|
// Should not happen, because onepass_ == 1
|
|
assert(0);
|
|
}
|
|
|
|
if (no_decomp)
|
|
{
|
|
queue.push_back // why not push_front?
|
|
(successor(old->acc,
|
|
old_state->clone()));
|
|
|
|
assert(pos == queue.end());
|
|
|
|
inc_depth();
|
|
|
|
// If we had not done the first loop
|
|
// over the container to check for
|
|
// equal states, we would have to do
|
|
// one here to make sure that state
|
|
// s is not equal to another known
|
|
// state. (We risk some intricate
|
|
// memory corruption if we don't
|
|
// destroy "clone states" at this
|
|
// point.)
|
|
|
|
// Since we have that first loop and
|
|
// we therefore know that state s is
|
|
// genuinely new, position j so that
|
|
// we won't destroy it.
|
|
j = l.end();
|
|
}
|
|
else
|
|
{
|
|
State* succ_tgba_ = 0;
|
|
size_t size_tgba_ = 0;
|
|
|
|
Diff_succ(old_state->left(),
|
|
new_state->left(),
|
|
&succ_tgba_, &size_tgba_);
|
|
|
|
for (size_t i = 0; i < size_tgba_; i++)
|
|
{
|
|
state_gspn_ssp* s =
|
|
new state_gspn_ssp
|
|
(succ_tgba_[i],
|
|
old_state->right()->clone());
|
|
// why not push_front?
|
|
queue.push_back(successor(old->acc, s));
|
|
inc_depth();
|
|
}
|
|
if (size_tgba_ != 0)
|
|
diff_succ_free(succ_tgba_);
|
|
}
|
|
|
|
break;
|
|
}
|
|
if (stack_inclusion
|
|
&& double_inclusion
|
|
&& reversed_double_inclusion
|
|
&& spot_inclusion(new_state->left(),
|
|
old_state->left()))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
found_match:
|
|
if (j != l.end())
|
|
{
|
|
if (s != *j)
|
|
{
|
|
s->destroy();
|
|
s = *j;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0;
|
|
}
|
|
|
|
// s points to the resulting state, or to 0 if we didn't find
|
|
// the state in the list.
|
|
|
|
numbered_state_heap::state_index_p res;
|
|
if (s == 0)
|
|
{
|
|
res.first = 0;
|
|
res.second = 0;
|
|
}
|
|
else
|
|
{
|
|
hash_type::iterator k = h.find(s);
|
|
assert(k != h.end());
|
|
assert(s == k->first);
|
|
res.first = k->first;
|
|
res.second = &k->second;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
};
|
|
|
|
|
|
// The only purpose of this class is the inclusion_count counter.
|
|
class couvreur99_check_shy_semi_ssp : public couvreur99_check_shy
|
|
{
|
|
public:
|
|
couvreur99_check_shy_semi_ssp(const tgba* a)
|
|
: couvreur99_check_shy(a,
|
|
option_map(),
|
|
numbered_state_heap_ssp_factory_semi::instance()),
|
|
find_count(0)
|
|
{
|
|
onepass_ = true;
|
|
|
|
stats["find_state count"] =
|
|
static_cast<spot::unsigned_statistics::unsigned_fun>
|
|
(&couvreur99_check_shy_semi_ssp::get_find_count);
|
|
stats["contained map size"] =
|
|
static_cast<spot::unsigned_statistics::unsigned_fun>
|
|
(&couvreur99_check_shy_semi_ssp::get_contained_map_size);
|
|
stats["inclusion count"] =
|
|
static_cast<spot::unsigned_statistics::unsigned_fun>
|
|
(&couvreur99_check_shy_semi_ssp::get_inclusion_count);
|
|
|
|
//down_cast<numbered_state_heap_ssp_semi*>(ecs_->h)->stats = this;
|
|
}
|
|
|
|
private:
|
|
unsigned find_count;
|
|
|
|
protected:
|
|
unsigned
|
|
get_find_count() const
|
|
{
|
|
return find_count;
|
|
};
|
|
|
|
unsigned
|
|
get_inclusion_count() const
|
|
{
|
|
return
|
|
down_cast<numbered_state_heap_ssp_semi*>(ecs_->h)->inclusions;
|
|
|
|
};
|
|
|
|
unsigned
|
|
get_contained_map_size() const
|
|
{
|
|
return
|
|
down_cast<numbered_state_heap_ssp_semi*>(ecs_->h)->contained.size();
|
|
}
|
|
|
|
virtual numbered_state_heap::state_index_p
|
|
find_state(const state* s)
|
|
{
|
|
++find_count;
|
|
return couvreur99_check_shy::find_state(s);
|
|
}
|
|
};
|
|
|
|
|
|
couvreur99_check*
|
|
couvreur99_check_ssp_semi(const tgba* ssp_automata)
|
|
{
|
|
assert(dynamic_cast<const tgba_gspn_ssp*>(ssp_automata));
|
|
return
|
|
new couvreur99_check(ssp_automata,
|
|
option_map(),
|
|
numbered_state_heap_ssp_factory_semi::instance());
|
|
}
|
|
|
|
couvreur99_check*
|
|
couvreur99_check_ssp_shy_semi(const tgba* ssp_automata)
|
|
{
|
|
assert(dynamic_cast<const tgba_gspn_ssp*>(ssp_automata));
|
|
return
|
|
new couvreur99_check_shy_semi_ssp(ssp_automata);
|
|
}
|
|
|
|
couvreur99_check*
|
|
couvreur99_check_ssp_shy(const tgba* ssp_automata, bool stack_inclusion,
|
|
bool double_inclusion,
|
|
bool reversed_double_inclusion,
|
|
bool no_decomp)
|
|
{
|
|
assert(dynamic_cast<const tgba_gspn_ssp*>(ssp_automata));
|
|
return new couvreur99_check_shy_ssp(ssp_automata, stack_inclusion,
|
|
double_inclusion,
|
|
reversed_double_inclusion,
|
|
no_decomp);
|
|
}
|
|
|
|
#if 0
|
|
// I rewrote couvreur99_check_result today, and it no longer uses
|
|
// connected_component_ssp_factory. So this cannot work anymore.
|
|
// -- adl 2004-12-10.
|
|
couvreur99_check_result*
|
|
counter_example_ssp(const couvreur99_check_status* status)
|
|
{
|
|
return new
|
|
couvreur99_check_result(status,
|
|
connected_component_ssp_factory::instance());
|
|
}
|
|
#endif
|
|
}
|