-
-
Notifications
You must be signed in to change notification settings - Fork 414
Description
Your environment
Which OS do you use:
MacBook Pro 14" (2021) with 16GB ram, Apple M1 pro, serial # VGWRXQ2KN7
Which LSP client (editor/plugin) do you use:
VSCode with Haskell-language-server-wrapper.
Describe your project (alternative: link to the project):
stack.yaml:
# This file was automatically generated by 'stack init'
#
# Some commonly used options have been documented as comments in this file.
# For advanced use and comprehensive documentation of the format, please see:
# https://docs.haskellstack.org/en/stable/yaml_configuration/
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
# A snapshot resolver dictates the compiler version and the set of packages
# to be used for project dependencies. For example:
#
# resolver: lts-3.5
# resolver: nightly-2015-09-21
# resolver: ghc-7.10.2
#
# The location of a snapshot can be provided as a file or url. Stack assumes
# a snapshot provided as a file might change, whereas a url resource does not.
#
# resolver: ./custom-snapshot.yaml
# resolver: https://example.com/snapshots/2018-01-01.yaml
resolver: lts-18.24
# User packages to be built.
# Various formats can be used as shown in the example below.
#
# packages:
# - some-directory
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
# subdirs:
# - auto-update
# - wai
packages:
- .
# Dependency packages to be pulled from upstream that are not in the resolver.
# These entries can reference officially published versions as well as
# forks / in-progress versions pinned to a git hash. For example:
#
# extra-deps:
# - acme-missiles-0.3
# - git: https://github.com/commercialhaskell/stack.git
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
#
extra-deps:
- hmatrix-glpk-0.19.0.0@sha256:cf46c54bc3878bd207674ad88c3389083809f4df862df68ee64c6708dc517a52,1683
- Extra-1.46.3@sha256:eae163f553ba2f3252e2daf36c8ba3790c0b1435b359132f4e4a14976087827c,1412
- Unixutils-1.54.2@sha256:8061890ca05f13ee3bfb058b8a9b55eeb68410940c929b84f6086fe4750c19e6,1218
# Override default flag values for local packages and extra-deps
# flags: {}
# Extra package databases containing global packages
# extra-package-dbs: []
# Control whether we use the GHC we find on the path
system-ghc: true
#
# Require a specific version of stack, using version ranges
# require-stack-version: -any # Default
# require-stack-version: ">=2.7"
#
# Override the architecture used by stack, especially useful on Windows
# arch: i386
# arch: x86_64
#
# Extra directories used by stack for building
extra-include-dirs: [/opt/homebrew/Cellar/glpk/5.0/include]
extra-lib-dirs: [/opt/homebrew/Cellar/glpk/5.0/lib]
#
# Allow a newer minor version of GHC than the snapshot specifies
# compiler-check: newer-minorpackage.yaml:
name: Problem103
version: 0.1.0.0
github: "githubuser/Problem103"
license: BSD3
author: "Author name here"
maintainer: "example@example.com"
copyright: "2022 Author name here"
extra-source-files:
- README.md
- ChangeLog.md
# Metadata used when publishing your package
# synopsis: Short description of your package
# category: Web
# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description: Please see the README on GitHub at <https://github.com/githubuser/Problem103#readme>
dependencies:
- base >= 4.7 && < 5
- hspec
- hmatrix-glpk
- containers
- data-ordlist
library:
source-dirs: src
executables:
Problem103-exe:
main: Main.hs
source-dirs: app
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
- -Wall
dependencies:
- Problem103
tests:
Problem103-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
- -Wall
dependencies:
- Problem103Lib.hs:
{-# LANGUAGE TupleSections #-}
module Lib (optimalSetOfLength, isSpecialSumSet, sumString) where
import Data.Function (on)
import Data.List
( elemIndex,
find,
minimumBy,
sort,
subsequences,
)
import Data.List.Ordered (isSortedBy)
import Data.Maybe (catMaybes)
import Data.Tree (flatten, unfoldTree)
import GHC.Float (double2Int)
import Numeric.LinearProgramming
( Bound ((:>=:)),
Constraints (General),
Optimization (Minimize),
Solution (Feasible, Optimal),
exact,
)
-- | Build string encoding of sum string.
-- >>> sumString [1,2,3]
-- <BLANKLINE>
-- ByteCodeLink.lookupIE
-- During interactive linking, GHCi couldn't find the following symbol:
-- hmatrixzmglpkzm0zi19zi0zi0zm4WWw7FtlyHzz9Q9FBl9Okvq_NumericziLinearProgramming_ZCzgzeZC_con_info or hmatrixzmglpkzm0zi19zi0zi0zm4WWw7FtlyHzz9Q9FBl9Okvq_NumericziLinearProgramming_ZCzgzeZC_static_info
-- This may be due to you not asking GHCi to load extra object files,
-- archives or DLLs needed by your current session. Restart GHCi, specifying
-- the missing library using the -L/path/to/object/dir and -lmissinglibname
-- flags, or simply by naming the relevant files on the GHCi command line.
-- Alternatively, this link failure might indicate a bug in GHCi.
-- If you suspect the latter, please report this as a GHC bug:
-- https://www.haskell.org/ghc/reportabug
sumString ::
-- | sum string to encode.
[Int] ->
String
sumString = foldr (\int str -> show int <> str) ""
-- | Compute the integer set which minimizes the set sum,
-- subject to the constraints on a special subset set.
optimalSetOfLength ::
-- | The cardinality of the desired set.
Int ->
Maybe [Int]
optimalSetOfLength cardinality
| cardinality < 0 = Nothing
| cardinality == 1 = Just [1]
| cardinality == 2 = Just [1, 2]
| otherwise =
( solutionToSet
. minimumBy solutionCompare
. catMaybes
. flatten
. unfoldTree (simplexSolutionUnfolder cardinality)
)
(orderBounds cardinality <> borderBounds cardinality)
-- | Bounds to ensure that n1 < n2 < ... < nn given cardinality
orderBounds ::
-- | Cardinality
Int ->
[[(Double, Int)]]
orderBounds cardinality
| cardinality < 1 = error "This shouldn't have happened"
| cardinality == 1 = []
| otherwise =
(\c -> [(1, c), (negate 1, pred c)]) <$> [2 .. cardinality]
-- | Comparison of solutions.
solutionCompare ::
-- | x
Solution ->
-- | y
Solution ->
Ordering
solutionCompare (Optimal o) (Optimal o') = compare o o'
solutionCompare (Optimal o) (Feasible f) = compare o f
solutionCompare (Feasible f) (Optimal o) = compare f o
solutionCompare (Feasible f) (Feasible f') = compare f f'
solutionCompare (Optimal _) _ = LT
solutionCompare _ (Optimal _) = GT
solutionCompare (Feasible _) _ = LT
solutionCompare _ (Feasible _) = GT
solutionCompare _ _ = EQ
-- | Build the tree of simplex solutions.
simplexSolutionUnfolder ::
-- | Cardinality
Int ->
-- | Sparse matrix encoding the constraints for the simplex
-- solver.
[[(Double, Int)]] ->
(Maybe Solution, [[[(Double, Int)]]])
simplexSolutionUnfolder cardinality constraints =
case nextConstraintPair sol of
[[]] ->
( case sol of
Feasible _ -> Just sol
Optimal _ -> Just sol
_ -> Nothing,
[]
)
cons -> (Nothing, (: constraints) <$> cons)
where
sol :: Solution
sol =
exact
(Minimize $ replicate cardinality 1)
(General ((:>=: 1) <$> constraints))
[1 :>=: 1]
-- | Is xs a special sum set?
isSpecialSumSet ::
-- | xs: Set to test
[Int] ->
Bool
isSpecialSumSet =
isSortedBy ((<) `on` snd)
. sort
. ((\ys -> (length ys, sum ys)) <$>)
. subsequences
-- | Next pair of constraints to force special set conditions.
nextConstraintPair ::
-- | Solution for current set of constraints.
Solution ->
[[(Double, Int)]]
nextConstraintPair (Optimal (_, set)) =
nextConstraintPairForSet set
nextConstraintPair (Feasible (_, set)) =
nextConstraintPairForSet set
nextConstraintPair _ = []
-- | Compute next pair of constraints to drive solution to
-- special set.
nextConstraintPairForSet ::
-- | Current solution set members
[Double] ->
[[(Double, Int)]]
nextConstraintPairForSet solution =
case pairPairs of
Nothing -> [[]]
Just ((_, xs), (_, ys)) ->
[ ((1,) <$> indices xs) <> ((negate 1,) <$> indices ys),
((negate 1,) <$> indices xs) <> ((1,) <$> indices ys)
]
where
pairs :: [(Double, [Double])]
pairs =
sort $ (\xs -> (sum xs, xs)) <$> subsequences solution
pairPairs :: Maybe ((Double, [Double]), (Double, [Double]))
pairPairs =
find
(\((s1, _), (s2, _)) -> s1 == s2)
(zip pairs (tail pairs))
indices :: [Double] -> [Int]
indices xs =
(catMaybes . (((1 +) <$>) . (`elemIndex` solution) <$>)) xs
-- | Unpack solution if it is optimal or feasible.
solutionToSet ::
-- | Solution to unpack.
Solution ->
Maybe [Int]
solutionToSet (Optimal (_, xs)) = Just $ double2Int <$> xs
solutionToSet (Feasible (_, xs)) = Just $ double2Int <$> xs
solutionToSet _ = Nothing
-- | Build the constraints requiring subsets of greater
-- cardinality to have greater sums than those of lesser
-- cardinality.
borderBounds ::
-- | Cardinality of total set
Int ->
[[(Double, Int)]]
borderBounds cardinality =
borderBoundForLesserLength indices <$> [1 .. pred cardinality]
where
-- | List of (length, subset index) pairs
indices :: [(Int, [Int])]
indices =
( ((\xs -> (length xs, xs)) <$>)
. subsequences
)
[1 .. cardinality]
-- | Return a constraint to ensure that the maximum sum among
-- sets of a given cardinality is less than the minimum sum of
-- the next higher cardinality.
borderBoundForLesserLength ::
-- | List of (length, subset index) pairs
[(Int, [Int])] ->
-- | Cardinality for the lesser subset.
Int ->
[(Double, Int)]
borderBoundForLesserLength indices lesserCardinality =
constraint
( minimum $
filter
(\(len, _) -> len == succ lesserCardinality)
indices
)
( maximum $
filter
(\(len, _) -> len == lesserCardinality)
indices
)
-- | form constraint coefficient set for greater and
-- lesser (length, index subset)
constraint ::
-- | Greater subset characterization.
(Int, [Int]) ->
-- | Lesser subset characterization.
(Int, [Int]) ->
[(Double, Int)]
constraint (_, xs) (_, ys) =
((1,) <$> xs) <> ((negate 1,) <$> ys)Steps to reproduce
Open Lib.hs, search for -- >>> in commentary for function sumString. Click on "Evaluate" above line.
Expected behaviour
You should get a result "123"
Actual behaviour
Get error message
--
-- ByteCodeLink.lookupIE
-- During interactive linking, GHCi couldn't find the following symbol:
-- hmatrixzmglpkzm0zi19zi0zi0zm4WWw7FtlyHzz9Q9FBl9Okvq_NumericziLinearProgramming_ZCzgzeZC_con_info or hmatrixzmglpkzm0zi19zi0zi0zm4WWw7FtlyHzz9Q9FBl9Okvq_NumericziLinearProgramming_ZCzgzeZC_static_info
-- This may be due to you not asking GHCi to load extra object files,
-- archives or DLLs needed by your current session. Restart GHCi, specifying
-- the missing library using the -L/path/to/object/dir and -lmissinglibname
-- flags, or simply by naming the relevant files on the GHCi command line.
-- Alternatively, this link failure might indicate a bug in GHCi.
-- If you suspect the latter, please report this as a GHC bug:
-- https://www.haskell.org/ghc/reportabug
Include debug information
I don't understand where to go for this. The project builds and runs with stack run, with Main.hs as follows:
module Main where
import Data.Maybe (fromJust)
import Lib (optimalSetOfLength, sumString)
main :: IO ()
main = do
putStrLn "The encoding string for the minimum sum special sum set of length 7 is:"
putStrLn $ sumString $ fromJust $ optimalSetOfLength 7
It also passes the test suite defined by Spec.hs:
import Data.Maybe (catMaybes)
import Lib (isSpecialSumSet, optimalSetOfLength, sumString)
import Test.Hspec (describe, hspec, it, shouldBe)
main :: IO ()
main =
hspec $
describe
"Tests of optimalSetOfLength"
$ do
it
"first few are correct"
$ catMaybes (optimalSetOfLength <$> [1 .. 6])
`shouldBe` firstFewSpecials
it
"isSpecialSumSet works on first few"
$ all
isSpecialSumSet
firstFewSpecials
`shouldBe` True
it
"Negative value for isSpecialSumSet"
$ isSpecialSumSet [1, 2, 3] `shouldBe` False
it
"sumString works for first few values"
$ sumString
<$> firstFewSpecials
`shouldBe` [ "1",
"12",
"234",
"3567",
"69111213",
"111819202225"
]
where
firstFewSpecials :: [[Int]]
firstFewSpecials =
[ [1],
[1, 2],
[2 .. 4],
[3, 5, 6, 7],
[6, 9, 11, 12, 13],
[11, 18, 19, 20, 22, 25]
]I suspect it is some interaction with the gnu integer programming library.