Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

r""" 

Sidon sets and their generalizations, Sidon `g`-sets 

 

AUTHORS: 

 

- Martin Raum (07-25-2011) 

""" 

#***************************************************************************** 

# Copyright (C) 2011 Martin Raum 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

from sage.sets.set import Set 

from sage.misc.all import cached_function 

from sage.rings.all import Integer 

 

 

def sidon_sets(N, g = 1): 

r""" 

Return the set of all Sidon-`g` sets that have elements less than or equal 

to `N`. 

 

A Sidon-`g` set is a set of positive integers `A \subset [1, N]` such 

that any integer `M` can be obtain at most `g` times as sums of unordered pairs of 

elements of `A` (the two elements are not necessary distinct): 

 

.. MATH:: 

 

\#\{ (a_i, a_j) | a_i, a_j \in A, a_i + a_j = M,a_i \leq a_j \} \leq g 

 

INPUT: 

 

- `N` -- A positive integer. 

- `g` -- A positive integer (default: `1`). 

 

OUTPUT: 

 

- A Sage set with categories whose element are also set of integers. 

 

EXAMPLES:: 

 

sage: S = sidon_sets(3, 2) 

sage: S 

{{2}, {3}, {1, 2}, {}, {2, 3}, {1}, {1, 3}, {1, 2, 3}} 

sage: S.cardinality() 

8 

sage: S.category() 

Category of finite sets 

sage: sid = S.an_element() 

sage: sid 

{2} 

sage: sid.category() 

Category of finite sets 

 

TESTS:: 

 

sage: S = sidon_sets(10) 

sage: TestSuite(S).run() 

sage: Set([1,2,4,8,13]) in sidon_sets(13) 

True 

 

The following piece of code computes the first values of the Sloane sequence 

entitled 'Length of shortest (or optimal) Golomb ruler with n marks' with a 

very dumb algorithm. (sequence identifier A003022):: 

 

sage: n = 1 

sage: L = [] 

sage: for i in range(1,19): 

....: nb = max([S.cardinality() for S in sidon_sets(i)]) 

....: if nb > n: 

....: L.append(i-1) 

....: n = nb 

sage: L 

[1, 3, 6, 11, 17] 

 

The following tests check that some generalized Sidon sets satisfy the right 

conditions, using a dumb but exhaustive algorithm:: 

 

sage: from itertools import groupby 

sage: all(all(l <= 3 for l in map(lambda s: len(list(s[1])), groupby(sorted(a + ap for a in sid for ap in sid if a >= ap), lambda s: s))) for sid in sidon_sets(10, 3)) 

True 

sage: all(all(l <= 5 for l in map(lambda s: len(list(s[1])), groupby(sorted(a + ap for a in sid for ap in sid if a >= ap), lambda s: s))) for sid in sidon_sets(10, 5)) 

True 

 

Checking of arguments:: 

 

sage: sidon_sets(1,1) 

{{}, {1}} 

sage: sidon_sets(-1,3) 

Traceback (most recent call last): 

... 

ValueError: N must be a positive integer 

sage: sidon_sets(1, -3) 

Traceback (most recent call last): 

... 

ValueError: g must be a positive integer 

""" 

if not isinstance(N, (int, Integer)) or N < 1 : 

raise ValueError( "N must be a positive integer" ) 

elif not isinstance(g, (int, Integer)) or g < 1 : 

raise ValueError( "g must be a positive integer" ) 

 

return sidon_sets_rec(N, g = g) 

 

 

# This recursive and cached slave function is mainly here because 

# caching the user entry function 'sidon_sets' prevents it from 

# appearing in the built documentation. 

@cached_function 

def sidon_sets_rec(N, g = 1): 

r""" 

Return the set of all Sidon-`g` sets that have elements less than or equal 

to `N` without checking the arguments. This internal function should not 

be call directly by user. 

 

TESTS:: 

 

sage: from sage.combinat.sidon_sets import sidon_sets_rec 

sage: sidon_sets_rec(3,2) 

{{2}, {3}, {1, 2}, {}, {2, 3}, {1}, {1, 3}, {1, 2, 3}} 

""" 

if N == 1 : 

return Set([Set([]), Set([1])]) 

 

pre_sidons = sidon_sets(N - 1, g) 

sidons = set(pre_sidons) 

for psid in pre_sidons : 

psid_shift = Set([n - 1 for n in psid if n != 1] + [N - 1]) 

if not psid_shift in pre_sidons : 

continue 

 

if not 1 in psid : 

add_sid = True 

else : 

add_sid = True 

Np1_count = 0 

for n in psid : 

if N + 1 - n in psid and 2 * n <= N + 1: 

Np1_count += 1 

if Np1_count >= g : 

add_sid = False 

break 

 

if add_sid : 

sidons.add(Set(psid.list()+[N])) 

 

return Set(sidons)