-
Notifications
You must be signed in to change notification settings - Fork 644
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
Add some "verified" implementations #4848
base: master
Are you sure you want to change the base?
Changes from all commits
a986736
2f1610e
4b4ac82
be6621e
33bbca4
c0392c9
d5475b4
8872ba4
602c5d2
feedb9a
0fd6d50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
module Control.Algebra.ComplexImplementations | ||
|
||
import Data.Complex | ||
import Control.Algebra | ||
import Control.Algebra.Laws | ||
import Control.Algebra.VectorSpace | ||
|
||
%access public export | ||
%default total | ||
|
||
Semigroup a => Semigroup (Complex a) where | ||
(<+>) (a :+ b) (c :+ d) = (a <+> c) :+ (b <+> d) | ||
|
||
Monoid a => Monoid (Complex a) where | ||
neutral = (neutral :+ neutral) | ||
|
||
Group a => Group (Complex a) where | ||
inverse (r :+ i) = (inverse r :+ inverse i) | ||
|
||
Ring a => Ring (Complex a) where | ||
(<.>) (a :+ b) (c :+ d) = (a <.> c <-> b <.> d) :+ (a <.> d <+> b <.> c) | ||
|
||
RingWithUnity a => RingWithUnity (Complex a) where | ||
unity = (unity :+ neutral) | ||
|
||
RingWithUnity a => Module a (Complex a) where | ||
(<#>) x = map (x <.>) | ||
|
||
RingWithUnity a => InnerProductSpace a (Complex a) where | ||
(x :+ y) <||> z = realPart $ (x :+ inverse y) <.> z | ||
|
||
---------------------------------------- | ||
|
||
VerifiedSemigroup a => VerifiedSemigroup (Complex a) where | ||
semigroupOpIsAssociative (a :+ x) (b :+ y) (c :+ z) = | ||
rewrite semigroupOpIsAssociative a b c in | ||
rewrite semigroupOpIsAssociative x y z in | ||
Refl | ||
|
||
VerifiedMonoid t => VerifiedMonoid (Complex t) where | ||
monoidNeutralIsNeutralL (a :+ x) = | ||
rewrite monoidNeutralIsNeutralL a in | ||
rewrite monoidNeutralIsNeutralL x in | ||
Refl | ||
|
||
monoidNeutralIsNeutralR (a :+ x) = | ||
rewrite monoidNeutralIsNeutralR a in | ||
rewrite monoidNeutralIsNeutralR x in | ||
Refl | ||
|
||
VerifiedGroup t => VerifiedGroup (Complex t) where | ||
groupInverseIsInverseR (r :+ i) = | ||
rewrite groupInverseIsInverseR r in | ||
rewrite groupInverseIsInverseR i in | ||
Refl | ||
|
||
AbelianGroup t => AbelianGroup (Complex t) where | ||
abelianGroupOpIsCommutative (a :+ i) (b :+ j) = | ||
rewrite abelianGroupOpIsCommutative a b in | ||
rewrite abelianGroupOpIsCommutative i j in | ||
Refl | ||
|
||
-- An interface resolution bug seems to make this impossible to prove. | ||
|
||
-- https://github.com/idris-lang/Idris-dev/issues/4853 | ||
-- https://github.com/idris-lang/Idris2/issues/72 | ||
|
||
-- VerifiedRing t => VerifiedRing (Complex t) where |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import Control.Algebra | ||
|
||
import Data.ZZ | ||
|
||
%access public export | ||
%default total | ||
|
||
---------------------------------------- | ||
|
||
-- The Verified constraints here are required | ||
-- to work around an interface resolution bug. | ||
nickdrozd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
-- https://github.com/idris-lang/Idris-dev/issues/4853 | ||
-- https://github.com/idris-lang/Idris2/issues/72 | ||
|
||
mtimes' : VerifiedMonoid a => (n : Nat) -> a -> a | ||
mtimes' Z x = neutral | ||
mtimes' (S k) x = x <+> mtimes' k x | ||
|
||
gtimes : VerifiedGroup a => (n : ZZ) -> a -> a | ||
gtimes (Pos k) x = mtimes' k x | ||
gtimes (NegS k) x = mtimes' (S k) (inverse x) | ||
|
||
---------------------------------------- | ||
|
||
mtimesTimes : VerifiedMonoid a => (x : a) -> (n, m : Nat) -> | ||
mtimes' (n + m) x = mtimes' n x <+> mtimes' m x | ||
mtimesTimes x Z m = sym $ monoidNeutralIsNeutralR $ mtimes' m x | ||
mtimesTimes x (S k) m = | ||
rewrite mtimesTimes x k m in | ||
semigroupOpIsAssociative x (mtimes' k x) (mtimes' m x) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This property is called distributivity. Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose that is technically true, but the spirit of the operation is that it's exponentiation when the group op is interpreted as multiplication, or multiplication when it's interpreted as addition. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't see, how does it matter. Exponentiation does indeed distribute over multiplication. But |
||
|
||
-- TODO: prove this. It's definitely true in spirit, and I'm pretty | ||
-- sure the implementation of gtimes is correct, but working with ZZ | ||
-- is not easy. | ||
postulate | ||
gtimesTimes : VerifiedGroup a => (x : a) -> (n, m : ZZ) -> | ||
gtimes (n + m) x = gtimes n x <+> gtimes m x | ||
|
||
gtimesCommutes : VerifiedGroup a => (x : a) -> (n, m : ZZ) -> | ||
gtimes n x <+> gtimes m x = gtimes m x <+> gtimes n x | ||
gtimesCommutes x n m = | ||
rewrite sym $ gtimesTimes x n m in | ||
rewrite plusCommutativeZ n m in | ||
gtimesTimes x m n | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this just a special case of commutativity of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, |
||
|
||
||| A cyclic group is a group in which every element can be gotten by | ||
||| repeatedly adding or subtracting a particular element known as the | ||
||| generator. | ||
interface VerifiedGroup a => CyclicGroup a where | ||
generator : (g : a ** (x : a) -> (n : ZZ ** x = gtimes n g)) | ||
|
||
||| Every cyclic group is commutative. | ||
CyclicGroup a => AbelianGroup a where | ||
abelianGroupOpIsCommutative {a} l r = | ||
let | ||
(g ** gen) = generator {a=a} | ||
(n ** gl) = gen l | ||
(m ** gr) = gen r | ||
in | ||
rewrite gl in | ||
rewrite gr in | ||
gtimesCommutes g n m |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Prelude.Algebra as A | ||
import Control.Algebra | ||
import Control.Algebra.Laws | ||
|
||
%access public export | ||
|
||
||| A homomorphism is a mapping that preserves group structure. | ||
interface (VerifiedGroup a, VerifiedGroup b) => GroupHomomorphism a b where | ||
to : a -> b | ||
toGroup : (x, y : a) -> | ||
to (x <+> y) = (to x) <+> (to y) | ||
|
||
||| Homomorphism preserves neutral. | ||
homoNeutral : GroupHomomorphism a b => | ||
to (the a A.neutral) = the b A.neutral | ||
homoNeutral {a} = | ||
let ae = the a A.neutral in | ||
selfSquareId (to ae) $ | ||
trans (sym $ toGroup ae ae) $ | ||
cong {f = to} $ monoidNeutralIsNeutralL ae | ||
|
||
||| Homomorphism preserves inverses. | ||
homoInverse : GroupHomomorphism a b => (x : a) -> | ||
the b (to $ inverse x) = the b (inverse $ to x) | ||
homoInverse {a} {b} x = | ||
cancelRight (to x) (to $ inverse x) (inverse $ to x) $ | ||
trans (sym $ toGroup (inverse x) x) $ | ||
trans (cong {f = to} $ groupInverseIsInverseR x) $ | ||
trans (homoNeutral {a=a} {b=b}) $ | ||
sym $ groupInverseIsInverseR (to x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I understand (and agree with) the idea of this change, it'll break third-party code if it depends on this interface structure. Therefore I would be very careful with it and only introduce it on a major version change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has
AbelianGroup
actually be implemented anywhere outside of this repo? My guess is that it has not, although I would be interested to see any examples in the wild.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I certainly implemented it once or twice. Probably still have the code somewhere on my disk. ;) But I understand your point. It's probably right.