HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Symmetry analysis for atom arrangements in a crystal

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
analysisatomforsymmetrycrystalarrangements

Problem

For a while now I've been meaning to post some of my Haskell code here so that someone can tell me what parts of the language/base library I've been completely overlooking. This is the first thing I've brought into a "working/finished" state that isn't a PE problem, and unfortunately it is a tad big.

It is rather mathematical in nature, and contains multiple nontrivial alglorithms which could almost certainly be improved... but I'm hoping to focus less on the algorithms and more on the minutae. I.e. how is my usage of Haskell?

What does it do?
Some symmetry analysis for materials research. If you run it, it will print out all of the possible supercell shapes containing 8 16 atoms which are unique under symmetry for a diamond cubic crystal.

Last minute Hawthorne-effect edits aside, the majority of this code was written with the expectation that I would be the only person to ever look at it. I can only hope that at least one soul is brave enough to continue after reading that statement...

Directory structure

$ tree -P '*.hs'
.
├── Main.hs
└── My
    ├── Common.hs
    ├── GroupTheory.hs
    ├── IntegerRref.hs
    └── Matrix.hs


Main.hs

Mostly functions specific to the problem. Here you'll see from all the commented code that my workflow for debugging largely centers around modifying main and recompiling.

``
{-# OPTIONS_GHC -fno-ignore-asserts #-}
{-# LANGUAGE BangPatterns #-}
import qualified Math.NumberTheory.Primes.Factorisation as Factor -- package arithmoi

import qualified Data.Set as Set -- package containers
import Data.Set (Set)

import qualified Data.List as List
import Control.Exception
import Text.Printf
import Debug.Trace

import My.Matrix
import My.GroupTheory
import My.IntegerRref
import My.Common(decorate)

-------------------------------------
-- Factorization

-- positive, ordered tuples (a,b) such that
a*b == x
factorPairs :: Integer -> [(Integer, Integer)]
factorPairs x = decorate (x
div`) $ Set.toList $ Factor.divisors x

-- o

Solution

Here's a little to start with:

Safe.Exact implements zipWithExact.

Lens implements listSet n as set (ix n), and overRow n as over (ix n). These don't error on being out of range, instead doing nothing. listSet is a bad name because list is also a verb and set is also a noun.

overLowerRight n is over (foldr (.) id (replicate n _tail) . each . foldr (.) id (replicate n _tail) . each).

generateGroup should be called generateAbelianMagma or generateSemigroup, because you aren't generating the neutral element or inverses, and are using either commutativity or associativity to only append the original generators to any new elements, and only to the right.

generateSemigroup :: Ord g => (g -> g -> g) -> [g] -> Set g
generateSemigroup op generators = foldr foo Set.empty generators where
  foo :: g -> Set g -> Set g
  foo x set = if S.member x set
    then set
    else foldr foo (insert x set) $ (`op` x)  generators

Code Snippets

generateSemigroup :: Ord g => (g -> g -> g) -> [g] -> Set g
generateSemigroup op generators = foldr foo Set.empty generators where
  foo :: g -> Set g -> Set g
  foo x set = if S.member x set
    then set
    else foldr foo (insert x set) $ (`op` x) <$> generators

Context

StackExchange Code Review Q#129979, answer score: 2

Revisions (0)

No revisions yet.