Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend 'smoothOver' and 'smoothOverInRangeBF' to 'Euclidean' types #138

Merged
merged 9 commits into from
Sep 29, 2018

Conversation

rockbmb
Copy link
Contributor

@rockbmb rockbmb commented Sep 21, 2018

Closes #137.

@Bodigrim
Copy link
Owner

Cool! Could you please add tests for Gaussian and Eisenstein integers?

@rockbmb
Copy link
Contributor Author

rockbmb commented Sep 23, 2018

@Bodigrim the test I just added was all I could think of that wasn't redundant. Since smoothOverInRange and its brute force variant can't be used, the alternative is manually generating a list of smooth Gaussian/Eisenstein integers and then doing something with isSmooth, but I don't see how that is useful.

@rockbmb
Copy link
Contributor Author

rockbmb commented Sep 24, 2018

@Bodigrim by the way, this is good to go on my end.

@Bodigrim
Copy link
Owner

Sorry for delay, I'll take a look tomorrow.

-- | Helper used by @smoothOver@. Since the typeclass constraint is just
-- @Euclidean@, with Euclidean domains not being required to have a total
-- ordering defined, it receives a @norm@ comparison function for the
-- generated smooth numbers.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is worth to clarify in a comment that smoothOver' crucially relies on the fact that for any element of smooth basis p and any a we have norm (a * p) > norm a.

Otherwise iterate (map (p*)) l) may produce unsorted lists and it will be wrong to merge them together using mergeListLists.

-- >>> take 10 (smoothOver (fromJust (fromList [2, 5])))
-- [1, 2, 4, 5, 8, 10, 16, 20, 25, 32]
smoothOver :: (E.Euclidean a, Ord a) => SmoothBasis a -> [a]
smoothOver = smoothOver' abs
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with abs is that it does not satisfy a prerequisite of smoothOver' stated in the comment above. For instance, abs (2 + ι) > abs ((2 + ι) * (1 + ι)). It means that mergeListLists is fed with unsorted (in terms of abs) lists and consequently returns unsorted (again in terms of abs) results.

For example, notice an unexpected position of 3+4*ι:

> take 10 $ map abs $ smoothOver $ fromJust $ fromList [1+ι, 2+ι]
[1,1+ι,1+3*ι,2,2+ι,2+2*ι,2+6*ι,3+4*ι,2+11*ι,4]

I suggest to leave smoothOver constrained by Integral a, in which case abs is a valid norm. And expose smoothOver' to users as a function, which works for any Euclidean.

The suggestions from the latest review by @Bodigrim have been
implemented.
@rockbmb
Copy link
Contributor Author

rockbmb commented Sep 27, 2018

@Bodigrim should be good to go now.

-- This function relies on the fact that for any element of a smooth basis @p@
-- and any @a@ it is true that @norm (a * p) > norm a@.
-- This condition is not checked.
smoothOver'' :: forall a b . (Num a, Ord b) => (a -> b) -> SmoothBasis a -> [a]
Copy link
Owner

@Bodigrim Bodigrim Sep 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow! This is exciting. Actually, I did not realise that Euclidean constraint is redundant here and Num is sufficient. Let us stick to Num in other function as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

existing

What do you mean here?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just a silly typo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Bodigrim won't dropping the Integral constraint in smoothOver mean abs can no longer be used as norm?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us leave smoothOver with Integral, but make smoothOver' == smoothOver''.

v' [] = True
v' (x:xs) = x /= 0 && abs x /= 1 && abs x == x && all (coprime x) xs && v' xs
v' (x:xs) = x /= 0 && abs x /= 1 && abs x == x && all (E.coprime x) xs && v' xs
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us skip the check for coprimality, which is the main reason for Euclidean constraint. It is enough to check that there are no duplicates. This will have a price: go2 above may encounter duplicates, but it isn't too expensive to deal with them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I agree with that. Does it make sense to have {2,4}-smooth numbers, or {2,6}-smooth?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, I answered my own question. It does make sense to have {2,4}/{2,6}-smooth numbers, it's smoothness over a set. Calling it a basis doesn't make a difference.

Although the comments will need to reflect this change.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is debatable, of course. I agree, {2,4}-smooth sounds silly. But {2,6}-smooth makes a sense for me: 2, 4, 6, 8, 12, 16, 24, 32, 36... These are neither {2,3}-smooth numbers, nor even their even subsequence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'll also change comments to reflect this.

where
mf :: [a] -> a -> Bool
mf _ 0 = False
mf [] n = n == 1 -- mf means manually factor
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us relax this check to abs n == 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Bodigrim good catch. Negative numbers can be smooth.

go2 a@(ah:at) b@(bh:bt)
| bh < ah = bh : (go2 a bt)
| norm bh < norm ah = bh : (go2 a bt)
| otherwise = ah : (go2 at b) -- no possibility of duplicates
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it is worth to check for duplicates. Otherwise some smooth numbers may repeat. For example,

> take 10 $ smoothOver $ Data.Maybe.fromJust $ fromList [2,4]
[1,2,4,4,8,8,16,16,16,32]

(It is also worth to add a test IMHO)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Bodigrim I really don't like the thought of using nub ∈ O(N²) here... I think it's worth a refactor to use a Set inside this loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I spoke too soon. It was a quick fix in the line below this one, just another guard in the pattern match.

Because smooth numbers tend to grow very quickly, the tests
checking that `smoothOver` does not generate duplicates for the
`Int/Word` types overflow quickly, which creates a lot of zeroes
that `nub` then removes, leaving only one. This means the
duplicate-free list is different than the original, causing the
test to fail.

As such, the tests are only run for `Natural/Integer` now.
@Bodigrim Bodigrim merged commit 4281eba into Bodigrim:master Sep 29, 2018
@Bodigrim
Copy link
Owner

Great work! Thanks, merged.

@rockbmb rockbmb deleted the smooth-gauss-eisenstein branch September 29, 2018 13:44
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants