packages feed

CarneadesIntoDung 1.0 → 2.0.0.0

raw patch · 14 files changed

+709/−506 lines, 14 filesdep +CarneadesIntoDungdep +optparse-applicativedep +tastydep −cmdargsdep ~CarneadesDSLdep ~Dungdep ~basesetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: CarneadesIntoDung, optparse-applicative, tasty, tasty-hunit

Dependencies removed: cmdargs

Dependency ranges changed: CarneadesDSL, Dung, base, containers, fgl

API changes (from Hackage documentation)

Files

− CHANGELOG
@@ -1,7 +0,0 @@-0.9 => 1.0-=============-This package version is updated with a command line utility.--* Make use of the CarneadesDSL Input and Dung Output modules to provide a -  command line interface reading a Carneades Argument Evaluation Structure-  and possible give the evaluation result or output in CEGARTIX format.
+ CHANGELOG.md view
@@ -0,0 +1,29 @@+# Changelog++## 1.0 → 2.0.0.0++### Breaking changes++- **CLI rewritten**: The `caell` executable now uses `optparse-applicative`+  instead of `cmdargs`. Command-line flags have changed:+  - Use `--cegartix` / `--lax-cegartix` for output format selection+  - Use `--extension`, `--correspondence`, `--x-semantics` to select output++### Improvements++- Upgraded to `cabal-version: 3.0` format+- Relaxed dependency bounds to build on GHC 9.4++- Updated to CarneadesDSL 2.0 and Dung 2.0+- Added test suite (tasty + HUnit)+- Added GitHub Actions CI for GHC 9.4, 9.6, 9.8, 9.10+- Fixed all `-Wall` warnings+- Removed dependency on unmaintained `cmdargs` library+- Converted documentation to Markdown++## 0.9 → 1.0++This package version is updated with a command line utility.++- Make use of the CarneadesDSL Input and Dung Output modules to provide a+  command line interface reading a Carneades Argument Evaluation Structure+  and possible give the evaluation result or output in CEGARTIX format.
CarneadesIntoDung.cabal view
@@ -1,50 +1,88 @@+cabal-version: 3.0 name:          CarneadesIntoDung-category:      Argumentation, Embedded, AI-version:       1.0-license:       BSD3-cabal-version: >= 1.6+version:       2.0.0.0+license:       BSD-3-Clause license-file:  LICENSE author:        Bas van Gijzel, Henrik Nilsson-maintainer:    Bas van Gijzel <bmv@cs.nott.ac.uk>+maintainer:    Bas van Gijzel <nenekotan+git@gmail.com>+copyright:     Copyright (C) 2014-2026 Bas van Gijzel stability:     experimental-homepage:      http://www.cs.nott.ac.uk/~bmv/CarneadesIntoDung/-copyright:     Copyright (C) 2014 Bas van Gijzel+category:      Argumentation, Embedded, AI+homepage:      https://github.com/nebasuke/CarneadesIntoDung synopsis:      A translation from the Carneades argumentation model into Dung's AFs.-description:   A translation from the Carneades argumentation model -               (<http://hackage.haskell.org/package/CarneadesDSL>) into Dung's -               argumentation frameworks (<http://hackage.haskell.org/package/Dung>). -               This package provides a translation function and correspondence-               properties. For the papers accompanying this library see -               \"Towards a framework for the implementation and verification of -               translations between argumentation models\" and \"A principled -               approach to the implementation of argumentation models\",-               available at <http://www.cs.nott.ac.uk/~bmv/CarneadesIntoDung/>.+description:+  A translation from the Carneades argumentation model+  (<http://hackage.haskell.org/package/CarneadesDSL>) into Dung's+  argumentation frameworks (<http://hackage.haskell.org/package/Dung>).+  This package provides a translation function and correspondence+  properties. For the papers accompanying this library see "Towards a+  framework for the implementation and verification of translations+  between argumentation models" and "A principled approach to the+  implementation of argumentation models", available at+  <https://scholar.google.com/citations?user=Xu4yjvwAAAAJ&hl>. build-type:    Simple+tested-with:   GHC == 9.4.8, GHC == 9.6.6, GHC == 9.8.4, GHC == 9.10.1 -Extra-Source-Files:-                           CHANGELOG-                           examplecaes.txt+extra-doc-files:+  README.md+  CHANGELOG.md -Library-  build-depends:-    base                   >= 4        && < 5,-    containers             >= 0.3      && < 0.6,-    fgl                    >= 5.4.2.4,-    cmdargs                >= 0.10.2,-    CarneadesDSL           >= 1.3,-    Dung                   >= 1.0.0.1-    -  hs-source-dirs:-    src+extra-source-files:+  LICENSE+  examplecaes.txt+  exampleaf.txt +source-repository head+  type:     git+  location: https://github.com/nebasuke/CarneadesIntoDung++common warnings+  ghc-options:+    -Wall+    -Wcompat+    -Widentities+    -Wincomplete-record-updates+    -Wincomplete-uni-patterns+    -Wredundant-constraints+  default-language: Haskell2010++library+  import:           warnings+  hs-source-dirs:   src+  build-depends:+    base         >= 4.16 && < 5,+    containers   >= 0.6  && < 0.8,+    fgl          >= 5.7  && < 5.9,+    CarneadesDSL >= 2.0  && < 2.1,+    Dung         >= 2.0  && < 2.1   exposed-modules:     Language.CarneadesIntoDung.Translation     Language.CarneadesIntoDung.Examples -Executable caell-  main-Is:                 Main.hs-  hs-source-dirs:          src+executable caell+  import:           warnings+  main-is:          Main.hs+  hs-source-dirs:   app+  build-depends:+    base                 >= 4.16 && < 5,+    CarneadesIntoDung,+    CarneadesDSL         >= 2.0  && < 2.1,+    Dung                 >= 2.0  && < 2.1,+    optparse-applicative >= 0.17 && < 0.19+  ghc-options:      -threaded -source-repository head-  Type:     git-  Location: https://github.com/nebasuke/CarneadesIntoDung+test-suite carneadesintodung-tests+  import:           warnings+  type:             exitcode-stdio-1.0+  main-is:          Main.hs+  hs-source-dirs:   test+  build-depends:+    base              >= 4.16 && < 5,+    CarneadesIntoDung,+    CarneadesDSL      >= 2.0  && < 2.1,+    Dung              >= 2.0  && < 2.1,+    containers        >= 0.6  && < 0.8,+    tasty             >= 1.4  && < 1.6,+    tasty-hunit       >= 0.10 && < 0.11+  other-modules:+    Test.Language.CarneadesIntoDung.Translation
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c)2014, Bas van Gijzel+Copyright (c) 2014-2026, Bas van Gijzel  All rights reserved. 
+ README.md view
@@ -0,0 +1,42 @@+# CarneadesIntoDung++A translation from the Carneades argumentation model+([CarneadesDSL](http://hackage.haskell.org/package/CarneadesDSL)) into Dung's+argumentation frameworks ([Dung](http://hackage.haskell.org/package/Dung)).++This package provides a translation function and correspondence properties+showing that the translation preserves applicability and acceptability.++For the papers accompanying this library see "Towards a framework for the+implementation and verification of translations between argumentation models"+and "A principled approach to the implementation of argumentation models",+available at <https://scholar.google.com/citations?user=Xu4yjvwAAAAJ&hl>.++## Usage++```haskell+import Language.CarneadesIntoDung.Translation+import Language.CarneadesIntoDung.Examples++-- Translate the example CAES into a Dung AF+translate caes++-- Verify correspondence properties+corApp caes  -- True+corAcc caes  -- True+```++## Executable++The `caell` executable reads a Carneades Argument Evaluation Structure from a+file and translates it into a Dung argumentation framework:++```+caell --filename examplecaes.txt --extension+caell --filename examplecaes.txt --correspondence+caell --filename examplecaes.txt --cegartix --outputfile out.txt+```++## License++BSD-3-Clause. See [LICENSE](LICENSE) for details.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple
-main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,108 @@+-- |This module implements a command-line interface to the implementation of+-- Carneades. CAES + Haskell = caell+{-# LANGUAGE RecordWildCards #-}+module Main+  ( main+  ) where++import Language.CarneadesIntoDung.Translation+import Language.Carneades.CarneadesDSL (CAES(..), getAllArgs, applicable,+                                        getProps, acceptable)+import Language.Carneades.Input+import Language.Dung.AF (groundedExt)+import Language.Dung.Output++import Options.Applicative+import System.Exit+import Control.Monad (when)++data Options = Options+  { optCegartix       :: Bool+  , optLaxCegartix    :: Bool+  , optFileName       :: FilePath+  , optOutputFile     :: Maybe FilePath+  , optCorrespondence :: Bool+  , optExtension      :: Bool+  , optXSemantics     :: Bool+  } deriving (Show)++optionsParser :: Parser Options+optionsParser = Options+  <$> switch+        (  long "cegartix"+        <> help "Output in strict CEGARTIX/PrefSat format (standard)"+        )+  <*> switch+        (  long "lax-cegartix"+        <> help "Output in lax CEGARTIX/PrefSat format (+parentheses)"+        )+  <*> strOption+        (  long "filename"+        <> metavar "FILE"+        <> help "Name of the file to be read"+        )+  <*> optional (strOption+        (  long "outputfile"+        <> metavar "FILE"+        <> help "Name of the file to be written"+        ))+  <*> switch+        (  long "correspondence"+        <> help "Display satisfaction of correspondence result"+        )+  <*> switch+        (  long "extension"+        <> help "Output unique complete extension for the translated CAES"+        )+  <*> switch+        (  long "x-semantics"+        <> help "Output evaluation of the original Carneades semantics"+        )++opts :: ParserInfo Options+opts = info (optionsParser <**> helper)+  (  fullDesc+  <> progDesc "An implementation of Carneades in Haskell"+  <> header "caell - Carneades + Haskell argumentation tool"+  )++main :: IO ()+main = do+  options@Options{..} <- execParser opts+  input <- readFile optFileName+  caes <- case parseCAES input of+    Left err -> do+      putStrLn "Parsing error: "+      print err+      exitWith (ExitFailure 1)+    Right c -> return c+  exec options caes++-- |Execute supplied options+exec :: Options -> CAES -> IO ()+exec Options{..} caes@(CAES (argSet, (assumptions, _), _)) = do+  let args = getAllArgs argSet+  let transCaes = translate caes+  putStrLn $ "Argument set: " ++ show args+  when optXSemantics $ do+    putStrLn "Evaluation under original semantics:"+    putStrLn "Applicable arguments:"+    print (filter (`applicable` caes) args)+    putStrLn "Acceptable propositions:"+    print (filter (\p -> p `acceptable` caes+                      || p `elem` assumptions)+                  (getProps argSet))+  when optExtension $+    putStrLn "Extension after translation: "+      >> print (groundedExt transCaes)+  when optCorrespondence $+    putStrLn ("Correspondence of applicability is: " ++ show (corApp caes))+      >> putStrLn ("Correspondence of acceptability is: " ++ show (corAcc caes))+  let useStrict = optCegartix && not optLaxCegartix+  case optOutputFile of+    Nothing -> return ()+    Just fp -> do+      if useStrict+        then writeFile fp (toStrictCegartix transCaes)+        else writeFile fp (toCegartix transCaes)+      putStrLn "File outputted."
+ exampleaf.txt view
@@ -0,0 +1,15 @@+arg(a).+arg(b).+arg(c).+arg(d).+arg(e).+arg(f).+arg(g).+att(a,b).+att(c,b).+att(c,d).+att(d,c).+att(d,e).+att(e,g).+att(f,e).+att(g,f).
examplecaes.txt view
@@ -1,25 +1,25 @@-argument arg1 ["kill", "intent"] [ ] "murder"
-argument arg2 ["witness"] ["unreliable"] "intent"
-argument arg3 ["witness2"] ["unreliable2"] "-intent"
-
-weight arg1 0.8
-weight arg2 0.3
-weight arg3 0.8
-
-assumptions ["kill", "witness", "witness2", "unreliable2"]
-
-
--- Comments are allowed
--- also valid: standard "intent" BeyondReasonableDoubt
--- Propositions either as string literals or plain identifiers
-standard "kill" scintilla
-standard "intent" beyond_reasonable_doubt
-standard "-intent" scintilla
-standard murder scintilla
-standard "-murder" scintilla
-standard "unreliable" scintilla
-standard "unreliable2" scintilla
-standard witness scintilla
-standard witness2 scintilla
-
-
+argument arg1 ["kill", "intent"] [ ] "murder"+argument arg2 ["witness"] ["unreliable"] "intent"+argument arg3 ["witness2"] ["unreliable2"] "-intent"++weight arg1 0.8+weight arg2 0.3+weight arg3 0.8++assumptions ["kill", "witness", "witness2", "unreliable2"]+++-- Comments are allowed+-- also valid: standard "intent" BeyondReasonableDoubt+-- Propositions either as string literals or plain identifiers+standard "kill" scintilla+standard "intent" beyond_reasonable_doubt+standard "-intent" scintilla+standard murder scintilla+standard "-murder" scintilla+standard "unreliable" scintilla+standard "unreliable2" scintilla+standard witness scintilla+standard witness2 scintilla++
src/Language/CarneadesIntoDung/Examples.hs view
@@ -1,107 +1,106 @@--- | This is the examples module accompanying the implementation of the 
--- translation from the Carneades argumentation model into Dung's 
--- argumentation frameworks. 
---
--- This module contains a collection of examples, showing how to translate
--- an existing Carneades Argument Evaluation Structure (CAES) into an argumentation
--- framework. 
---
--- To run these examples, or your own: start GHCi and do the following:
---
--- @\:l Language.CarneadesIntoDung.Examples@
--- 
-
-module Language.CarneadesIntoDung.Examples 
-  (
-   -- *Example translation
-   -- |We use the example CAES as defined in "Language.Carneades.ExampleCAES".
-   caes, 
-   exTrans, exTrans',
-   -- *Correspondence properties
-   corProp,    
-  )
- where
-import Language.CarneadesIntoDung.Translation
-import Language.Dung.AF
-import Language.Carneades.CarneadesDSL
-import Language.Carneades.ExampleCAES
-
--- |Translation of the example CAES 'caes'.
--- The following is the prettified output of the translation, where
--- the five propositions in the middle are the assumptions and 'defeater'.
--- 
--- >>> translate caes
--- AF [
--- Left (True,"murder"),
--- Left (False,"murder"),
--- Right ["kill","intent"] ~[]=>"murder",
--- Left (False,"intent"),
--- Left (True,"intent"),
--- Right ["witness2"] ~["unreliable2"]=>"-intent",
--- Right ["witness"] ~["unreliable"]=>"intent",
--- Left (True,"unreliable"),
--- Left (False,"unreliable")
--- ,
--- Left (True,"defeater"),
--- Left (True,"kill"),
--- Left (True,"witness"),
--- Left (True,"witness2"),
--- Left (True,"unreliable2")] 
--- [
--- (Left (True,"defeater"), Left (True,"murder")),
--- (Left (True,"defeater"), Left (False,"murder")),
--- (Left (True,"defeater"), Right ["kill","intent"] ~[]=>"murder"),
--- (Left (True,"defeater"), Left (False,"intent")),
--- (Left (True,"defeater"),Left (True,"intent")),
--- (Left (True,"unreliable2"),Right ["witness2"] ~["unreliable2"]=>"-intent"),
--- (Left (True,"defeater"),Left (True,"unreliable")),
--- (Left (True,"defeater"),Left (False,"unreliable"))
--- ]
-exTrans :: ConcreteAF
-exTrans = translate caes
-
-
-
--- |Translation of the example CAES 'caes', keeping labels.
--- The following is the prettified output of the translation, where 
--- the five propositions in the middle are the assumptions and 'defeater'.
---
--- >>> translate' caes
--- AF [
--- (False,Left (True,"murder")),
--- (False,Left (False,"murder")),
--- (False,Right ["kill","intent"] ~[]=>"murder"),
--- (False,Left (False,"intent")),
--- (False,Left (True,"intent")),
--- (False,Right ["witness2"] ~["unreliable2"]=>"-intent"),
--- (True,Right ["witness"] ~["unreliable"]=>"intent"),
--- (False,Left (True,"unreliable")),
--- (False,Left (False,"unreliable"))
--- ,
--- (True,Left (True,"defeater")),
--- (True,Left (True,"kill")),
--- (True,Left (True,"witness")),
--- (True,Left (True,"witness2")),
--- (True,Left (True,"unreliable2"))]
--- [
--- ((True,Left (True,"defeater")),(False,Left (True,"murder"))),
--- ((True,Left (True,"defeater")),(False,Left (False,"murder"))),
--- ((True,Left (True,"defeater")), (False,Right ["kill","intent"] ~[]=>"murder")),
--- ((True,Left (True,"defeater")),(False,Left (False,"intent"))),
--- ((True,Left (True,"defeater")),(False,Left (True,"intent"))),
--- ((True,Left (True,"unreliable2")),(False,Right ["witness2"] ~["unreliable2"]=>"-intent")),
--- ((True,Left (True,"defeater")),(False,Left (True,"unreliable"))),
--- ((True,Left (True,"defeater")),(False,Left (False,"unreliable")))
-exTrans' :: LConcreteAF
-exTrans' = translate' caes
-
-
-
--- |Combining the correspondence properties.
---
--- And as expected:
--- 
--- >>> corApp caes && corAcc caes
--- True
-corProp :: CAES -> Bool
+-- | This is the examples module accompanying the implementation of the +-- translation from the Carneades argumentation model into Dung's +-- argumentation frameworks. +--+-- This module contains a collection of examples, showing how to translate+-- an existing Carneades Argument Evaluation Structure (CAES) into an argumentation+-- framework. +--+-- To run these examples, or your own: start GHCi and do the following:+--+-- @\:l Language.CarneadesIntoDung.Examples@+-- ++module Language.CarneadesIntoDung.Examples +  (+   -- *Example translation+   -- |We use the example CAES as defined in "Language.Carneades.ExampleCAES".+   caes, +   exTrans, exTrans',+   -- *Correspondence properties+   corProp,    +  )+ where+import Language.CarneadesIntoDung.Translation+import Language.Carneades.CarneadesDSL (CAES)+import Language.Carneades.ExampleCAES++-- |Translation of the example CAES 'caes'.+-- The following is the prettified output of the translation, where+-- the five propositions in the middle are the assumptions and 'defeater'.+-- +-- >>> translate caes+-- AF [+-- Left (True,"murder"),+-- Left (False,"murder"),+-- Right ["kill","intent"] ~[]=>"murder",+-- Left (False,"intent"),+-- Left (True,"intent"),+-- Right ["witness2"] ~["unreliable2"]=>"-intent",+-- Right ["witness"] ~["unreliable"]=>"intent",+-- Left (True,"unreliable"),+-- Left (False,"unreliable")+-- ,+-- Left (True,"defeater"),+-- Left (True,"kill"),+-- Left (True,"witness"),+-- Left (True,"witness2"),+-- Left (True,"unreliable2")] +-- [+-- (Left (True,"defeater"), Left (True,"murder")),+-- (Left (True,"defeater"), Left (False,"murder")),+-- (Left (True,"defeater"), Right ["kill","intent"] ~[]=>"murder"),+-- (Left (True,"defeater"), Left (False,"intent")),+-- (Left (True,"defeater"),Left (True,"intent")),+-- (Left (True,"unreliable2"),Right ["witness2"] ~["unreliable2"]=>"-intent"),+-- (Left (True,"defeater"),Left (True,"unreliable")),+-- (Left (True,"defeater"),Left (False,"unreliable"))+-- ]+exTrans :: ConcreteAF+exTrans = translate caes++++-- |Translation of the example CAES 'caes', keeping labels.+-- The following is the prettified output of the translation, where +-- the five propositions in the middle are the assumptions and 'defeater'.+--+-- >>> translate' caes+-- AF [+-- (False,Left (True,"murder")),+-- (False,Left (False,"murder")),+-- (False,Right ["kill","intent"] ~[]=>"murder"),+-- (False,Left (False,"intent")),+-- (False,Left (True,"intent")),+-- (False,Right ["witness2"] ~["unreliable2"]=>"-intent"),+-- (True,Right ["witness"] ~["unreliable"]=>"intent"),+-- (False,Left (True,"unreliable")),+-- (False,Left (False,"unreliable"))+-- ,+-- (True,Left (True,"defeater")),+-- (True,Left (True,"kill")),+-- (True,Left (True,"witness")),+-- (True,Left (True,"witness2")),+-- (True,Left (True,"unreliable2"))]+-- [+-- ((True,Left (True,"defeater")),(False,Left (True,"murder"))),+-- ((True,Left (True,"defeater")),(False,Left (False,"murder"))),+-- ((True,Left (True,"defeater")), (False,Right ["kill","intent"] ~[]=>"murder")),+-- ((True,Left (True,"defeater")),(False,Left (False,"intent"))),+-- ((True,Left (True,"defeater")),(False,Left (True,"intent"))),+-- ((True,Left (True,"unreliable2")),(False,Right ["witness2"] ~["unreliable2"]=>"-intent")),+-- ((True,Left (True,"defeater")),(False,Left (True,"unreliable"))),+-- ((True,Left (True,"defeater")),(False,Left (False,"unreliable")))+exTrans' :: LConcreteAF+exTrans' = translate' caes++++-- |Combining the correspondence properties.+--+-- And as expected:+-- +-- >>> corApp caes && corAcc caes+-- True+corProp :: CAES -> Bool corProp caes = corApp caes && corAcc caes
src/Language/CarneadesIntoDung/Translation.hs view
@@ -1,230 +1,230 @@--- |This module implements a translation from the Carneades argumentation model
--- into Dung's argumentation frameworks. Any cycle-free Carneades Argument
--- Evaluation Structure (CAES) is handled. We also give a Haskell implementation of 
--- correspondence properties. 
--- 
--- Translation is done according to the following algorithm (see also \"Towards a
--- framework for the implementation and verification of translations between 
--- argumentation models\" by Bas van Gijzel and Henrik Nilsson)
--- 
--- 1. generatedArgs = /emptyset/.
--- 
--- 2. sortedArgs = Topological sort of arguments on its dependency graph.
--- 
--- 3. while sortedArgs != /emptyset/: 
---  
---   * Pick the first argument in sortedArgs.
---     Remove all arguments from sortedArgs that have the same conclusion,
---     c, and put them in argSet. 
--- 
---   * Translate applicability part of arguments argSet, building on previously
---     generatedArgs and put the generated arguments in tempArgs.
---
---   * argSet = /emptyset/
--- 
---   * Repeat the above three steps for the arguments for the opposite conclusion. 
---
---   * Translate the acceptability part of c and the opposite conclusion based on 
---     arguments in tempArgs. Add the results and tempArgs to generatedArgs.
---   
---   * tempArgs = /emptyset/
-module Language.CarneadesIntoDung.Translation
- (
-    -- * Basic types
-    ConcreteArg, LConcreteArg,
-    ConcreteAF, LConcreteAF,
-    -- * Translation functions
-    translate, translate', 
-    -- * Correspondence properties
-    -- | Informally, the correspondence properties below state that every 
-    -- argument and proposition in a CAES, after translation, will have a
-    -- corresponding argument and keep the same acceptability status. 
-    --
-    -- If the translation function is a correct implementation, the Haskell 
-    -- implementation of the correspondence properties should always return 
-    -- 'True'. However to constitute an actual (mechanised) proof we would 
-    -- need to convert the translation and the implementation of the 
-    -- correspondence properties in Haskell to a theorem prover like Agda.
-    --
-    -- See Section 4.4 of the paper for the formally stated properties.
- 
-
-    corApp, corAcc)
- where
-import Language.Dung.AF hiding (acceptable)
-import Language.Carneades.CarneadesDSL
-import Language.Carneades.Cyclic
-import Data.Graph.Inductive
-import Data.List(find, delete, intersect)  
-import Data.Maybe(fromMaybe) 
-import Data.Either(lefts, rights)
-import Data.Set(fromList)
-import Prelude hiding (negate)
-
--- |A concrete argument (in an argumentation framework) is either a Carneades 
--- propositional literal, or a Carneades argument.
-type ConcreteArg = Either PropLiteral Argument   
-
--- |A labelled version of the concrete argument allowing a more efficient 
--- translation by keeping track of the translation status.
-type LConcreteArg = (Bool, ConcreteArg) 
-
--- |An argumentation framework (AF) instantiated with 'ConcreteArg'.
-type ConcreteAF = DungAF ConcreteArg
-
--- |An argumentation framework (AF) instantiated with 'LConcreteArg'.
-type LConcreteAF = DungAF LConcreteArg
-
--- |Assumed true argument in the translated AF. It is used to attack arguments
--- that do not uphold their proof standard or have unacceptable premises.
-defeater :: LConcreteArg 
-defeater = (True, Left $ mkProp "defeater")
-
-
--- | Topological sort of the dependency graph
--- The result is a list, pairing a proposition with all its pro arguments
-topSort :: ArgSet -> [(PropLiteral, [Argument])]
-topSort g | cyclic g  = error "Argumentation graph is cyclic!"
-          | otherwise = reverse $ topsort' g
-
--- |Transforms a Carneades proposition into a Dung argument and labels it 'True'.
-propToLArg :: PropLiteral -> LConcreteArg
-propToLArg p = (True, Left p)
-
--- |Strips the label of both the 'LConcreteArg's in the attack.
-stripAttack :: (LConcreteArg, LConcreteArg) -> (ConcreteArg, ConcreteArg) 
-stripAttack (a, b) = (snd a, snd b)
-
--- |Translation function. It translate an arbitrary /cycle-free/ Carneades argument
--- Evaluation Structure (CAES) into a Dung argumentation framework (instantiated
--- with a ConcreteArg)
-translate :: CAES -> ConcreteAF
-translate caes@(CAES (argSet, (assumptions, _), _)) 
- = AF (map snd args) (map stripAttack attacks)
- where AF args attacks = argsToAF (topSort argSet) 
-                                  caes 
-                                  (AF (defeater : map propToLArg assumptions) [])
-
-
--- |Mainly, for testing purposes. This function behaves exactly like 'translate', 
--- but retains the labels. 
-translate' :: CAES -> LConcreteAF 
-translate' caes@(CAES (argSet, (assumptions, _), _))
- = AF args attacks
- where AF args attacks = argsToAF (topSort argSet) 
-                                  caes 
-                                  (AF (defeater : map propToLArg assumptions) [])
-
-
--- |Retrieves the arguments con the given proposition 'p'. 
-conArgs :: PropLiteral -> [(PropLiteral, [Argument])] -> (PropLiteral, [Argument])
-conArgs p argList = fromMaybe (negate p, []) (find ((== negate p) . fst) argList)
-
--- |Corresponds to the whole of 3. of the above algorithm (or Algorithm 4.1 in 
--- the paper)
--- 
--- If there are no more arguments to process, the translated AF is returned. 
-
--- If there is a propositional literal left, but it is an assumption, it has
--- already been translated and does not need to be considered. 
--- 
--- Otherwise, collect all pro and con arguments for p (con arguments are obtained
--- by calling 'conArgs') and remove them from @argList@. The translation is then 
--- done in four steps. 'transApps' is called to translate the applicability part of 
--- the pro and con arguments. 'transAcc' is called to translate the acceptability of 
--- p and the opposite of p (note that the order of applicable arguments is switched
--- for translating the acceptability of the opposite of p). The results of these 
--- four calls are collected and used in the recursive step of 'argsToAF'. 
-argsToAF :: [(PropLiteral, [Argument])] -> CAES -> LConcreteAF -> LConcreteAF
-argsToAF [] _ transAF = transAF
-argsToAF (pro@(p, proArgs) : argList) caes@(CAES (_, (assumptions, _), _)) (AF args defs) 
- | p `elem` assumptions = argsToAF argList caes (AF args defs)
- | otherwise = 
- let  con                    = conArgs p argList
-      (proAppArgs, proDefs)  = transApps args pro
-      (conAppArgs, conDefs)  = transApps args con
-      (newArgPro, proDefs')  = transAcc p proAppArgs conAppArgs caes
-      (newArgCon, conDefs')  = transAcc (negate p) conAppArgs proAppArgs caes
-      argList'               = delete con argList
- in argsToAF argList' caes 
-            (AF (newArgPro : newArgCon : proAppArgs ++ conAppArgs ++ args) 
-                (proDefs' ++ conDefs' ++ proDefs ++ conDefs ++ defs))
-
--- |Filters out propositional literals that have been labelled 'True'.
-accProps :: [LConcreteArg] -> [PropLiteral]
-accProps []                     = []
-accProps ((True, Left p) : ls)  = p : accProps ls
-accProps ((True, Right _) : ls) = accProps ls 
-accProps ((False, _) : ls)      = accProps ls
-            
--- |This function takes two arguments, a list of already translated arguments
--- (including the translated premises and exceptions) and a proposition 
--- paired with its to be translated arguments. It collects the results 
--- of the transApp function, which does the main work. 
-transApps :: [LConcreteArg] -> (PropLiteral, [Argument]) -> ([LConcreteArg], [(LConcreteArg, LConcreteArg)])
-transApps tArgs (p, args) = 
- let tr = map (transApp tArgs p) args
- in (map fst tr, concatMap snd tr)
-
--- |Given a list of already translated arguments and a propositional literal, 
--- an argument (pro the propositional literal) is translated into a Dung argument
--- and a possibly empty list of attackers. 
-transApp :: [LConcreteArg] -> PropLiteral -> Argument -> (LConcreteArg, [(LConcreteArg, LConcreteArg)])
-transApp tArgs p a@(Arg (prems, excs, c)) 
- | accProps tArgs `intersect` prems /= prems = ((False, Right a), [(defeater, (False, Right a))])
- | otherwise = 
- let acceptableExceptions = filter (\ (b, arg) -> b && either (`elem` excs) (const False) arg) tArgs
-     applicableArg        = (null acceptableExceptions, Right a)
-     defeats              = map (\ argExc -> (argExc, applicableArg)) acceptableExceptions
- in (applicableArg, defeats)
-
--- |Determines the maximum weight of a list of applicable arguments (assumed
--- to have the same conclusion).
-maxWeight :: [LConcreteArg] -> CAES -> Double
-maxWeight as caes@(CAES (_, (_, argWeight), _))
- = foldl max 0 [argWeight a | (True, Right a) <- as] 
-
- 
--- |This function expects the following arguments: a propositional literal at
--- question, a list of pro arguments (labelled 'True', and thus acceptable in
--- the current AF), a list of con arguments (acceptable in the current AF) and 
--- a CAES. The result will be an argument corresponding to the proposition and 
--- a list of attacks. 
-transAcc :: PropLiteral -> [LConcreteArg] -> [LConcreteArg] -> CAES -> (LConcreteArg, [(LConcreteArg, LConcreteArg)])
-transAcc c [] conArgs caes = ((False, Left c),  [(defeater, (False, Left c))]) -- no applicable argument for p
-transAcc c ((_, Left _): proArgs) conArgs caes = error "Proposition in the list of applicable arguments"
-transAcc c ((False, _) : proArgs) conArgs caes = transAcc c proArgs conArgs caes
-transAcc c proArgs@((True, _) : proArgs') conArgs caes@(CAES (_, _, standard)) 
- | standard c == Scintilla  = ((True, Left c), []) -- there is an applicable argument for p, thus acceptable under Scintilla
- | standard c == Preponderance && 
-   maxWeight proArgs caes > maxWeight conArgs caes = ((True, Left c), [])
- | standard c == ClearAndConvincing && 
-   maxWeight proArgs caes > alpha && 
-   maxWeight proArgs caes > maxWeight conArgs caes + beta = ((True, Left c), []) 
- | standard c == BeyondReasonableDoubt && 
-   maxWeight proArgs caes > alpha && 
-   maxWeight proArgs caes > maxWeight conArgs caes + beta && 
-   maxWeight conArgs caes < gamma = ((True, Left c), [])
- | standard c == DialecticalValidity && null conArgs  = ((True, Left c), [])
- | otherwise = ((False, Left c), [(defeater, (False, Left c))])
-
--- |Correspondence of the applicability of arguments. 
-corApp :: CAES -> Bool
-corApp caes@(CAES (argSet, _, _)) = 
-  let translatedCAES  = translate caes
-      applicableArgs  = filter  (`applicable` caes) 
-                                (getAllArgs argSet)
-      transArgs       = rights $ groundedExt translatedCAES
-  in fromList applicableArgs == fromList transArgs
-
--- |Correspondence of the acceptability of propositional literals, including 
--- assumptions.
-corAcc :: CAES -> Bool
-corAcc caes@(CAES (argSet, (assumptions, _), _)) =                 
-  let translatedCAES   = translate caes
-      acceptableProps  = filter  (\ p -> p `acceptable` caes || 
-                                         p `elem` assumptions)  
-                                 (getProps argSet)
-      transProps       = lefts $ delete (Left $ mkProp "defeater") 
-                                        (groundedExt translatedCAES )
+-- |This module implements a translation from the Carneades argumentation model+-- into Dung's argumentation frameworks. Any cycle-free Carneades Argument+-- Evaluation Structure (CAES) is handled. We also give a Haskell implementation of +-- correspondence properties. +-- +-- Translation is done according to the following algorithm (see also \"Towards a+-- framework for the implementation and verification of translations between +-- argumentation models\" by Bas van Gijzel and Henrik Nilsson)+-- +-- 1. generatedArgs = /emptyset/.+-- +-- 2. sortedArgs = Topological sort of arguments on its dependency graph.+-- +-- 3. while sortedArgs != /emptyset/: +--  +--   * Pick the first argument in sortedArgs.+--     Remove all arguments from sortedArgs that have the same conclusion,+--     c, and put them in argSet. +-- +--   * Translate applicability part of arguments argSet, building on previously+--     generatedArgs and put the generated arguments in tempArgs.+--+--   * argSet = /emptyset/+-- +--   * Repeat the above three steps for the arguments for the opposite conclusion. +--+--   * Translate the acceptability part of c and the opposite conclusion based on +--     arguments in tempArgs. Add the results and tempArgs to generatedArgs.+--   +--   * tempArgs = /emptyset/+module Language.CarneadesIntoDung.Translation+ (+    -- * Basic types+    ConcreteArg, LConcreteArg,+    ConcreteAF, LConcreteAF,+    -- * Translation functions+    translate, translate', +    -- * Correspondence properties+    -- | Informally, the correspondence properties below state that every +    -- argument and proposition in a CAES, after translation, will have a+    -- corresponding argument and keep the same acceptability status. +    --+    -- If the translation function is a correct implementation, the Haskell +    -- implementation of the correspondence properties should always return +    -- 'True'. However to constitute an actual (mechanised) proof we would +    -- need to convert the translation and the implementation of the +    -- correspondence properties in Haskell to a theorem prover like Agda.+    --+    -- See Section 4.4 of the paper for the formally stated properties.+ ++    corApp, corAcc)+ where+import Language.Dung.AF (DungAF(..), groundedExt)+import Language.Carneades.CarneadesDSL+import Language.Carneades.Cyclic+import Data.Graph.Inductive+import Data.List (find, delete, intersect)+import Data.Maybe (fromMaybe)+import Data.Either (lefts, rights)+import Data.Set (fromList)+import Prelude hiding (negate)++-- |A concrete argument (in an argumentation framework) is either a Carneades +-- propositional literal, or a Carneades argument.+type ConcreteArg = Either PropLiteral Argument   ++-- |A labelled version of the concrete argument allowing a more efficient +-- translation by keeping track of the translation status.+type LConcreteArg = (Bool, ConcreteArg) ++-- |An argumentation framework (AF) instantiated with 'ConcreteArg'.+type ConcreteAF = DungAF ConcreteArg++-- |An argumentation framework (AF) instantiated with 'LConcreteArg'.+type LConcreteAF = DungAF LConcreteArg++-- |Assumed true argument in the translated AF. It is used to attack arguments+-- that do not uphold their proof standard or have unacceptable premises.+defeater :: LConcreteArg +defeater = (True, Left $ mkProp "defeater")+++-- | Topological sort of the dependency graph+-- The result is a list, pairing a proposition with all its pro arguments+topSort :: ArgSet -> [(PropLiteral, [Argument])]+topSort g | cyclic g  = error "Argumentation graph is cyclic!"+          | otherwise = reverse $ topsort' g++-- |Transforms a Carneades proposition into a Dung argument and labels it 'True'.+propToLArg :: PropLiteral -> LConcreteArg+propToLArg p = (True, Left p)++-- |Strips the label of both the 'LConcreteArg's in the attack.+stripAttack :: (LConcreteArg, LConcreteArg) -> (ConcreteArg, ConcreteArg) +stripAttack (a, b) = (snd a, snd b)++-- |Translation function. It translate an arbitrary /cycle-free/ Carneades argument+-- Evaluation Structure (CAES) into a Dung argumentation framework (instantiated+-- with a ConcreteArg)+translate :: CAES -> ConcreteAF+translate caes@(CAES (argSet, (assumptions, _), _)) + = AF (map snd args) (map stripAttack attacks)+ where AF args attacks = argsToAF (topSort argSet) +                                  caes +                                  (AF (defeater : map propToLArg assumptions) [])+++-- |Mainly, for testing purposes. This function behaves exactly like 'translate', +-- but retains the labels. +translate' :: CAES -> LConcreteAF +translate' caes@(CAES (argSet, (assumptions, _), _))+ = AF args attacks+ where AF args attacks = argsToAF (topSort argSet) +                                  caes +                                  (AF (defeater : map propToLArg assumptions) [])+++-- |Retrieves the arguments con the given proposition 'p'. +conArgs :: PropLiteral -> [(PropLiteral, [Argument])] -> (PropLiteral, [Argument])+conArgs p argList = fromMaybe (negate p, []) (find ((== negate p) . fst) argList)++-- |Corresponds to the whole of 3. of the above algorithm (or Algorithm 4.1 in +-- the paper)+-- +-- If there are no more arguments to process, the translated AF is returned. ++-- If there is a propositional literal left, but it is an assumption, it has+-- already been translated and does not need to be considered. +-- +-- Otherwise, collect all pro and con arguments for p (con arguments are obtained+-- by calling 'conArgs') and remove them from @argList@. The translation is then +-- done in four steps. 'transApps' is called to translate the applicability part of +-- the pro and con arguments. 'transAcc' is called to translate the acceptability of +-- p and the opposite of p (note that the order of applicable arguments is switched+-- for translating the acceptability of the opposite of p). The results of these +-- four calls are collected and used in the recursive step of 'argsToAF'. +argsToAF :: [(PropLiteral, [Argument])] -> CAES -> LConcreteAF -> LConcreteAF+argsToAF [] _ transAF = transAF+argsToAF (pro@(p, _proArgs) : argList) caes@(CAES (_, (assumptions, _), _)) (AF args defs)+ | p `elem` assumptions = argsToAF argList caes (AF args defs)+ | otherwise = + let  con                    = conArgs p argList+      (proAppArgs, proDefs)  = transApps args pro+      (conAppArgs, conDefs)  = transApps args con+      (newArgPro, proDefs')  = transAcc p proAppArgs conAppArgs caes+      (newArgCon, conDefs')  = transAcc (negate p) conAppArgs proAppArgs caes+      argList'               = delete con argList+ in argsToAF argList' caes +            (AF (newArgPro : newArgCon : proAppArgs ++ conAppArgs ++ args) +                (proDefs' ++ conDefs' ++ proDefs ++ conDefs ++ defs))++-- |Filters out propositional literals that have been labelled 'True'.+accProps :: [LConcreteArg] -> [PropLiteral]+accProps []                     = []+accProps ((True, Left p) : ls)  = p : accProps ls+accProps ((True, Right _) : ls) = accProps ls +accProps ((False, _) : ls)      = accProps ls+            +-- |This function takes two arguments, a list of already translated arguments+-- (including the translated premises and exceptions) and a proposition +-- paired with its to be translated arguments. It collects the results +-- of the transApp function, which does the main work. +transApps :: [LConcreteArg] -> (PropLiteral, [Argument]) -> ([LConcreteArg], [(LConcreteArg, LConcreteArg)])+transApps tArgs (p, args) = + let tr = map (transApp tArgs p) args+ in (map fst tr, concatMap snd tr)++-- |Given a list of already translated arguments and a propositional literal, +-- an argument (pro the propositional literal) is translated into a Dung argument+-- and a possibly empty list of attackers. +transApp :: [LConcreteArg] -> PropLiteral -> Argument -> (LConcreteArg, [(LConcreteArg, LConcreteArg)])+transApp tArgs _p a@(Arg (prems, excs, _c))+ | accProps tArgs `intersect` prems /= prems = ((False, Right a), [(defeater, (False, Right a))])+ | otherwise = + let acceptableExceptions = filter (\ (b, arg) -> b && either (`elem` excs) (const False) arg) tArgs+     applicableArg        = (null acceptableExceptions, Right a)+     defeats              = map (\ argExc -> (argExc, applicableArg)) acceptableExceptions+ in (applicableArg, defeats)++-- |Determines the maximum weight of a list of applicable arguments (assumed+-- to have the same conclusion).+maxWeight :: [LConcreteArg] -> CAES -> Double+maxWeight args (CAES (_, (_, argWeight), _))+ = foldl max 0 [argWeight a | (True, Right a) <- args]++ +-- |This function expects the following arguments: a propositional literal at+-- question, a list of pro arguments (labelled 'True', and thus acceptable in+-- the current AF), a list of con arguments (acceptable in the current AF) and +-- a CAES. The result will be an argument corresponding to the proposition and +-- a list of attacks. +transAcc :: PropLiteral -> [LConcreteArg] -> [LConcreteArg] -> CAES -> (LConcreteArg, [(LConcreteArg, LConcreteArg)])+transAcc c [] _conArgs _caes = ((False, Left c),  [(defeater, (False, Left c))]) -- no applicable argument for p+transAcc _c ((_, Left _): _proArgs) _conArgs _caes = error "Proposition in the list of applicable arguments"+transAcc c ((False, _) : proArgs) conArgs caes = transAcc c proArgs conArgs caes+transAcc c proArgs@((True, _) : _) conArgs caes@(CAES (_, _, standard))+ | standard c == Scintilla  = ((True, Left c), []) -- there is an applicable argument for p, thus acceptable under Scintilla+ | standard c == Preponderance &&+   maxWeight proArgs caes > maxWeight conArgs caes = ((True, Left c), [])+ | standard c == ClearAndConvincing &&+   maxWeight proArgs caes > alpha &&+   maxWeight proArgs caes > maxWeight conArgs caes + beta = ((True, Left c), [])+ | standard c == BeyondReasonableDoubt &&+   maxWeight proArgs caes > alpha &&+   maxWeight proArgs caes > maxWeight conArgs caes + beta &&+   maxWeight conArgs caes < gamma = ((True, Left c), [])+ | standard c == DialecticalValidity && null conArgs  = ((True, Left c), [])+ | otherwise = ((False, Left c), [(defeater, (False, Left c))])++-- |Correspondence of the applicability of arguments. +corApp :: CAES -> Bool+corApp caes@(CAES (argSet, _, _)) =+  let translatedCAES = translate caes+      applicableArgs  = filter (`applicable` caes)+                               (getAllArgs argSet)+      transArgs       = rights $ groundedExt translatedCAES+  in fromList applicableArgs == fromList transArgs++-- |Correspondence of the acceptability of propositional literals, including +-- assumptions.+corAcc :: CAES -> Bool+corAcc caes@(CAES (argSet, (assumptions, _), _)) =+  let translatedCAES = translate caes+      acceptableProps = filter (\p -> p `acceptable` caes ||+                                      p `elem` assumptions)+                               (getProps argSet)+      transProps      = lefts $ delete (Left $ mkProp "defeater")+                                       (groundedExt translatedCAES)   in fromList acceptableProps == fromList transProps
− src/Main.hs
@@ -1,100 +0,0 @@--- |This module implements a command-line interface to the implementation of 
--- Carneades. CAES + Haskell = caell
---
--- Code in this module partly taken from/inspired by Shinobu
--- See: http://zuttobenkyou.wordpress.com/2011/04/19/haskell-using-cmdargs-single-and-multi-mode/
--- and http://listx.github.com/
-{-# LANGUAGE DeriveDataTypeable, RecordWildCards #-}
-module Main
-  (
-    main
-  )
- where
-import Language.CarneadesIntoDung.Translation
-import Language.Carneades.CarneadesDSL(CAES(..), getAllArgs, applicable,
-                                       getProps, acceptable)
-import Language.Carneades.Input
-import Language.Dung.AF(groundedExt, preferredExt, stableExt, semiStableExt,
-                        DungAF(..))
-import Language.Dung.Output
-
-import System.Console.CmdArgs
-import System.Environment (getArgs, withArgs)
-import System.Exit
-import Control.Monad (when, unless)
-
-data MyOptions = MyOptions {
-  cegartix          :: Bool,
-  laxCegartix       :: Bool,
-  fileName          :: String,
-  outputFile        :: String,
-  correspondence    :: Bool,
-  extension         :: Bool,
-  xSemantics :: Bool
- } deriving (Show, Data, Typeable)
-
-myProgOpts :: MyOptions
-myProgOpts = MyOptions
-    { cegartix    = True     &= help "Output in strict CEGARTIX/PrefSat format (standard)" 
-    , laxCegartix = False    &= help "Output in lax CEGARTIX/PrefSat format (+parentheses)" 
-    , fileName   = def       &= typFile &= help "Name of the file to be read"
-    , outputFile = def       &= typFile &= help "Name of the file to be written"
-    , extension  = True      &= help "Output unique complete extension for the translated CAES (standard)"
-    , correspondence = False &= help "Display satisfaction of correspondence result"
-    , xSemantics = False     &= help "Output evaluation of the original Carneades semantics"
-   }
- 
-getOpts :: IO MyOptions
-getOpts = cmdArgs $ myProgOpts
-    &= versionArg [explicit, name "version", name "v", summary _PROGRAM_INFO]
-    &= summary (_PROGRAM_INFO ++ ", " ++ _COPYRIGHT)
-    &= help _PROGRAM_ABOUT
-    &= helpArg [explicit, name "help", name "h"]
-    &= program _PROGRAM_NAME
- 
-_PROGRAM_NAME = "caell"
-_PROGRAM_VERSION = "1.0"
-_PROGRAM_INFO = _PROGRAM_NAME ++ " version " ++ _PROGRAM_VERSION
-_PROGRAM_ABOUT = "An implementation of Carneades in Haskell"
-_COPYRIGHT = "(C) Bas van Gijzel 2014"
-
-
-main :: IO ()
-main = do 
-        args <- getArgs
-        opts <- (if null args then withArgs ["--help"] else id) getOpts
-        optionHandler opts
-
--- |Check any malformed arguments/missing arguments. 
-optionHandler :: MyOptions -> IO ()
-optionHandler opts@MyOptions{..}  = do
-    when (null fileName) $ putStrLn "--fileName is blank!" >> exitWith (ExitFailure 1)
-    input <- readFile fileName
-    let opts' = opts {cegartix = not laxCegartix}
-    caes <- case parseCAES input of 
-           Left err -> putStrLn "Parsing error: " >> print err >> exitWith (ExitFailure 1)
-           Right caes -> return caes
-    exec opts' caes
-
--- |Execute supplied options
-exec :: MyOptions -> CAES -> IO ()
-exec opts@MyOptions{..} caes@(CAES (argSet, (assumptions, _), _)) = do
-    let args = getAllArgs argSet
-    let transCaes = translate caes
-    putStrLn $ "Argument set: " ++ show args
-    when xSemantics $
-      putStrLn "Evaluation under original semantics:" >>
-      putStrLn "Applicable arguments:" >> 
-      print (filter (`applicable` caes) args) >>
-      putStrLn "Acceptable propositions:" >> 
-      print (filter (\ p -> p `acceptable` caes 
-                         || p `elem` assumptions)
-                    (getProps argSet))  
-    when extension $ putStrLn "Extension after translation: " 
-      >> print (groundedExt transCaes)
-    when correspondence $ putStrLn ("Correspondence of applicability is: " ++ show (corApp caes))
-      >> putStrLn ("Correspondence of acceptability is: " ++ show (corAcc caes))
-    unless (null outputFile)
-      $ if cegartix 
-          then writeFile outputFile (toStrictCegartix transCaes) >> putStrLn "File outputted."
-          else writeFile outputFile (toCegartix transCaes) >> putStrLn "File outputted."
+ test/Main.hs view
@@ -0,0 +1,10 @@+module Main (main) where++import Test.Tasty++import qualified Test.Language.CarneadesIntoDung.Translation as Translation++main :: IO ()+main = defaultMain $ testGroup "CarneadesIntoDung"+  [ Translation.tests+  ]
+ test/Test/Language/CarneadesIntoDung/Translation.hs view
@@ -0,0 +1,71 @@+module Test.Language.CarneadesIntoDung.Translation (tests) where++import Data.Either (lefts, rights)+import Data.Set (fromList)+import Test.Tasty+import Test.Tasty.HUnit++import Language.Dung.AF (DungAF(..), groundedExt)+import Language.Carneades.CarneadesDSL (CAES(..), mkProp, getAllArgs, applicable,+                                        getProps, acceptable)+import Language.Carneades.ExampleCAES (caes)+import Language.CarneadesIntoDung.Translation++tests :: TestTree+tests = testGroup "Language.CarneadesIntoDung.Translation"+  [ translateTests+  , groundedExtTests+  , correspondenceTests+  ]++translateTests :: TestTree+translateTests = testGroup "translate"+  [ testCase "translate produces a non-empty AF" $ do+      let AF args attacks = translate caes+      assertBool "AF should have arguments" (not (null args))+      assertBool "AF should have attacks" (not (null attacks))+  , testCase "translate' produces a non-empty labelled AF" $ do+      let AF args attacks = translate' caes+      assertBool "labelled AF should have arguments" (not (null args))+      assertBool "labelled AF should have attacks" (not (null attacks))+  , testCase "defeater is in the grounded extension" $ do+      let ext = groundedExt (translate caes)+      assertBool "defeater should be in grounded extension"+        (Left (mkProp "defeater") `elem` ext)+  , testCase "assumptions are in the grounded extension" $ do+      let CAES (_, (assumptions, _), _) = caes+      let ext = lefts $ groundedExt (translate caes)+      mapM_ (\a -> assertBool ("assumption " ++ show a ++ " should be in extension")+                              (a `elem` ext))+            assumptions+  ]++groundedExtTests :: TestTree+groundedExtTests = testGroup "groundedExt"+  [ testCase "grounded extension contains applicable arguments" $ do+      let CAES (argSet, _, _) = caes+      let appArgs = filter (`applicable` caes) (getAllArgs argSet)+      let ext = rights $ groundedExt (translate caes)+      mapM_ (\a -> assertBool ("applicable arg " ++ show a ++ " should be in extension")+                              (a `elem` ext))+            appArgs+  , testCase "grounded extension contains acceptable propositions" $ do+      let CAES (argSet, (assumptions, _), _) = caes+      let accProps = filter (\p -> p `acceptable` caes || p `elem` assumptions)+                            (getProps argSet)+      let ext = lefts $ filter (/= Left (mkProp "defeater"))+                                (groundedExt (translate caes))+      assertEqual "acceptable propositions should match"+        (fromList accProps) (fromList ext)+  ]++correspondenceTests :: TestTree+correspondenceTests = testGroup "correspondence"+  [ testCase "corApp caes returns True" $+      corApp caes @?= True+  , testCase "corAcc caes returns True" $+      corAcc caes @?= True+  , testCase "corProp (combined) returns True" $ do+      let result = corApp caes && corAcc caes+      result @?= True+  ]