├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── _oasis ├── _tags ├── bin └── .gitkeep ├── doc ├── Makefile ├── benchmarks.tex ├── changelog.tex ├── develop.tex ├── display.tex ├── gensolv.tex ├── graphics │ ├── examplegame.ps │ ├── marcingame.eepic │ ├── marcingame.fig │ └── titlegame.ps ├── implalg.tex ├── implheur.tex ├── install.tex ├── intro.tex ├── license.tex ├── literature.bib ├── locglob.tex ├── main.tex ├── makros.tex ├── ntheorem.cfg ├── pgfgraphics.tex ├── pgsolver.pdf ├── results.tex ├── running.tex ├── specs.tex ├── tech.tex ├── tools.tex ├── univopt.tex └── verify.tex ├── myocamlbuild.ml ├── oasis.sh ├── opam-local.sh ├── opam ├── findlib └── opam ├── package.json ├── pgsolver.install ├── scripts ├── benchfamily.sh ├── benchrandom.sh ├── benchrandomfamily.sh ├── callfamily.sh ├── clusteredcall.sh ├── createrandomgames.sh ├── policyitervis │ ├── buildanim.sh │ ├── commands.txt │ ├── graphs │ │ ├── cunninghamexpgame.mp │ │ ├── cunninghamexpgraph.mp │ │ ├── cunninghamexptemplate.mp │ │ ├── cunninghamsubexpgame.mp │ │ ├── cunninghamsubexpgraph.mp │ │ ├── cunninghamsubexptemplate.mp │ │ ├── fearnleysubexpgame.mp │ │ ├── fearnleysubexpgraph.mp │ │ ├── fearnleysubexpnogadgettemplate.mp │ │ ├── fearnleysubexptemplate.mp │ │ ├── friedmannsubexpgame.mp │ │ ├── friedmannsubexpgraph.mp │ │ ├── friedmannsubexptemplate.mp │ │ ├── zadehexpgame.mp │ │ ├── zadehexpgraph.mp │ │ └── zadehexptemplate.mp │ └── template.tex └── sqrtpriorandom.sh ├── setup.ml ├── src ├── META ├── generators │ ├── cliquegame.ml │ ├── cliquegame.mli │ ├── cliquegame_aux.ml │ ├── clusteredrandomgame.ml │ ├── clusteredrandomgame.mli │ ├── clusteredrandomgame_aux.ml │ ├── jurdzinskigame.ml │ ├── jurdzinskigame.mli │ ├── jurdzinskigame_aux.ml │ ├── laddergame.ml │ ├── laddergame.mli │ ├── laddergame_aux.ml │ ├── langincl.ml │ ├── langincl.mli │ ├── langincl_aux.ml │ ├── modelcheckerladder.ml │ ├── modelcheckerladder.mli │ ├── modelcheckerladder_aux.ml │ ├── modelchecking │ │ ├── elevators.ml │ │ ├── elevators.mli │ │ ├── elevators_aux.ml │ │ ├── mucalculus.ml │ │ ├── mucalculus.mli │ │ ├── philosophers.ml │ │ ├── roadworks.ml │ │ ├── roadworks.mli │ │ └── roadworks_aux.ml │ ├── policyiter │ │ ├── generators │ │ │ ├── cunninghamexp.ml │ │ │ ├── cunninghamexp.mli │ │ │ ├── cunninghamsubexp.ml │ │ │ ├── cunninghamsubexp.mli │ │ │ ├── fearnleysubexp.ml │ │ │ ├── fearnleysubexp.mli │ │ │ ├── friedmannsubexp.ml │ │ │ ├── friedmannsubexp.mli │ │ │ ├── randomedgeexptest.ml │ │ │ ├── randomedgeexptest.mli │ │ │ ├── randomedgesubexp.ml │ │ │ ├── randomedgesubexp.mli │ │ │ ├── randomfacetsubexp.ml │ │ │ ├── randomfacetsubexp.mli │ │ │ ├── switchallexp.ml │ │ │ ├── switchallexp.mli │ │ │ ├── switchallsubexp.ml │ │ │ ├── switchallsubexp.mli │ │ │ ├── switchbestexp.ml │ │ │ ├── switchbestexp.mli │ │ │ ├── switchbestsubexp.ml │ │ │ ├── switchbestsubexp.mli │ │ │ ├── zadehexp.ml │ │ │ ├── zadehexp.mli │ │ │ ├── zadehsubexp.ml │ │ │ └── zadehsubexp.mli │ │ ├── stratimprgen.ml │ │ ├── stratimprgenerators.ml │ │ ├── stratimprgenerators.mli │ │ ├── stratimprgenlist.ml │ │ └── stratimprgenlist.mli │ ├── randomgame.ml │ ├── randomgame.mli │ ├── randomgame_aux.ml │ ├── recursivedullgame.ml │ ├── recursivedullgame.mli │ ├── recursivedullgame_aux.ml │ ├── recursiveladder.ml │ ├── recursiveladder.mli │ ├── recursiveladder_aux.ml │ ├── steadygame.ml │ ├── steadygame.mli │ ├── steadygame_aux.ml │ ├── taskscheduler.ml │ ├── towersofhanoi.ml │ ├── towersofhanoi.mli │ └── towersofhanoi_aux.ml ├── paritygame │ ├── generatorregistry.ml │ ├── generatorregistry.mli │ ├── generators.ml │ ├── generators.mli │ ├── mdp.ml │ ├── mdp.mli │ ├── paritygame.ml │ ├── paritygame.mli │ ├── paritygamebitset.ml │ ├── paritygamebitset.mli │ ├── parsers.ml │ ├── parsers.mli │ ├── solverregistry.ml │ ├── solverregistry.mli │ ├── solvers.ml │ ├── solvers.mli │ ├── specialsolve.ml │ ├── specialsolve.mli │ ├── transformations.ml │ ├── transformations.mli │ ├── univsolve.ml │ ├── univsolve.mli │ ├── verification.ml │ └── verification.mli ├── pgsolver.mldylib ├── pgsolver.mllib ├── pgsolver │ ├── basics.ml │ ├── basics.mli │ ├── info.ml │ ├── info.mli │ ├── pgprofiling.ml │ ├── pgprofiling.mli │ ├── pgsolver.ml │ ├── whoiswho.ml │ └── whoiswho.mli ├── solvers │ ├── bigstep.ml │ ├── bigstep.mli │ ├── dominiondecomp.ml │ ├── dominiondecomp.mli │ ├── externalsolver.ml │ ├── externalsolver.mli │ ├── fpiter.ml │ ├── fpiter.mli │ ├── genetic.ml │ ├── genetic.mli │ ├── guessstrategy.ml │ ├── guessstrategy.mli │ ├── localmodelchecker.ml │ ├── localmodelchecker.mli │ ├── optstratimprov.ml │ ├── optstratimprov.mli │ ├── prioprom.ml │ ├── prioprom.mli │ ├── priopromdelay.ml │ ├── priopromdelay.mli │ ├── priopromplus.ml │ ├── priopromplus.mli │ ├── priopromrecovery.ml │ ├── priopromrecovery.mli │ ├── recursive.ml │ ├── recursive.mli │ ├── satsolve.ml │ ├── satsolve.mli │ ├── smallprogress.ml │ ├── smallprogress.mli │ ├── smtsolve.ml │ ├── smtsolve.mli │ ├── stratimpralgs.ml │ ├── stratimpralgs.mli │ ├── stratimpralgs │ │ ├── switch_cunningham.ml │ │ ├── switch_cunningham.mli │ │ ├── switch_globally_best.ml │ │ ├── switch_globally_best.mli │ │ ├── switch_history.ml │ │ ├── switch_history.mli │ │ ├── switch_internal.ml │ │ ├── switch_internal.mli │ │ ├── switch_locally_best.ml │ │ ├── switch_locally_best.mli │ │ ├── switch_random.ml │ │ ├── switch_random.mli │ │ ├── switch_snare.ml │ │ ├── switch_snare.mli │ │ ├── switch_zadeh.ml │ │ └── switch_zadeh.mli │ ├── stratimprdisc.ml │ ├── stratimprdisc.mli │ ├── stratimprlocal.ml │ ├── stratimprlocal.mli │ ├── stratimprlocal2.ml │ ├── stratimprlocal2.mli │ ├── stratimprovement.ml │ ├── stratimprovement.mli │ ├── stratimprsat.ml │ ├── stratimprsat.mli │ ├── succinctsmallprogress.ml │ ├── succinctsmallprogress.mli │ ├── viasat.ml │ └── viasat.mli └── tools │ ├── auso.ml │ ├── benchmark.ml │ ├── benchstratimpr.ml │ ├── combine.ml │ ├── complexdecomp.ml │ ├── compressor.ml │ ├── fullimprarena.ml │ ├── imprarena.ml │ ├── infotool.ml │ ├── itersat.ml │ ├── obfuscator.ml │ ├── policyitervis.ml │ ├── transformer.ml │ └── winningstrats.ml └── tests └── solverstest.ml /.gitignore: -------------------------------------------------------------------------------- 1 | temp*.ml 2 | *.cache 3 | *.annot 4 | *.cmo 5 | *.cma 6 | *.cmi 7 | *.a 8 | *.o 9 | *.cmx 10 | *.cmxs 11 | *.cmxa 12 | bin/* 13 | Config 14 | *.aux 15 | *.bbl 16 | *.blg 17 | doc/main.dvi 18 | *.log 19 | doc/main.thm 20 | doc/main.toc 21 | .paths 22 | _build 23 | .idea 24 | *.native 25 | temp 26 | SatConfig 27 | .project 28 | *.out 29 | doc/main.pdf 30 | doc/pgsolver.pdf 31 | scripts/policyitervis/metapostgraphs 32 | setup.data 33 | *.byte 34 | *.cache -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2021 Oliver Friedmann, Martin Lange 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PGSolver 2 | ======== 3 | 4 | A collection of tools for generating, manipulating and - most of all - solving parity games. 5 | 6 | Version 4.3, Copyright (c) 2008-2024, BSD 3 LICENSE 7 | 8 | It is developed and maintained by: 9 | - (c) Oliver Friedmann, University of Munich (http://oliverfriedmann.com) 10 | - (c) Martin Lange, University of Kassel (http://carrick.fmv.informatik.uni-kassel.de/~mlange/) 11 | 12 | 13 | ## Documentation 14 | 15 | Please consult [```./doc/pgsolver.pdf```](https://github.com/tcsprojects/pgsolver/blob/master/doc/pgsolver.pdf) for a guide to installation, usage and development of this tool. 16 | 17 | 18 | ## Installation 19 | 20 | Install the OCaml Package Manager [OPAM](https://opam.ocaml.org). 21 | 22 | Then: 23 | ```bash 24 | opam update 25 | opam upgrade 26 | opam switch 4.07.0 27 | eval `opam config env` 28 | opam install ocamlbuild ocamlfind ounit TCSLib extlib ocaml-sat-solvers minisat 29 | git clone https://github.com/tcsprojects/pgsolver.git 30 | cd pgsolver 31 | ocaml setup.ml -configure 32 | ocaml setup.ml -build 33 | ``` 34 | 35 | 36 | ## Examples 37 | 38 | Run the exponential lower bound construction for Zadeh's rule on PGSolver: 39 | ``` 40 | bin/stratimprgen -pg zadehexp [n] | bin/pgsolver -dsd -dgo -dlo -dsg -v 2 -jh -global policyiter -x -sfse 41 | ``` 42 | where [n] is the index of the game, e.g. 3. 43 | -------------------------------------------------------------------------------- /bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcsprojects/pgsolver/8fde6003daffeb9b5da829001cec5e8acb7a340a/bin/.gitkeep -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | LATEX=pdflatex 2 | BIBTEX=bibtex 3 | #DVI2PDF=dvipdfm 4 | RENAME=mv 5 | 6 | doc: pgsolver.pdf 7 | 8 | pgsolver.pdf: main.pdf 9 | # $(DVI2PDF) -o pgsolver.pdf main.dvi 10 | $(RENAME) main.pdf pgsolver.pdf 11 | 12 | #main.dvi: main.bbl 13 | # $(LATEX) main 14 | # $(LATEX) main 15 | 16 | main.bbl: main.aux 17 | $(BIBTEX) main 18 | 19 | main.aux: 20 | $(LATEX) main 21 | 22 | main.pdf: main.bbl 23 | $(LATEX) main 24 | 25 | clean: 26 | rm -f main.dvi main.aux pgsolver.pdf 27 | -------------------------------------------------------------------------------- /doc/display.tex: -------------------------------------------------------------------------------- 1 | \section{Viewing Parity Games} 2 | \label{sec:viewing} 3 | 4 | \pgsolver can display parity games in two different ways: textually and graphically. The former 5 | can be invoked using the command-line option \texttt{-f}. 6 | \begin{verbatim} 7 | ~/proj/pgsolver> bin/pgsolver -f 8 | \end{verbatim} 9 | This results in a simple reprinting of the parity game to be solved at the end of \pgsolver's usual 10 | output. The format is the same as the input format described in the previous section. 11 | 12 | In order to display parity games graphically one needs the \texttt{graphviz} package, available for 13 | free from 14 | \begin{quotation} 15 | \url{http://www.graphviz.org/} 16 | \end{quotation} 17 | \pgsolver can create output in the \texttt{dot}-format which can be displayed using \texttt{dotty} from 18 | the \texttt{graphviz} package for example. The relevant command-line parameter is \texttt{-d} with 19 | a filename which tells \pgsolver to write the \texttt{dot} code into that file after solving the game. 20 | Beware that you need to tell \pgsolver explicitly (how) to solve the game. If you omit this, \pgsolver 21 | will parse the input but not solve the game. However, this can be used to display the game as it is. 22 | \begin{verbatim} 23 | ~/proj/pgsolver> bin/pgsolver -d graph.dot tests/test1.gm 24 | \end{verbatim} 25 | Then, in order to view it, try 26 | \begin{verbatim} 27 | ~/proj/pgsolver> dotty graph.dot 28 | \end{verbatim} 29 | \pgsolver can also display a game together with the winning information. This happens when you tell it 30 | to create \texttt{dot}-code for the game \emph{and} tell it to solve it. 31 | \begin{verbatim} 32 | ~/proj/pgsolver> bin/pgsolver -global recursive -d graph.dot tests/test1.gm 33 | \end{verbatim} 34 | Again, the result can be viewed using 35 | \begin{verbatim} 36 | ~/proj/pgsolver> dotty graph.dot 37 | \end{verbatim} 38 | for example. However, now nodes and some edges are coloured according to the following specification. 39 | \begin{itemize} 40 | \item The winning region for player $0$, i.e.\ all nodes from which he/she can win the game, is coloured 41 | green. The winning region for player $1$ is coloured red. 42 | \item An edge coloured green belongs to the positional strategy for player $0$ that is winning on his/her 43 | winning region. An edge coloured red belongs to player $1$'s respective winning strategy. 44 | \end{itemize} 45 | An example display of a solved parity game is given on the title page. 46 | 47 | 48 | 49 | %%% Local Variables: 50 | %%% mode: latex 51 | %%% TeX-master: "main" 52 | %%% End: 53 | -------------------------------------------------------------------------------- /doc/gensolv.tex: -------------------------------------------------------------------------------- 1 | \section{The Generic Solver} 2 | 3 | Solving a parity game is done by a central module called the \emph{generic solver}. 4 | It combines the universal optimisations described above with any of the implemented 5 | algorithms of heuristics described above. This is realised by taking a solver, i.e.\ 6 | one of these algorithms or heuristics as a parameter. Then it roughly works as follows. 7 | \begin{enumerate} 8 | \item Self-cycles are eliminated from the game, and attractors of nodes for which the 9 | self-cycle is part of a winning strategy are computed and removed. 10 | \item The entire game is decomposed into SCCs. 11 | \item Terminal SCCs are solved as follows. 12 | \begin{enumerate} 13 | \item Priorities are compressed. 14 | \item The SCC is checked for being a special case of a game. 15 | \begin{itemize} 16 | \item If it is, winning regions and strategies are constructed accordingly. 17 | \item Otherwise, the solver given as the parameter is used to solve this 18 | SCC. 19 | \end{itemize} 20 | \item Attractors of the computed winning regions are also computed, together with 21 | corresponding strategies which are added to the winning regions and strategies. 22 | \item The computed winning regions are removed from the game. 23 | \item All non-terminal SCCs which have lost some nodes in the removal of these 24 | attractors are again decomposed into more fine-grained SCCs. 25 | \end{enumerate} 26 | \item Step 3 is repeated until the entire game is solved. 27 | \end{enumerate} 28 | Note that the removal of terminal SCCs will make other, previously non-terminal SCCs terminal. 29 | Also, note that this scheme is sound -- the regions and strategies it computes are 30 | in fact winning regions and winning strategies for the corresponding players on the given 31 | game -- if the parameter solver is sound. Hence, it can also be used with sound heuristics. 32 | Furthermore, it is complete if it is guaranteed that the parameter solver solves at least 33 | one node of every SCC that it is given. Hence, the solvers used as backends need not be 34 | complete for the generic solver to be complete. This is why this scheme can solve whole games 35 | using heuristics that are incomplete themselves. 36 | 37 | We also note that the features SCC decomposition, detection of special cases, and priority 38 | compression can be switched off via command-line options. This may be useful when the performance 39 | of an algorithm on its own is to be measured. In addition, it is possible to turn the feature 40 | priority propagation on in which case it is done before priority compression. However, in general 41 | this does not seem to be an optimisation since it slows down virtually any backend. 42 | 43 | 44 | 45 | %%% Local Variables: 46 | %%% mode: latex 47 | %%% TeX-master: "main" 48 | %%% End: 49 | -------------------------------------------------------------------------------- /doc/install.tex: -------------------------------------------------------------------------------- 1 | \section{Installation Guide} 2 | 3 | \subsection{Obtaining the Relevant Parts} 4 | 5 | You can obtain the source code for \pgsolver from 6 | \begin{center} 7 | \url{https://github.com/tcsprojects/pgsolver} 8 | \end{center} 9 | Download the latest sources. 10 | \begin{verbatim} 11 | ~> git clone https://github.com/tcsprojects/pgsolver 12 | \end{verbatim} 13 | This will create a directory \texttt{pgsolver} and various subdirectories in it. 14 | \begin{verbatim} 15 | ~> cd pgsolver 16 | \end{verbatim} 17 | 18 | In order to compile \pgsolver from source code you will need the OCaml compiler. A convenient way is to install the OCaml 19 | Package Manager \texttt{opam}. Install it via any package manager for your system or download it from 20 | \begin{center} 21 | \url{https://opam.ocaml.org/} 22 | \end{center} 23 | Then get the OCaml compiler installed via. 24 | \begin{verbatim} 25 | ~> opam switch 4.07.0 26 | ~> eval `opam config env` 27 | \end{verbatim} 28 | It may be recommendable to use a later version of the OCaml compiler. Previous versions before 4.07.0 may also work. 29 | 30 | Next you need the compilation tool \texttt{ocamlbuild} and some additional packages which can be installed via: 31 | \begin{verbatim} 32 | ~> opam install ocamlbuild ocamlfind TCSLib extlib ocaml-sat-solvers minisat 33 | \end{verbatim} 34 | 35 | If you intent to contribute to the development of \pgsolver you may want to use unit tests as well. This requires: 36 | \begin{verbatim} 37 | ~> opam install ounit 38 | \end{verbatim} 39 | 40 | 41 | 42 | \subsection{Compiling \pgsolver} 43 | 44 | Now change into the \pgsolver directory. 45 | \begin{verbatim} 46 | ~> cd pgsolver 47 | \end{verbatim} 48 | 49 | To start the compilation, type 50 | \begin{verbatim} 51 | ~/pgsolver> ocaml setup.ml -configure 52 | ~/pgsolver> ocaml setup.ml -build 53 | \end{verbatim} 54 | 55 | -------------------------------------------------------------------------------- /doc/license.tex: -------------------------------------------------------------------------------- 1 | \section{License} 2 | 3 | This software is distributed under the BSD license. 4 | \begin{verbatim} 5 | Copyright (c) 2008-2021 Oliver Friedmann and Martin Lange 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the author may not be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | \end{verbatim} 30 | 31 | %%% Local Variables: 32 | %%% mode: latex 33 | %%% TeX-master: "main" 34 | %%% End: 35 | -------------------------------------------------------------------------------- /doc/locglob.tex: -------------------------------------------------------------------------------- 1 | \section{Local vs.\ Global Solvers} 2 | 3 | The problem of \emph{solving} a parity game $G = (V,V_0,V_1,E,\Omega)$ is, roughly speaking, to determine 4 | which of the players has a winning strategy for that game. However, this does not take starting nodes into 5 | account. In order to obtain a well-defined problem, this is refined in two ways. 6 | 7 | The problem of solving the parity game $G$ \emph{globally} is to determine, for \emph{every} node $v \in V$ 8 | whether $v \in W_0$ or $v \in W_1$. The problem of solving $G$ \emph{locally} is to determine for a 9 | \emph{given} $v \in V$ whether $v \in W_0$ or $v \in W_1$ holds. In addition, we require a \emph{solver} 10 | to compute (partial) winning strategies in the following sense: a local solver should return one strategy 11 | that is a winning strategy for player $i$ if $v \in W_i$ for the given input node $v$. A global solver 12 | should return two strategies, one for each player s.t.\ player $i$ wins exactly on the nodes $v \in W_i$ 13 | if he/she plays according to the strategy computed for her. 14 | 15 | Clearly, the local and global problem are interreducible, the global one solves the local one for free, 16 | and the global one is solved by calling the local one $|V|$ many times. But neither of these indirect 17 | methods is particularly clever. Thus, there are algorithms for the global, and other algorithms for the 18 | local problem. We focus on the global problem here, but also use local solvers. In that case we expect 19 | them to determine for \emph{at least} the given node $v$ to which winning set it belongs but possibly and 20 | preferably also for other nodes. These methods can then be used to solve the global problem by calling 21 | the local algorithm \emph{at most} $|V|$ many times. 22 | 23 | Suppose $V = \{v_0,\ldots,v_n\}$. Then one can solve $G$ globally using a local solver $A$ as follows. 24 | Start $A$ with starting node $v_0$. It will return two (possibly empty) winning sets $W'_0$ and $W'_1$. 25 | In any case, we will have $W'_0 \cap W'_1 = \emptyset$, but not necessarily $W'_0 \cup W'_1 = V$. Let 26 | $W' := V \setminus (\attr{}{0}{W'_0} \cup \attr{}{1}{W'_1})$. Then taking out all nodes in $W'$ from $G$ 27 | will result in a total parity game again by two applications of Lemma~\ref{lem:minusattr} and the fact 28 | that $\attr{}{0}{W'_0} \cap \attr{}{1}{W'_1} = \emptyset$. Let $G'$ be this game. Then the winning positions 29 | for player $i$ in $G$ are $\attr{}{i}{W'_i}$ plus the winning positions for him/her in $G'$. Since $G'$ 30 | will be smaller than $G$ this can be used iteratively or recursively, to compute the entire $W_0$ and $W_1$. 31 | 32 | The winning strategies can equally be assembled to a winning strategy $\sigma$ for player $i$. Let 33 | $\sigma'$ be player $i$'s winning strategy on the subgame $G'$, $\alpha$ be his/her attractor strategy 34 | for reaching $W'_i$, and $\eta$ be the strategy that guarantees him/her to win on $W'_i$. Then define 35 | \begin{displaymath} 36 | \sigma(v) \enspace := \enspace 37 | \begin{cases} 38 | \eta(v) \enspace, &\mbox{if } v \in W'_i \\ 39 | \alpha(v) \enspace, &\mbox{if } v \in \attr{}{i}{W'_i} \setminus W'_i \\ 40 | \sigma'(v) \enspace, &\mbox{if } v \mbox{ is a node in } G' \\ 41 | \mbox{anything} & \mbox{otherwise} 42 | \end{cases} 43 | \end{displaymath} 44 | The following theorem provides correctness of this construction. 45 | 46 | \begin{proposition} 47 | Let $G = (V,V_0,V_1,E,\Omega)$ be a parity game, let $W_i$ be the winning set of player $i$ and 48 | $i \in \{0,1\}$. Player $i$ has a positional strategy $\sigma$ for $G$ s.t. $\sigma$ is a positional 49 | winning strategy for $G$ starting in any node $v \in W_i$. 50 | \end{proposition} 51 | 52 | To see that this holds let $\sigma_v$ be positional winning strategies for $G$ starting in $v$ for each node 53 | $v \in W_i$ (which have to exist by the former theorem). We assume all nodes $v \in W_i$ to be ordered 54 | w.r.t.\ a well-ordering $<$. A positional strategy $\sigma$ winning from each node $v \in W_i$ can be 55 | defined as follows: 56 | \begin{displaymath} 57 | \sigma: v \in W_i \cap V_i \mapsto \sigma_{\min_{<} \{u \in W_i \mid v \in dom(\sigma_u)\}} (v) 58 | \end{displaymath} 59 | To see that $\sigma$ indeed is a positional winning strategy for $G$ starting in any node $v \in W_i$ let 60 | $v_0 v_1 \ldots$ be a $\sigma$-conforming play with $v_j \in W_i$ for all $j \in \Nat$. Since $<$ is a 61 | well-ordering $\sigma$ finally simulates the strategy of $\sigma_u$ for some $u \in W_i$ and thus player 62 | $i$ is wins this play. 63 | 64 | 65 | 66 | 67 | 68 | %%% Local Variables: 69 | %%% mode: latex 70 | %%% TeX-master: "main" 71 | %%% End: 72 | -------------------------------------------------------------------------------- /doc/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[open=left,twopage=true]{scrreprt} 2 | 3 | \usepackage{xspace} 4 | \usepackage{amsmath} 5 | \usepackage{amssymb} 6 | \usepackage{latexsym} 7 | \usepackage{pgf} 8 | \usepackage{pgfarrows} 9 | \usepackage{ntheorem} 10 | \usepackage{lscape} 11 | \usepackage{graphicx} 12 | \usepackage{epic,eepic} 13 | \usepackage{tikz} 14 | \usetikzlibrary{automata,calc,shapes.geometric,arrows,shadings,chains} 15 | 16 | \input{./makros} 17 | \definecolor{darkgreen}{rgb}{.1,.6,.1} 18 | \definecolor{darkred}{rgb}{.6,.1,.1} 19 | 20 | \definecolor{light-blue}{rgb}{0.7,0.8,1} 21 | \usepackage[allbordercolors={light-blue},pdfborderstyle={/S/U/W 0.8}]{hyperref} 22 | 23 | \begin{document} 24 | 25 | \begin{titlepage} 26 | %\subject{Report} 27 | \title{The \pgsolver Collection of Parity Game Solvers \\[2mm] {\large Version 4.3}} 28 | \author{Oliver Friedmann \\ \normalsize Institut f\"ur Informatik \\ \normalsize Ludwig-Maximilians-Universit\"at M\"unchen, Germany \and 29 | Martin Lange \\ \normalsize Theoretical Computer Science / Formal Methods \\ \normalsize School of Electr.\ Eng.\ and Computer Science \\ 30 | \normalsize University of Kassel, Germany} 31 | \publishers{ 32 | \vspace*{1cm} 33 | \scalebox{0.8}{\begin{tikzpicture}[very thick,node distance=2.5cm,-triangle 45] 34 | %\scalebox{0.59}{\includegraphics{graphics/titlegame}} 35 | 36 | \tikzstyle{redboxnode}=[draw=black,very thin,shape=rectangle,inner sep=10pt,ball color=red!90,shading=ball] 37 | \tikzstyle{reddiamnode}=[draw=red,shape=diamond] 38 | \tikzstyle{greenboxnode}=[shape=rectangle,inner sep=10pt,ball color=green,shading=ball] 39 | \tikzstyle{greendiamnode}=[draw=black,very thin,shape=diamond,ball color=green,shading=ball] 40 | 41 | \node[redboxnode] (v0) {$1$}; 42 | \node[redboxnode] (v1) [below of=v0] {$1$}; 43 | \node[greendiamnode] (v2) [right of=v1] {$5$}; 44 | \node[greendiamnode] (v3) [right of=v2] {$5$}; 45 | \node[redboxnode] (v4) [right of=v3] {$8$}; 46 | \node[greendiamnode] (v5) [below right of=v1] {$5$}; 47 | \node[redboxnode] (v6) [below right of=v2] {$1$}; 48 | \node[greendiamnode] (v7) [below right of=v3] {$7$}; 49 | \node[greendiamnode] (v8) [below right of=v5] {$2$}; 50 | \node[greenboxnode] (v9) [below of=v8] {$0$}; 51 | 52 | \path[black!70] (v0) edge [bend right=10] (v1) 53 | (v1) edge (v5) 54 | (v2) edge (v6) 55 | (v3) edge (v6) 56 | (v4) edge [bend right=10] (v7) 57 | (v5) edge [bend left=70] (v0) 58 | (v6) edge [bend left] (v9) 59 | (v7) edge [bend right=10] (v4) 60 | (v8) edge [bend right=10] (v9); 61 | 62 | \draw[darkgreen] (v2) edge (v5) 63 | (v3) edge (v7) 64 | (v5) edge (v8) 65 | (v7) edge (v8) 66 | (v9) edge [bend right=10] (v8); 67 | 68 | \draw[darkred] (v0) edge [bend left=25] (v6) 69 | (v1) edge [bend right=10] (v0) 70 | (v4) edge (v6); 71 | 72 | \draw[darkgreen] (v8) .. controls ($(v8)+(-1.5,.5)$) and ($(v8)+(-1.5,-.5)$) .. (v8); 73 | \draw[darkgreen] (v9) .. controls ($(v9)+(-1.5,.5)$) and ($(v9)+(-1.5,-.5)$) .. (v9); 74 | \draw[darkred] (v6) .. controls ($(v6)+(-1.5,.5)$) and ($(v6)+(-1.5,-.5)$) .. (v6); 75 | 76 | \end{tikzpicture}}} 77 | \end{titlepage} 78 | \maketitle[0] 79 | 80 | \cleardoublepage 81 | \pdfbookmark{Contents}{table-of-contents} 82 | \tableofcontents 83 | 84 | \chapter{Introduction} 85 | 86 | \input{./intro} 87 | 88 | \chapter{Solving Parity Games} 89 | \label{chp:pgames} 90 | 91 | \input{./tech} 92 | \input{./locglob} 93 | \input{./verify} 94 | \input{./univopt} 95 | \input{./gensolv} 96 | \input{./implalg} 97 | \input{./implheur} 98 | 99 | \chapter{User's Guide} 100 | \label{chp:uguide} 101 | 102 | \input{./license} 103 | \input{./changelog} 104 | \input{./install} 105 | \input{./running} 106 | \input{./specs} 107 | \input{./display} 108 | \input{./tools} 109 | 110 | \chapter{Benchmarks} 111 | \label{chp:benchmarks} 112 | 113 | \input{./benchmarks} 114 | %\input{./results} 115 | 116 | \chapter{Developer's Guide} 117 | \label{chp:dguide} 118 | 119 | \input{./develop} 120 | 121 | %\appendix 122 | 123 | %\chapter{New Algorithms} 124 | %\label{app:newalg} 125 | 126 | 127 | 128 | \cleardoublepage 129 | \pdfbookmark{Bibliography}{bibliography} 130 | \bibliographystyle{alpha} 131 | \bibliography{./literature} 132 | 133 | \end{document} 134 | 135 | 136 | 137 | %%% Local Variables: 138 | %%% mode: latex 139 | %%% TeX-master: t 140 | %%% End: 141 | -------------------------------------------------------------------------------- /doc/makros.tex: -------------------------------------------------------------------------------- 1 | % Kill any active \bfseries etc. with \normalfont to get the old behavior of \sc 2 | \newcommand{\pgsolver}{{\normalfont\textsc{PGSolver}}\xspace} 3 | 4 | \newcommand{\Nat}{\ensuremath{\mathbb{N}}} 5 | 6 | \newcommand{\attr}[3]{\ensuremath{\mathit{Attr}^{#1}_{#2}(#3)}} 7 | 8 | \newcounter{algcounter} 9 | \newcounter{heurcounter} 10 | \newcommand{\nextalg}{\stepcounter{algcounter}\arabic{algcounter}} 11 | \newcommand{\nextheur}{\stepcounter{heurcounter}\arabic{heurcounter}} 12 | 13 | \newcommand{\nonterminal}[1]{\ensuremath{\langle\mathit{#1}\rangle}} 14 | \newcommand{\terminal}[1]{\ensuremath{\texttt{#1}}} 15 | \newcommand{\sem}[1]{\ensuremath{[\![ #1 ]\!]}} 16 | \newcommand{\hide}[1]{} 17 | 18 | \def\newarrow#1{\mathop{{\hbox{\setbox0=\hbox{$\scriptstyle{#1\quad}$}{$% 19 | \mathrel{\mathop{\setbox1=\hbox to 20 | \wd0{\rightarrowfill}\ht1=3pt\dp1=-2pt\box1}\limits^{#1}}% 21 | $}}}}} 22 | \newcommand{\Transition}[3]{\ensuremath{#1 \newarrow{#2} #3}} 23 | \newcommand{\Mubox}[1]{\ensuremath{[ #1 ]}} 24 | \newcommand{\Mudiam}[1]{\ensuremath{\langle #1 \rangle}} 25 | 26 | \newcommand{\TODOcomment}[2]{% 27 | \stepcounter{TODOcounter#1}% 28 | {\scriptsize\bf$^{(\arabic{TODOcounter#1})}$}% 29 | \marginpar[\fbox{ 30 | \parbox{2cm}{\raggedleft 31 | \scriptsize$^{({\bf{\arabic{TODOcounter#1}{#1}}})}$% 32 | \scriptsize #2}}]% 33 | {\fbox{\parbox{2cm}{\raggedright 34 | \scriptsize$^{({\bf{\arabic{TODOcounter#1}{#1}}})}$% 35 | \scriptsize #2}}} 36 | }% 37 | 38 | \newcommand{\simpleTODOcomment}[2]{% 39 | \stepcounter{TODOcounter#1}% 40 | {\bf 41 | \scriptsize({\arabic{TODOcounter#1}~{#1}}) 42 | {\bfseries{TODO:} #2} 43 | } 44 | } 45 | 46 | \newcounter{TODOcounter} 47 | \newcommand{\TODO}[1]{\TODOcomment{}{#1}} 48 | \newcommand{\TODOX}[1]{\simpleTODOcomment{}{#1}} 49 | 50 | 51 | %%% Local Variables: 52 | %%% mode: latex 53 | %%% TeX-master: "main" 54 | %%% End: 55 | -------------------------------------------------------------------------------- /doc/ntheorem.cfg: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `ntheorem.std', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% ntheorem.dtx (with options: `standard') 8 | %% 9 | %% IMPORTANT NOTICE: 10 | %% 11 | %% For the copyright see the source file. 12 | %% 13 | %% Any modified versions of this file must be renamed 14 | %% with new filenames distinct from ntheorem.std. 15 | %% 16 | %% For distribution of the original source see the terms 17 | %% for copying and modification in the file ntheorem.dtx. 18 | %% 19 | %% This generated file may be distributed as long as the 20 | %% original source files, as listed above, are part of the 21 | %% same distribution. (The sources need not necessarily be 22 | %% in the same archive or directory.) 23 | \def\filedate{2001/11/28} 24 | \def\docdate{2001/01/13} 25 | \def\fileversion{1.20 alpha} 26 | \def\basename{ntheorem} 27 | %% \CharacterTable 28 | %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z 29 | %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z 30 | %% Digits \0\1\2\3\4\5\6\7\8\9 31 | %% Exclamation \! Double quote \" Hash (number) \# 32 | %% Dollar \$ Percent \% Ampersand \& 33 | %% Acute accent \' Left paren \( Right paren \) 34 | %% Asterisk \* Plus \+ Comma \, 35 | %% Minus \- Point \. Solidus \/ 36 | %% Colon \: Semicolon \; Less than \< 37 | %% Equals \= Greater than \> Question mark \? 38 | %% Commercial at \@ Left bracket \[ Backslash \\ 39 | %% Right bracket \] Circumflex \^ Underscore \_ 40 | %% Grave accent \` Left brace \{ Vertical bar \| 41 | %% Right brace \} Tilde \~} 42 | \theoremnumbering{arabic} 43 | \theoremstyle{plain} 44 | \RequirePackage{latexsym} 45 | %\theoremsymbol{\ensuremath{_\Box}} 46 | \theoremsymbol{} 47 | \theorembodyfont{\itshape} 48 | \theoremheaderfont{\normalfont\bfseries} 49 | \theoremseparator{} 50 | \newtheorem{theorem}{Theorem} 51 | \newtheorem{Theorem}[theorem]{Theorem} 52 | \newtheorem{Satz}[theorem]{Satz} 53 | \newtheorem{satz}[theorem]{Satz} 54 | \newtheorem{Proposition}[theorem]{Proposition} 55 | \newtheorem{proposition}[theorem]{Proposition} 56 | \newtheorem{Lemma}[theorem]{Lemma} 57 | \newtheorem{lemma}[theorem]{Lemma} 58 | \newtheorem{Korollar}[theorem]{Korollar} 59 | \newtheorem{korollar}[theorem]{Korollar} 60 | \newtheorem{Corollary}[theorem]{Corollary} 61 | \newtheorem{corollary}[theorem]{Corollary} 62 | \newtheorem{fact}[theorem]{Fact} 63 | \newtheorem{Fact}[theorem]{Fact} 64 | 65 | \theorembodyfont{\upshape} 66 | \newtheorem{Example}[theorem]{Example} 67 | \newtheorem{example}[theorem]{Example} 68 | \newtheorem{Beispiel}[theorem]{Beispiel} 69 | \newtheorem{beispiel}[theorem]{Beispiel} 70 | \newtheorem{Bemerkung}[theorem]{Bemerkung} 71 | \newtheorem{bemerkung}[theorem]{Bemerkung} 72 | \newtheorem{Anmerkung}[theorem]{Anmerkung} 73 | \newtheorem{anmerkung}[theorem]{Anmerkung} 74 | \newtheorem{Remark}[theorem]{Remark} 75 | \newtheorem{remark}[theorem]{Remark} 76 | \newtheorem{Definition}[theorem]{Definition} 77 | \newtheorem{definition}[theorem]{Definition} 78 | 79 | \theoremstyle{nonumberplain} 80 | \theoremheaderfont{\scshape} 81 | \theorembodyfont{\normalfont} 82 | \theoremsymbol{\ensuremath{_\blacksquare}} 83 | \RequirePackage{amssymb} 84 | \newtheorem{Proof}{Proof} 85 | \newtheorem{proof}{Proof} 86 | \newtheorem{Beweis}{Beweis} 87 | \newtheorem{beweis}{Beweis} 88 | \qedsymbol{\ensuremath{_\blacksquare}} 89 | \theoremclass{LaTeX} 90 | \endinput 91 | %% 92 | %% End of file `ntheorem.std'. 93 | -------------------------------------------------------------------------------- /doc/pgsolver.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcsprojects/pgsolver/8fde6003daffeb9b5da829001cec5e8acb7a340a/doc/pgsolver.pdf -------------------------------------------------------------------------------- /doc/results.tex: -------------------------------------------------------------------------------- 1 | \section{Comparison of the Solvers} 2 | 3 | 4 | 5 | %%% Local Variables: 6 | %%% mode: latex 7 | %%% TeX-master: "main" 8 | %%% End: 9 | -------------------------------------------------------------------------------- /doc/verify.tex: -------------------------------------------------------------------------------- 1 | \section{Verifying Strategies} 2 | 3 | The problem of \emph{verifying strategies} is to decide whether a given partition $(W'_0, W'_1)$ of a parity 4 | game $G$ along with two strategies $\sigma_0: W'_0 \cap V_0 \rightarrow V$ and 5 | $\sigma_1: W'_1 \cap V_1 \rightarrow V$ matches the partition into winning sets, i.e. whether $W'_0 = W_0$ 6 | and $W'_1 = W_1$ as well as $\sigma_0$ and $\sigma_1$ ensure the win of the respective player in the 7 | respective winning set. 8 | 9 | The verification process basically traverses three phases. The algorithm verifies in the first phase that 10 | $\sigma_0$ and $\sigma_1$ are welldefined in the sense that a strategy actually uses valid transitions in 11 | the game graph. In the second phase the algorithm checks whether the strategies stay in their winning 12 | regions, i.e. $\sigma_i[W'_i] \subseteq W'_i$ for both player $i$, as well as whether the winning regions 13 | are closed w.r.t. the respective player. 14 | 15 | The third phase finally checks whether the given strategies are winning strategies. In order to solve this 16 | problem, the algorithm computes the subgames $G_i := (G|_{W'_i})|_{\sigma_i}$ induced by the respective sets 17 | and strategies in question. Note that both $G_i$ are special games, namely one-player games. Hence, they 18 | can be solved as described above. 19 | 20 | Since $\sigma_i$ is a winning strategy on $W'_i$ iff $\sigma_i$ is a winning strategy on $G_i$, it suffices 21 | to check whether the computed winning set $W^{G_i}_i$ correspond with 22 | $W'_i$, and if they do not, the counter strategy for player $1 - i$ can be used to extract a cycle in $G$ 23 | following strategy $\sigma_i$ that is won by $1-i$. 24 | 25 | 26 | 27 | 28 | %%% Local Variables: 29 | %%% mode: latex 30 | %%% TeX-master: "main" 31 | %%% End: 32 | -------------------------------------------------------------------------------- /oasis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | oasis setup 3 | ocaml setup.ml -configure 4 | ocaml setup.ml -build 5 | -------------------------------------------------------------------------------- /opam-local.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | opam uninstall pgsolver 3 | opam pin remove pgsolver 4 | oasis setup 5 | ocaml setup.ml -configure 6 | ocaml setup.ml -build 7 | oasis2opam --local -y 8 | opam pin add pgsolver . -n -y 9 | opam install pgsolver 10 | -------------------------------------------------------------------------------- /opam/findlib: -------------------------------------------------------------------------------- 1 | pgsolver 2 | -------------------------------------------------------------------------------- /opam/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "opam-devel@lists.ocaml.org" 3 | authors: [ "Oliver Friedmann" 4 | "Martin Lange" ] 5 | license: "BSD-3-clause" 6 | homepage: "https://github.com/tcsprojects/pgsolver" 7 | dev-repo: "git://github.com/tcsprojects/pgsolver.git" 8 | bug-reports: "https://github.com/tcsprojects/pgsolver/issues" 9 | build: [ 10 | ["ocaml" "setup.ml" "-configure" "--prefix" prefix] 11 | ["ocaml" "setup.ml" "-build"] 12 | ["ocaml" "setup.ml" "-configure" "--enable-tests"] {with-test} 13 | ["ocaml" "setup.ml" "-build"] {with-test} 14 | ["ocaml" "setup.ml" "-test"] {with-test} 15 | ] 16 | install: ["ocaml" "setup.ml" "-install"] 17 | remove: [ 18 | ["ocaml" "%{etc}%/pgsolver/setup.ml" "-C" "%{etc}%/pgsolver" "-uninstall"] 19 | ] 20 | depends: [ 21 | "ocaml" {>= "4.08.0" & < "5.0"} 22 | "TCSLib" {>= "0.2"} 23 | "extlib" | "extlib-compat" 24 | "minisat" 25 | "ocaml-sat-solvers" {>= "0.7.1"} 26 | "ocamlbuild" {build} 27 | "ocamlfind" {build} 28 | "ounit" {build} 29 | ] 30 | synopsis: 31 | "A collection of tools for generating, manipulating and - most of all - solving parity games" 32 | description: """\ 33 | A collection of tools for generating, manipulating and - most of all - 34 | solving parity games.""" 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "opam-build": "ocaml setup.ml -build", 4 | "opam-publish": "opam publish opam/opam" 5 | } 6 | } -------------------------------------------------------------------------------- /pgsolver.install: -------------------------------------------------------------------------------- 1 | etc: [ 2 | "setup.ml" 3 | "setup.data" 4 | "setup.log" 5 | ] 6 | -------------------------------------------------------------------------------- /scripts/benchfamily.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # PrefixCall SuffixCall Benchmark Params LowerBound UpperBound 4 | 5 | function call #string 6 | { 7 | $2 $1 $3 | $4 -s -gp -n $1 $5 8 | } 9 | 10 | m=$5 11 | 12 | while [ $6 -ge $m ] 13 | do 14 | call $m "$1" "$2" "$3" "$4" 15 | m=$(expr $m + 1) 16 | done 17 | -------------------------------------------------------------------------------- /scripts/benchrandom.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # RandomFunc Count Benchmark BenchParams 4 | 5 | randomfunc=$1 6 | count=$2 7 | benchmark=$3 8 | benchparams=$4 9 | 10 | files= 11 | i=0 12 | 13 | while [ $count -ge $i ] 14 | do 15 | f=tempbench_$RANDOM.temp 16 | $randomfunc > $f 17 | files="$files $f" 18 | i=$(expr $i + 1) 19 | done 20 | 21 | $benchmark $files $benchparams 22 | 23 | rm $files -------------------------------------------------------------------------------- /scripts/benchrandomfamily.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # PrefixCall SuffixCall Benchmark Params LowerBound UpperBound Multiplier Count BenchRandom.Sh 4 | 5 | function call #string 6 | { 7 | $7 "$2 $1 $3" $6 "$4" "$5 -s -gp -n $1" 8 | } 9 | 10 | m=$5 11 | 12 | while [ $6 -ge $m ] 13 | do 14 | a=$(expr $m "*" $7) 15 | call "$a" "$1" "$2" "$3" "$4" $8 $9 16 | m=$(expr $m + 1) 17 | done 18 | -------------------------------------------------------------------------------- /scripts/callfamily.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # CallPrefix CallPostfix Count Prefix 4 | 5 | files= 6 | i=1 7 | 8 | while [ $3 -ge $i ] 9 | do 10 | f=$4_$i.gm 11 | files="$files $f" 12 | i=$(expr $i + 1) 13 | done 14 | 15 | $1 $files $2 16 | -------------------------------------------------------------------------------- /scripts/clusteredcall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | function awful_sqrt 4 | { 5 | i=0 6 | j=0 7 | while [ $1 -ge $j ] 8 | do 9 | i=$(expr $i + 1) 10 | j=$(expr $i \* $i) 11 | done 12 | echo $i 13 | } 14 | 15 | function awful_log 16 | { 17 | i=1 18 | j=10 19 | while [ $1 -ge $j ] 20 | do 21 | i=$(expr $i + 1) 22 | j=$(expr 10 \* $j) 23 | done 24 | echo $i 25 | } 26 | 27 | clust=$1 28 | n=$2 29 | 30 | # n sqrt(n) 1 4 log(n) log(n) 2*log(n) sqrt(n) 2*sqrt(n) 31 | 32 | sqrt=$(awful_sqrt $n) 33 | sqrtx=$(expr 2 \* $sqrt) 34 | log=$(awful_log $n) 35 | sqrtxl=$(expr $log \* $sqrt) 36 | logx=$(expr 2 \* $log) 37 | logxx=$(expr 2 \* $logx) 38 | logxxx=$(expr 2 \* $logxx) 39 | sqrtlog=$(awful_log $sqrt) 40 | loglog=$(awful_log $log) 41 | b=$(expr $log / $logsqrt + 1) 42 | 43 | $clust $n $sqrt 1 4 $b $sqrtlog $log $sqrt $sqrtxl 44 | -------------------------------------------------------------------------------- /scripts/createrandomgames.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # RandomFunc Count Prefix 4 | 5 | files= 6 | i=1 7 | 8 | while [ $2 -ge $i ] 9 | do 10 | f=$3_$i.gm 11 | echo Creating $f... 12 | $1 > $f 13 | files="$files $f" 14 | i=$(expr $i + 1) 15 | done 16 | -------------------------------------------------------------------------------- /scripts/policyitervis/buildanim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 1st parameter = call to game generator 4 | # 2nd parameter = argument to policyitervis 5 | # 3rd parameter = target files base name 6 | # 4th parameter = Metapost template 7 | # 5th parameter = Latex template 8 | 9 | BASEDIR=$(dirname $0)/../.. 10 | 11 | $BASEDIR/bin/$1 | $BASEDIR/bin/policyitervis -pi "$2" > $3_animation.mp 12 | 13 | cp $4 $3_main.mp 14 | 15 | echo "input ./$3_animation;" >> $3_main.mp 16 | echo "end;" >> $3_main.mp 17 | 18 | cp $5 $3_main.tex 19 | 20 | for line in `cat $3_animation.mp | grep "beginfig" | sed s/beginfig\(// | sed s/\)\;//`; do 21 | echo "\\\\animationgraphic{$3_main.$line}" >> $3_main.tex 22 | echo "" >> $3_main.tex 23 | done 24 | 25 | echo "\\\\end{document}" >> $3_main.tex 26 | 27 | mpost $3_main.mp 28 | mpost $3_main.mp 29 | pdflatex $3_main.tex 30 | -------------------------------------------------------------------------------- /scripts/policyitervis/commands.txt: -------------------------------------------------------------------------------- 1 | Cunningham Exponential Lower Bound 2 | ./buildanim.sh "stratimprgen -pg cunninghamexp 3" "-sirrse" animation graphs/cunninghamexptemplate.mp template.tex 3 | 4 | Cunningham Subexponential Lower Bound 5 | ./buildanim.sh "stratimprgen -pg cunninghamsubexp 3" "-sirrse" animation graphs/cunninghamsubexptemplate.mp template.tex 6 | 7 | Zadeh Exponential Lower Bound 8 | ./buildanim.sh "stratimprgen -pg zadehexp 3" "-sfse" animation graphs/zadehexptemplate.mp template.tex 9 | 10 | Fearnley Subexponential Lower Bound 11 | ./buildanim.sh "stratimprgen -pg fearnleysubexp 3" "-sm" animation graphs/fearnleysubexptemplate.mp template.tex 12 | 13 | Friedmann Subexponential Lower Bound 14 | ./buildanim.sh "stratimprgen -pg friedmannsubexp 3" "-sa" animation graphs/friedmannsubexptemplate.mp template.tex -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/cunninghamexpgame.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input cunninghamexpgraph; 14 | 15 | beginfig(1); 16 | build_graph(true); 17 | graph_draw; 18 | endfig; 19 | 20 | end; 21 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/cunninghamexptemplate.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input graphs/cunninghamexpgraph; 14 | 15 | build_graph(true); 16 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/cunninghamsubexpgame.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input .././metapostgraphs/graphicslib 11 | input .././metapostgraphs/graphlib 12 | 13 | input cunninghamsubexpgame; 14 | 15 | beginfig(1); 16 | build_graph; 17 | graph_draw; 18 | endfig; 19 | 20 | end; 21 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/cunninghamsubexptemplate.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input graphs/cunninghamsubexpgraph; 14 | 15 | build_graph; 16 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/fearnleysubexpgame.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input .././metapostgraphs/graphicslib 11 | input .././metapostgraphs/graphlib 12 | 13 | input fearnleysubexpgame; 14 | 15 | beginfig(1); 16 | build_graph(false, 3); 17 | graph_draw; 18 | endfig; 19 | 20 | beginfig(2); 21 | build_graph(true, 3); 22 | graph_draw; 23 | endfig; 24 | 25 | 26 | end; 27 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/fearnleysubexpnogadgettemplate.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input graphs/fearnleysubexpgraph; 14 | 15 | build_graph(false, 3); 16 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/fearnleysubexptemplate.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input graphs/fearnleysubexpgraph; 14 | 15 | build_graph(true, 3); 16 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/friedmannsubexpgame.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input .././metapostgraphs/graphicslib 11 | input .././metapostgraphs/graphlib 12 | 13 | input friedmannsubexpgraph; 14 | 15 | beginfig(1); 16 | build_graph(false, 3); 17 | graph_draw; 18 | endfig; 19 | 20 | beginfig(2); 21 | build_graph(true, 3); 22 | graph_draw; 23 | endfig; 24 | 25 | end; 26 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/friedmannsubexptemplate.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input graphs/friedmannsubexpgraph; 14 | 15 | build_graph(true, 3); 16 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/zadehexpgame.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input zadehexpgame; 14 | 15 | beginfig(1); 16 | build_graph(true); 17 | graph_draw; 18 | endfig; 19 | 20 | end; 21 | -------------------------------------------------------------------------------- /scripts/policyitervis/graphs/zadehexptemplate.mp: -------------------------------------------------------------------------------- 1 | verbatimtex 2 | %&latex 3 | \documentclass{article} 4 | \usepackage{amsmath,amssymb} 5 | \begin{document} 6 | etex 7 | 8 | input "latex"; 9 | 10 | input ./metapostgraphs/graphicslib 11 | input ./metapostgraphs/graphlib 12 | 13 | input graphs/zadehexpgraph; 14 | 15 | build_graph(true); 16 | -------------------------------------------------------------------------------- /scripts/policyitervis/template.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{fullpage} 3 | \usepackage{graphics,graphicx} 4 | \usepackage[landscape]{geometry} 5 | \usepackage{lscape} 6 | 7 | \usepackage{ifpdf} 8 | \ifpdf 9 | \DeclareGraphicsRule{*}{mps}{*}{} 10 | \else 11 | \DeclareGraphicsRule{*}{eps}{*}{} 12 | \fi 13 | 14 | \newcommand{\animationgraphic}[1]{\includegraphics[height=15cm]{#1}} 15 | 16 | \begin{document} 17 | 18 | -------------------------------------------------------------------------------- /scripts/sqrtpriorandom.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | function awful_sqrt 4 | { 5 | i=0 6 | j=0 7 | while [ $1 -ge $j ] 8 | do 9 | i=$(expr $i + 1) 10 | j=$(expr $j + $i + $i + 1) 11 | done 12 | echo $i 13 | } 14 | 15 | $1 $2 $(awful_sqrt $2) $3 $4 $5 $6 $7 $8 $9 16 | -------------------------------------------------------------------------------- /src/META: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 7d1ab25d32bcb25c6175adc061458140) 3 | version = "4.3" 4 | description = 5 | "A collection of tools for generating, manipulating and - most of all - solving parity games." 6 | requires = "num str TCSLib extlib ocaml-sat-solvers minisat unix threads" 7 | archive(byte) = "pgsolver.cma" 8 | archive(byte, plugin) = "pgsolver.cma" 9 | archive(native) = "pgsolver.cmxa" 10 | archive(native, plugin) = "pgsolver.cmxs" 11 | exists_if = "pgsolver.cma" 12 | # OASIS_STOP 13 | 14 | -------------------------------------------------------------------------------- /src/generators/cliquegame.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | let n = ref 0 4 | let with_self_cycles = ref true 5 | 6 | module Clique = 7 | struct 8 | type gamenode = int 9 | 10 | let compare = compare 11 | 12 | let owner i = plr_benefits i 13 | 14 | let priority i = i 15 | 16 | let successors i = 17 | let rec succs acc j = 18 | if j=i 19 | then (if !with_self_cycles 20 | then succs (j::acc) (j-1) 21 | else succs acc (j-1)) 22 | else (if j<0 23 | then acc 24 | else succs (j::acc) (j-1)) 25 | in 26 | succs [] !n 27 | 28 | let show_node i = Some (string_of_int i) 29 | 30 | let initnodes _ = [0] 31 | end;; 32 | 33 | module CliqueGame = Build(Clique);; 34 | 35 | let generator_game_func arguments = 36 | 37 | let show_help _ = 38 | print_string (Info.get_title "Clique Game Generator"); 39 | print_string ("Usage: cliquegame n \n\n" ^ 40 | " where n = Number of nodes\n" ^ 41 | " is either the string > self < or absent\n\n") 42 | in 43 | 44 | (try 45 | n := int_of_string arguments.(0); 46 | with_self_cycles := Array.length arguments = 2 && arguments.(1) = "self" 47 | with _ -> (show_help (); exit 1)); 48 | 49 | let successors i = 50 | let rec succs acc j = 51 | if j=i 52 | then (if !with_self_cycles 53 | then succs (j::acc) (j-1) 54 | else succs acc (j-1)) 55 | else (if j<0 56 | then acc 57 | else succs (j::acc) (j-1)) 58 | in 59 | succs [] (!n-1) 60 | in 61 | pg_init !n (fun v -> (v, plr_benefits v, successors v, Some (nd_show v))) 62 | 63 | 64 | 65 | (* CliqueGame.build () *) 66 | 67 | 68 | let register _ = Generatorregistry.register_generator generator_game_func "cliquegame" "Clique Game";; 69 | -------------------------------------------------------------------------------- /src/generators/cliquegame.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/cliquegame_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "cliquegame";; 2 | -------------------------------------------------------------------------------- /src/generators/clusteredrandomgame.ml: -------------------------------------------------------------------------------- 1 | open Tcsmaths.RandomUtils;; 2 | open Tcsset;; 3 | open Paritygame;; 4 | 5 | let generator_game_func arguments = 6 | 7 | let show_help _ = 8 | print_string (Info.get_title "Clustered Random Game Generator"); 9 | print_string ("Usage: clusteredrandomgame n p l h r a b x y\n\n" ^ 10 | " where n = Number of nodes\n" ^ 11 | " p = Highest possibly occurring priority\n" ^ 12 | " l = Lowest possible out-degree in the lowest layer\n" ^ 13 | " h = Highest possible out-degree in the lowest layer\n" ^ 14 | " r = Recursion depth\n" ^ 15 | " a = Lowest possible recursion breadth\n" ^ 16 | " b = Highest possible recursion breadth\n" ^ 17 | " x = Lowest possible inter-connection edges\n" ^ 18 | " y = Highest possible inter-connection edges\n\n") 19 | in 20 | 21 | if (Array.length arguments != 9) then (show_help (); exit 1); 22 | 23 | let size = int_of_string arguments.(0) in 24 | let max_prio = 1+(int_of_string arguments.(1)) in 25 | let outdegmin = int_of_string arguments.(2) in 26 | 27 | if outdegmin < 1 then (show_help (); exit 1); 28 | 29 | let outdegmax = int_of_string arguments.(3) in 30 | let recdepth = int_of_string arguments.(4) in 31 | let recintmin = int_of_string arguments.(5) in 32 | let recintmax = int_of_string arguments.(6) in 33 | let recconmin = int_of_string arguments.(7) in 34 | let recconmax = int_of_string arguments.(8) in 35 | 36 | Random.self_init (); 37 | 38 | let pg = Array.make size [] in 39 | 40 | let rec generate recd rangemin rangemax = 41 | let d = rangemax - rangemin + 1 in 42 | if (recd = 0) || (d < recintmin) then 43 | for i = rangemin to rangemax do 44 | let outdeg = min d (randrange outdegmin outdegmax) in 45 | let succs = Array.to_list (get_pairwise_different_from_range outdeg rangemin rangemax) in 46 | pg.(i) <- succs 47 | done 48 | else ( 49 | let parts = min d (randrange recintmin recintmax) in 50 | let randarray = get_pairwise_different_from_range (parts - 1) (rangemin+1) rangemax in 51 | let partslist = (rangemax + 1) :: (Array.to_list randarray) in 52 | let _ = List.fold_left (fun head next_head -> 53 | generate (recd - 1) head (next_head - 1); 54 | next_head 55 | ) rangemin (List.sort compare partslist) in 56 | let inter_edges = randrange recconmin recconmax in 57 | for i = 0 to inter_edges - 1 do 58 | let from_node = randrange rangemin rangemax in 59 | let to_node = randrange rangemin rangemax in 60 | pg.(from_node) <- to_node::pg.(from_node) 61 | done 62 | ) 63 | in 64 | 65 | generate recdepth 0 (size - 1); 66 | 67 | pg_init size (fun v -> (Random.int max_prio, 68 | plr_random (), 69 | TreeSet.remove_list_dups pg.(v), 70 | Some (nd_show v)) 71 | );; 72 | 73 | let register _ = Generatorregistry.register_generator generator_game_func "clusteredrg" "Clustered Random Game";; 74 | -------------------------------------------------------------------------------- /src/generators/clusteredrandomgame.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/clusteredrandomgame_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "clusteredrg";; 2 | -------------------------------------------------------------------------------- /src/generators/jurdzinskigame.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | let height = ref 0 4 | let width = ref 0 5 | 6 | let rec range x y = if x > y then [] else x :: (range (x+1) y) 7 | 8 | module JGame = Build( 9 | struct 10 | type gamenode = Left of int * int 11 | | Right of int * int 12 | | Above of int * int 13 | 14 | let compare = compare 15 | 16 | let owner = function Left(0,_) -> plr_Even 17 | | Right(0,_) -> plr_Odd 18 | | Left(_,_) -> plr_Odd 19 | | Right(_,_) -> plr_Even 20 | | Above(_,_) -> plr_Even 21 | 22 | let priority = function Left(0,_) -> 0 23 | | Right(0,_) -> 1 24 | | Left(h,_) -> 2*h 25 | | Right(h,_) -> 2*h 26 | | Above(h,_) -> 2*h+1 27 | 28 | let successors = function Left(0,0) -> [ Right(0,0) ] 29 | | Left(0,w) -> if w < !width then 30 | [ Right(0,w-1); Right(0,w) ] 31 | else 32 | [ Right(0,w-1) ] 33 | | Right(0,w) -> (Left(0,w))::(Left(0,w+1))::(List.map (fun v -> Right(v,w)) (range 1 (!height-1))) 34 | | Left(h,0) -> [ Above(h,0); Right(h,0) ] 35 | | Left(h,w) -> if w < !width then 36 | [ Right(h,w-1); Above(h,w); Right(h,w) ] 37 | else 38 | [ Right(h,w-1) ] 39 | | Above(h,w) -> [ Right(h,w) ] 40 | | Right(h,w) -> [ Left(h,w); Left(h,w+1); Right(0,w) ] 41 | 42 | let show_node = function Left(h,w) -> Some("L(" ^ string_of_int h ^ "," ^ string_of_int w ^ ")") 43 | | Right(h,w) -> Some("R(" ^ string_of_int h ^ "," ^ string_of_int w ^ ")") 44 | | Above(h,w) -> Some("A(" ^ string_of_int h ^ "," ^ string_of_int w ^ ")") 45 | 46 | let initnodes _ = [ Left(0,0) ] 47 | 48 | end);; 49 | 50 | let generator_game_func arguments = 51 | 52 | let show_help _ = 53 | print_string (Info.get_title "Jurdzinski Game Generator"); 54 | print_string ("Usage: jurdzinskigame h w\n\n" ^ 55 | " generates the Jurdzinski game of height h and width w for h,w >= 0\n" ^ 56 | " as a max-parity game\n\n") 57 | in 58 | 59 | (try 60 | height := int_of_string arguments.(0); 61 | width := int_of_string arguments.(1) 62 | with _ -> (show_help (); exit 1)); 63 | 64 | if not (!height >= 0 && !width >= 0) then (show_help(); exit 1); 65 | 66 | JGame.build () 67 | 68 | 69 | let register _ = Generatorregistry.register_generator generator_game_func "jurdzinskigame" "Jurdzinski Game";; 70 | -------------------------------------------------------------------------------- /src/generators/jurdzinskigame.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/jurdzinskigame_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "jurdzinskigame";; 2 | -------------------------------------------------------------------------------- /src/generators/laddergame.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | let generator_game_func arguments = 4 | 5 | let show_help _ = 6 | print_string (Info.get_title "Ladder Game Generator"); 7 | print_string ("Usage: laddergame n\n\n" ^ 8 | " where n = n-th ladder game\n\n") 9 | 10 | in 11 | 12 | if (Array.length arguments != 1) then (show_help (); exit 1); 13 | 14 | let n = int_of_string arguments.(0) in 15 | let m = 2*n in 16 | 17 | pg_init m (fun v -> (v mod 2, plr_benefits v, [ ((v+1) mod m); ((v+2) mod m) ], Some (nd_show v)));; 18 | 19 | let register _ = Generatorregistry.register_generator generator_game_func "laddergame" "Ladder Game";; 20 | -------------------------------------------------------------------------------- /src/generators/laddergame.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/laddergame_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "laddergame";; 2 | -------------------------------------------------------------------------------- /src/generators/langincl.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | let n = ref 0 4 | let m = ref 2 5 | 6 | let rec range x y = if x > y then [] else x :: (range (x+1) y) 7 | let even x = (x mod 2) = 0 8 | 9 | module LangInclGame = Build( 10 | struct 11 | type gamenode = int * int 12 | let compare = compare 13 | 14 | let owner _ = plr_Odd 15 | 16 | let initnodes _ = [ (0,0) ] 17 | 18 | let priority (u,v) = if even v then 2 else if u > 0 then 1 else 0 19 | 20 | let dettrans v a = 21 | let row = v mod !n in 22 | (* let col = v / !n in *) 23 | if a-1 = row then 24 | (v + !n) mod (!m * !n) 25 | else 26 | !n+a-1 27 | 28 | let successors (u,v) = 29 | let symbols = range 1 !n in 30 | if u=0 then 31 | (List.map (fun a -> (0,dettrans v a)) symbols) @ 32 | (List.map (fun a -> (a,dettrans v a)) symbols) 33 | else if u > (!m-2) * !n then 34 | [(0, dettrans v (u - (!m-2) * !n))] 35 | else [(u + !n, dettrans v (u mod !n))] 36 | 37 | let show_node (u,v) = Some ("(" ^ string_of_int u ^ "," ^ string_of_int v ^ ")") 38 | end);; 39 | 40 | let generator_game_func arguments = 41 | 42 | let show_help _ = 43 | print_string (Info.get_title "Language Inclusion Problem Game Generator"); 44 | print_string ("Usage: langincl n [m]\n\n" ^ 45 | " where n = number of alphabet symbols for the language of infinitely many repetitions'\n" ^ 46 | " m = length of parts with repeated symbols (>=2), default is 2\n\n") 47 | 48 | in 49 | 50 | if (Array.length arguments < 1) || (Array.length arguments > 2) then (show_help (); exit 1); 51 | 52 | n := int_of_string arguments.(0); 53 | (try 54 | m := int_of_string arguments.(1) 55 | with Invalid_argument _ -> ()); 56 | 57 | LangInclGame.build () 58 | 59 | 60 | 61 | let register _ = Generatorregistry.register_generator generator_game_func "langincl" "Language Inclusion Problem Game";; 62 | -------------------------------------------------------------------------------- /src/generators/langincl.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/langincl_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "langincl";; 2 | -------------------------------------------------------------------------------- /src/generators/modelcheckerladder.ml: -------------------------------------------------------------------------------- 1 | (* size: 4 * n 2 | index: 4 * n 3 | counter: 6 * 2^n - 5 4 | *) 5 | 6 | open Paritygame;; 7 | 8 | let n = ref 0 9 | 10 | module ModelcheckerLadderGame = Build( 11 | struct 12 | type gamenode = Player0 of int 13 | | Player1 of int 14 | | Player1x of int 15 | 16 | let compare = compare 17 | 18 | let owner _ = plr_Odd 19 | 20 | let priority = function 21 | | Player0 i -> 2 * !n - 2 * i 22 | | Player1 i -> 0 23 | | Player1x i -> 2 * !n - 2 * i - 1 24 | 25 | let show_node = 26 | let fmt x i = Some (x ^ string_of_int (!n - i)) in 27 | function 28 | | Player0 i -> fmt "a" i 29 | | Player1 i -> fmt "b" i 30 | | Player1x i -> fmt "c" i 31 | 32 | let successors = function 33 | | Player0 i -> [if i = !n then Player0 0 else Player1 i] 34 | | Player1 i -> [Player1x i; Player0 (i + 1)] 35 | | Player1x i -> [Player0 (i + 1)] 36 | 37 | let initnodes _ = [ Player0 0 ] 38 | end);; 39 | 40 | 41 | let generator_game_func arguments = 42 | 43 | let show_help _ = 44 | print_string (Info.get_title "Modelchecker Ladder Game Generator"); 45 | print_string ("Usage: modelcheckerladder n\n\n" ^ 46 | " where n = n-th model checker ladder game\n\n") 47 | in 48 | 49 | if (Array.length arguments != 1) then (show_help (); exit 1); 50 | 51 | n := int_of_string arguments.(0); 52 | 53 | ModelcheckerLadderGame.build () ;; 54 | 55 | 56 | let register _ = Generatorregistry.register_generator generator_game_func "modelcheckerladder" "Model Checker Ladder";; 57 | -------------------------------------------------------------------------------- /src/generators/modelcheckerladder.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/modelcheckerladder_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "modelcheckerladder";; 2 | -------------------------------------------------------------------------------- /src/generators/modelchecking/elevators.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/modelchecking/elevators_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "elevatorvergm";; 2 | -------------------------------------------------------------------------------- /src/generators/modelchecking/mucalculus.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | type ('p,'a) mucalc = Prop of 'p 4 | | Var of string 5 | | Neg of ('p,'a) mucalc 6 | | Imp of ('p,'a) mucalc * ('p,'a) mucalc 7 | | Conj of ('p,'a) mucalc list 8 | | Disj of ('p,'a) mucalc list 9 | | Diam of 'a option * (('p,'a) mucalc) 10 | | Box of 'a option * (('p,'a) mucalc) 11 | | Mu of string * (('p,'a) mucalc) 12 | | Nu of string * (('p,'a) mucalc) 13 | 14 | 15 | module type VerificationProblem = 16 | sig 17 | type state 18 | type proposition 19 | type action 20 | 21 | val actions : unit -> action list 22 | 23 | val initstate : unit -> state 24 | val labels : state -> proposition -> bool 25 | val successors : state -> action -> state list 26 | 27 | val show_state : state -> string 28 | val show_proposition : proposition -> string 29 | val show_action : action -> string 30 | 31 | val property : unit -> (proposition,action) mucalc 32 | end;; 33 | 34 | module Make: functor (T: VerificationProblem) -> PGBuilder 35 | -------------------------------------------------------------------------------- /src/generators/modelchecking/philosophers.ml: -------------------------------------------------------------------------------- 1 | open Tcsset ;; 2 | 3 | let n = ref 5 4 | 5 | module Philosophers = 6 | struct 7 | type proposition = IsHungry of int 8 | | IsEating of int 9 | 10 | type action = PickupRight of int 11 | | PickupLeft of int 12 | | PutdownRight of int 13 | | PutdownLeft of int 14 | 15 | type philosopher = Eating | Thinking | HasLeft | HasRight 16 | type state = philosopher array 17 | 18 | let initstate = Array.init !n (fun i -> Thinking) 19 | 20 | let labeling s = 21 | let t = Treeset.empty_def ref in 22 | Array.iteri (fun i p -> match p with 23 | Hungry -> t := Treeset.add t (isHungry i) 24 | | Eating -> t := Treeset.add t (isEating i) 25 | | _ -> ()) 26 | s; 27 | !t 28 | 29 | let successors s = 30 | let left i = (i-1) mod !n in 31 | let right i = (i+1) mod !n in 32 | let update t j p = (Array.copy t).(j) <- p in 33 | function PickupLeft i -> (let i' = left i in 34 | if s.(i') != HasRight && s.(i') != Eating then 35 | if s.(i) = HasRight then 36 | [ update s i Eating ] 37 | else if s.(i) = Thinking then 38 | [ update s i HasLeft ] 39 | else 40 | [] 41 | else 42 | []) 43 | | PickupRight i -> (let i' = right i in 44 | if s.(i') != HasLeft && s.(i') != Eating then 45 | if s.(i) = HasLeft then 46 | [ update s i Eating ] 47 | else if s.(i) = Thinking then 48 | [ update s i HasRight ] 49 | else 50 | [] 51 | else 52 | []) 53 | | PutdownRight i -> (match s.(i) with 54 | HasRight -> [ update s i Thinking ] 55 | | Eating -> [ update s i HasLeft ] 56 | | _ -> []) 57 | | PutdownLeft i -> (match s.(i) with 58 | HasLeft -> [ update s i Thinking ] 59 | | Eating -> [ update s i HasRight ] 60 | | _ -> []) 61 | 62 | let action_list = 63 | let rec actlst i acc = if i < 0 then acc else actlst (i-1) (PickupLeft i :: PickupRight i :: PutdownLeft i :: PutdownRight i :: acc) 64 | in 65 | actlst (!n-1) [] 66 | 67 | let show_state s = Array.fold_left (fun t -> fun p -> t ^ (match p with Thinking -> "_" 68 | | HasLeft -> "\\" 69 | | HasRight -> "/" 70 | | Eating -> "*")) 71 | "" s 72 | end;; 73 | -------------------------------------------------------------------------------- /src/generators/modelchecking/roadworks.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit 2 | -------------------------------------------------------------------------------- /src/generators/modelchecking/roadworks_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "roadworksvergm";; 2 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/cunninghamexp.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Stratimprgenerators;; 3 | open Mdp;; 4 | open Arg;; 5 | open Tcsargs;; 6 | 7 | let auso_compat = ref false 8 | let index_one = ref false 9 | let bits = ref 0 10 | let mapindex i = string_of_int (if !index_one then i + 1 else i) 11 | 12 | type gamenode = 13 | FinalCycle 14 | | CycleExit of int 15 | | UpperSelector of int 16 | | CycleSelector of int 17 | | CycleCenter of int 18 | | CycleNodePaced of int 19 | | CycleNodeLaned of int 20 | | CycleEntry of int 21 | | PacerNode of int 22 | | PacerEntry of int 23 | | AusoHelper of int 24 | 25 | let symb_to_str = function 26 | | CycleCenter i -> "x" ^ mapindex i 27 | | CycleNodePaced i -> "e" ^ mapindex i 28 | | CycleNodeLaned i -> "d" ^ mapindex i 29 | | PacerNode i -> "c" ^ mapindex i 30 | | CycleExit i -> "y" ^ mapindex i 31 | | CycleEntry i -> "q" ^ mapindex i 32 | | CycleSelector i -> "b" ^ mapindex i 33 | | UpperSelector i -> "a" ^ mapindex i 34 | | FinalCycle -> "t" 35 | | PacerEntry i -> "p" ^ mapindex i 36 | | AusoHelper i -> "z" ^ mapindex i 37 | 38 | let generator_game_func arguments = 39 | 40 | let speclist = [(["-tiefree"], Unit(fun _ -> auso_compat := true), 41 | "\n make game tie-free") ; 42 | (["-indexone"], Unit(fun _ -> index_one := true), 43 | "\n start with index one") ] in 44 | 45 | SimpleArgs.parsearr arguments speclist (fun n -> bits := int_of_string n) ("Options are") SimpleArgs.argprint_help SimpleArgs.argprint_bad; 46 | let n = !bits in 47 | let auso_compat = !auso_compat in 48 | 49 | let pg = SymbolicParityGame.create_new FinalCycle in 50 | 51 | let addnode sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 52 | 53 | if (*auso_compat*) true then ( 54 | let touchnode sy = SymbolicParityGame.touch_node pg sy in 55 | 56 | for i = 0 to n - 1 do 57 | if i > 0 then touchnode (UpperSelector i); 58 | done; 59 | for i = 0 to n - 1 do 60 | if i > 0 then touchnode (CycleSelector i); 61 | done; 62 | for i = 0 to n - 1 do 63 | touchnode (PacerNode i); 64 | done; 65 | for i = 0 to n - 1 do 66 | if i > 0 then touchnode (CycleNodeLaned i); 67 | done; 68 | for i = 0 to n - 1 do 69 | touchnode (CycleNodePaced i); 70 | done; 71 | ); 72 | 73 | addnode FinalCycle 1 plr_Odd [FinalCycle]; 74 | addnode (UpperSelector n) 3 plr_Odd [FinalCycle]; 75 | addnode (PacerEntry 0) 8 plr_Odd [if auso_compat then AusoHelper 0 else PacerNode (n-1)]; 76 | addnode (PacerEntry 1) 3 plr_Odd [PacerEntry 0]; 77 | 78 | for i = 0 to n - 1 do 79 | if auso_compat then addnode (AusoHelper i) 3 plr_Odd [if i = n-1 then PacerNode (n-1) else AusoHelper (i+1)]; 80 | 81 | addnode (CycleExit i) (2 * i + 10) plr_Odd [UpperSelector (i + 1)]; 82 | addnode (CycleEntry i) (2 * i + 9) plr_Odd [CycleCenter i]; 83 | addnode (CycleCenter i) 6 plr_Odd (if i > 0 then [CycleNodePaced i; CycleNodeLaned i; CycleExit i] else [CycleNodePaced i; CycleExit i]); 84 | addnode (CycleCenter (i+n)) 5 plr_Odd [CycleCenter i]; 85 | if i < n - 1 then addnode (UpperSelector (i+1)) 3 plr_Even [UpperSelector (i+2); CycleEntry (i+1)]; 86 | if i < n - 1 then addnode (CycleSelector (i+1)) 3 plr_Even (if i > 0 then [CycleSelector i; CycleEntry i] else [CycleEntry 0]); 87 | addnode (PacerNode i) 3 plr_Even (if i = 0 then [CycleEntry 0] else [PacerNode (i-1); CycleEntry i]); 88 | addnode (CycleNodePaced i) 5 plr_Even [(if i = 0 then PacerEntry 1 else PacerEntry 0); CycleCenter i]; 89 | if i > 0 then addnode (CycleNodeLaned i) 5 plr_Even [CycleSelector i; CycleCenter (i+n)]; 90 | done; 91 | 92 | SymbolicParityGame.to_paritygame pg;; 93 | 94 | let generator_mdp_func arguments = 95 | let game = generator_game_func arguments in 96 | parity_game_to_generalized_mdp game 8 (fun _ j -> pg_get_priority game j >= 8);; 97 | 98 | let register _ = 99 | register_strat_impr_gen { 100 | ident = "cunninghamexp"; 101 | description = "Binary-Case Exponential Lower Bound for Cunningham's rule"; 102 | parity_game = Some generator_game_func; 103 | generalized_mdp = Some generator_mdp_func; 104 | } 105 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/cunninghamexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/cunninghamsubexp.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Paritygame;; 5 | open Stratimprgenerators;; 6 | open Mdp;; 7 | 8 | type gamenode = 9 | FinalCycle 10 | | FinalSink 11 | | LowSel 12 | | CycleExit of int 13 | | UpperSelector of int 14 | | CycleSelector of int 15 | | CycleCenter of int 16 | | CycleNode of int * int 17 | | CycleEntry of int 18 | 19 | let symb_to_str = function 20 | | CycleCenter i -> "e" ^ string_of_int i 21 | | CycleNode (i,k) -> "d(" ^ string_of_int i ^ "," ^ string_of_int k ^ ")" 22 | | CycleExit i -> "y" ^ string_of_int i 23 | | CycleEntry i -> "q" ^ string_of_int i 24 | | CycleSelector i -> "u" ^ string_of_int i 25 | | UpperSelector i -> "w" ^ string_of_int i 26 | | FinalSink -> "s" 27 | | FinalCycle -> "t" 28 | | LowSel -> "p" 29 | 30 | let generator_game_func arguments = 31 | 32 | let n = ref None in 33 | let binary = ref false in 34 | SimpleArgs.parsearr arguments 35 | [(["-binary"], Unit (fun _ -> binary := true), "\n binary-case")] 36 | (fun s -> n := Some (int_of_string s)) ("Options are") 37 | SimpleArgs.argprint_help SimpleArgs.argprint_bad; 38 | let n = OptionUtils.get_some !n in 39 | let binary = !binary in 40 | 41 | let pg = SymbolicParityGame.create_new FinalCycle in 42 | 43 | let addnode sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 44 | 45 | addnode FinalCycle 1 plr_Odd [FinalCycle]; 46 | addnode FinalSink (2 * n + 10) plr_Odd [FinalCycle]; 47 | addnode (UpperSelector n) 3 plr_Even [FinalSink]; 48 | addnode (CycleSelector n) 3 plr_Even [FinalSink]; 49 | addnode LowSel 8 plr_Odd [CycleEntry 0]; 50 | 51 | for i = 0 to n - 1 do 52 | addnode (CycleExit i) (2 * i + 10) plr_Odd [UpperSelector (i + 1)]; 53 | addnode (CycleEntry i) (2 * i + 9) plr_Odd [CycleCenter i]; 54 | addnode (CycleCenter i) 6 plr_Odd [CycleNode (i,0); CycleExit i]; 55 | addnode (UpperSelector i) 3 plr_Even [UpperSelector (i+1); CycleEntry i]; 56 | addnode (CycleSelector i) 3 plr_Even [CycleSelector (i+1); CycleEntry i]; 57 | if binary then 58 | for j = 0 to 2 * i + 1 do 59 | addnode (CycleNode (i,j)) 5 plr_Even [FinalSink; (if j mod 2 = 0 then LowSel else CycleSelector 0); 60 | (if j < 2 * i + 1 then CycleNode (i,j+1) else CycleCenter i)] 61 | done 62 | else 63 | for j = 0 to i do 64 | addnode (CycleNode (i,j)) 5 plr_Even [CycleSelector 0; FinalSink; LowSel; (if j < i then CycleNode (i,j+1) else CycleCenter i)] 65 | done; 66 | done; 67 | 68 | SymbolicParityGame.to_paritygame pg;; 69 | 70 | let generator_mdp_func arguments = 71 | let game = generator_game_func arguments in 72 | parity_game_to_generalized_mdp game 8 (fun _ j -> pg_get_priority game j >= 8);; 73 | 74 | let register _ = 75 | register_strat_impr_gen { 76 | ident = "cunninghamsubexp"; 77 | description = "Binary Subexponential Lower Bound for Cunningham's rule"; 78 | parity_game = Some generator_game_func; 79 | generalized_mdp = Some generator_mdp_func; 80 | } 81 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/cunninghamsubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/fearnleysubexp.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Paritygame;; 5 | open Stratimprgenerators;; 6 | 7 | type gamenode = DecLaneEven of int (*a*) 8 | | DecLaneOdd of int (*t*) 9 | | DecLaneRoot (*c*) 10 | | CycleNode of int * int (*d*) 11 | | CycleCenter of int (*e*) 12 | | CycleCenterBadEntry of int (*m*) 13 | | CycleCenterBadEntryX of int (*q*) 14 | | CycleNodeCho of int * int (*u*) 15 | | CycleBadEntrySel of int * int (*v*) 16 | | CycleBadEntrySelX of int * int (*w*) 17 | | CycleAccess of int (*f*) 18 | | CycleSelector of int (*g*) 19 | | CycleLeaver of int (*h*) 20 | | UpperSelector of int (*k*) 21 | | FinalSink (*z*) 22 | | FinalCycle (*x*) 23 | | BitSelector (*r*) 24 | | StartEven (*s*) 25 | 26 | let symb_to_str = function DecLaneEven i -> "a" ^ string_of_int i | DecLaneOdd i -> "t" ^ string_of_int i | DecLaneRoot -> "c" | CycleNode (i,j) -> "d(" ^ string_of_int i ^ "," ^ string_of_int j ^ ")" | CycleCenter i -> "e" ^ string_of_int i | CycleCenterBadEntry i -> "m" ^ string_of_int i | CycleCenterBadEntryX i -> "q" ^ string_of_int i | CycleNodeCho (i,j) -> "u(" ^ string_of_int i ^ "," ^ string_of_int j ^ ")" | CycleBadEntrySel (i,j) -> "v(" ^ string_of_int i ^ "," ^ string_of_int j ^ ")" | CycleBadEntrySelX (i,j) -> "w(" ^ string_of_int i ^ "," ^ string_of_int j ^ ")" | CycleAccess i -> "f" ^ string_of_int i | CycleSelector i -> "g" ^ string_of_int i | CycleLeaver i -> "h" ^ string_of_int i | UpperSelector i -> "k" ^ string_of_int i | FinalSink -> "z" | FinalCycle -> "x" | StartEven -> "s" | BitSelector -> "r" 27 | 28 | let mkli n f = (Array.to_list (Array.init n f)) 29 | 30 | 31 | let generator_game_func arguments = 32 | 33 | let n = ref None in 34 | let withfearnley = ref true in 35 | SimpleArgs.parsearr arguments 36 | [(["-nogadget"], Unit (fun _ -> withfearnley := false), "\n disable fearnley gadgets")] 37 | (fun s -> n := Some (int_of_string s)) ("Options are") 38 | SimpleArgs.argprint_help SimpleArgs.argprint_bad; 39 | let n = OptionUtils.get_some !n in 40 | let withfearnley = !withfearnley in 41 | 42 | let pg = SymbolicParityGame.create_new FinalCycle in 43 | 44 | let add sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 45 | 46 | add FinalCycle 1 plr_Odd [FinalCycle]; 47 | add StartEven (10 * n + 6) plr_Even ( (FinalSink::(mkli n (fun j -> CycleAccess j)))); 48 | add DecLaneRoot (10 * n + 4) plr_Even [StartEven; BitSelector]; 49 | add BitSelector (10 * n + 8) plr_Even ( (FinalSink::(mkli n (fun j -> CycleSelector j)))); 50 | add FinalSink (18 * n + 10) plr_Odd [FinalCycle]; 51 | 52 | for i = 0 to 3 * n - 1 do 53 | add (DecLaneEven i) (4 * n + 2 * i + 4) plr_Odd [DecLaneOdd i]; 54 | add (DecLaneOdd i) (4 * n + 2 * i + 3) plr_Even (if i = 0 then [DecLaneRoot; BitSelector; StartEven] else [DecLaneOdd (i - 1); BitSelector; StartEven]) 55 | done; 56 | 57 | for i = 0 to n - 1 do 58 | if withfearnley then ( 59 | for j = i + 1 to n - 1 do 60 | add (CycleNodeCho (i,j)) 3 plr_Even [CycleBadEntrySel (i,j); CycleBadEntrySelX (i,j)]; 61 | add (CycleBadEntrySel (i,j)) 3 plr_Odd [CycleCenterBadEntry j; (if j = i+1 then CycleCenter i else CycleNodeCho (i,j-1))]; 62 | add (CycleBadEntrySelX (i,j)) 2 plr_Odd [CycleCenterBadEntryX j; (if j = i+1 then CycleCenter i else CycleNodeCho (i,j-1))]; 63 | done; 64 | ); 65 | add (CycleNode (i,1)) (4 * i + 3) plr_Even ( ([StartEven; CycleNode (i,0)] @ (mkli (3 * i + 3) (fun j -> DecLaneEven j)) @ [BitSelector])); 66 | add (CycleNode (i,0)) (4 * i + 3) plr_Even ( ([StartEven; (if (i = n-1) || not withfearnley then CycleCenter i else CycleNodeCho (i,n-1))] @ (mkli (3 * i + 3) (fun j -> DecLaneEven j)) @ [BitSelector])); 67 | add (CycleCenter i) (4 * i + 4) plr_Odd [CycleNode (i,1); CycleLeaver i]; 68 | if withfearnley then ( 69 | add (CycleCenterBadEntry i) (10 * n + 9 + 2 * i) plr_Odd [CycleCenter i]; 70 | add (CycleCenterBadEntryX i) (12 * n + 6 * i + 13) plr_Odd [CycleLeaver i]; 71 | ); 72 | add (CycleLeaver i) (12 * n + 6 * i + 14) plr_Odd [UpperSelector i]; 73 | add (UpperSelector i) (12 * n + 6 * i + 9) plr_Even ((FinalSink::(mkli (n - i - 1) (fun j -> CycleSelector (n - j - 1))))); 74 | add (CycleAccess i) (12 * n + 6 * i + 11) plr_Odd [CycleCenter i]; 75 | add (CycleSelector i) (4 * i + 6) plr_Even [CycleAccess i; UpperSelector i]; 76 | done; 77 | 78 | SymbolicParityGame.to_paritygame pg;; 79 | 80 | let register _ = 81 | register_strat_impr_gen { 82 | ident = "fearnleysubexp"; 83 | description = "Subexponential Lower Bound for Fearnley's rule"; 84 | parity_game = Some generator_game_func; 85 | generalized_mdp = None; 86 | } 87 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/fearnleysubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/friedmannsubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/randomedgeexptest.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/randomedgesubexp.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Stratimprgenerators;; 3 | 4 | type gamenode = 5 | FinalCycle 6 | | FinalSink 7 | | CycleExit of int 8 | | UpperSelector of int 9 | | CycleSelector of int 10 | | CycleCenter of int 11 | | CycleNode of int * int 12 | | IntermediateNode of int * int 13 | | CycleEntry of int 14 | | AccessCenter of int 15 | | AccessNode of int * int 16 | | AccessExit of int 17 | | UpperRoot 18 | | SelectorRoot 19 | 20 | let symb_to_str = function 21 | | CycleCenter i -> "e" ^ string_of_int i 22 | | CycleNode (i,k) -> "d(" ^ string_of_int i ^ "," ^ string_of_int 0 ^ "," ^ string_of_int k ^ ")" 23 | | IntermediateNode (i,k) -> "d(" ^ string_of_int i ^ "," ^ string_of_int 1 ^ "," ^ string_of_int k ^ ")" 24 | | _ -> "" 25 | 26 | let mkli n f = if n < 1 then [] else (Array.to_list (Array.init n f)) 27 | 28 | let mkli2 i n f = mkli (n - i) (fun j -> f (i + j)) 29 | 30 | let mkli_wo n i f = mkli (n - 1) (fun j -> if j < i then f j else f (i + 1)) 31 | 32 | let binlog n = int_of_float (ceil ((log (float_of_int n)) /. (log 2.))) 33 | 34 | let with_strategy = false 35 | 36 | let generator_game_func arguments = 37 | 38 | if (Array.length arguments != 1) then (failwith "specify index of game"); 39 | let n = int_of_string arguments.(0) in 40 | 41 | let access_cycle = 2 * n in 42 | let intermediate_cycle = 4 * n in 43 | 44 | let counting_cycle i = (i + 2) * n * 4 in 45 | 46 | let pg = SymbolicParityGame.create_new FinalCycle in 47 | 48 | let addnodenormal sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 49 | 50 | let addnodestrat sy pr pl li strat = 51 | SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy ^ "[" ^ symb_to_str strat ^ "]")) in 52 | 53 | let addnode sy pr pl li strat = 54 | if with_strategy 55 | then addnodestrat sy pr pl li strat 56 | else addnodenormal sy pr pl li 57 | in 58 | 59 | addnodenormal FinalCycle 1 plr_Odd [FinalCycle]; 60 | addnodenormal FinalSink (4 * n + 10) plr_Odd [FinalCycle]; 61 | addnode (UpperSelector n) 3 plr_Even [FinalSink] FinalSink; 62 | addnode (CycleSelector n) 3 plr_Even [FinalSink] FinalSink; 63 | addnodenormal UpperRoot 8 plr_Odd [UpperSelector 0]; 64 | addnodenormal SelectorRoot 3 plr_Odd [CycleSelector 0]; 65 | 66 | for i = 0 to n - 1 do 67 | addnodenormal (CycleExit i) (4 * i + 12) plr_Odd [UpperSelector (i + 1)]; 68 | addnodenormal (AccessExit i) (4 * i + 9) plr_Odd [SelectorRoot]; 69 | addnodenormal (CycleEntry i) (4 * i + 11) plr_Odd [CycleCenter i]; 70 | addnodenormal (AccessCenter i) 6 plr_Odd [CycleEntry i; AccessNode (i,0)]; 71 | addnodenormal (CycleCenter i) 6 plr_Odd [CycleNode (i,0); (*IntermediateNode (i,0);*) CycleExit i]; 72 | addnode (UpperSelector i) 3 plr_Even [UpperSelector (i+1); FinalSink; AccessCenter i] FinalSink; 73 | addnode (CycleSelector i) 3 plr_Even [CycleSelector (i+1); FinalSink; CycleEntry i] FinalSink; 74 | for j = 0 to counting_cycle i - 1 do 75 | addnode (CycleNode (i,j)) 5 plr_Even [SelectorRoot; FinalSink; (if j < counting_cycle i - 1 then CycleNode (i,j+1) else IntermediateNode (i,0) (*CycleCenter i*))] FinalSink 76 | done; 77 | for j = 0 to intermediate_cycle - 1 do 78 | addnode (IntermediateNode (i,j)) 5 plr_Even [UpperRoot; FinalSink; (if j < intermediate_cycle - 1 then IntermediateNode (i,j+1) else CycleCenter i)] FinalSink 79 | done; 80 | for j = 0 to access_cycle - 1 do 81 | addnode (AccessNode (i,j)) 5 plr_Even [AccessExit i; FinalSink; (if j < access_cycle - 1 then AccessNode (i,j+1) else AccessCenter i)] FinalSink 82 | done; 83 | done; 84 | 85 | SymbolicParityGame.to_paritygame pg;; 86 | 87 | 88 | let register _ = 89 | register_strat_impr_gen { 90 | ident = "randomedgesubexp"; 91 | description = "Subexponential Lower Bound for the random-edge rule"; 92 | parity_game = Some generator_game_func; 93 | generalized_mdp = None; 94 | } 95 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/randomedgesubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/randomfacetsubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/switchallexp.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Stratimprgenerators;; 3 | 4 | type gamenode = DecLaneEven of int (*a*) 5 | | DecLaneOdd of int (*b*) 6 | | DecLaneOddRoot (*d*) 7 | | CycleNode of int (*e*) 8 | | CycleToLaneEven of int (*f*) 9 | | CycleToLaneOdd of int (*g*) 10 | | CycleCenter of int (*h*) 11 | | CycleAccess of int (*k*) 12 | | CycleSelector of int (*l*) 13 | | CycleSelectorDecelerator of int (*r*) 14 | | CycleLeaver of int (*m*) 15 | | UpperSelector of int (*z*) 16 | | UpperSelectorHelper of int (*v*) 17 | | FinalSink (*p*) 18 | | FinalCycle (*q*) 19 | | StartEven (*s*) 20 | | StartSelector (*t*) 21 | | HighEntryBit (*w*) 22 | | LowestBit (*y*) 23 | | BitSelector (*x*) 24 | 25 | let symb_to_str = function DecLaneEven i ->"a" ^ string_of_int i | DecLaneOdd i ->"b" ^ string_of_int i | DecLaneOddRoot ->"d" | CycleNode i ->"e" ^ string_of_int i | CycleToLaneEven i ->"f" ^ string_of_int i | CycleToLaneOdd i ->"g" ^ string_of_int i | CycleCenter i ->"h" ^ string_of_int i | CycleAccess i ->"k" ^ string_of_int i | CycleSelector i ->"l" ^ string_of_int i | CycleSelectorDecelerator i ->"r" ^ string_of_int i | CycleLeaver i ->"m" ^ string_of_int i | UpperSelector i ->"z" ^ string_of_int i | UpperSelectorHelper i -> "v" ^ string_of_int i | FinalSink ->"p" | FinalCycle ->"q" | StartEven ->"s" | StartSelector ->"t" | HighEntryBit ->"w" | LowestBit ->"y" | BitSelector ->"x" 26 | 27 | let mkli n f = (Array.to_list (Array.init n f)) 28 | 29 | 30 | let generator_game_func arguments = 31 | 32 | if (Array.length arguments != 1) then (failwith "specify index of game"); 33 | let n = int_of_string arguments.(0) in 34 | 35 | let pg = SymbolicParityGame.create_new FinalCycle in 36 | 37 | let add sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 38 | 39 | add FinalCycle 1 plr_Odd [FinalCycle]; 40 | add StartEven 2 plr_Even (FinalSink::(mkli n (fun j -> CycleAccess j))); 41 | add StartSelector 3 plr_Even [BitSelector; StartEven]; 42 | add LowestBit 5 plr_Even [HighEntryBit; CycleSelector 0]; 43 | add HighEntryBit 7 plr_Even (LowestBit::FinalSink::(mkli (n - 1) (fun j -> CycleSelector (j + 1)))); (***) 44 | add DecLaneOddRoot (12 * n + 8) plr_Even [StartSelector; BitSelector]; 45 | add BitSelector (12 * n + 10) plr_Even [HighEntryBit; LowestBit]; 46 | add FinalSink (16 * n + 12) plr_Odd [FinalCycle]; 47 | 48 | for i = 0 to 2 * n - 1 do 49 | add (DecLaneEven i) (8 * n + 2 * i + 8) plr_Odd [DecLaneOdd i]; 50 | add (DecLaneOdd i) (8 * n + 2 * i + 7) plr_Even [(if i < 2 then DecLaneOddRoot else DecLaneOdd (i - 1)); BitSelector; StartEven] 51 | done; 52 | 53 | for i = 0 to n - 1 do 54 | add (CycleNode i) (6 * n + 2 * i + 7) plr_Even [DecLaneEven 0; BitSelector; StartEven; CycleCenter i; CycleToLaneEven i; CycleToLaneOdd i]; (***) 55 | add (CycleToLaneEven i) (6 * i + 8) plr_Even ((if i = 0 then [] else [CycleToLaneEven (i-1)]) @ [DecLaneOddRoot; DecLaneEven (2 * i)]); (***) 56 | add (CycleToLaneOdd i) (6 * i + 10) plr_Even ((if i = 0 then [] else [CycleToLaneOdd (i-1)]) @ [DecLaneOddRoot; DecLaneEven (2 * i + 1)]); (***) 57 | add (CycleCenter i) (6 * n + 2 * i + 8) plr_Odd [CycleNode i; CycleLeaver i]; 58 | add (CycleLeaver i) (12 * n + 4 * i + 14) plr_Odd [UpperSelector i]; 59 | add (UpperSelector i) (12 * n + 4 * i + 11) plr_Even (if i = n - 1 then [FinalSink] else [FinalSink; UpperSelectorHelper i]); 60 | add (CycleAccess i) (12 * n + 4 * i + 13) plr_Odd [CycleCenter i]; 61 | add (CycleSelector i) (6 * i + 11) plr_Even [CycleAccess i; UpperSelector i]; 62 | add (CycleSelectorDecelerator i) (6 * i + 12) plr_Even [CycleSelector i; UpperSelector i]; 63 | if i < n - 1 then add (UpperSelectorHelper i) (6 * i + 9) plr_Even (if i = n - 2 then [FinalSink; CycleSelectorDecelerator (n - 1)] else [UpperSelectorHelper (i+1); CycleSelectorDecelerator (i + 1)]) 64 | done; 65 | 66 | SymbolicParityGame.to_paritygame pg;; 67 | 68 | 69 | let register _ = 70 | register_strat_impr_gen { 71 | ident = "switchallexp"; 72 | description = "Exponential Lower Bound for (Voege's) switch-all rule"; 73 | parity_game = Some generator_game_func; 74 | generalized_mdp = None; 75 | } 76 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/switchallexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/switchallsubexp.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Paritygame;; 5 | open Stratimprgenerators;; 6 | 7 | type gamenode = DecLaneEven of int (*a*) 8 | | DecLaneOdd of int (*b*) 9 | | DecLaneRoot (*c*) 10 | | CycleNode of int (*d*) 11 | | CycleCenter of int (*e*) 12 | | CycleAccess of int (*f*) 13 | | CycleSelector of int (*g*) 14 | | CycleLeaver of int (*h*) 15 | | UpperSelector of int (*k*) 16 | | FinalSink (*p*) 17 | | FinalCycle (*q*) 18 | | BitSelector (*r*) 19 | | StartEven (*s*) 20 | | Helper of int 21 | 22 | let symb_to_str = function DecLaneEven i -> "a" ^ string_of_int i | DecLaneOdd i -> "b" ^ string_of_int i | DecLaneRoot -> "c" | CycleNode i -> "d" ^ string_of_int i | CycleCenter i -> "e" ^ string_of_int i | CycleAccess i -> "f" ^ string_of_int i | CycleSelector i -> "g" ^ string_of_int i | CycleLeaver i -> "h" ^ string_of_int i | UpperSelector i -> "k" ^ string_of_int i | FinalSink -> "p" | FinalCycle -> "q" | StartEven -> "s" | BitSelector -> "r" | Helper i -> "h" ^ string_of_int i 23 | 24 | let mkli n f = (Array.to_list (Array.init n f)) 25 | 26 | 27 | let generator_game_func arguments = 28 | 29 | let n = ref None in 30 | let od2 = ref false in 31 | SimpleArgs.parsearr arguments 32 | [(["-binary"], Unit (fun _ -> od2 := true), "\n binary-case")] 33 | (fun s -> n := Some (int_of_string s)) ("Options are") 34 | SimpleArgs.argprint_help SimpleArgs.argprint_bad; 35 | let n = OptionUtils.get_some !n in 36 | let od2 = !od2 in 37 | 38 | 39 | let helpercnt = ref 0 in 40 | 41 | let pg = SymbolicParityGame.create_new FinalCycle in 42 | 43 | let add sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 44 | 45 | let rec left_exp = function [] -> failwith "imp" | [a] -> a 46 | | a::b::r -> incr helpercnt; add (Helper !helpercnt) 0 plr_Even [a; b]; left_exp ((Helper !helpercnt)::r) 47 | in 48 | 49 | let left_exp' l = 50 | if List.length l <= 2 then l 51 | else let r = List.rev l in 52 | let (h, t) = (List.hd r, List.rev (List.tl r)) in 53 | [left_exp t; h] 54 | in 55 | 56 | let lexp l = if od2 then left_exp' l else l in 57 | 58 | add FinalCycle 1 plr_Odd [FinalCycle]; 59 | add StartEven (8 * n + 6) plr_Even (lexp (FinalSink::(mkli n (fun j -> CycleAccess j)))); 60 | add DecLaneRoot (8 * n + 4) plr_Even [StartEven; BitSelector]; 61 | add BitSelector (8 * n + 8) plr_Even (lexp (FinalSink::(mkli n (fun j -> CycleSelector j)))); 62 | add FinalSink (12 * n + 10) plr_Odd [FinalCycle]; 63 | 64 | for i = 0 to 2 * n - 1 do 65 | add (DecLaneEven i) (4 * n + 2 * i + 4) plr_Odd [DecLaneOdd i]; 66 | add (DecLaneOdd i) (4 * n + 2 * i + 3) plr_Even (if i = 0 then lexp [DecLaneRoot; BitSelector; StartEven] else lexp [DecLaneOdd (i - 1); BitSelector; StartEven]) 67 | done; 68 | 69 | for i = 0 to n - 1 do 70 | add (CycleNode i) (4 * i + 3) plr_Even (lexp ([StartEven; CycleCenter i] @ (mkli (2 * i + 2) (fun j -> DecLaneEven j)) @ [BitSelector])); 71 | add (CycleCenter i) (4 * i + 4) plr_Odd [CycleNode i; CycleLeaver i]; 72 | add (CycleLeaver i) (8 * n + 4 * i + 12) plr_Odd [UpperSelector i]; 73 | add (UpperSelector i) (8 * n + 4 * i + 9) plr_Even (lexp (FinalSink::(mkli (n - i - 1) (fun j -> CycleSelector (n - j - 1))))); 74 | add (CycleAccess i) (8 * n + 4 * i + 11) plr_Odd [CycleCenter i]; 75 | add (CycleSelector i) (4 * i + 6) plr_Even [CycleAccess i; UpperSelector i]; 76 | done; 77 | 78 | SymbolicParityGame.to_paritygame pg;; 79 | 80 | 81 | let register _ = 82 | register_strat_impr_gen { 83 | ident = "switchallsubexp"; 84 | description = "Binary-Case Subexponential Lower Bound for (Voege's) switch-all rule"; 85 | parity_game = Some generator_game_func; 86 | generalized_mdp = None; 87 | } 88 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/switchallsubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/switchbestexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/switchbestsubexp.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Paritygame;; 5 | open Stratimprgenerators;; 6 | 7 | 8 | type gamenode = DecLaneEven of int (*a*) 9 | | DecLaneOdd of int (*b*) 10 | | DecLaneRoot (*c*) 11 | | CycleNode0 of int (*e*) 12 | | CycleNode1 of int (*f*) 13 | | CycleNode2 of int (*g*) 14 | | CycleCenter of int (*h*) 15 | | CycleAccess of int (*k*) 16 | | CycleSelector of int (*l*) 17 | | CycleSelectorX of int (*y*) 18 | | CycleLeaver of int (*m*) 19 | | UpperSelector of int (*z*) 20 | | FinalSink (*p*) 21 | | FinalCycle (*q*) 22 | | StartEven (*s*) 23 | | BitSelector (*u*) 24 | | Helper of int 25 | 26 | let symb_to_str = function DecLaneEven i ->"a" ^ string_of_int i | DecLaneOdd i ->"b" ^ string_of_int i | DecLaneRoot ->"c" | CycleNode0 i ->"e" ^ string_of_int i | CycleNode1 i ->"f" ^ string_of_int i | CycleNode2 i ->"g" ^ string_of_int i | CycleCenter i ->"h" ^ string_of_int i | CycleAccess i ->"k" ^ string_of_int i | CycleSelector i ->"l" ^ string_of_int i | CycleSelectorX i ->"y" ^ string_of_int i | CycleLeaver i ->"m" ^ string_of_int i | UpperSelector i ->"z" ^ string_of_int i | FinalSink ->"p" | FinalCycle ->"q" | StartEven ->"s" | BitSelector ->"u" | Helper i ->"h" ^ string_of_int i 27 | 28 | let mkli n f = (Array.to_list (Array.init n f)) 29 | 30 | 31 | let generator_game_func arguments = 32 | 33 | let n = ref None in 34 | let od2 = ref false in 35 | SimpleArgs.parsearr arguments 36 | [(["-binary"], Unit (fun _ -> od2 := true), "\n binary-case")] 37 | (fun s -> n := Some (int_of_string s)) ("Options are") 38 | SimpleArgs.argprint_help SimpleArgs.argprint_bad; 39 | let n = OptionUtils.get_some !n in 40 | let od2 = !od2 in 41 | 42 | 43 | let helpercnt = ref 0 in 44 | 45 | let pg = SymbolicParityGame.create_new FinalCycle in 46 | 47 | let add sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 48 | 49 | let rec left_exp = function [] -> failwith "imp" | [a] -> a 50 | | a::b::r -> incr helpercnt; add (Helper !helpercnt) 0 plr_Even [a; b]; left_exp ((Helper !helpercnt)::r) 51 | in 52 | 53 | let left_exp' l = 54 | if List.length l <= 2 then l 55 | else let r = List.rev l in 56 | let (h, t) = (List.hd r, List.rev (List.tl r)) in 57 | [left_exp t; h] 58 | in 59 | 60 | let lexp l = if od2 then left_exp' l else l in 61 | 62 | add FinalCycle 1 plr_Odd [FinalCycle]; 63 | 64 | add DecLaneRoot (20 * n) plr_Odd [BitSelector]; 65 | add StartEven (20 * n + 2) plr_Even (lexp (FinalSink::(mkli n (fun j -> CycleAccess j)))); 66 | add BitSelector (20 * n + 4) plr_Even (lexp (FinalSink::(mkli n (fun j -> CycleSelectorX j)))); 67 | 68 | add FinalSink (24 * n + 6) plr_Odd [FinalCycle]; 69 | 70 | for i = 0 to 6 * n - 3 do 71 | add (DecLaneEven i) (8 * n + 4 + 2 * i) plr_Odd [DecLaneOdd i]; 72 | add (DecLaneOdd i) (8 * n + 3 + 2 * i) plr_Even (lexp [(if i = 0 then DecLaneRoot else DecLaneOdd (i - 1)); BitSelector; StartEven]) 73 | done; 74 | 75 | for i = 0 to n - 1 do 76 | add (CycleNode0 i) (i * 8 + 3) plr_Even (lexp (([StartEven; CycleNode1 i; DecLaneRoot] @ (mkli (2 * i + 1) (fun j -> DecLaneEven (3 * j + 2)))))); 77 | add (CycleNode1 i) (i * 8 + 5) plr_Even (lexp (((CycleNode2 i)::(mkli (2 * i + 1) (fun j -> DecLaneEven (3 * j + 1)))))); 78 | add (CycleNode2 i) (i * 8 + 7) plr_Even (lexp (((CycleCenter i)::(mkli (2 * i + 2) (fun j -> DecLaneEven (3 * j)))))); 79 | add (CycleCenter i) (i * 8 + 8) plr_Odd [CycleNode0 i; CycleLeaver i]; 80 | add (CycleSelector i) (i * 8 + 9) plr_Even [CycleAccess i; UpperSelector i]; 81 | add (CycleSelectorX i) (i * 8 + 10) plr_Even [CycleSelector i; UpperSelector i]; 82 | add (UpperSelector i) (20 * n + 5 + 4 * i) plr_Even (lexp (FinalSink::(mkli (n - i - 1) (fun j -> CycleSelectorX (n - j - 1))))); 83 | add (CycleAccess i) (20 * n + 7 + 4 * i) plr_Odd [CycleCenter i]; 84 | add (CycleLeaver i) (20 * n + 8 + 4 * i) plr_Odd [UpperSelector i]; 85 | done; 86 | 87 | SymbolicParityGame.to_paritygame pg;; 88 | 89 | let register _ = 90 | register_strat_impr_gen { 91 | ident = "switchbestsubexp"; 92 | description = "Binary-Case Subexponential Lower Bound for (Schewe's) switch-best rule"; 93 | parity_game = Some generator_game_func; 94 | generalized_mdp = None; 95 | } 96 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/switchbestsubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/zadehexp.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Stratimprgenerators;; 3 | open Mdp;; 4 | 5 | type gamenode = 6 | FinalCycle (*Z*) (*t*) 7 | | FinalSink (*Y*) (*-*) 8 | | PairSelector of int (*d*) (*k*) 9 | | CycleCenter1 of int (*E*) (*A*) 10 | | CycleCenter2 of int (*E'*) (*A'*) 11 | | CycleNodeX1 of int (*a*) (*b*) 12 | | CycleNodeX2 of int (*a'*) (*b'*) 13 | | CycleNodeY1 of int (*b*) (*c*) 14 | | CycleNodeY2 of int (*b'*) (*c'*) 15 | | CycleNodeX1T of int (*a*) (*b*) 16 | | CycleNodeX2T of int (*a'*) (*b'*) 17 | | CycleNodeY1T of int (*b*) (*c*) 18 | | CycleNodeY2T of int (*b'*) (*c'*) 19 | | UpDown1 of int (*g*) (*d*) 20 | | UpDown2 of int (*g'*) (*d'*) 21 | | UpperSelector1 of int (*c*) (*h*) 22 | | UpperSelector2 of int (*c'*) (*h'*) 23 | | Selector of int (*f*) (*s*) 24 | | Helper of int 25 | 26 | 27 | 28 | let symb_to_str = function 29 | FinalCycle -> "Z" 30 | | FinalSink -> "Y" 31 | | PairSelector i -> "d" ^ string_of_int i 32 | | CycleCenter1 i -> "E" ^ string_of_int i 33 | | CycleCenter2 i -> "X" ^ string_of_int i 34 | | CycleNodeX1 i -> "a" ^ string_of_int i 35 | | CycleNodeX2 i -> "w" ^ string_of_int i 36 | | CycleNodeY1 i -> "b" ^ string_of_int i 37 | | CycleNodeY2 i -> "v" ^ string_of_int i 38 | | CycleNodeX1T i -> "o" ^ string_of_int i 39 | | CycleNodeX2T i -> "q" ^ string_of_int i 40 | | CycleNodeY1T i -> "p" ^ string_of_int i 41 | | CycleNodeY2T i -> "r" ^ string_of_int i 42 | | UpperSelector1 i -> "c" ^ string_of_int i 43 | | UpperSelector2 i -> "z" ^ string_of_int i 44 | | Selector i -> "m" ^ string_of_int i 45 | | UpDown1 i -> "g" ^ string_of_int i 46 | | UpDown2 i -> "s" ^ string_of_int i 47 | | Helper i -> "u" ^ string_of_int i 48 | 49 | 50 | let generator_game_func arguments = 51 | 52 | if (Array.length arguments != 1) then (failwith "specify index of game"); 53 | let n = int_of_string arguments.(0) in 54 | 55 | let pg = SymbolicParityGame.create_new FinalCycle in 56 | 57 | let add sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 58 | 59 | let add1 sy pr li = add sy pr plr_Odd li in 60 | 61 | let add0 sy pr li = add sy pr plr_Even li in 62 | 63 | add1 FinalCycle 1 [FinalCycle]; 64 | add1 FinalSink (2 * n + 12) [FinalCycle]; 65 | (* add1 (PairSelector n) (2 * n + 11) [FinalSink];*) 66 | 67 | for i = 0 to n - 1 do 68 | add0 (CycleNodeX1 i) 3 [CycleCenter1 i; CycleNodeX1T i]; 69 | add0 (CycleNodeX1T i) 3 [PairSelector 0; Selector 1]; 70 | if i < n-1 then add0 (CycleNodeX2 i) 3 [CycleCenter2 i;CycleNodeX2T i]; 71 | if i < n-1 then add0 (CycleNodeX2T i) 3 [PairSelector 0;Selector 1]; 72 | add0 (CycleNodeY1 i) 3 [CycleCenter1 i; CycleNodeY1T i]; 73 | add0 (CycleNodeY1T i) 3 [PairSelector 0; Selector 1]; 74 | if i < n-1 then add0 (CycleNodeY2 i) 3 [CycleCenter2 i; CycleNodeY2T i]; 75 | if i < n-1 then add0 (CycleNodeY2T i) 3 [PairSelector 0; Selector 1]; 76 | 77 | add0 (PairSelector i) (2 * i + 11) (if i < n-1 then [CycleCenter1 i; CycleCenter2 i] else [CycleCenter1 i]); 78 | add0 (Selector i) 3 [PairSelector i; (if i < n - 1 then Selector (i+1) else FinalSink)]; 79 | add1 (CycleCenter1 i) 6 [CycleNodeX1 i; CycleNodeY1 i; UpDown1 i]; 80 | if i < n-1 then add1 (CycleCenter2 i) 4 [CycleNodeX2 i; CycleNodeY2 i; UpDown2 i]; 81 | add0 (UpDown1 i) 10 [UpperSelector1 i; Selector 0]; 82 | if i < n-1 then add0 (UpDown2 i) 8 [Helper i; Selector 0]; 83 | add0 (UpperSelector1 i) (2 * i + 12) [if i < n - 2 then Selector (i+2) else FinalSink]; 84 | if i < n-1 then ( 85 | add1 (Helper i) 5 [UpperSelector2 i]; 86 | add0 (UpperSelector2 i) (2 * i + 12) [PairSelector (i+1)]; 87 | ); 88 | done; 89 | 90 | SymbolicParityGame.to_paritygame pg;; 91 | 92 | 93 | let generator_mdp_func arguments = 94 | let game = generator_game_func arguments in 95 | parity_game_to_generalized_mdp game 8 (fun _ j -> pg_get_priority game j >= 8);; 96 | 97 | let register _ = 98 | register_strat_impr_gen { 99 | ident = "zadehexp"; 100 | description = "Exponential Lower Bound for Zadeh's rule"; 101 | parity_game = Some generator_game_func; 102 | generalized_mdp = Some generator_mdp_func; 103 | } 104 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/zadehexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/generators/zadehsubexp.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Stratimprgenerators;; 3 | open Mdp;; 4 | 5 | type gamenode = 6 | FinalCycle (*Z*) (*t*) 7 | | FinalSink (*Y*) (*-*) 8 | | PairSelector of int (*d*) (*k*) 9 | | CycleEntry1 of int (*h*) 10 | | CycleEntry2 of int (*h'*) 11 | | CycleCenter1 of int (*E*) (*A*) 12 | | CycleCenter2 of int (*E'*) (*A'*) 13 | | CycleNodeX1 of int (*a*) (*b*) 14 | | CycleNodeX2 of int (*a'*) (*b'*) 15 | | CycleNodeY1 of int (*b*) (*c*) 16 | | CycleNodeY2 of int (*b'*) (*c'*) 17 | | UpDown1 of int (*g*) (*d*) 18 | | UpDown2 of int (*g'*) (*d'*) 19 | | UpperSelector1 of int (*c*) (*h*) 20 | | UpperSelector2 of int (*c'*) (*h'*) 21 | | Selector (*f*) (*s*) 22 | 23 | 24 | 25 | let symb_to_str = function 26 | FinalCycle -> "Z" 27 | | FinalSink -> "Y" 28 | | PairSelector i -> "d" ^ string_of_int i 29 | | CycleEntry1 i -> "h" ^ string_of_int i 30 | | CycleEntry2 i -> "k" ^ string_of_int i 31 | | CycleCenter1 i -> "E" ^ string_of_int i 32 | | CycleCenter2 i -> "X" ^ string_of_int i 33 | | CycleNodeX1 i -> "a" ^ string_of_int i 34 | | CycleNodeX2 i -> "w" ^ string_of_int i 35 | | CycleNodeY1 i -> "b" ^ string_of_int i 36 | | CycleNodeY2 i -> "v" ^ string_of_int i 37 | | UpperSelector1 i -> "c" ^ string_of_int i 38 | | UpperSelector2 i -> "u" ^ string_of_int i 39 | | Selector -> "f" 40 | | UpDown1 i -> "g" ^ string_of_int i 41 | | UpDown2 i -> "s" ^ string_of_int i 42 | 43 | let mkli n f = if n < 1 then [] else (Array.to_list (Array.init n f)) 44 | 45 | let mkli2 i n f = mkli (n - i) (fun j -> f (i + j)) 46 | 47 | let generator_game_func arguments = 48 | 49 | if (Array.length arguments != 1) then (failwith "specify index of game"); 50 | let n = int_of_string arguments.(0) in 51 | 52 | let pg = SymbolicParityGame.create_new FinalCycle in 53 | 54 | let add sy pr pl li = SymbolicParityGame.add_node pg sy pr pl (Array.of_list li) (Some (symb_to_str sy)) in 55 | 56 | let add1 sy pr li = add sy pr plr_Odd li in 57 | 58 | let add0 sy pr li = add sy pr plr_Even li in 59 | 60 | add1 FinalCycle 1 [FinalCycle]; 61 | add1 FinalSink (2 * n + 14) [FinalCycle]; 62 | add0 Selector 3 (FinalSink::mkli n (fun j -> PairSelector j)); 63 | add1 (PairSelector n) (2 * n + 13) [FinalSink]; 64 | 65 | for i = 0 to n - 1 do 66 | add0 (PairSelector i) (2 * i + 13) (FinalSink::CycleCenter1 i::CycleCenter2 i::mkli n (fun j -> PairSelector j)); 67 | add1 (CycleEntry1 i) 11 [CycleCenter1 i]; 68 | add1 (CycleEntry2 i) 11 [CycleCenter2 i]; 69 | add1 (CycleCenter1 i) 6 [CycleNodeX1 i; CycleNodeY1 i; UpDown1 i]; 70 | add1 (CycleCenter2 i) 4 [CycleNodeX2 i; CycleNodeY2 i; UpDown2 i]; 71 | add0 (CycleNodeX1 i) 3 (FinalSink::CycleCenter1 i::mkli n (fun j -> PairSelector j)); 72 | add0 (CycleNodeX2 i) 3 (FinalSink::CycleCenter2 i::mkli n (fun j -> PairSelector j)); 73 | add0 (CycleNodeY1 i) 3 (FinalSink::CycleCenter1 i::mkli n (fun j -> PairSelector j)); 74 | add0 (CycleNodeY2 i) 3 (FinalSink::CycleCenter2 i::mkli n (fun j -> PairSelector j)); 75 | add0 (UpDown1 i) 10 [UpperSelector1 i; Selector]; 76 | add0 (UpDown2 i) 8 [UpperSelector2 i; Selector]; 77 | add0 (UpperSelector1 i) (2 * i + 14) (FinalSink::mkli2 (i+2) n (fun j -> PairSelector j)); 78 | add0 (UpperSelector2 i) (2 * i + 14) [PairSelector (i+1)]; 79 | done; 80 | 81 | SymbolicParityGame.to_paritygame pg;; 82 | 83 | 84 | let generator_mdp_func arguments = 85 | let game = generator_game_func arguments in 86 | parity_game_to_generalized_mdp game 8 (fun _ j -> pg_get_priority game j >= 8);; 87 | 88 | let register _ = 89 | register_strat_impr_gen { 90 | ident = "zadehsubexp"; 91 | description = "Subexponential Lower Bound for Zadeh's rule"; 92 | parity_game = Some generator_game_func; 93 | generalized_mdp = Some generator_mdp_func; 94 | } 95 | -------------------------------------------------------------------------------- /src/generators/policyiter/generators/zadehsubexp.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/policyiter/stratimprgen.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Basics ;; 5 | open Paritygame;; 6 | open Mdp;; 7 | open Tcsstrings ;; 8 | open Stratimprgenerators;; 9 | open Stratimprgenlist;; 10 | 11 | Stratimprgenlist.register();; 12 | 13 | module CommandLine = 14 | struct 15 | 16 | type action = NoAction | GeneratePg of strat_impr_gen | GenerateMdp of strat_impr_gen | GenerateLp of strat_impr_gen | GenerateDualLp of strat_impr_gen 17 | 18 | let action = ref NoAction 19 | let subargs = ref "" 20 | 21 | let genlistpg = fold_strat_impr_gen (fun gen t -> if gen.parity_game = None then t else t ^ " " ^ gen.ident) "" 22 | let genlistmdp = fold_strat_impr_gen (fun gen t -> if gen.generalized_mdp = None then t else t ^ " " ^ gen.ident) "" 23 | 24 | let speclist = [ 25 | (["-pg"], Tuple [String (fun s -> action := GeneratePg (find_strat_impr_gen s)); 26 | String (fun a -> subargs := a)], 27 | " \"\"\n generate parity game, valid ones are:" ^ genlistpg); 28 | (["-mdp"], Tuple [String (fun s -> action := GenerateMdp (find_strat_impr_gen s)); 29 | String (fun a -> subargs := a)], 30 | " \"\"\n generate mdp, valid ones are:" ^ genlistmdp); 31 | (["-lp"], Tuple [String (fun s -> action := GenerateLp (find_strat_impr_gen s)); 32 | String (fun a -> subargs := a)], 33 | " \"\"\n generate primal lp, valid ones are:" ^ genlistmdp); 34 | (["-duallp"], Tuple [String (fun s -> action := GenerateDualLp (find_strat_impr_gen s)); 35 | String (fun a -> subargs := a)], 36 | " \"\"\n generate dual lp, valid ones are:" ^ genlistmdp); 37 | ] 38 | 39 | let header = Info.get_title "Strategy Improvement Generator Tool" 40 | 41 | let usage = "Usage: stratimprgen [-pg | -mdp | -lp | -duallp] \"\"\n" 42 | end ;; 43 | 44 | 45 | open CommandLine ;; 46 | 47 | 48 | let _ = 49 | SimpleArgs.parsedef speclist (fun _ -> failwith "no direct argument expected") (header ^ usage ^ "\nOptions are"); 50 | 51 | match !action with 52 | NoAction -> () 53 | | GeneratePg generator -> 54 | let game = (OptionUtils.get_some (generator.parity_game) (Array.of_list (Tcsstrings.StringUtils.explode !subargs ' '))) in 55 | print_game game 56 | | GenerateMdp generator -> 57 | let generalized_mdp = (OptionUtils.get_some (generator.generalized_mdp) (Array.of_list (Tcsstrings.StringUtils.explode !subargs ' '))) in 58 | print_mdp (generalized_mdp_to_mdp generalized_mdp) 59 | | GenerateLp generator -> 60 | let generalized_mdp = (OptionUtils.get_some (generator.generalized_mdp) (Array.of_list (Tcsstrings.StringUtils.explode !subargs ' '))) in 61 | print_lp (unichain_mdp_to_primal_lp (generalized_mdp_to_mdp generalized_mdp)) 62 | | GenerateDualLp generator -> 63 | let generalized_mdp = (OptionUtils.get_some (generator.generalized_mdp) (Array.of_list (Tcsstrings.StringUtils.explode !subargs ' '))) in 64 | print_lp (unichain_mdp_to_dual_lp (generalized_mdp_to_mdp generalized_mdp)) 65 | -------------------------------------------------------------------------------- /src/generators/policyiter/stratimprgenerators.ml: -------------------------------------------------------------------------------- 1 | open Tcsset 2 | open Paritygame 3 | open Mdp 4 | 5 | 6 | 7 | module SymbolicParityGame = struct 8 | 9 | open Tcsset 10 | open Tcsgraph 11 | 12 | type 'a symbolic_paritygame = ('a, int) Hashtbl.t * dynamic_paritygame 13 | 14 | let create_new x = (Hashtbl.create 10, DynamicGraph.make ()) 15 | 16 | let to_paritygame (ht, gr) = 17 | let pg = pg_create (Hashtbl.length ht) in 18 | Hashtbl.iter (fun _ ind -> 19 | let (pr, pl, desc) = DynamicGraph.get_node_data ind gr in 20 | pg_set_priority pg ind pr; 21 | pg_set_owner pg ind pl; 22 | pg_set_desc pg ind desc; 23 | TreeSet.iter (fun w -> pg_add_edge pg ind w) (DynamicGraph.get_node_succ ind gr) 24 | ) ht; 25 | pg 26 | 27 | let internal_add (ht, gr) symb pr pl desc override = 28 | if Hashtbl.mem ht symb 29 | then let ind = Hashtbl.find ht symb in 30 | if override then DynamicGraph.set_node_data ind (pr, pl, desc) gr; 31 | ind 32 | else let ind = Hashtbl.length ht in 33 | Hashtbl.add ht symb ind; 34 | DynamicGraph.add_node ind (pr, pl, desc) gr; 35 | ind 36 | 37 | let touch_node (ht, gr) symb = 38 | let _ = internal_add (ht, gr) symb (-1) plr_Even None false in () 39 | 40 | let add_node (ht, gr) symb pr pl tr desc = 41 | let ind = internal_add (ht, gr) symb pr pl desc true in 42 | Array.iter (fun symb' -> 43 | let ind' = internal_add (ht, gr) symb' (-1) plr_Even None false in 44 | DynamicGraph.add_edge ind ind' gr 45 | ) tr 46 | 47 | end;; 48 | 49 | 50 | type strat_impr_gen_args = string array 51 | 52 | type strat_impr_gen = { 53 | ident: string; 54 | description: string; 55 | parity_game: (strat_impr_gen_args -> paritygame) option; 56 | generalized_mdp: (strat_impr_gen_args -> generalized_mdp) option; 57 | } 58 | 59 | let strat_impr_gen_map = ref TreeMap.empty_def 60 | 61 | let register_strat_impr_gen gen = 62 | if TreeMap.mem gen.ident !strat_impr_gen_map 63 | then failwith ("generator `" ^ gen.ident ^ "' already registered!\n") 64 | else strat_impr_gen_map := TreeMap.add gen.ident gen !strat_impr_gen_map 65 | 66 | let mem_strat_impr_gen ident = TreeMap.mem ident !strat_impr_gen_map 67 | 68 | let find_strat_impr_gen ident = TreeMap.find ident !strat_impr_gen_map 69 | 70 | let enum_strat_impr_gen f = TreeMap.iter (fun _ -> f) !strat_impr_gen_map 71 | 72 | let fold_strat_impr_gen f = TreeMap.fold (fun _ -> f) !strat_impr_gen_map 73 | -------------------------------------------------------------------------------- /src/generators/policyiter/stratimprgenerators.mli: -------------------------------------------------------------------------------- 1 | open Paritygame 2 | open Mdp 3 | 4 | module SymbolicParityGame : sig 5 | 6 | type 'a symbolic_paritygame 7 | 8 | val create_new: 'a -> 'a symbolic_paritygame 9 | 10 | val to_paritygame: 'a symbolic_paritygame -> paritygame 11 | 12 | val touch_node: 'a symbolic_paritygame -> 'a -> unit 13 | 14 | val add_node: 'a symbolic_paritygame -> 'a -> priority -> player -> 'a array -> string option -> unit 15 | 16 | end 17 | 18 | 19 | type strat_impr_gen_args = string array 20 | 21 | type strat_impr_gen = { 22 | ident: string; 23 | description: string; 24 | parity_game: (strat_impr_gen_args -> paritygame) option; 25 | generalized_mdp: (strat_impr_gen_args -> generalized_mdp) option; 26 | } 27 | 28 | val register_strat_impr_gen: strat_impr_gen -> unit 29 | 30 | val mem_strat_impr_gen: string -> bool 31 | 32 | val find_strat_impr_gen: string -> strat_impr_gen 33 | 34 | val enum_strat_impr_gen: (strat_impr_gen -> unit) -> unit 35 | 36 | val fold_strat_impr_gen: (strat_impr_gen -> 'a -> 'a) -> 'a -> 'a 37 | -------------------------------------------------------------------------------- /src/generators/policyiter/stratimprgenlist.ml: -------------------------------------------------------------------------------- 1 | let register _ = 2 | Zadehexp.register(); 3 | Cunninghamexp.register(); 4 | Zadehsubexp.register(); 5 | Cunninghamsubexp.register(); 6 | Fearnleysubexp.register(); 7 | Friedmannsubexp.register(); 8 | Switchallsubexp.register(); 9 | Switchbestsubexp.register(); 10 | Switchallexp.register(); 11 | Switchbestexp.register(); 12 | Randomfacetsubexp.register(); 13 | Randomedgesubexp.register(); 14 | Randomedgeexptest.register();; -------------------------------------------------------------------------------- /src/generators/policyiter/stratimprgenlist.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/randomgame.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | let random_game_func arguments = 4 | 5 | let show_help _ = 6 | print_string (Info.get_title "Random Game Generator"); 7 | print_string ("Usage: randomgame n p l h [x]\n\n" ^ 8 | " where n = Number of nodes\n" ^ 9 | " p = Highest possibly occurring priority\n" ^ 10 | " l = Lowest possible out-degree (l > 0)\n" ^ 11 | " h = Highest possible out-degree\n" ^ 12 | " x = disable self-cycles\n\n") 13 | in 14 | 15 | if (Array.length arguments < 4) || (Array.length arguments > 5) then (show_help (); exit 1); 16 | 17 | let size = int_of_string arguments.(0) in 18 | let max_prio = 1+(int_of_string arguments.(1)) in 19 | let outdegmin = int_of_string arguments.(2) in 20 | 21 | if outdegmin < 1 then (show_help (); exit 1); 22 | 23 | let outdegmax = int_of_string arguments.(3) in 24 | let self_cycles = Array.length arguments = 4 in 25 | 26 | Random.self_init (); 27 | 28 | pg_init size (fun i -> (Random.int max_prio, 29 | plr_random (), 30 | List.map (fun j -> if j < i || self_cycles then j else j + 1) 31 | (Array.to_list (Tcsmaths.RandomUtils.get_pairwise_different_from_range (outdegmin + Random.int (outdegmax - outdegmin + 1)) 32 | 0 33 | (size-1 - (if self_cycles then 0 else 1)))), 34 | Some (nd_show i)));; 35 | 36 | let register _ = 37 | Generatorregistry.register_generator random_game_func "randomgame" "Random Game";; 38 | -------------------------------------------------------------------------------- /src/generators/randomgame.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/randomgame_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "randomgame";; 2 | -------------------------------------------------------------------------------- /src/generators/recursivedullgame.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Arg;; 3 | 4 | let n = ref 0 5 | 6 | module RecursiveDullGame = Build( 7 | struct 8 | type gamenode = V of int | U of int 9 | let compare = compare 10 | 11 | let owner _ = plr_Even 12 | 13 | let priority = function 14 | | U _ -> 1 15 | | V i -> i + 2 16 | 17 | let show_node = function 18 | | V i -> Some ("v" ^ string_of_int i) 19 | | U i -> Some ("u" ^ string_of_int i) 20 | 21 | let successors = function 22 | | U i -> [V (2 * i - 1); U i] 23 | | V i -> [if i = 0 then V i else V (i-1)] 24 | 25 | let initnodes _ = (Array.to_list (Array.init !n (fun i -> U (i+1)))) 26 | end);; 27 | 28 | let generator_game_func arguments = 29 | 30 | if (Array.length arguments != 1) then (failwith "specify index of game"); 31 | n := int_of_string arguments.(0); 32 | 33 | RecursiveDullGame.build () ;; 34 | 35 | 36 | let register _ = Generatorregistry.register_generator generator_game_func "recursivedullgame" "Recursive Dull Game";; 37 | -------------------------------------------------------------------------------- /src/generators/recursivedullgame.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/recursivedullgame_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "recursivedullgame";; 2 | -------------------------------------------------------------------------------- /src/generators/recursiveladder.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | let generator_game_func arguments = 4 | 5 | let show_help _ = 6 | print_string (Info.get_title "Recursive Ladder Game Generator"); 7 | print_string ("Usage: recursiveladder n\n\n" ^ 8 | " where n = n-th recursive ladder game\n\n") 9 | in 10 | 11 | if (Array.length arguments != 1) then (show_help (); exit 1); 12 | 13 | let height = 1 + int_of_string arguments.(0) in 14 | 15 | let w = 5 in 16 | 17 | let game = pg_create (5 * height - 5) in 18 | 19 | for i = 0 to height-1 do 20 | let start_idx = i * w - 2 in 21 | let p = (i + 1) * 3 + 2 in 22 | let start_pl = i mod 2 in 23 | let o = 1 - start_pl in 24 | let mx = i = height - 1 in 25 | let mfx = i = height - 2 in 26 | let mn = i = 0 in 27 | 28 | let prnt j pr pl succs = 29 | let j' = start_idx + j in 30 | pg_set_priority game j' pr; 31 | pg_set_owner game j' (plr_benefits (start_pl + pl)); 32 | pg_set_desc game j' (Some (nd_show (start_idx + j))); 33 | List.iter (fun w -> pg_add_edge game j' (w+start_idx)) succs 34 | in 35 | 36 | if not mn then ( 37 | prnt 0 o 1 [3-w;1]; 38 | prnt 1 o 0 (if mx then [0] else [0;2]); 39 | ); 40 | if not mx then ( 41 | prnt 2 p 1 [w+1;3]; 42 | prnt 3 (p - 1) 0 ((if mn then [] else [3-w])@(if mfx then [] else [w+3])@[4]); 43 | prnt 4 (p - 2) 1 (if mx then [3] else [3;w+1]) 44 | ) 45 | done; 46 | game;; 47 | 48 | let register _ = Generatorregistry.register_generator generator_game_func "recursiveladder" "Recursive Ladder Game";; 49 | -------------------------------------------------------------------------------- /src/generators/recursiveladder.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/recursiveladder_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "recursiveladder";; 2 | -------------------------------------------------------------------------------- /src/generators/steadygame.ml: -------------------------------------------------------------------------------- 1 | open Tcsarray;; 2 | open Paritygame;; 3 | 4 | let generator_game_func arguments = 5 | 6 | let show_help _ = 7 | print_string (Info.get_title "Steady Game Generator"); 8 | print_string ("Usage: steadygame n l h x y\n\n" ^ 9 | " where n = Number of nodes\n" ^ 10 | " l = Lowest possible out-degree\n" ^ 11 | " h = Highest possible out-degree\n" ^ 12 | " x = Lowest possible in-degree\n" ^ 13 | " y = Highest possible in-degree\n\n") 14 | in 15 | 16 | if (Array.length arguments != 5) then (show_help (); exit 1); 17 | 18 | let size = int_of_string arguments.(0) in 19 | let outdegmin = int_of_string arguments.(1) in 20 | 21 | if outdegmin < 1 then (show_help (); exit 1); 22 | 23 | let outdegmax = int_of_string arguments.(2) in 24 | let indegmin = int_of_string arguments.(3) in 25 | 26 | if indegmin < 1 then (show_help (); exit 1); 27 | 28 | let indegmax = int_of_string arguments.(4) in 29 | let outavail = DynArray.init 0 size (fun i -> i) in 30 | let inavail = DynArray.init 0 size (fun i -> i) in 31 | let outtodo = ref size in 32 | let intodo = ref size in 33 | 34 | Random.self_init (); 35 | 36 | let pg = Array.make size [] in 37 | let pgtr = Array.make size 0 in 38 | 39 | while ((!outtodo > 0 && DynArray.length inavail > 0) || (!intodo > 0 && DynArray.length outavail > 0)) do 40 | let ii = Random.int (DynArray.length outavail) in 41 | let i = DynArray.get outavail ii in 42 | let findin forb = 43 | let jj = ref (Random.int (DynArray.length inavail)) in 44 | while (List.mem (DynArray.get inavail !jj) forb) && (DynArray.length inavail > 1) do 45 | jj := Random.int (DynArray.length inavail) 46 | done; 47 | !jj 48 | in 49 | let jj = findin (i::pg.(i)) in 50 | let j = DynArray.get inavail jj in 51 | pg.(i) <- j::pg.(i); 52 | pgtr.(j) <- pgtr.(j) + 1; 53 | let leni = List.length pg.(i) in 54 | let lenj = pgtr.(j) in 55 | if leni = outdegmin then decr outtodo 56 | else if leni = outdegmax then DynArray.delete outavail ii; 57 | if lenj = indegmin then decr intodo 58 | else if lenj = indegmax then DynArray.delete inavail jj; 59 | done; 60 | 61 | pg_init size (fun i -> (i, 62 | plr_random (), 63 | pg.(i), 64 | Some (nd_show i)) 65 | );; 66 | 67 | let register _ = Generatorregistry.register_generator generator_game_func "steadygame" "Steady Game";; 68 | -------------------------------------------------------------------------------- /src/generators/steadygame.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/steadygame_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "steadygame";; -------------------------------------------------------------------------------- /src/generators/taskscheduler.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | let number_cpus = ref 2 4 | let number_tasks = ref 5 5 | let waiting_time = ref 7 6 | let running_time = ref 3 7 | 8 | module Tasks = 9 | struct 10 | type status = Waiting 11 | | Interrupted 12 | | Sleeping of int 13 | | Running of int 14 | type importance = int 15 | type task = status * importance 16 | type tasks = task array 17 | 18 | type formulaType = FP of int * int (* fixpoint formula with priority and next subformula *) 19 | | BOOL of player * int * int (* con-/disjunction with player and left and right subformula *) 20 | | MOD of player * int (* modality with player and next subformula *) 21 | | PROP of (tasks -> bool) (* proposition with function that evaluates it in a state *) 22 | 23 | type formula = int 24 | 25 | let formula = Array.init (!number_tasks * 2 + ....) 26 | 27 | type gamenode = tasks * formula 28 | 29 | let initconf = Array.init (fun i -> (Waiting !waiting_time, i)) 30 | end;; 31 | -------------------------------------------------------------------------------- /src/generators/towersofhanoi.ml: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | let levels = ref 0 4 | 5 | module ToHGame = Build( 6 | struct 7 | type gamenode = int list array 8 | 9 | let compare = compare 10 | 11 | let owner _ = plr_Even 12 | 13 | let finished ts = (ts.(0) = []) && (ts.(2) = []) 14 | 15 | let priority ts = 16 | if finished ts then 0 else 1 17 | 18 | let successors ts = 19 | if finished ts then [ts] else 20 | begin 21 | let tops = [| if ts.(0) <> [] then List.hd ts.(0) else 0; 22 | if ts.(1) <> [] then List.hd ts.(1) else 0; 23 | if ts.(2) <> [] then List.hd ts.(2) else 0 |] 24 | in 25 | let succs = ref [] in 26 | let moves = [ (0,1,2); (0,2,1); (1,0,2); (1,2,0); (2,0,1); (2,1,0) ] in 27 | 28 | List.iter (fun (f,t,o) -> if tops.(f) > 0 && (tops.(f) < tops.(t) || tops.(t) = 0) then 29 | begin 30 | let tt = Array.make 3 [] in 31 | tt.(f) <- List.tl ts.(f); 32 | tt.(t) <- tops.(f) :: ts.(t); 33 | tt.(o) <- ts.(o); 34 | succs := tt :: !succs 35 | end) 36 | moves; 37 | !succs 38 | end 39 | 40 | 41 | let show_node ts = Some ("[" ^ (String.concat "," (List.map string_of_int ts.(0))) ^ "] " ^ 42 | "[" ^ (String.concat "," (List.map string_of_int ts.(1))) ^ "] " ^ 43 | "[" ^ (String.concat "," (List.map string_of_int ts.(2))) ^ "]") 44 | 45 | let initnodes _ = 46 | let rec lvs i aux = if i=0 then aux else lvs (i-1) (i::aux) 47 | in 48 | [ [| lvs !levels []; []; [] |] ] 49 | 50 | end);; 51 | 52 | 53 | 54 | let towers_of_hanoi_func arguments = 55 | 56 | let show_help _ = 57 | print_string (Info.get_title "Towers of Hanoi Reachability Game Generator"); 58 | print_string ("Usage: towersofhanoi n \n\n" ^ 59 | " where n = number of levels that the tower to be moved has (>= 1)\n\n") 60 | 61 | in 62 | 63 | if (Array.length arguments <> 1) then (show_help (); exit 1); 64 | 65 | (try 66 | levels := int_of_string arguments.(0) 67 | with _ -> (show_help (); exit 1)); 68 | 69 | if not (!levels > 0) then (show_help(); exit 1); 70 | 71 | 72 | ToHGame.build () 73 | 74 | 75 | let register _ = Generatorregistry.register_generator towers_of_hanoi_func "towersofhanoi" "Towers of Hanoi Reachability Game";; 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/generators/towersofhanoi.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/generators/towersofhanoi_aux.ml: -------------------------------------------------------------------------------- 1 | Generators.run_command_line_generator "towersofhanoi";; -------------------------------------------------------------------------------- /src/paritygame/generatorregistry.ml: -------------------------------------------------------------------------------- 1 | (* open Paritygame;; *) 2 | open Tcsset;; 3 | 4 | let generatormap = ref TreeMap.empty_def;; 5 | 6 | let register_generator generator_func identifier description = 7 | if TreeMap.mem identifier !generatormap 8 | then failwith ("generator `" ^ identifier ^ "' already registered!\n") 9 | else generatormap := TreeMap.add identifier (generator_func, description) !generatormap;; 10 | 11 | let mem_generator identifier = TreeMap.mem identifier !generatormap;; 12 | 13 | let find_generator identifier = TreeMap.find identifier !generatormap;; 14 | 15 | let enum_generators it = TreeMap.iter (fun i (f, d) -> it f i d) !generatormap;; 16 | 17 | let fold_generators fo b = TreeMap.fold (fun i (f, d) x -> fo f i d x) !generatormap b;; 18 | -------------------------------------------------------------------------------- /src/paritygame/generatorregistry.mli: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | val register_generator: (string array -> paritygame) -> string -> string -> unit 4 | 5 | val mem_generator: string -> bool 6 | 7 | val find_generator: string -> (string array -> paritygame) * string 8 | 9 | val enum_generators: ((string array -> paritygame) -> string -> string -> unit) -> unit 10 | 11 | val fold_generators: ((string array -> paritygame) -> string -> string -> 'a -> 'a) -> 'a -> 'a 12 | -------------------------------------------------------------------------------- /src/paritygame/generators.ml: -------------------------------------------------------------------------------- 1 | let register_generator = Generatorregistry.register_generator;; 2 | 3 | let mem_generator = Generatorregistry.mem_generator;; 4 | 5 | let find_generator = Generatorregistry.find_generator;; 6 | 7 | let enum_generators = Generatorregistry.enum_generators;; 8 | 9 | let fold_generators = Generatorregistry.fold_generators;; 10 | 11 | let run_command_line_generator generator = 12 | let (gen, _) = find_generator generator in 13 | let args = Array.sub Sys.argv 1 (Array.length Sys.argv - 1) in 14 | let pg = gen args in 15 | Paritygame.print_game pg;; 16 | 17 | let _ = 18 | Randomgame.register (); 19 | Laddergame.register (); 20 | Clusteredrandomgame.register (); 21 | Cliquegame.register (); 22 | Modelcheckerladder.register (); 23 | Recursiveladder.register (); 24 | Steadygame.register (); 25 | Jurdzinskigame.register (); 26 | Elevators.register (); 27 | Roadworks.register (); 28 | Towersofhanoi.register (); 29 | Langincl.register (); 30 | Recursivedullgame.register ();; 31 | -------------------------------------------------------------------------------- /src/paritygame/generators.mli: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | val register_generator: (string array -> paritygame) -> string -> string -> unit 4 | 5 | val mem_generator: string -> bool 6 | 7 | val find_generator: string -> (string array -> paritygame) * string 8 | 9 | val enum_generators: ((string array -> paritygame) -> string -> string -> unit) -> unit 10 | 11 | val fold_generators: ((string array -> paritygame) -> string -> string -> 'a -> 'a) -> 'a -> 'a 12 | 13 | val run_command_line_generator: string -> unit -------------------------------------------------------------------------------- /src/paritygame/mdp.mli: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Tcsmaths;; 3 | 4 | type generalized_mdp_node = Controller of int array * string option 5 | | Randomizer of (BigFloat.t * int) array 6 | | Reward of (BigFloat.t * int) 7 | | Sink 8 | 9 | type generalized_mdp = generalized_mdp_node array 10 | 11 | val parity_game_to_generalized_mdp: paritygame -> int -> (int -> int -> bool) -> generalized_mdp 12 | 13 | type mdp = (((BigFloat.t * BigFloat.t * int) array) array * string option) array 14 | 15 | val generalized_mdp_to_mdp: generalized_mdp -> mdp 16 | 17 | val print_mdp: mdp -> unit 18 | 19 | type lp_objective = Maximize | Minimize 20 | 21 | type lp_constraint_type = LPEq | LPGeq 22 | 23 | type lp = lp_objective * (string option array) * (BigFloat.t array) * (BigFloat.t array * BigFloat.t * lp_constraint_type * string option) array 24 | 25 | val unichain_mdp_to_primal_lp: mdp -> lp 26 | 27 | val unichain_mdp_to_dual_lp: mdp -> lp 28 | 29 | val print_lp: lp -> unit -------------------------------------------------------------------------------- /src/paritygame/paritygamebitset.ml: -------------------------------------------------------------------------------- 1 | open Basics;; 2 | open Paritygame;; 3 | 4 | let is_empty_bset bset length = 5 | let i = ref 0 in 6 | let empty = ref true in 7 | while !i < length && !empty do 8 | if BitSet.is_set bset !i 9 | then empty := false 10 | else incr i; 11 | done; 12 | !empty;; 13 | 14 | let bit_dom_array_bound array length bound = 15 | let dom = BitSet.create length in 16 | for i = 0 to length - 1 do 17 | if array.(i) > bound 18 | then BitSet.set dom i 19 | done; 20 | dom;; 21 | 22 | let collect_nodes_bit game length = 23 | let bset = BitSet.create length in 24 | for i = 0 to length - 1 do 25 | if pg_isDefined game i 26 | then BitSet.set bset i 27 | done; 28 | bset;; 29 | 30 | let pre_bit game pre subgame_vr player target length = 31 | for i = 0 to length - 1 do 32 | if BitSet.is_set subgame_vr i 33 | then ( 34 | let pl = pg_get_owner game i in 35 | let ws = pg_get_successors game i in 36 | let take = ref false in 37 | if pl = player 38 | then take := ns_fold (fun b -> fun w -> b || (BitSet.is_set target w)) false ws 39 | else ( 40 | if pl != plr_undef 41 | then ( 42 | take := true; 43 | ns_iter (fun v -> 44 | if (BitSet.is_set subgame_vr v) && not (BitSet.is_set target v) 45 | then take := false 46 | ) ws; 47 | ); 48 | ); 49 | if !take then BitSet.set pre i else BitSet.unset pre i; 50 | ); 51 | done;; 52 | 53 | let attr_bit game game_vr todoS todoQ strategy player region region_en = 54 | let attr = BitSet.copy region in 55 | let used = BitSet.copy region in 56 | Enum.iter (fun v -> 57 | ns_iter (fun w -> if not (BitSet.is_set used w) 58 | then ( 59 | let pl = pg_get_owner game w in 60 | BitSet.set used w; 61 | if pl<>player 62 | then Queue.add w todoQ 63 | else (Queue.add w todoS; strategy.(w) <- v;) 64 | ); 65 | ) (ns_filter (fun w -> BitSet.is_set game_vr w) (pg_get_predecessors game v)) 66 | ) region_en; 67 | while not (Queue.is_empty todoS && Queue.is_empty todoQ) do 68 | if not (Queue.is_empty todoS) 69 | then ( 70 | let v = Queue.take todoS in 71 | BitSet.set attr v; 72 | ns_iter (fun w -> if not (BitSet.is_set used w) 73 | then ( 74 | let pl = pg_get_owner game w in 75 | BitSet.set used w; 76 | if pl<>player 77 | then Queue.add w todoQ 78 | else (Queue.add w todoS; strategy.(w) <- v;) 79 | ); 80 | ) (ns_filter (fun w -> BitSet.is_set game_vr w) (pg_get_predecessors game v)); 81 | ) 82 | else ( 83 | let v = Queue.take todoQ in 84 | let ws = pg_get_successors game v in 85 | if ns_fold (fun b w -> b && (if BitSet.is_set game_vr w then BitSet.is_set attr w else true)) true ws 86 | then ( 87 | BitSet.set attr v; 88 | ns_iter (fun w -> if not (BitSet.is_set used w) 89 | then ( 90 | let pl = pg_get_owner game w in 91 | BitSet.set used w; 92 | if pl<>player 93 | then Queue.add w todoQ 94 | else (Queue.add w todoS; strategy.(w) <- v;) 95 | ); 96 | ) (ns_filter (fun w -> BitSet.is_set game_vr w) (pg_get_predecessors game v)); 97 | ) 98 | else BitSet.unset used v; 99 | ); 100 | done; 101 | attr;; 102 | -------------------------------------------------------------------------------- /src/paritygame/paritygamebitset.mli: -------------------------------------------------------------------------------- 1 | open Paritygame 2 | 3 | (************************************************************** 4 | * Priority Promotion Approach Definitions * 5 | **************************************************************) 6 | 7 | val is_empty_bset : BitSet.t -> int -> bool 8 | val bit_dom_array_bound : int array -> int -> int -> BitSet.t 9 | val collect_nodes_bit : paritygame -> int -> BitSet.t 10 | val pre_bit : paritygame -> BitSet.t -> BitSet.t -> player -> BitSet.t -> int -> unit 11 | val attr_bit : paritygame -> BitSet.t -> int Queue.t -> int Queue.t -> strategy -> player -> BitSet.t -> int Enum.t -> BitSet.t -------------------------------------------------------------------------------- /src/paritygame/parsers.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Bytes;; 3 | 4 | let parse_init_parity_game in_channel = 5 | let game = ref (pg_create 0) in 6 | let add v pr pl succs desc = 7 | pg_set_priority !game v pr; 8 | pg_set_owner !game v (if pl = 0 then plr_Even else plr_Odd); 9 | pg_set_desc !game v (if desc = "" then None else Some desc); 10 | List.iter (fun w -> pg_add_edge !game v w) succs 11 | in 12 | let queue = ref [] in 13 | let max_node = ref (-1) in 14 | let adder = ref (fun v pr pl succs desc -> 15 | queue := (v, pr, pl, succs, desc)::!queue; 16 | max_node := max !max_node v 17 | ) in 18 | let init_value = ref 0 in 19 | Tcsgameparser.parse_parity_game (fun n -> 20 | game := pg_create n; 21 | adder := add 22 | ) (fun i -> init_value := i) !adder (fun _ -> ()) in_channel; 23 | if !queue != [] then ( 24 | game := pg_create (!max_node + 1); 25 | List.iter (fun (v, pr, pl, succs, desc) -> add v pr pl succs desc) !queue 26 | ); 27 | (!init_value, !game) 28 | 29 | let parse_parity_game in_channel = snd (parse_init_parity_game in_channel) 30 | 31 | let parse_solution in_channel = 32 | let (sol, str) = Tcsgameparser.parse_explicit_parity_solution in_channel in 33 | (Array.map (fun pl -> if pl = 0 then plr_Even else plr_Odd) sol, str) 34 | -------------------------------------------------------------------------------- /src/paritygame/parsers.mli: -------------------------------------------------------------------------------- 1 | open Tcsgameparser 2 | open Paritygame 3 | 4 | val parse_parity_game: in_channel -> paritygame 5 | val parse_init_parity_game: in_channel -> node * paritygame 6 | val parse_solution: in_channel -> solution * strategy 7 | -------------------------------------------------------------------------------- /src/paritygame/solverregistry.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | open Tcsset;; 3 | 4 | type global_solver_factory = string array -> global_solver 5 | 6 | let solvermap = ref TreeMap.empty_def;; 7 | 8 | let register_solver_factory solver_func identifier abbreviation description = 9 | if TreeMap.mem identifier !solvermap 10 | then failwith ("Solver `" ^ identifier ^ "' already registered!\n") 11 | else solvermap := TreeMap.add identifier (solver_func, abbreviation, description) !solvermap;; 12 | 13 | let register_solver solver_func = register_solver_factory (fun _ -> solver_func);; 14 | 15 | let mem_solver identifier = TreeMap.mem identifier !solvermap;; 16 | 17 | let find_solver identifier = TreeMap.find identifier !solvermap;; 18 | 19 | let enum_solvers it = TreeMap.iter (fun i (f, a, d) -> it f i a d) !solvermap;; 20 | 21 | let fold_solvers fo b = TreeMap.fold (fun i (f, a, d) x -> fo f i a d x) !solvermap b;; 22 | 23 | 24 | type partial_solver_factory = string array -> partial_solver 25 | 26 | let partialsolvermap = ref TreeMap.empty_def;; 27 | 28 | let register_partial_solver_factory solver_func identifier abbreviation description = 29 | if TreeMap.mem identifier !partialsolvermap 30 | then failwith ("Partial Solver `" ^ identifier ^ "' already registered!\n") 31 | else partialsolvermap := TreeMap.add identifier (solver_func, abbreviation, description) !partialsolvermap;; 32 | 33 | let register_partial_solver solver_func = register_partial_solver_factory (fun _ -> solver_func);; 34 | 35 | let mem_partial_solver identifier = TreeMap.mem identifier !partialsolvermap;; 36 | 37 | let find_partial_solver identifier = TreeMap.find identifier !partialsolvermap;; 38 | 39 | let enum_partial_solvers it = TreeMap.iter (fun i (f, a, d) -> it f i a d) !partialsolvermap;; 40 | 41 | let fold_partial_solvers fo b = TreeMap.fold (fun i (f, a, d) x -> fo f i a d x) !partialsolvermap b;; -------------------------------------------------------------------------------- /src/paritygame/solverregistry.mli: -------------------------------------------------------------------------------- 1 | open Paritygame 2 | 3 | type global_solver_factory = string array -> global_solver 4 | 5 | val register_solver_factory: global_solver_factory -> string -> string -> string -> unit 6 | 7 | val register_solver: global_solver -> string -> string -> string -> unit 8 | 9 | val mem_solver: string -> bool 10 | 11 | val find_solver: string -> global_solver_factory * string * string 12 | 13 | val enum_solvers: (global_solver_factory -> string -> string -> string -> unit) -> unit 14 | 15 | val fold_solvers: (global_solver_factory -> string -> string -> string -> 'a -> 'a) -> 'a -> 'a 16 | 17 | 18 | type partial_solver_factory = string array -> partial_solver 19 | 20 | val register_partial_solver_factory: partial_solver_factory -> string -> string -> string -> unit 21 | 22 | val register_partial_solver: partial_solver -> string -> string -> string -> unit 23 | 24 | val mem_partial_solver: string -> bool 25 | 26 | val find_partial_solver: string -> partial_solver_factory * string * string 27 | 28 | val enum_partial_solvers: (partial_solver_factory -> string -> string -> string -> unit) -> unit 29 | 30 | val fold_partial_solvers: (partial_solver_factory -> string -> string -> string -> 'a -> 'a) -> 'a -> 'a -------------------------------------------------------------------------------- /src/paritygame/solvers.ml: -------------------------------------------------------------------------------- 1 | let register_solver_factory = Solverregistry.register_solver_factory 2 | 3 | let register_solver = Solverregistry.register_solver 4 | 5 | let mem_solver = Solverregistry.mem_solver 6 | 7 | let find_solver = Solverregistry.find_solver 8 | 9 | let enum_solvers = Solverregistry.enum_solvers 10 | 11 | let fold_solvers = Solverregistry.fold_solvers 12 | 13 | let register_partial_solver_factory = Solverregistry.register_partial_solver_factory 14 | 15 | let register_partial_solver = Solverregistry.register_partial_solver 16 | 17 | let mem_partial_solver = Solverregistry.mem_partial_solver 18 | 19 | let find_partial_solver = Solverregistry.find_partial_solver 20 | 21 | let enum_partial_solvers = Solverregistry.enum_partial_solvers 22 | 23 | let fold_partial_solvers = Solverregistry.fold_partial_solvers 24 | 25 | let _ = 26 | Bigstep.register (); 27 | Dominiondecomp.register (); 28 | Externalsolver.register (); 29 | Fpiter.register (); 30 | Genetic.register (); 31 | Guessstrategy.register (); 32 | Localmodelchecker.register (); 33 | Optstratimprov.register (); 34 | Prioprom.register (); 35 | Priopromplus.register (); 36 | Priopromdelay.register (); 37 | Priopromrecovery.register (); 38 | Recursive.register (); 39 | Satsolve.register (); 40 | Smallprogress.register (); 41 | (*Smtsolve.register ();*) 42 | Stratimprdisc.register (); 43 | Stratimprlocal.register (); 44 | Stratimprlocal2.register (); 45 | Stratimprovement.register (); 46 | Stratimprsat.register (); 47 | Viasat.register (); 48 | Stratimpralgs.register (); 49 | Switch_cunningham.register (); 50 | Switch_globally_best.register (); 51 | Switch_history.register (); 52 | Switch_internal.register (); 53 | Switch_locally_best.register (); 54 | Switch_random.register (); 55 | Switch_snare.register (); 56 | Switch_zadeh.register (); 57 | Succinctsmallprogress.register ();; 58 | -------------------------------------------------------------------------------- /src/paritygame/solvers.mli: -------------------------------------------------------------------------------- 1 | open Paritygame 2 | open Solverregistry 3 | 4 | val register_solver_factory: global_solver_factory -> string -> string -> string -> unit 5 | 6 | val register_solver: global_solver -> string -> string -> string -> unit 7 | 8 | val mem_solver: string -> bool 9 | 10 | val find_solver: string -> global_solver_factory * string * string 11 | 12 | val enum_solvers: (global_solver_factory -> string -> string -> string -> unit) -> unit 13 | 14 | val fold_solvers: (global_solver_factory -> string -> string -> string -> 'a -> 'a) -> 'a -> 'a 15 | 16 | 17 | val register_partial_solver_factory: partial_solver_factory -> string -> string -> string -> unit 18 | 19 | val register_partial_solver: partial_solver -> string -> string -> string -> unit 20 | 21 | val mem_partial_solver: string -> bool 22 | 23 | val find_partial_solver: string -> partial_solver_factory * string * string 24 | 25 | val enum_partial_solvers: (partial_solver_factory -> string -> string -> string -> unit) -> unit 26 | 27 | val fold_partial_solvers: (partial_solver_factory -> string -> string -> string -> 'a -> 'a) -> 'a -> 'a -------------------------------------------------------------------------------- /src/paritygame/specialsolve.mli: -------------------------------------------------------------------------------- 1 | open Basics;; 2 | open Paritygame;; 3 | 4 | type compact_sol_strat = (node * player * node) list 5 | 6 | val compact_sol_strat_to_sol_strat: paritygame -> compact_sol_strat -> solution * strategy 7 | 8 | val find_useful_self_cycles: paritygame -> compact_sol_strat 9 | 10 | val solve_cycle_scc: paritygame -> solution * strategy 11 | 12 | val solve_single_player_scc: paritygame -> player -> solution * strategy 13 | 14 | val solve_single_parity_scc: paritygame -> player -> solution * strategy 15 | 16 | (* Instead use the functions in univsolve. The only reason why you would want to use the following two function is to avoid the use of the universal solving process. *) 17 | val compute_winning_nodes_for_direct: paritygame -> player -> solution * strategy 18 | 19 | val compute_winning_nodes_direct: paritygame -> strategy -> player -> node list 20 | -------------------------------------------------------------------------------- /src/paritygame/transformations.mli: -------------------------------------------------------------------------------- 1 | open Basics;; 2 | open Paritygame;; 3 | 4 | 5 | 6 | (************************************************************** 7 | * Global Preprocessing * 8 | **************************************************************) 9 | 10 | val remove_useless_self_cycles_inplace: paritygame -> node list 11 | 12 | 13 | 14 | (************************************************************** 15 | * Local Preprocessing * 16 | **************************************************************) 17 | 18 | val compact_prio_inplace: paritygame -> bool -> priority array 19 | 20 | val priority_propagation_inplace: paritygame -> unit 21 | 22 | val anti_propagation_inplace: paritygame -> unit 23 | 24 | 25 | 26 | (************************************************************** 27 | * Game Transformations * 28 | **************************************************************) 29 | 30 | val single_scc_transformation: paritygame -> paritygame 31 | 32 | val anti_priority_compactation_transformation: paritygame -> paritygame 33 | 34 | val cheap_escape_cycles_transformation: paritygame -> bool -> paritygame 35 | 36 | val total_transformation_inplace: paritygame -> unit 37 | 38 | val total_revertive_restriction_inplace: paritygame -> strategy -> unit 39 | 40 | val alternating_transformation: paritygame -> bool -> paritygame 41 | 42 | val alternating_revertive_restriction: paritygame -> paritygame -> solution -> strategy -> solution * strategy 43 | 44 | val partialpg_alternating_transformation: partial_paritygame -> partial_paritygame 45 | 46 | val partialpg_alternating_revertive_restriction: partial_solution -> partial_solution 47 | 48 | val increase_priority_occurrence: paritygame -> paritygame 49 | 50 | val prio_alignment_transformation: paritygame -> paritygame 51 | 52 | val dummy_transformation: paritygame -> paritygame 53 | 54 | val shift_game: paritygame -> int -> paritygame 55 | 56 | val combine_games: paritygame list -> paritygame 57 | 58 | val bouncing_node_transformation: paritygame -> paritygame 59 | 60 | val compress_nodes: paritygame -> paritygame * node array * node array 61 | 62 | val normal_form_translation: paritygame -> paritygame 63 | 64 | val normal_form_revertive_translation: paritygame -> solution -> strategy -> solution * strategy 65 | 66 | val uniquize_sorted_prios_inplace: paritygame -> unit 67 | 68 | val uniquize_prios_inplace: paritygame -> unit 69 | 70 | val min_max_swap_transformation: paritygame -> paritygame 71 | 72 | 73 | (* broken; unfixed; replaced by non-inplace version, specialised to sorting by priority comparison 74 | val sort_game_inplace : paritygame -> ((priority * player * nodeset * string option) -> 75 | (priority * player * nodeset * string option) -> int) -> 76 | (player array * node array) 77 | *) 78 | 79 | val sort_game_by_prio : paritygame -> (paritygame * node array * node array) 80 | -------------------------------------------------------------------------------- /src/paritygame/verification.mli: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | type verifier = paritygame -> solution -> strategy -> (node list * string) option 4 | 5 | (* Default verification *) 6 | val verify_solution_strategy: verifier 7 | 8 | (* Using universal_solve *) 9 | val verify_solution_strategy_univ: verifier 10 | 11 | (* Using compute_winning_nodes_direct *) 12 | val verify_solution_strategy_direct: verifier 13 | 14 | (* Using a generic algorithm *) 15 | val verify_solution_strategy_generic: verifier 16 | 17 | -------------------------------------------------------------------------------- /src/pgsolver.mldylib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 6b0dae0a47fa1502179a773eaff2ca9b) 3 | pgsolver/Basics 4 | pgsolver/Info 5 | paritygame/Paritygame 6 | paritygame/Verification 7 | paritygame/Univsolve 8 | paritygame/Solvers 9 | paritygame/Solverregistry 10 | paritygame/Mdp 11 | paritygame/Paritygamebitset 12 | paritygame/Parsers 13 | paritygame/Specialsolve 14 | paritygame/Transformations 15 | solvers/Bigstep 16 | solvers/Dominiondecomp 17 | solvers/Externalsolver 18 | solvers/Fpiter 19 | solvers/Genetic 20 | solvers/Guessstrategy 21 | solvers/Localmodelchecker 22 | solvers/Optstratimprov 23 | solvers/Prioprom 24 | solvers/Priopromdelay 25 | solvers/Priopromplus 26 | solvers/Priopromrecovery 27 | solvers/Recursive 28 | solvers/Satsolve 29 | solvers/Smallprogress 30 | solvers/Stratimpralgs 31 | solvers/Stratimprdisc 32 | solvers/Stratimprlocal 33 | solvers/Stratimprlocal2 34 | solvers/Stratimprovement 35 | solvers/Stratimprsat 36 | solvers/Viasat 37 | solvers/stratimpralgs/Switch_cunningham 38 | solvers/stratimpralgs/Switch_globally_best 39 | solvers/stratimpralgs/Switch_history 40 | solvers/stratimpralgs/Switch_internal 41 | solvers/stratimpralgs/Switch_locally_best 42 | solvers/stratimpralgs/Switch_random 43 | solvers/stratimpralgs/Switch_snare 44 | solvers/stratimpralgs/Switch_zadeh 45 | solvers/Succinctsmallprogress 46 | paritygame/Generatorregistry 47 | paritygame/Generators 48 | generators/Randomgame 49 | generators/Laddergame 50 | generators/Clusteredrandomgame 51 | generators/Cliquegame 52 | generators/Modelcheckerladder 53 | generators/Recursiveladder 54 | generators/Steadygame 55 | generators/Jurdzinskigame 56 | generators/modelchecking/Mucalculus 57 | generators/modelchecking/Elevators 58 | generators/modelchecking/Roadworks 59 | generators/Towersofhanoi 60 | generators/Langincl 61 | generators/Recursivedullgame 62 | generators/policyiter/Stratimprgen 63 | generators/policyiter/Stratimprgenerators 64 | generators/policyiter/Stratimprgenlist 65 | generators/policyiter/generators/Zadehexp 66 | generators/policyiter/generators/Cunninghamexp 67 | generators/policyiter/generators/Zadehsubexp 68 | generators/policyiter/generators/Cunninghamsubexp 69 | generators/policyiter/generators/Fearnleysubexp 70 | generators/policyiter/generators/Friedmannsubexp 71 | generators/policyiter/generators/Switchallsubexp 72 | generators/policyiter/generators/Switchbestsubexp 73 | generators/policyiter/generators/Switchallexp 74 | generators/policyiter/generators/Switchbestexp 75 | generators/policyiter/generators/Randomfacetsubexp 76 | generators/policyiter/generators/Randomedgesubexp 77 | generators/policyiter/generators/Randomedgeexptest 78 | # OASIS_STOP 79 | -------------------------------------------------------------------------------- /src/pgsolver.mllib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 6b0dae0a47fa1502179a773eaff2ca9b) 3 | pgsolver/Basics 4 | pgsolver/Info 5 | paritygame/Paritygame 6 | paritygame/Verification 7 | paritygame/Univsolve 8 | paritygame/Solvers 9 | paritygame/Solverregistry 10 | paritygame/Mdp 11 | paritygame/Paritygamebitset 12 | paritygame/Parsers 13 | paritygame/Specialsolve 14 | paritygame/Transformations 15 | solvers/Bigstep 16 | solvers/Dominiondecomp 17 | solvers/Externalsolver 18 | solvers/Fpiter 19 | solvers/Genetic 20 | solvers/Guessstrategy 21 | solvers/Localmodelchecker 22 | solvers/Optstratimprov 23 | solvers/Prioprom 24 | solvers/Priopromdelay 25 | solvers/Priopromplus 26 | solvers/Priopromrecovery 27 | solvers/Recursive 28 | solvers/Satsolve 29 | solvers/Smallprogress 30 | solvers/Stratimpralgs 31 | solvers/Stratimprdisc 32 | solvers/Stratimprlocal 33 | solvers/Stratimprlocal2 34 | solvers/Stratimprovement 35 | solvers/Stratimprsat 36 | solvers/Viasat 37 | solvers/stratimpralgs/Switch_cunningham 38 | solvers/stratimpralgs/Switch_globally_best 39 | solvers/stratimpralgs/Switch_history 40 | solvers/stratimpralgs/Switch_internal 41 | solvers/stratimpralgs/Switch_locally_best 42 | solvers/stratimpralgs/Switch_random 43 | solvers/stratimpralgs/Switch_snare 44 | solvers/stratimpralgs/Switch_zadeh 45 | solvers/Succinctsmallprogress 46 | paritygame/Generatorregistry 47 | paritygame/Generators 48 | generators/Randomgame 49 | generators/Laddergame 50 | generators/Clusteredrandomgame 51 | generators/Cliquegame 52 | generators/Modelcheckerladder 53 | generators/Recursiveladder 54 | generators/Steadygame 55 | generators/Jurdzinskigame 56 | generators/modelchecking/Mucalculus 57 | generators/modelchecking/Elevators 58 | generators/modelchecking/Roadworks 59 | generators/Towersofhanoi 60 | generators/Langincl 61 | generators/Recursivedullgame 62 | generators/policyiter/Stratimprgen 63 | generators/policyiter/Stratimprgenerators 64 | generators/policyiter/Stratimprgenlist 65 | generators/policyiter/generators/Zadehexp 66 | generators/policyiter/generators/Cunninghamexp 67 | generators/policyiter/generators/Zadehsubexp 68 | generators/policyiter/generators/Cunninghamsubexp 69 | generators/policyiter/generators/Fearnleysubexp 70 | generators/policyiter/generators/Friedmannsubexp 71 | generators/policyiter/generators/Switchallsubexp 72 | generators/policyiter/generators/Switchbestsubexp 73 | generators/policyiter/generators/Switchallexp 74 | generators/policyiter/generators/Switchbestexp 75 | generators/policyiter/generators/Randomfacetsubexp 76 | generators/policyiter/generators/Randomedgesubexp 77 | generators/policyiter/generators/Randomedgeexptest 78 | # OASIS_STOP 79 | -------------------------------------------------------------------------------- /src/pgsolver/basics.ml: -------------------------------------------------------------------------------- 1 | let message_ch = ref stdout 2 | 3 | (* Verbosity levels: 0 = quiet, no messages at all 4 | * 1 = normal, result and timing information 5 | * 2 = alert, some more statistics 6 | * 3 = debug, swamp the user *) 7 | let verbosity = ref 1 8 | 9 | type verbosity_level = int 10 | 11 | let verbosity_level_verbose = 2 12 | 13 | let verbosity_level_default = 3 14 | 15 | let last_time = ref 0.0 16 | 17 | let init_message_timing _ = last_time := Sys.time () 18 | 19 | let message u s = if !verbosity >= u then 20 | begin 21 | output_string !message_ch (s ()); 22 | flush !message_ch 23 | end 24 | 25 | 26 | 27 | let message_depth u depth s = message u (fun x -> (String.make (depth * 2) ' ') ^ s x) 28 | 29 | let message_depth_tagged u depth tag s = 30 | message_depth u depth (fun x -> 31 | let now = Sys.time () in 32 | let msg = "[" ^ String.capitalize_ascii (tag x) ^ ": " ^ Printf.sprintf "%.2f msec" (1000.0 *. (now -. !last_time)) ^ "] " ^ s x in 33 | last_time := now; 34 | msg 35 | ) 36 | 37 | let message_depth_counter = ref 0 38 | let message_incrdepth _ = incr message_depth_counter 39 | let message_decrdepth _ = decr message_depth_counter 40 | 41 | let message_autod u = message_depth u !message_depth_counter 42 | 43 | let message_autotagged u = message_depth_tagged u !message_depth_counter 44 | 45 | let rec split_by_newline s = 46 | try 47 | let i = String.index s '\n' in 48 | let hd = String.sub s 0 (i + 1) in 49 | let tl = String.sub s (i + 1) (String.length s - i - 1) in 50 | hd::(split_by_newline tl) 51 | with Not_found -> 52 | if String.length s = 0 then [] else [s] 53 | 54 | let message_autotagged_newline u tag s = 55 | if !verbosity >= u 56 | then List.iter (fun t -> message_autotagged u tag (fun _ -> t)) (split_by_newline (s ())) 57 | -------------------------------------------------------------------------------- /src/pgsolver/basics.mli: -------------------------------------------------------------------------------- 1 | val message_ch : out_channel ref 2 | val verbosity : int ref 3 | 4 | type verbosity_level = int 5 | 6 | val init_message_timing : unit -> unit 7 | 8 | val verbosity_level_verbose: verbosity_level 9 | 10 | val verbosity_level_default: verbosity_level 11 | 12 | (* Calling message v (fun _ -> s) outputs the string s on STDOUT if the verbosity level is greater than or equal to v. *) 13 | val message : verbosity_level -> (unit -> string) -> unit 14 | 15 | val message_depth : verbosity_level -> int -> (unit -> string) -> unit 16 | 17 | val message_depth_tagged : verbosity_level -> int -> (unit -> string) -> (unit -> string) -> unit 18 | 19 | val message_incrdepth: unit -> unit 20 | val message_decrdepth: unit -> unit 21 | 22 | val message_autod : verbosity_level -> (unit -> string) -> unit 23 | 24 | val message_autotagged : verbosity_level -> (unit -> string) -> (unit -> string) -> unit 25 | 26 | (* val message_autotagged : verbosity_level -> (unit -> string) -> (unit -> string) -> unit *) 27 | 28 | val message_autotagged_newline : verbosity_level -> (unit -> string) -> (unit -> string) -> unit 29 | -------------------------------------------------------------------------------- /src/pgsolver/info.ml: -------------------------------------------------------------------------------- 1 | let pgsolver_collection_version = "4.3" 2 | let authors = "Oliver Friedmann (University of Munich) and Martin Lange (University of Kassel)" 3 | let timeperiod = "2008-2024" 4 | let url = "http://tcsprojects.org" 5 | 6 | let get_title s = 7 | "PGSolver Collection Ver. " ^ pgsolver_collection_version ^ ": " ^ 8 | s ^ "\n" ^ 9 | "Authors: " ^ authors ^ ", " ^ timeperiod ^ "\n" ^ 10 | url ^ "\n\n" 11 | -------------------------------------------------------------------------------- /src/pgsolver/info.mli: -------------------------------------------------------------------------------- 1 | val get_title: string -> string -------------------------------------------------------------------------------- /src/pgsolver/pgprofiling.ml: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | type prof_function = int 4 | 5 | let prof_priority = 0 6 | let prof_owner = 1 7 | let prof_successors = 2 8 | let prof_predecessors = 3 9 | let prof_definedcheck = 4 10 | let prof_untouched = [|0;0;0;0;0|] 11 | 12 | let prof_current_functions = ref [] 13 | 14 | let prof_start_time = ref 0.0 15 | 16 | module ProfTimingMap = Map.Make(struct 17 | type t = string 18 | let compare = compare 19 | end);; 20 | 21 | let prof_timing_map = ref ProfTimingMap.empty 22 | 23 | let prof_declare_originator s = 24 | prof_current_functions := s :: !prof_current_functions; 25 | prof_start_time := Sys.time () 26 | 27 | let prof_undeclare_originator _ = 28 | let e = Sys.time () -. !prof_start_time in 29 | match !prof_current_functions with 30 | f::fs -> prof_current_functions := fs; 31 | let t = try 32 | ProfTimingMap.find f !prof_timing_map 33 | with Not_found -> 0.0 34 | in 35 | prof_timing_map := ProfTimingMap.add f (t +. e) !prof_timing_map 36 | | [] -> failwith "Profiling.prof_undeclare_originator: no more profiled functions on the call stack!" 37 | 38 | module ProfNodes = Map.Make(struct 39 | type t = string * node 40 | let compare = compare 41 | end);; 42 | let prof_nodes = ref ProfNodes.empty 43 | 44 | let prof_access v i = 45 | match !prof_current_functions with 46 | f::_ -> let pv = try 47 | ProfNodes.find (f,v) !prof_nodes 48 | with Not_found -> prof_untouched 49 | in 50 | pv.(i) <- pv.(i) + 1; 51 | prof_nodes := ProfNodes.add (f,v) pv !prof_nodes 52 | | [] -> () 53 | 54 | let prof_print_results _ = 55 | print_string ("Profiling information:\n"); 56 | ProfTimingMap.iter (fun s -> fun t -> print_string ("Function \"" ^ s ^ "\":\n"); 57 | print_string (" overall runtime : " ^ string_of_float (t *. 1000.0) ^ "msec\n"); 58 | let (np,no,ns,nd,nc) = ProfNodes.fold (fun (f,_) -> fun acs -> fun (b0,b1,b2,b3,b4) -> 59 | if f=s then 60 | (b0+acs.(0), b1+acs.(1), b2+acs.(2), b3+acs.(3), b4+acs.(4)) 61 | else 62 | (b0,b1,b2,b3,b4)) 63 | !prof_nodes 64 | (0,0,0,0,0) 65 | in 66 | print_string (" accumulated accesses to\n"); 67 | print_string (" ..priority fields : " ^ string_of_int np ^ "\n"); 68 | print_string (" ..owner fields : " ^ string_of_int no ^ "\n"); 69 | print_string (" ..successor fields : " ^ string_of_int ns ^ "\n"); 70 | print_string (" ..predecessor fields : " ^ string_of_int nd ^ "\n"); 71 | print_string (" checks for (un)defined : " ^ string_of_int nc ^ "\n") 72 | ) 73 | !prof_timing_map 74 | 75 | -------------------------------------------------------------------------------- /src/pgsolver/pgprofiling.mli: -------------------------------------------------------------------------------- 1 | type prof_function 2 | 3 | val prof_priority : prof_function 4 | val prof_owner : prof_function 5 | val prof_successors : prof_function 6 | val prof_predecessors : prof_function 7 | val prof_definedcheck : prof_function 8 | 9 | val prof_declare_originator : string -> unit 10 | val prof_undeclare_originator : unit -> unit 11 | 12 | val prof_access : int -> prof_function -> unit 13 | 14 | val prof_print_results : unit -> unit 15 | -------------------------------------------------------------------------------- /src/pgsolver/whoiswho.mli: -------------------------------------------------------------------------------- 1 | val someone : unit -> string 2 | -------------------------------------------------------------------------------- /src/solvers/bigstep.ml: -------------------------------------------------------------------------------- 1 | (* The Big-Step Algorithm 2 | * 3 | * from: 4 | * Sven Schewe. Solving Parity Games in Big Steps. FSTTCS 2007: 449-460 5 | *) 6 | 7 | open Basics ;; 8 | open Paritygame ;; 9 | open Univsolve;; 10 | open Tcsarray;; 11 | open Smallprogress;; 12 | 13 | 14 | let solve_scc_restr game player u = 15 | let spmidx = Array.map (Array.map (fun m -> (0, min m u))) (compute_priority_reach_array game player) in 16 | 17 | let spmupd spmz _ = 18 | let l = Array.length spmz in 19 | let c = ref (Array.fold_left (fun r (v, _) -> r + v) 0 spmz) in 20 | for i = 0 to l - 1 do 21 | if (fst spmz.(i) > snd spmz.(i)) || (!c > u) then ( 22 | c := !c - (fst spmz.(i)); 23 | spmz.(i) <- (0, snd spmz.(i)); 24 | if (i < l - 1) then ( 25 | spmz.(i + 1) <- (1 + fst spmz.(i + 1), snd spmz.(i + 1)); 26 | incr c 27 | ) 28 | else for j = 0 to l - 1 do 29 | spmz.(j) <- (snd spmz.(j), snd spmz.(j)) 30 | done 31 | ) 32 | done 33 | in 34 | 35 | solve_scc_reach game player spmidx spmupd;; 36 | 37 | 38 | let solve_scc game = 39 | 40 | let n = pg_size game in 41 | let m = pg_max_prio game in 42 | let sqrt3 x = x ** (1.0 /. 3.0) in 43 | let u = int_of_float (ceil (sqrt3 (float (n * n * m)))) in 44 | 45 | let correct (sol, strat) pl = 46 | for i = 0 to n - 1 do 47 | if sol.(i) != pl then ( 48 | sol.(i) <- plr_undef; 49 | strat.(i) <- -1; 50 | ) 51 | done 52 | in 53 | 54 | let (sol, strat) = solve_scc_restr game plr_Even u in 55 | correct (sol, strat) plr_Even; 56 | 57 | if ArrayUtils.exists sol (fun _ pl -> pl != plr_undef) 58 | then (sol, strat) 59 | else ( 60 | let (sol, strat) = solve_scc_restr game plr_Odd u in 61 | correct (sol, strat) plr_Odd; 62 | (sol, strat) 63 | );; 64 | 65 | 66 | let solve game = Recursive.fallback_solve game solve_scc (universal_solve_init_options_verbose !universal_solve_global_options);; 67 | 68 | let register _ = 69 | Solverregistry.register_solver solve "bigstep" "bs" "use the big step procedure due to Schewe";; 70 | -------------------------------------------------------------------------------- /src/solvers/bigstep.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/dominiondecomp.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/externalsolver.ml: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | open Parsers ;; 3 | open Univsolve ;; 4 | open Basics;; 5 | 6 | let pipe : in_channel -> out_channel -> unit = fun c_in c_out -> 7 | let size = 4 * 1024 in 8 | let buffer = Bytes.create size in 9 | let eof = ref false in 10 | while not !eof do 11 | let len = input c_in buffer 0 size in 12 | if len > 0 13 | then output_string c_out (Bytes.sub_string buffer 0 len) 14 | else eof := true 15 | done;; 16 | 17 | let solve' : Solverregistry.global_solver_factory = fun args game -> 18 | let cmd = Array.get args 0 in 19 | let (c_out, c_in, c_err) : in_channel * out_channel * in_channel = Unix.open_process_full cmd [||] in 20 | let thread = (Thread.create (fun _ -> pipe c_err stderr) ()) in 21 | output_game c_in game; 22 | close_out c_in; 23 | let sol = parse_solution c_out in 24 | close_in c_out; 25 | Thread.join thread; 26 | let ret = Unix.close_process_full (c_out, c_in, c_err) in 27 | ignore ret; 28 | sol ;; 29 | let solve : Solverregistry.global_solver_factory = fun args -> 30 | universal_solve (universal_solve_init_options_verbose !universal_solve_global_options) (solve' args);; 31 | let register _ = 32 | Solverregistry.register_solver_factory solve "external_solver_univ" "esuniv" "directly solve by calling an executable"; 33 | Solverregistry.register_solver_factory solve' "external_solver" "es" "directly solve by calling an executable";; 34 | -------------------------------------------------------------------------------- /src/solvers/externalsolver.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve' : string array -> paritygame -> solution * strategy 4 | val solve : string array -> paritygame -> solution * strategy 5 | val register: unit -> unit 6 | -------------------------------------------------------------------------------- /src/solvers/fpiter.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/genetic.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/guessstrategy.ml: -------------------------------------------------------------------------------- 1 | (* The strategy guessing heuristic 2 | * 3 | * Why waste time computing winning strategies when all you have to do is pick them up from the floor? 4 | * Here is the simplest heuristc of them all: just guess a strategy and see what happens. 5 | * 6 | * from: 7 | * ... well, you guessed right (it's as if you just guessed a winning strategy, ha-ha-ha!). This has not 8 | * been published anywhere. We are still considering submitting it to LICS. Or POPL. Or STOC, FOCS, SODA, 9 | * any of them will do. 10 | *) 11 | 12 | 13 | open Basics ;; 14 | open Paritygame ;; 15 | open Univsolve;; 16 | 17 | let solve game = 18 | let solve' game = 19 | 20 | let msg_tagged v = message_autotagged v (fun _ -> "GUESSSTRATEGY") in 21 | let msg_plain = message in 22 | 23 | let generate_strat game pl = 24 | let n = pg_size game in 25 | let s = Array.make n (-1) in 26 | pg_iterate (fun v -> fun (_,pl',d,_,_) -> if (pl = pl') then s.(v) <- ns_some d) game; 27 | s 28 | in 29 | 30 | let heuristic_solve game = 31 | let n = pg_size game in 32 | let s0 = generate_strat game plr_Even in 33 | let s1 = generate_strat game plr_Odd in 34 | let (sol0, _) = universal_solve_trivial verbosity_level_default (subgame_by_strat game s0) in 35 | let (sol1, _) = universal_solve_trivial verbosity_level_default (subgame_by_strat game s1) in 36 | let sol = sol_init game (fun i -> if sol0.(i) = plr_Even then plr_Even else if sol1.(i) = plr_Odd then plr_Odd else plr_undef) in 37 | let strat = Array.init n (fun i -> if sol0.(i) = plr_Even then s0.(i) else if sol1.(i) = plr_Odd then s1.(i) else -1) in 38 | (sol, strat) 39 | in 40 | 41 | let counter = ref 0 in 42 | 43 | let rec iterate_strat game = 44 | incr counter; 45 | msg_tagged 2 (fun _ -> "Guessing strategy #" ^ string_of_int !counter ^ "\r"); 46 | let (sol, strat) = heuristic_solve game in 47 | let c = sol_number_solved sol in 48 | if c = 0 then iterate_strat game else ( 49 | msg_plain 2 (fun _ -> "\n"); 50 | msg_tagged 2 (fun _ -> "Returning " ^ string_of_int c ^ " solved nodes.\n"); 51 | (sol, strat) 52 | ) 53 | in 54 | 55 | iterate_strat game 56 | in 57 | universal_solve (universal_solve_init_options_verbose !universal_solve_global_options) solve' game;; 58 | 59 | 60 | let register _ = 61 | Solverregistry.register_solver solve "guessstrategy" "gs" "use the strategy guessing heuristic";; 62 | -------------------------------------------------------------------------------- /src/solvers/guessstrategy.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/localmodelchecker.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val partially_solve : partial_solver 4 | 5 | val solve : global_solver 6 | 7 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/optstratimprov.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/prioprom.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/priopromdelay.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/priopromplus.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/priopromrecovery.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/recursive.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | open Basics ;; 3 | open Univsolve;; 4 | 5 | val solve : paritygame -> solution * strategy 6 | val register : unit -> unit 7 | 8 | val solve2 : (paritygame -> solution * strategy) ref -> paritygame -> solution * strategy 9 | 10 | val fallback_solve: paritygame -> (paritygame -> solution * strategy) -> universal_solve_options -> solution * strategy 11 | 12 | val mcnaughton_zielonka : paritygame -> universal_solve_options -> solution * strategy 13 | 14 | -------------------------------------------------------------------------------- /src/solvers/satsolve.ml: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | open Basics ;; 3 | open Univsolve ;; 4 | open Tcstiming;; 5 | open Satwrapper;; 6 | 7 | 8 | type vars = 9 | Winning of int 10 | | Strategy of (int * int) 11 | | SubEdge of (player * int * int) 12 | | ReachLower of (player * int * int * int) 13 | 14 | 15 | let msg_tagged v = message_autotagged v (fun _ -> "SATSOLVE");; 16 | let msg_plain = message;; 17 | 18 | let solve' game = 19 | let solver = new Satwrapper.satWrapper (Satsolvers.get_default ()) None in 20 | 21 | msg_tagged 2 (fun _ -> "Using backend sat solver: " ^ (Satsolvers.get_default ())#identifier ^ "\n"); 22 | msg_tagged 2 (fun _ -> "Building constraints...\n"); 23 | 24 | let n = pg_size game in 25 | let prio_arr = Array.init n (fun i -> i) in 26 | Array.sort (fun i j -> compare (pg_get_priority game i) (pg_get_priority game j)) prio_arr; 27 | 28 | pg_iterate (fun i -> fun (_,_,d,_,_) -> let delta = Array.of_list (ns_nodes d) in 29 | solver#add_helper_exactlyone 0 (Array.length delta - 1) [||] (fun j -> Po (Strategy (i, delta.(j))))) game; 30 | 31 | pg_iterate (fun i -> fun (_,pl,delta,_,_) -> 32 | ns_iter (fun j -> 33 | solver#add_clause_array [|Ne (SubEdge (plr_Even, i, j)); Ne (Winning i)|]; 34 | solver#add_clause_array [|Ne (SubEdge (plr_Odd, i, j)); Po (Winning i)|]; 35 | solver#add_clause_array [|Ne (SubEdge (plr_Even, i, j)); Ne (Winning j)|]; 36 | solver#add_clause_array [|Ne (SubEdge (plr_Odd, i, j)); Po (Winning j)|]; 37 | solver#add_clause_array [|Ne (SubEdge (pl, i, j)); Po (Strategy (i, j))|]; 38 | solver#add_clause_array [|if pl = plr_Odd then Po (Winning i) else Ne (Winning i); Po (SubEdge (plr_opponent pl, i, j))|]; 39 | solver#add_clause_array [|if pl = plr_Odd then Ne (Winning i) else Po (Winning i); Ne (Strategy (i, j)); Po (SubEdge (pl, i, j))|] 40 | ) delta) game; 41 | 42 | plr_iterate (fun p -> 43 | pg_iterate (fun i -> fun _ -> 44 | pg_iterate (fun j -> fun _ -> 45 | if solver#mem_variable (SubEdge (p, i, j)) then ( 46 | solver#add_clause_array [|Ne (ReachLower (p, i, j, -1)); Po (SubEdge (p, i, j))|]; 47 | solver#add_clause_array [|Po (ReachLower (p, i, j, -1)); Ne (SubEdge (p, i, j))|] 48 | ) else ( 49 | solver#add_clause_array [|Ne (ReachLower (p, i, j, -1))|] 50 | ); 51 | for t = 0 to n - 1 do 52 | let s = prio_arr.(t) in 53 | let s_1 = if t = 0 then -1 else prio_arr.(t-1) in 54 | solver#add_clause_array [|Ne (ReachLower (p, i, j, s)); Po (ReachLower (p, i, j, s_1)); Po (ReachLower (p, i, s, s_1))|]; 55 | solver#add_clause_array [|Ne (ReachLower (p, i, j, s)); Po (ReachLower (p, i, j, s_1)); Po (ReachLower (p, s, j, s_1))|]; 56 | solver#add_clause_array [|Po (ReachLower (p, i, j, s)); Ne (ReachLower (p, i, j, s_1))|]; 57 | solver#add_clause_array [|Po (ReachLower (p, i, j, s)); Ne (ReachLower (p, i, s, s_1)); Ne (ReachLower (p, s, j, s_1))|]; 58 | done) game 59 | ) game); 60 | 61 | pg_iterate (fun i -> fun (pr,_,_,_,_) -> solver#add_clause_array [|Ne (ReachLower (plr_opponent (plr_benefits pr), i, i, i))|]) game; 62 | 63 | let v = solver#variable_count + solver#helper_variable_count in 64 | let c = solver#clause_count + solver#helper_clause_count in 65 | let l = solver#literal_count + solver#helper_literal_count in 66 | msg_tagged 2 (fun _ -> "Number of clauses: " ^ string_of_int c ^ " \n"); 67 | msg_tagged 2 (fun _ -> "Number of variables: " ^ string_of_int v ^ " \n"); 68 | msg_tagged 2 (fun _ -> "Number of literals: " ^ string_of_int l ^ " \n"); 69 | 70 | let tim = SimpleTiming.init false in 71 | msg_tagged 2 (fun _ -> SimpleTiming.start tim; "SAT Solving ... "); 72 | 73 | solver#solve; 74 | 75 | msg_plain 2 (fun _ -> SimpleTiming.stop tim; "done: " ^ SimpleTiming.format tim ^ "\n"); 76 | 77 | let satis = solver#get_solve_result = SolveSatisfiable in 78 | if not satis then failwith "impossible: unsatisfiable"; 79 | 80 | let sol = Array.init n (fun i -> if solver#get_variable (Winning i) = 0 then plr_Even else plr_Odd) in 81 | let strat = Array.init n (fun i -> if sol.(i) = pg_get_owner game i 82 | then let delta = Array.of_list (ns_nodes (pg_get_successors game i)) in 83 | delta.(solver#get_variable_first (Array.map (fun j -> Strategy (i, j)) delta)) else -1) 84 | in 85 | solver#dispose; 86 | (sol, strat);; 87 | 88 | 89 | let solve game = universal_solve (universal_solve_init_options_verbose !universal_solve_global_options) solve' game;; 90 | 91 | 92 | let register _ = Solverregistry.register_solver solve "satsolve" "ss" "directly solve the game by an NP predicate";; 93 | 94 | -------------------------------------------------------------------------------- /src/solvers/satsolve.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register : unit -> unit -------------------------------------------------------------------------------- /src/solvers/smallprogress.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve_scc_reach: paritygame -> player -> (int * int) array array -> ((int * int) array -> int -> unit) -> solution * strategy 4 | 5 | val solve : paritygame -> solution * strategy 6 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/smtsolve.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | -------------------------------------------------------------------------------- /src/solvers/stratimpralgs.mli: -------------------------------------------------------------------------------- 1 | open Paritygame 2 | open Tcsset 3 | 4 | val register: unit -> unit 5 | 6 | val enable_exp_bit_count: bool ref 7 | 8 | val get_last_exp_bit_count: unit -> int 9 | 10 | val get_last_iteration_count: unit -> int 11 | 12 | val _strat_impr_callback: (strategy -> int -> unit) option ref 13 | 14 | type node_total_ordering_fun = Paritygame.paritygame -> node -> node -> int 15 | 16 | val node_total_ordering_by_position : node_total_ordering_fun 17 | 18 | type node_valuation = node * node TreeSet.t * int 19 | type game_valuation = node_valuation array 20 | 21 | val evaluate_strategy : 22 | paritygame -> node_total_ordering_fun -> strategy -> game_valuation 23 | 24 | val strategy_improvable : 25 | paritygame -> node_total_ordering_fun -> strategy -> game_valuation -> bool 26 | 27 | val initial_strategy_by_best_reward : paritygame -> strategy 28 | 29 | val improvement_policy_optimize_all_locally : 30 | paritygame -> node_total_ordering_fun -> strategy -> game_valuation -> strategy 31 | 32 | val strategy_improvement_optimize_all_locally_policy: paritygame -> solution * strategy 33 | 34 | val best_decision_by_valuation_ordering : 35 | paritygame -> node_total_ordering_fun -> game_valuation -> node -> node 36 | 37 | val node_valuation_ordering : 38 | paritygame -> node_total_ordering_fun -> node_valuation -> node_valuation -> int 39 | 40 | val compute_counter_strategy: 41 | paritygame -> strategy -> strategy 42 | 43 | 44 | 45 | val register_sub_solver: (paritygame -> solution * strategy) -> string -> string -> string -> unit 46 | 47 | 48 | type initial_strategy_fun = paritygame -> strategy 49 | 50 | type 'a improvement_policy_fun = paritygame -> node_total_ordering_fun -> 'a -> strategy -> game_valuation -> strategy * 'a 51 | 52 | val strategy_improvement: paritygame -> initial_strategy_fun -> node_total_ordering_fun -> 'a improvement_policy_fun -> 'a -> bool -> string -> solution * strategy 53 | 54 | val strategy_improvement'': paritygame -> initial_strategy_fun -> node_total_ordering_fun -> 'a improvement_policy_fun -> (paritygame -> 'a) -> bool -> string -> solution * strategy 55 | 56 | val strategy_improvement_by_policy: paritygame -> 'a improvement_policy_fun -> 'a -> bool -> string -> solution * strategy 57 | 58 | 59 | val improvement_policy_no_user_data: ('a -> 'b -> 'c -> 'd -> 'e) -> 'a -> 'b -> 'f -> 'c -> 'd -> 'e * 'f 60 | 61 | val node_valuation_total_ordering: paritygame -> node_total_ordering_fun -> game_valuation -> node -> node -> int 62 | 63 | val best_decision_by_ordering: paritygame -> (node -> node -> int) -> node -> int 64 | 65 | val empty_descending_relevance_ordered_set: paritygame -> node_total_ordering_fun -> node TreeSet.t 66 | 67 | val initial_strategy_by_last_edge: paritygame -> strategy 68 | 69 | val winning_strategies: paritygame -> node_total_ordering_fun -> strategy -> game_valuation -> strategy 70 | 71 | 72 | 73 | type mdplike_valuation = (((node, float) TreeMap.t) * bool option) array 74 | 75 | val mdplike_valuation: paritygame -> int -> strategy -> mdplike_valuation 76 | 77 | val compare_mdplike_valuation: paritygame -> mdplike_valuation -> node -> node -> int 78 | 79 | -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_cunningham.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_globally_best.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_history.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_internal.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_locally_best.ml: -------------------------------------------------------------------------------- 1 | open Stratimpralgs;; 2 | open Paritygame;; 3 | open Tcsset;; 4 | open Tcsbasedata;; 5 | open Univsolve;; 6 | open Tcsarray;; 7 | open Tcslist;; 8 | open Tcsgraph;; 9 | 10 | let array_max a less = ArrayUtils.max_elt (fun x y -> if less x y then -1 else 1) a 11 | let list_max a less = ListUtils.max_elt (fun x y -> if less x y then -1 else 1) a 12 | 13 | 14 | let evaluate_player1_strategy game node_compare strategy = 15 | let game' = pg_copy game in 16 | for i = 0 to pg_size game' - 1 do 17 | pg_set_priority game' i (1 + pg_get_priority game' i); 18 | pg_set_owner game' i (plr_opponent (pg_get_owner game' i)) 19 | done; 20 | evaluate_strategy game' node_compare strategy 21 | 22 | let improvement_policy_by_counterstrategy game node_compare old_strategy valu = 23 | let n = pg_size game in 24 | let tau = winning_strategies game node_compare (Array.make n (-1)) valu in 25 | let valutau = evaluate_player1_strategy game node_compare tau in 26 | let find i = 27 | let ordering_valu x y = node_valuation_total_ordering game node_compare valu x y >= 0 in 28 | let ordering_valutau x y = node_valuation_total_ordering game node_compare valutau x y >= 0 in 29 | let tr = pg_get_successors game i in 30 | let a = ns_filter (fun j -> ordering_valu j old_strategy.(i)) tr in 31 | ns_max a (fun x y -> ordering_valutau y x) 32 | in 33 | let strategy = Array.mapi (fun i j -> 34 | if j = -1 then -1 35 | else let k = find i in 36 | if node_valuation_ordering game node_compare valu.(j) valu.(k) < 0 37 | then k 38 | else j 39 | ) old_strategy in 40 | let fnd = ref false in 41 | for i = 0 to n - 1 do 42 | fnd := !fnd || (strategy.(i) != old_strategy.(i)) 43 | done; 44 | if !fnd 45 | then strategy 46 | else improvement_policy_optimize_all_locally game node_compare old_strategy valu 47 | 48 | 49 | 50 | let improvement_policy_optimize_best_locally game node_total_ordering old_strategy valu = 51 | let n = pg_size game in 52 | let l = ref [] in 53 | for i = 0 to n - 1 do 54 | if old_strategy.(i) > -1 55 | then let k = best_decision_by_valuation_ordering game node_total_ordering valu i in 56 | if node_valuation_ordering game node_total_ordering valu.(old_strategy.(i)) valu.(k) < 0 57 | then l := (i, k)::!l 58 | done; 59 | let strategy = Array.copy old_strategy in 60 | let v i a = 61 | (* 62 | let (x, y, z) = valu.(a) in 63 | (x, TreeSet.add i y, z) 64 | *) 65 | valu.(a) 66 | in 67 | if not (!l = []) then ( 68 | let (i, k) = list_max !l (fun (i, a) (j, b) -> node_valuation_ordering game node_total_ordering (v i a) (v j b) < 0) in 69 | strategy.(i) <- k 70 | ); 71 | strategy 72 | 73 | 74 | 75 | 76 | let improvement_policy_optimize_worst_locally game node_total_ordering old_strategy valu = 77 | let n = pg_size game in 78 | let l = ref [] in 79 | for i = 0 to n - 1 do 80 | if old_strategy.(i) > -1 81 | then let k = best_decision_by_valuation_ordering game node_total_ordering valu i in 82 | if node_valuation_ordering game node_total_ordering valu.(old_strategy.(i)) valu.(k) < 0 83 | then l := (i, k)::!l 84 | done; 85 | let strategy = Array.copy old_strategy in 86 | let v i a = 87 | let (x, y, z) = valu.(a) in 88 | (x, TreeSet.add i y, z) 89 | in 90 | if not (!l = []) then ( 91 | let (i, k) = list_max !l (fun (i, a) (j, b) -> node_valuation_ordering game node_total_ordering (v i a) (v j b) > 0) in 92 | strategy.(i) <- k 93 | ); 94 | strategy 95 | 96 | 97 | 98 | 99 | 100 | 101 | let strategy_improvement_by_counterstrategy_policy game = 102 | strategy_improvement_by_policy game (improvement_policy_no_user_data improvement_policy_by_counterstrategy) () false "STRIMPR_BYCOU";; 103 | 104 | 105 | let strategy_improvement_optimize_best_locally_policy game = 106 | strategy_improvement game initial_strategy_by_best_reward node_total_ordering_by_position (improvement_policy_no_user_data improvement_policy_optimize_best_locally) () false "STRIMPR_LOCOPTBEST";; 107 | 108 | let strategy_improvement_optimize_worst_locally_policy game = 109 | strategy_improvement_by_policy game (improvement_policy_no_user_data improvement_policy_optimize_worst_locally) () false "STRIMPR_LOCOPTWORST";; 110 | 111 | 112 | 113 | 114 | 115 | 116 | let register _ = 117 | register_sub_solver 118 | (fun g -> universal_solve (universal_solve_init_options_verbose !universal_solve_global_options) strategy_improvement_optimize_best_locally_policy g) 119 | "strimprlocbest" "sibe" "use strategy improvement w. single best local optimization"; 120 | register_sub_solver 121 | (fun g -> universal_solve (universal_solve_init_options_verbose !universal_solve_global_options) strategy_improvement_optimize_worst_locally_policy g) 122 | "strimprlocwrst" "siwo" "use strategy improvement w. single worst local optimization";; 123 | 124 | -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_locally_best.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_random.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_snare.ml: -------------------------------------------------------------------------------- 1 | open Stratimpralgs;; 2 | open Paritygame;; 3 | open Tcsset;; 4 | open Tcsbasedata;; 5 | open Univsolve;; 6 | open Tcsarray;; 7 | open Tcslist;; 8 | open Tcsgraph;; 9 | 10 | 11 | let default_snare_sel _ _ _ _ snares = 12 | match snares with 13 | [] -> None 14 | | x::_ -> Some x 15 | 16 | let rec improvement_policy_snare_based sub_policy snare_sel game node_total_ordering (snares, enforce) old_strategy valu = 17 | let cmp i j = node_valuation_ordering game node_total_ordering valu.(i) valu.(j) in 18 | let valx i = let (_, x, _) = valu.(i) in x in 19 | match enforce with 20 | Some (sna,str,esc) -> ( 21 | let fnd = ref None in 22 | TreeSet.iter (fun (i,j) -> 23 | if cmp j old_strategy.(i) > 0 then fnd := Some (i,j) 24 | ) str; 25 | match !fnd with 26 | Some (i,j) -> ( 27 | let new_strat = Array.copy old_strategy in 28 | new_strat.(i) <- j; 29 | (new_strat, (snares, enforce)) 30 | ) 31 | | None -> improvement_policy_snare_based sub_policy snare_sel game node_total_ordering (snares, None) old_strategy valu 32 | ) 33 | | None -> ( 34 | (* Update set of snares *) 35 | let snares = ref snares in 36 | pg_iterate (fun i (_, pl, tr, _, _) -> 37 | if pl = plr_Even then ( 38 | ns_iter (fun j -> 39 | if (cmp j old_strategy.(i) > 0) && (TreeSet.mem i (valx j)) then ( 40 | let sna = ref TreeSet.empty_def in 41 | let todo = ref (TreeSet.singleton_def j) in 42 | while not (TreeSet.is_empty !todo) do 43 | let k = TreeSet.min_elt !todo in 44 | todo := TreeSet.remove k !todo; 45 | if (not (TreeSet.mem k !sna)) && (TreeSet.mem i (valx k)) then ( 46 | sna := TreeSet.add k !sna; 47 | let pl = pg_get_owner game k in 48 | let tr = pg_get_successors game k in 49 | if pl = plr_Even then todo := TreeSet.add old_strategy.(k) !todo 50 | else ns_iter (fun j -> todo := TreeSet.add j !todo) tr 51 | ) 52 | done; 53 | let esc = ref TreeSet.empty_def in 54 | let str = ref TreeSet.empty_def in 55 | TreeSet.iter (fun k -> 56 | let pl = pg_get_owner game k in 57 | let tr = pg_get_successors game k in 58 | if i = k then str := TreeSet.add (i, j) !str 59 | else if pl = plr_Even then str := TreeSet.add (k,old_strategy.(k)) !str 60 | else ns_iter (fun j -> if not (TreeSet.mem j !sna) then esc := TreeSet.add (k,j) !esc) tr 61 | ) !sna; 62 | snares := (!sna,!str,!esc)::!snares 63 | ) 64 | ) tr 65 | ) 66 | ) game; 67 | (* Filter set of applicable snares *) 68 | let appsnares = List.filter (fun (_,_,esc) -> 69 | TreeSet.for_all (fun (i,j) -> 70 | not (TreeSet.equal (valx i) (TreeSet.add i (valx j))) 71 | ) esc 72 | ) !snares in 73 | match (snare_sel game node_total_ordering old_strategy valu appsnares) with 74 | Some snare -> ( 75 | improvement_policy_snare_based sub_policy snare_sel game node_total_ordering (!snares, Some snare) old_strategy valu 76 | ) 77 | | None -> (sub_policy game node_total_ordering old_strategy valu, (!snares, None)) 78 | ) 79 | 80 | 81 | 82 | let strategy_improvement_snare_policy game = 83 | strategy_improvement game initial_strategy_by_best_reward node_total_ordering_by_position (improvement_policy_snare_based improvement_policy_optimize_all_locally default_snare_sel) ([], None) true "STRIMPR_SNARE";; 84 | 85 | 86 | 87 | 88 | let register _ = 89 | register_sub_solver 90 | (fun g -> universal_solve (universal_solve_init_options_verbose !universal_solve_global_options) strategy_improvement_snare_policy g) 91 | "snarememo" "sm" "Snare memorization policy iteration";; 92 | 93 | -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_snare.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimpralgs/switch_zadeh.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimprdisc.mli: -------------------------------------------------------------------------------- 1 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimprlocal.mli: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | val partially_solve : partial_solver 4 | 5 | val solve : global_solver 6 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimprlocal2.mli: -------------------------------------------------------------------------------- 1 | open Paritygame;; 2 | 3 | val partially_solve : partial_solver 4 | 5 | val solve : global_solver 6 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimprovement.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/stratimprsat.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register: unit -> unit -------------------------------------------------------------------------------- /src/solvers/succinctsmallprogress.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register : unit -> unit -------------------------------------------------------------------------------- /src/solvers/viasat.mli: -------------------------------------------------------------------------------- 1 | open Paritygame ;; 2 | 3 | val solve : paritygame -> solution * strategy 4 | val register : unit -> unit -------------------------------------------------------------------------------- /src/tools/auso.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Basics ;; 5 | open Paritygame ;; 6 | open Tcsstrings ;; 7 | open Str ;; 8 | open Stratimpralgs;; 9 | open Tcslist;; 10 | open Tcsarray;; 11 | 12 | let out s = 13 | print_string s; 14 | flush stdout 15 | 16 | let _ = 17 | let header = Info.get_title "Parity Game to AUSO / GridUSO transformer" in 18 | 19 | SimpleArgs.parsedef [] (fun _ -> ()) (header ^ "Usage: auso\n" ^ 20 | "Computes the AUSO / GridUSO associated with a parity game."); 21 | 22 | let (in_channel,name) = (stdin,"STDIN") in 23 | 24 | let game = Parsers.parse_parity_game in_channel in 25 | let n = pg_size game in 26 | 27 | (* Remove trivial player 0 nodes *) 28 | pg_iterate (fun i -> fun (_,pl,tr,_,_) -> if (pl = plr_Even) && (ns_size tr = 1) 29 | then pg_set_owner game i plr_Odd) 30 | game; 31 | 32 | (* Multiplier Table *) 33 | let m = Array.make n 1 in 34 | for i = n-1 downto 1 do 35 | let pl = pg_get_owner game i in 36 | let tr = pg_get_successors game i in 37 | if (pl = plr_Even) 38 | then m.(i-1) <- ns_size tr * m.(i) 39 | else m.(i-1) <- m.(i) 40 | done; 41 | 42 | (* Map Strategies to Ints *) 43 | let strategy_to_int strategy = 44 | let x = ref 0 in 45 | for i = n-1 downto 0 do 46 | let pl = pg_get_owner game i in 47 | let tr = pg_get_successors game i in 48 | if (pl = plr_Even) then ( 49 | let j = ArrayUtils.index_of (Array.of_list (ns_nodes tr)) strategy.(i) in 50 | x := !x + m.(i) * j; 51 | ) 52 | done; 53 | !x 54 | in 55 | 56 | (* Map Int to Strategies *) 57 | (* 58 | let int_to_strategy numb = 59 | let strategy = Array.make n (-1) in 60 | let numb = ref numb in 61 | for i = 0 to n-1 do 62 | let (_, pl, tr, _) = game.(i) in 63 | if (pl = 0) then ( 64 | strategy.(i) <- tr.(!numb / m.(i)); 65 | numb := !numb mod m.(i); 66 | ) 67 | done; 68 | strategy 69 | in 70 | *) 71 | 72 | let format_strategy strategy = 73 | let s = ref "" in 74 | for i = 0 to n-1 do 75 | let pl = pg_get_owner game i in 76 | let tr = pg_get_successors game i in 77 | if (pl = plr_Even) then ( 78 | let j = ArrayUtils.index_of (Array.of_list (ns_nodes tr)) strategy.(i) in 79 | s := !s ^ string_of_int j 80 | ) 81 | done; 82 | !s 83 | in 84 | 85 | let rec iterate strategy index callback = 86 | if index >= n 87 | then callback strategy 88 | else 89 | let pl = pg_get_owner game index in 90 | let tr = (Array.of_list (ns_nodes (pg_get_successors game index))) in 91 | if pl = plr_Odd 92 | then iterate strategy (index + 1) callback 93 | else 94 | for j = 0 to Array.length tr - 1 do 95 | strategy.(index) <- tr.(j); 96 | iterate strategy (index + 1) callback 97 | done 98 | in 99 | 100 | out "* "; 101 | pg_iterate (fun i -> fun (_,pl,_,_,desc) -> if pl = plr_Even then 102 | match desc with 103 | None -> print_string " _" | 104 | Some s -> print_string (" " ^ s)) game; 105 | out "\n"; 106 | 107 | iterate (Array.make n (-1)) 0 (fun strategy -> 108 | let temp = Array.copy strategy in 109 | let valu = evaluate_strategy game node_total_ordering_by_position strategy in 110 | let l = ref [] in 111 | let k = ref [] in 112 | pg_iterate (fun i -> fun (_,pl,succs,_,_) -> let tr = Array.of_list (ns_nodes succs) in 113 | if (pl = plr_Even) then 114 | for j = 0 to Array.length tr - 1 do 115 | let c = node_valuation_ordering game node_total_ordering_by_position valu.(strategy.(i)) valu.(tr.(j)) in 116 | if (c != 0) then ( 117 | temp.(i) <- tr.(j); 118 | if c < 0 119 | then l := strategy_to_int temp :: !l 120 | else k := strategy_to_int temp :: !k; 121 | temp.(i) <- strategy.(i) 122 | ) 123 | done; 124 | ) game; 125 | let l = List.rev !l in 126 | let k = List.rev !k in 127 | out (string_of_int (strategy_to_int strategy) ^ "(" ^ format_strategy strategy ^ "): "); 128 | out (ListUtils.custom_format string_of_int "" "" ", " l); 129 | out (" | "); 130 | out (ListUtils.custom_format string_of_int "" "" ", " k); 131 | out ("\n"); 132 | ); 133 | 134 | out "\n";; 135 | -------------------------------------------------------------------------------- /src/tools/combine.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | 4 | 5 | module CommandLine = 6 | struct 7 | let input_files = ref [] 8 | 9 | let speclist = [] 10 | 11 | let header = Info.get_title "Combine Tool" 12 | end ;; 13 | 14 | 15 | open CommandLine ;; 16 | 17 | let _ = 18 | SimpleArgs.parsedef speclist (fun f -> input_files := f::!input_files) (header ^ "Usage: combine [infile] [infile] ... [infile]\n" ^ 19 | "Combines all specified parity games into one game."); 20 | 21 | 22 | let in_channels = List.map open_in !input_files in 23 | 24 | let games = List.map Parsers.parse_parity_game in_channels in 25 | 26 | let game = Transformations.combine_games (List.rev games) in 27 | 28 | Paritygame.print_game game 29 | -------------------------------------------------------------------------------- /src/tools/complexdecomp.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Basics ;; 5 | open Paritygame ;; 6 | open Tcsstrings ;; 7 | open Tcslist;; 8 | open Str ;; 9 | open Stratimpralgs;; 10 | open Tcsset;; 11 | 12 | let out s = 13 | print_string s; 14 | flush stdout 15 | 16 | let _ = 17 | let header = Info.get_title "Graph Complexity Decomposition Tool" in 18 | 19 | SimpleArgs.parsedef [] (fun _ -> ()) (header ^ "Usage: game | ./complexdecomp\n" ^ 20 | "Computes graph complexity decomposition."); 21 | 22 | let (in_channel,name) = (stdin,"STDIN") in 23 | 24 | let game = Parsers.parse_parity_game in_channel in 25 | 26 | let number_of_nodes = ref 0 in 27 | let number_of_player0_nodes = ref 0 in 28 | let number_of_player1_nodes = ref 0 in 29 | let min_priority = ref (-1) in 30 | let max_priority = ref (-1) in 31 | let number_of_edges = ref 0 in 32 | let number_of_player0_edges = ref 0 in 33 | let number_of_player1_edges = ref 0 in 34 | 35 | pg_iterate (fun i -> fun (pr,pl,tr,_,_) -> let trn = ns_size tr in 36 | incr number_of_nodes; 37 | number_of_edges := !number_of_edges + trn; 38 | if pl = plr_Even then ( 39 | incr number_of_player0_nodes; 40 | number_of_player0_edges := !number_of_player0_edges + trn 41 | ) 42 | else ( 43 | incr number_of_player1_nodes; 44 | number_of_player1_edges := !number_of_player1_edges + trn 45 | ); 46 | if (!min_priority < 0) || (pr < !min_priority) then min_priority := pr; 47 | if (!max_priority < 0) || (pr > !max_priority) then max_priority := pr 48 | ) game; 49 | 50 | out ("Number of Nodes : " ^ string_of_int !number_of_nodes ^ "\n"); 51 | out ("Number of P0 Nodes : " ^ string_of_int !number_of_player0_nodes ^ "\n"); 52 | out ("Number of P1 Nodes : " ^ string_of_int !number_of_player1_nodes ^ "\n"); 53 | out ("Minimum Priority : " ^ string_of_int !min_priority ^ "\n"); 54 | out ("Maximum Priority : " ^ string_of_int !max_priority ^ "\n"); 55 | out ("Number of Edges : " ^ string_of_int !number_of_edges ^ "\n"); 56 | out ("Number of P0 Edges : " ^ string_of_int !number_of_player0_edges ^ "\n"); 57 | out ("Number of P1 Edges : " ^ string_of_int !number_of_player1_edges ^ "\n"); 58 | out "\n"; 59 | out ("Finding optimal strategies using strategy iteration... "); 60 | 61 | let sigma = ref [||] in 62 | _strat_impr_callback := Some (fun strat _ -> sigma := strat); 63 | let (_, _) = strategy_improvement_optimize_all_locally_policy game in 64 | _strat_impr_callback := None; 65 | let sigma = !sigma in 66 | 67 | let tau = compute_counter_strategy game sigma in 68 | 69 | out "done.\n"; 70 | 71 | out ("Optimal player 0 strategy: " ^ format_strategy sigma ^ "\n"); 72 | out ("Optimal player 1 strategy: " ^ format_strategy tau ^ "\n"); 73 | 74 | out "\n"; 75 | 76 | let game' = subgame_by_strat game sigma in 77 | 78 | let rec helper game indent sccfilter = 79 | let (sccs', _, topology', _) = strongly_connected_components game in 80 | let sccs = Array.map (fun scc -> if sccfilter scc then scc else ns_empty) sccs' in 81 | let topology = Array.mapi (fun i -> List.filter (fun j -> not (ns_isEmpty sccs.(j)))) topology' in 82 | 83 | Array.iteri (fun i nodes -> 84 | if not (ns_isEmpty nodes) then ( 85 | out (indent ^ "SCC #" ^ string_of_int i ^ " -> " ^ ListUtils.format string_of_int topology.(i) ^ " : " ^ ListUtils.format string_of_int (ns_nodes nodes) ^ "\n"); 86 | if (ns_size nodes > 1) then ( 87 | let sub = pg_copy game in 88 | let subnodes = nodes in 89 | ns_iter (fun v -> 90 | if (pg_get_owner game v = plr_Odd) && (not (ns_elem tau.(v) subnodes)) 91 | then 92 | begin 93 | ns_iter (fun w -> pg_del_edge sub v w) (pg_get_successors sub v); 94 | pg_add_edge sub v tau.(v) 95 | end 96 | ) nodes; 97 | helper sub (indent ^ " ") (fun scc -> ns_elem (ns_first scc) subnodes); 98 | ) 99 | ) 100 | ) sccs 101 | in 102 | 103 | helper game' "" (fun _ -> true); 104 | 105 | out "\n\n";; 106 | 107 | -------------------------------------------------------------------------------- /src/tools/compressor.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Basics ;; 4 | open Paritygame;; 5 | open Transformations;; 6 | 7 | 8 | 9 | let sccs_perform_inplace game performer = 10 | let (sccs, sccindex, topology, roots) = strongly_connected_components game in 11 | let visited = Array.make (Array.length sccs) false in 12 | 13 | let handlescc r = 14 | let subgame = subgame_by_list game sccs.(r) in 15 | performer subgame; 16 | let i = ref 0 in 17 | ns_iter (fun j -> 18 | pg_set_priority game j (pg_get_priority subgame !i); 19 | pg_set_owner game j (pg_get_owner subgame !i); 20 | incr i 21 | ) sccs.(r); 22 | in 23 | 24 | let rec perform r = 25 | if not visited.(r) then ( 26 | List.iter perform topology.(r); 27 | handlescc r; 28 | visited.(r) <- true 29 | ) 30 | in 31 | 32 | List.iter perform roots;; 33 | 34 | 35 | 36 | module CommandLine = 37 | struct 38 | let priority_compression = ref false 39 | let keep_fake_alternation = ref false 40 | 41 | let priority_propagation = ref false 42 | let anti_propagation = ref false 43 | 44 | let on_sccs = ref true 45 | 46 | let node_compression = ref false 47 | let input_file = ref "" 48 | 49 | let speclist = [(["--priorities"; "-pr"], Unit(fun _ -> priority_compression := true), 50 | "\n priority compression") ; 51 | (["--fakealt"; "-fa"], Unit(fun _ -> keep_fake_alternation := true), 52 | "\n keep fake alternation w.r.t. priorities") ; 53 | (["--priopropagation"; "-pp"], Unit(fun _ -> priority_propagation := true), 54 | "\n perform priority propagation") ; 55 | (["--antipropagation"; "-ap"], Unit(fun _ -> anti_propagation := true), 56 | "\n perform anti propagation") ; 57 | (["--wholegame"; "-wg"], Unit(fun _ -> on_sccs := false), 58 | "\n perform compression on the whole game instead of on the sccs") ; 59 | (["--nodes"; "-no"], Unit(fun _ -> node_compression := true), 60 | "\n node compression") ] 61 | 62 | let header = Info.get_title "Compressor Tool" 63 | end ;; 64 | 65 | open CommandLine ;; 66 | 67 | 68 | let _ = 69 | SimpleArgs.parsedef speclist (fun f -> input_file := f) (header ^ "Usage: compressor [options] [infile]\n" ^ 70 | "Compresses the parity game given in . If this argument is omitted it reads a game from STDIN.\n\nOptions are"); 71 | 72 | let in_channel = if !input_file = "" then stdin else open_in !input_file in 73 | 74 | let game = ref (Parsers.parse_parity_game in_channel) in 75 | 76 | if !anti_propagation 77 | then (if !on_sccs then sccs_perform_inplace !game anti_propagation_inplace else anti_propagation_inplace !game); 78 | 79 | if !priority_propagation 80 | then (if !on_sccs then sccs_perform_inplace !game priority_propagation_inplace else priority_propagation_inplace !game); 81 | 82 | if !priority_compression 83 | then (if !on_sccs then sccs_perform_inplace !game (fun g -> let _ = compact_prio_inplace g (not !keep_fake_alternation) in ()) else let _ = compact_prio_inplace !game (not !keep_fake_alternation) in ()); 84 | 85 | if !node_compression 86 | then ( 87 | let (game', _, _) = compress_nodes !game in 88 | game := game' 89 | ); 90 | 91 | Paritygame.print_game !game 92 | -------------------------------------------------------------------------------- /src/tools/fullimprarena.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Basics ;; 5 | open Paritygame ;; 6 | open Tcsstrings ;; 7 | open Str ;; 8 | open Stratimpralgs;; 9 | open Tcsset;; 10 | 11 | let out s = 12 | print_string s; 13 | flush stdout 14 | 15 | let _ = 16 | let header = Info.get_title "Parity Game Improvement Arena Tool" in 17 | 18 | SimpleArgs.parsedef [] (fun _ -> ()) (header ^ "Usage: fullimprarena\n" ^ 19 | "Provides some information about a parity game improvement arena."); 20 | 21 | let (in_channel,name) = (stdin,"STDIN") in 22 | 23 | let game = Parsers.parse_parity_game in_channel in 24 | 25 | let print_strat strategy = 26 | let valu = evaluate_strategy game node_total_ordering_by_position strategy in 27 | 28 | let compare_by_desc i j = 29 | compare (pg_get_desc game i) (pg_get_desc game j) 30 | in 31 | 32 | let ordered = ref (TreeSet.empty compare_by_desc) in 33 | let longest = ref 0 in 34 | 35 | pg_iterate (fun i -> fun (_,_,_,_,desc) -> longest := max !longest (String.length (OptionUtils.get_some desc)); 36 | ordered := TreeSet.add i !ordered) game; 37 | 38 | let getd i = (StringUtils.fillup (OptionUtils.get_some (pg_get_desc game i)) !longest ' ') in 39 | 40 | TreeSet.iter (fun i -> 41 | out (getd i); 42 | out " | "; 43 | let pl = pg_get_owner game i in 44 | let tr = pg_get_successors game i in 45 | let j = 46 | if pl = plr_Even then strategy.(i) 47 | else best_decision_by_valuation_ordering game node_total_ordering_by_position valu i 48 | in 49 | out (getd j); 50 | out " | "; 51 | if pl = plr_Even then ( 52 | ns_iter (fun j -> 53 | if node_valuation_ordering game node_total_ordering_by_position valu.(strategy.(i)) valu.(j) < 0 54 | then out (getd j ^ " "); 55 | ) tr; 56 | ); 57 | out "\n"; 58 | ) !ordered; 59 | out "\n\n"; 60 | in 61 | 62 | let rec iterate_strat strategy i = 63 | if i >= pg_size game 64 | then print_strat strategy 65 | else ( 66 | let pl = pg_get_owner game i in 67 | let tr = pg_get_successors game i in 68 | if pl = plr_Odd 69 | then iterate_strat strategy (i + 1) 70 | else ns_iter (fun j -> 71 | strategy.(i) <- j; 72 | iterate_strat strategy (i + 1) 73 | ) tr 74 | ) 75 | in 76 | 77 | let strategy = Array.make (pg_size game) (-1) in 78 | 79 | iterate_strat strategy 0; 80 | 81 | out "\n";; 82 | -------------------------------------------------------------------------------- /src/tools/imprarena.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Tcsbasedata;; 4 | open Basics ;; 5 | open Paritygame ;; 6 | open Tcsstrings ;; 7 | open Str ;; 8 | open Stratimpralgs;; 9 | open Tcsset;; 10 | 11 | let out s = 12 | print_string s; 13 | flush stdout 14 | 15 | let _ = 16 | let header = Info.get_title "Parity Game Improvement Arena Tool" in 17 | 18 | SimpleArgs.parsedef [] (fun _ -> ()) (header ^ "Usage: imprarena\n" ^ 19 | "Provides some information about a parity game improvement arena."); 20 | 21 | let (in_channel,name) = (stdin,"STDIN") in 22 | 23 | let game = Parsers.parse_parity_game in_channel in 24 | 25 | let pre_strategy = Array.make (pg_size game) "" in 26 | 27 | let rg = Str.regexp "\\(.*\\)\\[\\(.*\\)\\]" in 28 | 29 | pg_iterate (fun i -> fun (_,ow,_,_,desc) -> if ow = plr_Even then ( 30 | let desc = OptionUtils.get_some desc in 31 | if not (Str.string_match rg desc 0) then failwith "No strategy included!"; 32 | pre_strategy.(i) <- Str.matched_group 2 desc; 33 | pg_set_desc game i (Some (Str.matched_group 1 desc)) 34 | ) 35 | ) game; 36 | 37 | let strategy = Array.init (pg_size game) (fun i -> 38 | if pre_strategy.(i) = "" then -1 39 | else pg_find_desc game (Some pre_strategy.(i)) 40 | ) in 41 | 42 | let valu = evaluate_strategy game node_total_ordering_by_position strategy in 43 | 44 | let compare_by_desc i j = 45 | compare (pg_get_desc game i) (pg_get_desc game j) 46 | in 47 | 48 | let ordered = ref (TreeSet.empty compare_by_desc) in 49 | let longest = ref 0 in 50 | 51 | pg_iterate (fun i -> fun (_,_,_,_,desc) -> longest := max !longest (String.length (OptionUtils.get_some desc)); 52 | ordered := TreeSet.add i !ordered) game; 53 | 54 | let getd i = (StringUtils.fillup (OptionUtils.get_some (pg_get_desc game i)) !longest ' ') in 55 | 56 | TreeSet.iter (fun i -> 57 | out (getd i); 58 | out " | "; 59 | let pl = pg_get_owner game i in 60 | let tr = pg_get_successors game i in 61 | let j = 62 | if pl = plr_Even then strategy.(i) 63 | else best_decision_by_valuation_ordering game node_total_ordering_by_position valu i 64 | in 65 | out (getd j); 66 | out " | "; 67 | if pl = plr_Even then ( 68 | ns_iter (fun j -> 69 | if node_valuation_ordering game node_total_ordering_by_position valu.(strategy.(i)) valu.(j) < 0 70 | then out (getd j ^ " "); 71 | ) tr; 72 | ); 73 | out "\n"; 74 | ) !ordered; 75 | 76 | out "\n";; 77 | -------------------------------------------------------------------------------- /src/tools/infotool.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Basics ;; 4 | open Paritygame ;; 5 | 6 | let out s = 7 | print_string s; 8 | flush stdout 9 | 10 | let _ = 11 | let input_file = ref "" in 12 | let speclist = [] in 13 | 14 | let header = Info.get_title "Parity Game Info Tool" in 15 | 16 | SimpleArgs.parsedef speclist (fun f -> input_file := f) (header ^ "Usage: infotool [infile]\n" ^ 17 | "Provides some information about a parity game."); 18 | 19 | let (in_channel,name) = if !input_file = "" then (stdin,"STDIN") else (open_in !input_file,!input_file) in 20 | 21 | let game = Parsers.parse_parity_game in_channel in 22 | 23 | let number_of_nodes = ref 0 in 24 | let number_of_player0_nodes = ref 0 in 25 | let number_of_player1_nodes = ref 0 in 26 | let min_priority = ref (-1) in 27 | let max_priority = ref (-1) in 28 | let number_of_edges = ref 0 in 29 | let number_of_player0_edges = ref 0 in 30 | let number_of_player1_edges = ref 0 in 31 | 32 | pg_iterate (fun _ -> fun (pr, pl, tr, _, _) -> 33 | let trn = ns_size tr in 34 | incr number_of_nodes; 35 | number_of_edges := !number_of_edges + trn; 36 | if pl = plr_Even then ( 37 | incr number_of_player0_nodes; 38 | number_of_player0_edges := !number_of_player0_edges + trn 39 | ) 40 | else ( 41 | incr number_of_player1_nodes; 42 | number_of_player1_edges := !number_of_player1_edges + trn 43 | ); 44 | if (!min_priority < 0) || (pr < !min_priority) then min_priority := pr; 45 | if (!max_priority < 0) || (pr > !max_priority) then max_priority := pr; 46 | ) game; 47 | 48 | out ("Number of Nodes : " ^ string_of_int !number_of_nodes ^ "\n"); 49 | out ("Number of P0 Nodes : " ^ string_of_int !number_of_player0_nodes ^ "\n"); 50 | out ("Number of P1 Nodes : " ^ string_of_int !number_of_player1_nodes ^ "\n"); 51 | out ("Minimum Priority : " ^ string_of_int !min_priority ^ "\n"); 52 | out ("Maximum Priority : " ^ string_of_int !max_priority ^ "\n"); 53 | out ("Number of Edges : " ^ string_of_int !number_of_edges ^ "\n"); 54 | out ("Number of P0 Edges : " ^ string_of_int !number_of_player0_edges ^ "\n"); 55 | out ("Number of P1 Edges : " ^ string_of_int !number_of_player1_edges ^ "\n"); 56 | out "\n";; 57 | -------------------------------------------------------------------------------- /src/tools/obfuscator.ml: -------------------------------------------------------------------------------- 1 | open Arg;; 2 | open Tcsargs;; 3 | open Paritygame;; 4 | 5 | module CommandLine = 6 | struct 7 | let input_file = ref "" 8 | 9 | let obfuscate_nodes = ref true 10 | 11 | let obfuscate_edges = ref true 12 | 13 | let reverse_edges = ref false 14 | 15 | let seed = ref None 16 | 17 | let speclist = [(["--disablenodeobfuscation"; "-dn"], Unit(fun _ -> obfuscate_nodes := false), 18 | "\n keep ordering of nodes") ; 19 | (["--disableedgeobfuscation"; "-de"], Unit(fun _ -> obfuscate_edges := false), 20 | "\n keep ordering of edges"); (* TODO: does not make sense anymore. There is no explicit ordering visible to the outside. Option should probably be removed. *) 21 | (["--justreverseedges"; "-rv"], Unit(fun _ -> obfuscate_edges := false; reverse_edges := true), 22 | "\n reverse edges (disables a previous `-de')"); (* TODO: same as above. `reverse' is also misleading. *) 23 | (["--seed"; "-s"], Int(fun i -> seed := Some(i)), 24 | "\n set seed value")] 25 | 26 | let header = Info.get_title "Obfuscator Tool" 27 | end ;; 28 | 29 | open CommandLine ;; 30 | 31 | 32 | let _ = 33 | SimpleArgs.parsedef speclist (fun f -> input_file := f) (header ^ "Usage: obfuscator [infile]\n" ^ 34 | "Obfuscates the parity game given in . If this argument is omitted it reads a game from STDIN."); 35 | 36 | let in_channel = if !input_file = "" then stdin else open_in !input_file in 37 | 38 | let game = Parsers.parse_parity_game in_channel in 39 | 40 | let m = pg_size game in 41 | let swap = Array.make m 0 in 42 | 43 | for i=0 to m-1 do 44 | swap.(i) <- i 45 | done; 46 | 47 | Option.map_default (fun i _ -> Random.init i) (Random.self_init) !seed (); 48 | 49 | if !obfuscate_nodes then ( 50 | for k=1 to 10*(m-1) do 51 | let i = Random.int m in 52 | let j = Random.int m in 53 | 54 | let x = swap.(i) in 55 | swap.(i) <- swap.(j); 56 | swap.(j) <- x 57 | done 58 | ); 59 | 60 | (* print_string "Original game:\n"; 61 | Paritygame.print_game game; 62 | 63 | print_string "Swapping table:\n"; 64 | Array.iteri (fun i -> fun j -> print_string (" " ^ string_of_int i ^ " -> " ^ string_of_int j ^ "\n")) swap; 65 | *) 66 | let game' = pg_init m (fun _ -> (0,plr_Even,[],None)) in 67 | 68 | pg_iterate (fun i -> fun (p,pl,succs,_,name) -> let i' = swap.(i) in 69 | pg_set_priority game' i' p; 70 | pg_set_owner game' i' pl; 71 | pg_set_desc game' i' name; 72 | ns_iter (fun w -> pg_add_edge game' i' swap.(w)) succs) 73 | game; 74 | 75 | (* print_string "Obfuscated game:\n"; *) 76 | Paritygame.print_game game' 77 | -------------------------------------------------------------------------------- /src/tools/transformer.ml: -------------------------------------------------------------------------------- 1 | open Arg ;; 2 | open Tcsargs;; 3 | open Paritygame;; 4 | 5 | module CommandLine = 6 | struct 7 | let todo = ref [] 8 | let input_file = ref "" 9 | 10 | let speclist = [(["--total"; "-to"], Unit(fun _ -> todo := (fun g -> Transformations.total_transformation_inplace !g)::!todo), 11 | "\n total transformation") ; 12 | (["--alternating"; "-al"], Unit(fun _ -> todo := (fun g -> g := Transformations.alternating_transformation !g false)::!todo), 13 | "\n alternating transformation") ; 14 | (["--normalform"; "-nf"], Unit(fun _ -> todo := (fun g -> g := Transformations.normal_form_translation !g)::!todo), 15 | "\n transforms game into an equivalent version with out-degree <= 2") ; 16 | (["--singlescc"; "-ss"], Unit(fun _ -> todo := (fun g -> g := Transformations.single_scc_transformation !g)::!todo), 17 | "\n single scc transformation") ; 18 | (["--prioalignment"; "-pa"], Unit(fun _ -> todo := (fun g -> g := Transformations.prio_alignment_transformation !g)::!todo), 19 | "\n priority alignment transformation") ; 20 | (["--dummynodes"; "-dn"], Unit(fun _ -> todo := (fun g -> g := Transformations.dummy_transformation !g)::!todo), 21 | "\n dummy node transformation") ; 22 | (["--uniquizeprios"; "-up"], Unit(fun _ -> todo := (fun g -> Transformations.uniquize_prios_inplace !g)::!todo), 23 | "\n uniquize priorities") ; 24 | (["--cheapescapecycles"; "-ce"], Unit(fun _ -> todo := (fun g -> g := Transformations.cheap_escape_cycles_transformation !g false)::!todo), 25 | "\n cheap escale cycles transformation"); 26 | (["--bouncingnode"; "-bn"], Unit(fun _ -> todo := (fun g -> g := Transformations.bouncing_node_transformation !g)::!todo), 27 | "\n bouncing node transformation"); 28 | (["--increasepriorityoccurrence"; "-ip"], Unit(fun _ -> todo := (fun g -> g := Transformations.increase_priority_occurrence !g)::!todo), 29 | "\n increases priority occurrence by inserting dummy nodes"); 30 | (["--antiprioritycompactation"; "-ap"], Unit(fun _ -> todo := (fun g -> g := Transformations.anti_priority_compactation_transformation !g)::!todo), 31 | "\n anti priority compactation transformation"); 32 | (["--minmaxswap"; "-mm"], Unit(fun _ -> todo := (fun g -> g := Transformations.min_max_swap_transformation !g)::!todo), 33 | "\n transforms a min-parity game into a max-parity one and vice versa")] 34 | 35 | let header = Info.get_title "Transformer Tool" 36 | end ;; 37 | 38 | open CommandLine ;; 39 | 40 | 41 | let _ = 42 | SimpleArgs.parsedef speclist (fun f -> input_file := f) (header ^ "Usage: transformer [options] [infile]\n" ^ 43 | "Transforms the parity game given in . If this argument is omitted it reads a game from STDIN.\n\nOptions are"); 44 | 45 | let in_channel = if !input_file = "" then stdin else open_in !input_file in 46 | 47 | let game = ref (Parsers.parse_parity_game in_channel) in 48 | 49 | List.iter (fun f -> 50 | f game 51 | ) (List.rev !todo); 52 | 53 | Paritygame.print_game !game 54 | -------------------------------------------------------------------------------- /src/tools/winningstrats.ml: -------------------------------------------------------------------------------- 1 | open Arg;; 2 | open Tcsargs;; 3 | open Paritygame;; 4 | 5 | module CommandLine = 6 | struct 7 | let input_file = ref "" 8 | 9 | let player = ref plr_Even 10 | 11 | let speclist = [(["--player"; "-p"], Int(fun i -> if i = 1 then player := plr_Odd), 12 | "\n winning strategy for player (default: 0)") ] 13 | 14 | let header = Info.get_title "Winning Strategies " 15 | end ;; 16 | 17 | open CommandLine ;; 18 | 19 | 20 | let _ = 21 | SimpleArgs.parsedef speclist (fun f -> input_file := f) (header ^ "Usage: winningstrats [infile]\n" ^ 22 | "Computes all winning strategies for a player. If this argument is omitted it reads a game from STDIN."); 23 | 24 | let in_channel = if !input_file = "" then stdin else open_in !input_file in 25 | 26 | let game = Parsers.parse_parity_game in_channel in 27 | 28 | let solve = let (solve, _, _) = Solvers.find_solver "recursive" in solve [||] in 29 | 30 | let (sol, strat) = solve game in 31 | 32 | print_string ("\nWinning Set:\n " ^ Paritygame.format_solution sol ^ "\n"); 33 | 34 | print_string ("\nWinning Strategies for Player " ^ string_of_int (if !player = plr_Even then 0 else 1) ^ "\n"); 35 | 36 | let number = ref 0 in 37 | 38 | let rec work i = 39 | if (i >= pg_size game) then ( 40 | let game2 = Paritygame.subgame_by_strat game strat in 41 | let (sol2, _) = solve game2 in 42 | let good = ref true in 43 | for j = 0 to pg_size game - 1 do 44 | if (sol.(j) != sol2.(j)) then 45 | good := false; 46 | done; 47 | if (!good) then ( 48 | let strat2 = Array.copy strat in 49 | for j = 0 to Array.length strat2 - 1 do 50 | if (sol.(j) != !player) then 51 | strat2.(j) <- -1; 52 | done; 53 | print_string ("\n" ^ format_strategy strat2 ^ "\n"); 54 | number := !number + 1 55 | ); 56 | ) else ( 57 | if (sol.(i) == !player && strat.(i) != -1) then ( 58 | ns_iter (fun w -> strat.(i) <- w; 59 | work (i + 1)) 60 | (pg_get_successors game i) 61 | ) else ( 62 | work (i+1); 63 | ) 64 | ) 65 | in 66 | 67 | work 0; 68 | 69 | print_string ("\nTotal: " ^ string_of_int !number ^ "\n\n");; 70 | -------------------------------------------------------------------------------- /tests/solverstest.ml: -------------------------------------------------------------------------------- 1 | open OUnit;; 2 | open Solvers;; 3 | open Paritygame;; 4 | 5 | let random_game (size, max_prio, outdegmin, outdegmax, self_cycles, seed) = 6 | Random.init seed; 7 | Paritygame.pg_init size (fun i -> ( 8 | Random.int max_prio, 9 | (if Random.int 2 = 0 then plr_Even else plr_Odd), 10 | Array.to_list (Array.map (fun j -> 11 | if j < i || self_cycles then j else j + 1 12 | ) 13 | (Tcsmaths.RandomUtils.get_pairwise_different_from_range 14 | (outdegmin + Random.int (outdegmax - outdegmin + 1)) 15 | 0 16 | (size-1 - (if self_cycles then 0 else 1)) 17 | )), 18 | Some (string_of_int i)) 19 | );; 20 | 21 | let game_profiles = Array.init 500 (fun i -> 22 | let k = i + 2 in 23 | (10 + k, 10 + k, 3, 3, true, k) 24 | );; 25 | 26 | open Univsolve 27 | open Verification 28 | 29 | 30 | let solvers = [| 31 | ("recursive", [||], 150, false); 32 | ("recursive", [||], 150, true); 33 | ("bigstep", [||], 20, false); 34 | ("bigstep", [||], 20, true); 35 | ("dominiondec", [||], 40, false); 36 | ("dominiondec", [||], 40, true); 37 | ("fpiter", [||], 30, false); 38 | ("fpiter", [||], 30, true); 39 | ("genetic", [||], 40, false); 40 | ("genetic", [||], 40, true); 41 | ("guessstrategy", [||], 150, false); 42 | ("guessstrategy", [||], 150, true); 43 | ("modelchecker", [||], 150, false); 44 | ("modelchecker", [||], 150, true); 45 | ("smallprog", [||], 10, false); 46 | ("smallprog", [||], 10, true); 47 | ("optstratimprov", [||], 150, false); 48 | ("optstratimprov", [||], 150, true); 49 | ("stratimprdisc", [||], 25, false); 50 | ("stratimprdisc", [||], 25, true); 51 | ("stratimprloc2", [||], 150, false); 52 | ("stratimprloc2", [||], 150, true); 53 | ("stratimprlocal", [||], 150, false); 54 | ("stratimprlocal", [||], 150, true); 55 | ("stratimprove", [||], 150, false); 56 | ("stratimprove", [||], 150, true); 57 | ("policyiter", [|"-sirr"|], 50, false); 58 | ("policyiter", [|"-sirr"|], 50, true); 59 | ("policyiter", [|"-slre"|], 50, false); 60 | ("policyiter", [|"-slre"|], 50, true); 61 | ("policyiter", [|"-slrb"|], 50, false); 62 | ("policyiter", [|"-slrb"|], 50, true); 63 | ("policyiter", [|"-slbi"|], 50, false); 64 | ("policyiter", [|"-slbi"|], 50, true); 65 | ("policyiter", [|"-sh"|], 50, false); 66 | ("policyiter", [|"-sh"|], 50, true); 67 | ("policyiter", [|"-sf"|], 50, false); 68 | ("policyiter", [|"-sf"|], 50, true); 69 | ("policyiter", [|"-sb"|], 50, false); 70 | ("policyiter", [|"-sb"|], 50, true); 71 | ("policyiter", [|"-sa"|], 50, false); 72 | ("policyiter", [|"-sa"|], 50, true); 73 | ("policyiter", [|"-rfo"|], 50, false); 74 | ("policyiter", [|"-rfo"|], 50, true); 75 | ("policyiter", [|"-rf"|], 50, false); 76 | ("policyiter", [|"-rf"|], 50, true); 77 | ("policyiter", [|"-re"|], 50, false); 78 | ("policyiter", [|"-re"|], 50, true); 79 | ("policyiter", [|"-drf"|], 50, false); 80 | ("policyiter", [|"-drf"|], 50, true); 81 | ("succinctsmallprog", [||], 15, false); 82 | ("succinctsmallprog", [||], 15, true); 83 | |] 84 | 85 | 86 | let verifiers = [| 87 | ("universal verifier", verify_solution_strategy_univ); 88 | ("alternative verifier", verify_solution_strategy_direct); 89 | ("generic verifier", verify_solution_strategy_generic) 90 | |] 91 | 92 | 93 | let test_fixture = "Solvers Test" >::: Array.to_list (Array.map (fun (solver_str, solver_opts, upto, univ) -> 94 | "Test: " ^ solver_str ^ " " ^ Tcsarray.ArrayUtils.format (fun s -> s) solver_opts >:: (fun () -> 95 | (Univsolve.universal_solve_global_options := fun gen_stat verb -> { 96 | generate_statistics = gen_stat ; 97 | verb_level = verb ; 98 | global_optimization = univ ; 99 | decompose_sccs = univ ; 100 | solve_special_games = univ ; 101 | local_optimization = univ ; 102 | globalopt_remove_useless_self_cycles = univ ; 103 | globalopt_solve_useful_self_cycles = univ ; 104 | solvespec_single_parity = univ ; 105 | solvespec_single_player = univ ; 106 | localopt_priority_propagation = univ ; 107 | localopt_compact_priorities = univ ; 108 | }); 109 | Array.iteri (fun i profile -> 110 | if (upto >= i) then ( 111 | let game = random_game profile in 112 | let (solver, _, _) = Solvers.find_solver solver_str in 113 | let (solution, strategy) = (solver solver_opts) game in 114 | Array.iter (function (verifier_str, verifier) -> 115 | let verified = verifier game solution strategy in 116 | assert_equal ~msg:(solver_str ^ " : game " ^ string_of_int i ^ " verified with " ^ verifier_str) None verified 117 | ) verifiers 118 | ) 119 | ) game_profiles 120 | ) 121 | ) solvers) 122 | 123 | 124 | 125 | 126 | let _ = run_test_tt ~verbose:true test_fixture --------------------------------------------------------------------------------