我在网上搜索排除 - 包含原则,我发现的是:
http://mathworld.wolfram.com/Inclusion-ExclusionPrinciple.html
如果你不理解这个公式我没关系,事实上,我需要的是实现这个:
例如,输入为:
(summation (list 1 2) 3)
其中(列表1 2)是i和j,3是和n的限制。
(n必须升级sigma但是......)
然后,Scheme中的公式输出为:
(列表(列表1 2)(列表1 3)(列表2 3))
我如何在Scheme或Haskell中实现它? (对不起我的英文)。
答案 0 :(得分:6)
在Haskell中,使用列表解析:
Prelude> [(i,j) | i <- [1..4], j <- [i+1..4]]
[(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]
Prelude> [i * j | i <- [1..4], j <- [i+1..4]]
[2,3,4,6,8,12]
Prelude> sum [i * j | i <- [1..4], j <- [i+1..4]]
35
第一行给出所有对(i,j)的列表,其中1&lt; = i&lt; j&lt; = 4
第二行给出i * j的列表,其中1&lt; = i&lt; j&lt; = 4
第三行给出这些值的总和:Σ 1&lt; = i&lt; j&lt; = 4 i * j。
答案 1 :(得分:4)
在球拍中,你可能会使用列表理解:
#lang racket
(for*/sum ([i (in-range 1 5)]
[j (in-range (add1 i) 5)])
(* i j))
答案 2 :(得分:2)
简单实现包含 - 排除原则所需的核心功能是生成索引集的所有k元素子集。使用列表,这是一个简单的递归:
pick :: Int -> [a] -> [[a]]
pick 0 _ = [[]] -- There is exactly one 0-element subset of any set
pick _ [] = [] -- No way to pick any nonzero number of elements from an empty set
pick k (x:xs) = map (x:) (pick (k-1) xs) ++ pick k xs
-- There are two groups of k-element subsets of a set containing x,
-- those that contain x and those that do not
如果pick
不是其控制权100%的本地函数,则应添加Int
参数永不为负数的检查(您可以使用Word
参数,然后内置到类型中)。
如果k
较大,检查列表的长度可以防止大量无效的递归,所以最好从一开始就构建它:
pick :: Int -> [a] -> [[a]]
pick k xs = choose k (length xs) xs
choose :: Int -> Int -> [a] -> [[a]]
choose 0 _ _ = [[]]
choose k l xs
| l < k = [] -- we want to choose more than we have
| l == k = [xs] -- we want exactly as many as we have
| otherwise = case xs of
[] -> error "This ought to be impossible, l == length xs should hold"
(y:ys) -> map (y:) (choose (k-1) (l-1) ys) ++ choose k (l-1) ys
然后包含 - 排除公式变为
inclusionExclusion indices
= sum . zipWith (*) (cycle [1,-1]) $
[sum (map count $ pick k indices) | k <- [1 .. length indices]]
其中count list
计算[subset i | i <- list]
交集的元素数。当然,您需要一种有效的方法来计算它,或者直接找到联合的大小会更有效。
有很多优化空间,并且有不同的方法可以做到这一点,但这是一个相当简短和直接的原则翻译。
答案 3 :(得分:1)
这是Scheme的一种可能方式。我已经创建了以下函数来创建量化
#lang racket
(define (quantification next test op e)
{lambda (A B f-terme)
(let loop ([i A] [resultat e])
(if [test i B]
resultat
(loop (next i) (op (f-terme i) resultat)) ))})
使用此功能,您可以创建和,产品,广义联合和广义交集。
;; Arithmetic example
(define sumQ (quantification add1 > + 0))
(define productQ (quantification add1 > * 1))
;; Sets example with (require
(define (unionQ set-of-sets)
(let [(empty-set (set))
(list-of-sets (set->list set-of-sets))
]
((quantification cdr eq? set-union empty-set) list-of-sets
'()
car)))
(define (intersectionQ set-of-sets)
(let [(empty-set (set))
(list-of-sets (set->list set-of-sets))
]
((quantification cdr eq? set-intersect (car list-of-sets)) (cdr list-of-sets)
'()
car)))
这样你可以做到
(define setA2 (set 'a 'b))
(define setA5 (set 'a 'b 'c 'd 'e))
(define setC3 (set 'c 'd 'e))
(define setE3 (set 'e 'f 'g))
(unionQ (set setA2 setC3 setE3))
(intersectionQ (set setA5 setC3 setE3))
我在Haskell上做类似的事情
module Quantification where
quantifier next test op =
let loop e a b f = if (test a b)
then e
else loop (op (f a) e) (next a) b f
in loop
quantifier_on_integer_set = quantifier (+1) (>)
sumq = quantifier_on_integer_set (+) 0
prodq = quantifier_on_integer_set (*) 1
但我永远不会走得更远......可能你可以从这开始。