packages feed

horde-ad-0.2.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.2.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.2 || ==9.12.3

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
  other-extensions:   UnboxedTuples, CPP, ViewPatterns, OverloadedLists,
                      DeriveAnyClass, UndecidableInstances, AllowAmbiguousTypes,
                      QuantifiedConstraints, TemplateHaskell, DerivingVia,
                      ImpredicativeTypes
  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
  ghc-options:        -fprint-explicit-kinds
  -- This is supposedly risky, but prevents STG from creating thunks, #23848:
  ghc-options:        -fworker-wrapper-cbv
  -- Disabling this breaks performance:
  ghc-options:        -fexpose-all-unfoldings -fspecialise-aggressively -fsimpl-tick-factor=200
  -- Disabling hurts performance to some extent:
  ghc-options:        -fdicts-cheap -flate-dmd-anal
  -- ghc-options: -O2 -flate-specialise

  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
  -- Make GC more predictable in benchmarks.
  ghc-options:        "-with-rtsopts=-H1.5g -A0.75g -I0"

common exe-options-for-tests-that-reset-counters
  ghc-options:        -rtsopts -threaded
  ghc-options:        "-with-rtsopts=-H1.5g -A0.75g -I0"
    -- unconditionally seqential, because counter reset is not thread-safe

common exe-options-test
  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 -N"

library
    import:           options

    exposed-modules:  HordeAd
                      HordeAd.ADEngine
                      HordeAd.AstEngine
                      HordeAd.Core.Adaptor
                      HordeAd.Core.Ast
                      HordeAd.Core.AstEnv
                      HordeAd.Core.AstFreshId
                      HordeAd.Core.AstInline
                      HordeAd.Core.AstInterpret
                      HordeAd.Core.AstPrettyPrint
                      HordeAd.Core.AstSimplify
                      HordeAd.Core.AstTools
                      HordeAd.Core.AstTraverse
                      HordeAd.Core.AstVectorize
                      HordeAd.Core.CarriersADVal
                      HordeAd.Core.CarriersAst
                      HordeAd.Core.CarriersConcrete
                      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.TensorKind
                      HordeAd.Core.Types
                      HordeAd.Core.Unwind
                      HordeAd.External.CommonRankedOps
                      HordeAd.External.CommonShapedOps
                      HordeAd.External.Optimizer
                      HordeAd.External.OptimizerTools
                      HordeAd.OpsTensor
                      HordeAd.OpsTensorRanked
                      HordeAd.OpsTensorShaped
                      HordeAd.OpsTensorMixed

    hs-source-dirs:   src

    build-depends:
        assert-failure < 0.1.4
      , base >= 4.20.1 && < 4.21
          -- backport of https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13498 is required for GHC 9.12; TODO: adjust base bounds once 9.12.3 is out
      , Boolean < 0.3
      , containers >= 0.6 && < 0.9
      , deepseq < 1.7
      , data-default < 0.9
      , dependent-enummap < 0.2
      , dependent-sum >= 0.7 && < 0.8
      , enummapset < 0.8
      , ghc-typelits-knownnat < 1
      , ghc-typelits-natnormalise < 1
      , indexed-traversable < 0.2
      , orthotope < 0.2
      , ox-arrays < 0.2
      , random >= 1.3.0 && < 1.4
      , some >= 1 && < 2
      , atomic-counter < 0.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
      , ox-arrays
      , tasty >= 1.0 && < 1.6
      , tasty-hunit < 0.11
      , vector

library testCommonLibrary
    import:           options
    visibility:       public

    exposed-modules:  TestAdaptorSimplified
                      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.0 && < 1.6
      , tasty-hunit < 0.11
      , tasty-quickcheck < 0.12

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

    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 >= 1.0

test-suite CAFlessTest
    import:           options, exe-options-for-tests-that-reset-counters

    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 >= 1.0

test-suite parallelTest
    import:           options, exe-options-test

    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 >= 1.0

-- 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-for-tests-that-reset-counters

    type:             exitcode-stdio-1.0

    hs-source-dirs:   test

    main-is:          MinimalTest.hs

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

      , base
      , tasty >= 1.0