packages feed

horde-ad-0.3.0.0: horde-ad.cabal

cabal-version:      3.6
-- The cabal-version field refers to the version of the .cabal specification,
-- and can be different from the cabal-install (the tool) version and the
-- Cabal (the library) version you are using. As such, the Cabal (the library)
-- version used must be equal or greater than the version stated in this field.
-- Starting from the specification version 2.2, the cabal-version field must be
-- the first thing in the cabal file.

-- Initial package description 'horde-ad' generated by
-- 'cabal init'. For further documentation, see:
--   http://haskell.org/cabal/users-guide/
--
-- The name of the package.
name:               horde-ad

-- The package version.
-- See the Haskell package versioning policy (PVP) for standards
-- guiding when and how versions should be incremented.
-- https://pvp.haskell.org
-- PVP summary:     +-+------- breaking API changes
--                  | | +----- non-breaking API additions
--                  | | | +--- code changes with no API change
version:            0.3.0.0

-- A short (one-line) description of the package.
synopsis:           Higher Order Reverse Derivatives Efficiently - Automatic Differentiation

-- A longer description of the package.
description:        An Automatic Differentiation library originally inspired by the paper "Provably correct, asymptotically efficient, higher-order reverse-mode automatic differentiation" (POPL 2022). Compared to the paper and to classic taping AD Haskell packages, the library additionally efficiently supports array operations and generation of symbolic derivative programs, though the efficiency is confined to a narrowly typed class of source programs with limited higher-orderness. A detailed account of the extension is in the paper by Tom Smeding, Mikolaj Konarski, Simon Peyton Jones and Andrew Fitzgibbon available at http://arxiv.org/abs/2507.12640.

-- The license under which the package is released.
license:            BSD-3-Clause

-- The file containing the license text.
license-file:       LICENSE

-- The package author(s).
author:             Mikolaj Konarski and others

-- An email address to which users can send suggestions, bug reports, and patches.
maintainer:         mikolaj@well-typed.com

category:           Machine Learning, Tensors

-- A copyright notice.
-- copyright:
build-type:         Simple

-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.
extra-doc-files:    README.md
                    CHANGELOG.md
                    CREDITS.md

tested-with:        GHC ==9.10.3 || ==9.12.4 || ==9.14.1

bug-reports:        https://github.com/Mikolaj/horde-ad/issues

source-repository head
  type:               git
  location:           https://github.com/Mikolaj/horde-ad.git

flag with_expensive_assertions
  description:        turn on expensive assertions of well-tested code
  default:            False
  manual:             True

flag release
  description:        remember to set before tagging for a release (to expose internal functions and types, disable tests that depend on not packaged data, etc.)
  default:            True
  manual:             True

flag test_seq
  description:        run all of the test suite in sequential mode
  default:            False
  manual:             True

common options
  default-language:   GHC2024
  default-extensions: StrictData TypeFamilies TypeFamilyDependencies
                      FunctionalDependencies RecordWildCards MultiWayIf
                      DefaultSignatures PatternSynonyms NoStarIsType
                      TypeData TypeAbstractions
                      -- to molify stylish-haskell, until it's fixed
                      LambdaCase
  other-extensions:   UnboxedTuples CPP ViewPatterns OverloadedLists
                      DeriveAnyClass QuantifiedConstraints TemplateHaskell
                      DerivingVia ImpredicativeTypes
                      UndecidableInstances UndecidableSuperClasses
                      AllowAmbiguousTypes
  -- * Warnings and similar.
  ghc-options:        -Wall -Wcompat -Wimplicit-prelude -Widentities -Wredundant-constraints -Wmissing-export-lists -Wpartial-fields -Wunused-packages -Wredundant-bang-patterns -Woperator-whitespace -Wredundant-strictness-flags -Wterm-variable-capture -Wmissed-specialisations
  ghc-options:        -Wmissing-poly-kind-signatures -Wmissing-role-annotations -Wno-unticked-promoted-constructors
  -- Disables a warning we can't yet fix:
  if impl(ghc >= 9.14)
    ghc-options:      -Wno-pattern-namespace-specifier
  ghc-options:        -fprint-explicit-kinds -fsimpl-tick-factor=200

  -- * Performance.
  -- This is supposedly risky, but prevents STG from creating thunks, #23848:
  ghc-options:        -fworker-wrapper-cbv
  -- These improve performance, but slow down compilation:
  if impl(ghc >= 9.12)
    ghc-options:      -fexpose-overloaded-unfoldings
  ghc-options:        -fspecialise-aggressively
  if impl(ghc >= 9.14)
    ghc-options:      -fpolymorphic-specialisation
  -- This one improves both performance and compilation speed:
  ghc-options:        -fkeep-auto-rules
  -- These improve performance to some extent:
  ghc-options:        -fdicts-cheap -flate-dmd-anal
  -- Twice the compilation time and no consistent performance boost:
  -- ghc-options      -flate-specialise
  -- 30% longer compilation for small and inconsistent performance benefits:
  -- ghc-options:     -O2

  -- * Misc.
  if flag(with_expensive_assertions)
    cpp-options:      -DWITH_EXPENSIVE_ASSERTIONS

  if flag(release)
    cpp-options:      -DEXPOSE_INTERNAL

  -- This needs to be after -O2.
  ghc-options:        -fno-ignore-asserts

common exe-options
  ghc-options:        -rtsopts -threaded
  -- Make GC more predictable in benchmarks.
  ghc-options:        "-with-rtsopts=-H1.5g -A0.75g -I0"

common exe-options-for-parallel-tests
  ghc-options:        -rtsopts -threaded
  if flag(test_seq)
    ghc-options:      "-with-rtsopts=-H1.5g -A0.75g -I0"
  else
    -- Beware, -with-rtsopts is not cumulative!
    ghc-options:      "-with-rtsopts=-H1.5g -A0.75g -I0 -N8"

library
    import:           options

    exposed-modules:  HordeAd
                      HordeAd.ADEngine
                      HordeAd.OpsTensor
                      HordeAd.OpsTensorRanked
                      HordeAd.OpsTensorShaped
                      HordeAd.OpsTensorMixed
                      HordeAd.Core.Adaptor
                      HordeAd.Core.Ast
                      HordeAd.Core.AstEngine
                      HordeAd.Core.AstEnv
                      HordeAd.Core.AstFreshId
                      HordeAd.Core.AstInline
                      HordeAd.Core.AstInterpret
                      HordeAd.Core.AstMethodLet
                      HordeAd.Core.AstMethodShare
                      HordeAd.Core.AstSimplify
                      HordeAd.Core.AstTools
                      HordeAd.Core.AstTraverse
                      HordeAd.Core.AstVectorize
                      HordeAd.Core.CarriersADVal
                      HordeAd.Core.CarriersAst
                      HordeAd.Core.CarriersConcrete
                      HordeAd.Core.Conversion
                      HordeAd.Core.ConvertTensor
                      HordeAd.Core.Delta
                      HordeAd.Core.DeltaEval
                      HordeAd.Core.DeltaFreshId
                      HordeAd.Core.Ops
                      HordeAd.Core.OpsADVal
                      HordeAd.Core.OpsAst
                      HordeAd.Core.OpsConcrete
                      HordeAd.Core.PPEngine
                      HordeAd.Core.PPTools
                      HordeAd.Core.TensorKind
                      HordeAd.Core.Types
                      HordeAd.Core.Unwind
                      HordeAd.Core.UnwindNum
                      HordeAd.External.CommonRankedOps
                      HordeAd.External.CommonShapedOps
                      HordeAd.External.Optimizer
                      HordeAd.External.OptimizerTools

    hs-source-dirs:   src

    build-depends:
        assert-failure < 0.1.4
      , atomic-counter < 0.2
      , base >= 4.20.1 && < 4.23
      , Boolean < 0.3
      , containers >= 0.6 && < 0.9
      , deepseq < 1.7
      , data-default < 0.9
      , dependent-enummap >= 0.2 && < 0.3
      , dependent-sum >= 0.7 && < 0.8
      , enummapset < 0.8
      , ghc-typelits-knownnat >= 0.8.0 && < 1
      , ghc-typelits-natnormalise >= 0.8.1 && < 1
      , ox-arrays >= 0.2 && < 0.3
      , ox-arrays:strided-array-ops
      , random >= 1.3.0 && < 1.4
      , some >= 1 && < 2
      , vector >= 0.13.2.0 && < 0.14

library exampleLibrary
    import:           options
    visibility:       public

    exposed-modules:  MnistData
                      MnistCnnRanked2
                      MnistCnnShaped2
                      MnistFcnnRanked1
                      MnistFcnnRanked2
                      MnistRnnRanked2
                      MnistRnnShaped2

    hs-source-dirs:   example

    build-depends:
      , horde-ad:horde-ad

      , base
      , bytestring < 0.13
      , ghc-typelits-knownnat
      , ghc-typelits-natnormalise
      , mnist-idx < 0.2
      , ox-arrays
      , random
      , vector
      , zlib < 0.8

library benchCommonLibrary
    import:           options
    visibility:       public

    exposed-modules:  BenchMnistTools
                      BenchProdTools

    hs-source-dirs:   bench/common

    build-depends:
      , horde-ad:exampleLibrary
      , horde-ad:horde-ad

      , base
      , criterion < 1.7
      , deepseq < 1.7
      , data-default < 0.9
      , inspection-testing < 0.7
      , ox-arrays
      , random

benchmark longProdBench
    import:           options, exe-options

    type:             exitcode-stdio-1.0

    hs-source-dirs:   bench

    main-is:          LongProdBench.hs

    build-depends:
      , horde-ad:benchCommonLibrary

      , base
      , criterion
      , deepseq
      , random

benchmark shortProdForCI
    import:           options, exe-options

    type:             exitcode-stdio-1.0

    hs-source-dirs:   bench

    main-is:          ShortProdForCI.hs

    build-depends:
      , horde-ad:benchCommonLibrary

      , base
      , criterion
      , deepseq
      , random

-- The data files for this are not included in the cabal package,
-- hence 'buildable: False'.
benchmark longMnistBench
    import:           options, exe-options

    if flag(release)
      buildable: False
    else
      buildable: True

    type:             exitcode-stdio-1.0

    hs-source-dirs:   bench

    main-is:          LongMnistBench.hs

    build-depends:
      , horde-ad:benchCommonLibrary

      , base
      , criterion

-- The data files for this are not included in the cabal package,
-- hence 'buildable: False'.
benchmark shortMnistForCI
    import:           options, exe-options

    if flag(release)
      buildable: False
    else
      buildable: True

    type:             exitcode-stdio-1.0

    hs-source-dirs:   bench

    main-is:          ShortMnistForCI.hs

    build-depends:
      , horde-ad:benchCommonLibrary

      , base
      , criterion

-- takes forever, so mostly to invoke with --benchmark-options='-n 1 +RTS -s'
benchmark realisticMnistBench
    import:           options, exe-options

-- Disabled so that `cabal bench` terminates in finite time.
--    if flag(release)
    buildable: False
--    else
--      buildable: True

    type:             exitcode-stdio-1.0

    hs-source-dirs:   bench

    main-is:          RealisticMnistBench.hs

    build-depends:
      , horde-ad:benchCommonLibrary
      , horde-ad:exampleLibrary

      , base
      , criterion
      , random

library testToolLibrary
    import:           options
    visibility:       public

    exposed-modules:  CrossTesting
                      EqEpsilon
                      Shared

    hs-source-dirs:   test/tool

    build-depends:
      , horde-ad:horde-ad

      , base
      , orthotope >= 0.1.8 && < 0.1.9
      , ox-arrays
      , tasty >= 1.5.4 && < 1.6
      , tasty-hunit < 0.11
      , vector

library testCommonLibrary
    import:           options
    visibility:       public

    exposed-modules:  TestAdaptorSimplified
                      TestConvQuickCheck
                      TestConvSimplified
                      TestGatherSimplified
                      TestHighRankSimplified
                      TestMnistCNNR
                      TestMnistCNNS
                      TestMnistFCNNR
                      TestMnistPP
                      TestMnistRNNR
                      TestMnistRNNS
                      TestRevFwdFold

    hs-source-dirs:   test/simplified

    -- Other library packages from which modules are imported.
    build-depends:
      , horde-ad:horde-ad
      , horde-ad:exampleLibrary
      , horde-ad:testToolLibrary

      , assert-failure
      , base
      , ghc-typelits-knownnat
      , ghc-typelits-natnormalise
      , ox-arrays
      , random
      , tasty >= 1.5.4 && < 1.6
      , tasty-hunit < 0.11
      , tasty-quickcheck < 0.12
      , vector

-- The data files for this are not included in the cabal package,
-- hence 'buildable: False'.
test-suite fullTest
    import:           options, exe-options

    if flag(release)
      buildable: False
    else
      buildable: True

    type:             exitcode-stdio-1.0

    hs-source-dirs:   test

    main-is:          FullTest.hs

    build-depends:
      , horde-ad:testCommonLibrary
      , horde-ad:testToolLibrary

      , base
      , tasty

-- This test must be sequential, because counter reset is not thread-safe.
test-suite CAFlessTest
    import:           options, exe-options

    if flag(release)
      buildable: False
    else
      buildable: True

    type:             exitcode-stdio-1.0

    hs-source-dirs:   test

    main-is:          CAFlessTest.hs

    build-depends:
      , horde-ad:testCommonLibrary
      , horde-ad:testToolLibrary

      , base
      , tasty

test-suite parallelTest
    import:           options, exe-options-for-parallel-tests

    if flag(release)
      buildable: False
    else
      buildable: True

    type:             exitcode-stdio-1.0

    hs-source-dirs:   test

    main-is:          ParallelTest.hs

    build-depends:
      , horde-ad:testCommonLibrary
      , horde-ad:testToolLibrary

      , base
      , tasty

-- This test can serve as a benchmark when run sequentially.
test-suite sequentialMnistTest
    import:           options, exe-options

    if flag(release)
      buildable: False
    else
      buildable: True

    type:             exitcode-stdio-1.0

    hs-source-dirs:   test

    main-is:          SequentialMnistTest.hs

    build-depends:
      , horde-ad:testCommonLibrary
      , horde-ad:testToolLibrary

      , base
      , tasty

-- These tests don't require any dataset and are short, so can be enabled
-- in the Hackage package.
test-suite minimalTest
    import:           options, exe-options

    type:             exitcode-stdio-1.0

    hs-source-dirs:   test

    main-is:          MinimalTest.hs

    build-depends:
      , horde-ad:testCommonLibrary
      , horde-ad:testToolLibrary

      , base
      , tasty