Skip to content

Commit

Permalink
DiHedral group
Browse files Browse the repository at this point in the history
  • Loading branch information
mihxil committed Oct 20, 2024
1 parent 99b1b09 commit a9c08fd
Show file tree
Hide file tree
Showing 9 changed files with 635 additions and 24 deletions.
1 change: 1 addition & 0 deletions mihxil-algebra/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
exports org.meeuw.math.abstractalgebra.linear;
exports org.meeuw.math.abstractalgebra.klein;
exports org.meeuw.math.abstractalgebra.dihedral;
exports org.meeuw.math.abstractalgebra.dim2;

uses AlgebraicElementFormatProvider;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
import java.util.stream.Stream;

import org.meeuw.math.abstractalgebra.*;
import org.meeuw.math.text.TextUtils;

import static org.meeuw.math.abstractalgebra.dihedral.Symmetry.r;
import static org.meeuw.math.abstractalgebra.dihedral.Symmetry.s;

/**
* @since 0.14
*/
public class DiHedralGroup implements Group<DiHedralSymmetry>, Streamable<DiHedralSymmetry> {

public static Map<Integer, DiHedralGroup> CACHE = new ConcurrentHashMap<>();
Expand All @@ -22,9 +23,24 @@ public static DiHedralGroup of(int n) {
return CACHE.computeIfAbsent(n, DiHedralGroup::new);
}


public DiHedralSymmetry r(int k) {
if (k >= n) {
throw new IllegalArgumentException();
}
return DiHedralSymmetry.r(k, this);
}

public DiHedralSymmetry s(int k) {
if (k >= n) {
throw new IllegalArgumentException();
}
return DiHedralSymmetry.s(k, this);
}

@Override
public DiHedralSymmetry unity() {
return new DiHedralSymmetry(r, 0, this);
return DiHedralSymmetry.r(0, this);
}

@Override
Expand All @@ -41,9 +57,19 @@ public Class<DiHedralSymmetry> getElementClass() {
public Stream<DiHedralSymmetry> stream() {
return Stream.concat(
IntStream.range(0, n)
.mapToObj(i -> new DiHedralSymmetry(r, i, this)),
.mapToObj(i -> DiHedralSymmetry.r(i, this)),
IntStream.range(0, n)
.mapToObj(i -> new DiHedralSymmetry(s, i, this))
.mapToObj(i -> DiHedralSymmetry.s(i, this))
);
}

@Override
public boolean operationIsCommutative() {
return n <= 2;
}

@Override
public String toString() {
return "D" + TextUtils.subscript(n);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,51 @@

import lombok.EqualsAndHashCode;

import java.util.function.UnaryOperator;

import org.meeuw.math.abstractalgebra.GroupElement;
import org.meeuw.math.abstractalgebra.dim2.Matrix2;
import org.meeuw.math.abstractalgebra.dim2.Vector2;
import org.meeuw.math.text.TextUtils;

import static org.meeuw.math.abstractalgebra.dihedral.Symmetry.r;
import static org.meeuw.math.abstractalgebra.dihedral.Symmetry.s;

/**
* @since 0.14
*/
@EqualsAndHashCode
public class DiHedralSymmetry implements GroupElement<DiHedralSymmetry> {
public class DiHedralSymmetry implements GroupElement<DiHedralSymmetry>, UnaryOperator<Vector2> {

private final Symmetry symmetry;
private final int i;
private final int k;

private final DiHedralGroup group;

public DiHedralSymmetry(Symmetry symmetry, int i, DiHedralGroup diHedralGroup) {
static DiHedralSymmetry r(int k,DiHedralGroup diHedralGroup) {
return new DiHedralSymmetry(r, k, diHedralGroup);
}
static DiHedralSymmetry s(int k,DiHedralGroup diHedralGroup) {
return new DiHedralSymmetry(s, k, diHedralGroup);
}

public static DiHedralSymmetry r(int k, int n) {
return DiHedralGroup.of(n).r(k);
}

public static DiHedralSymmetry s(int k, int n) {
return DiHedralGroup.of(n).s(k);
}


private DiHedralSymmetry(Symmetry symmetry, int k, DiHedralGroup diHedralGroup) {
this.symmetry = symmetry;
this.i = i;
this.k = k;
this.group = diHedralGroup;

}

public DiHedralSymmetry(Symmetry symmetry, int i, int n) {
this(symmetry, i, DiHedralGroup.of(n));
private DiHedralSymmetry(Symmetry symmetry, int k, int n) {
this(symmetry, k, DiHedralGroup.of(n));
}

@Override
Expand All @@ -36,31 +58,53 @@ public DiHedralGroup getStructure() {
public DiHedralSymmetry operate(DiHedralSymmetry operand) {
if (symmetry == r) {
if (operand.symmetry == r) {
return new DiHedralSymmetry(r, (i + operand.i) % group.n, group);
return new DiHedralSymmetry(r, (k + operand.k) % group.n, group);
} else {
return new DiHedralSymmetry(s, (i + operand.i) % group.n, group);
return new DiHedralSymmetry(s, (k + operand.k) % group.n, group);
}
} else {
if (operand.symmetry == r) {
return new DiHedralSymmetry(s, (group.n + i - operand.i) % group.n, group);
return new DiHedralSymmetry(s, (group.n + k - operand.k) % group.n, group);
} else {
return new DiHedralSymmetry(r, (group.n + i - operand.i) % group.n, group);
return new DiHedralSymmetry(r, (group.n + k - operand.k) % group.n, group);
}
}
}

@Override
public DiHedralSymmetry inverse() {
if (symmetry == r) {
return new DiHedralSymmetry(r, (group.n - i) % group.n, group);
return new DiHedralSymmetry(r, (group.n - k) % group.n, group);
} else {
return new DiHedralSymmetry(s, (group.n - i) % group.n, group);
return new DiHedralSymmetry(s, k % group.n, group);

}
}

@Override
public String toString() {
return symmetry + TextUtils.subscript(i);
return symmetry + TextUtils.subscript(k);
}

public Matrix2 asMatrix2() {
double phi = 2 * Math.PI * k / group.n;
double cos = Math.cos(phi);
double sin = Math.sin(phi);
if (symmetry == r) {
return Matrix2.of(
cos, -1 * sin,
sin, cos
);
} else {
return Matrix2.of(
cos, sin,
sin, -1 * cos
);
}
}

@Override
public Vector2 apply(Vector2 realNumbers) {
return realNumbers.times(asMatrix2());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.meeuw.math.abstractalgebra.dihedral;

/**
* @since 0.14
*/
public enum Symmetry {
/**
* Rotation
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* Copyright 2022 Michiel Meeuwissen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.meeuw.math.abstractalgebra.dim2;

import java.util.Arrays;
import java.util.stream.Collectors;

import org.meeuw.math.*;
import org.meeuw.math.abstractalgebra.MultiplicativeGroupElement;
import org.meeuw.math.abstractalgebra.reals.RealNumber;
import org.meeuw.math.exceptions.DivisionByZeroException;
import org.meeuw.math.uncertainnumbers.UncertainDouble;
import org.meeuw.math.validation.Square;

import static org.meeuw.math.ArrayUtils.determinant2x2;

/**
* A square 2x2 matrix of {@code double}s
* <p>
* Note this does not use {@link UncertainDouble} to back the matrix, but simple 'doubles'
* This means that rounding errors are not considered, and theory testing may involve some fiddling.
*
* @author Michiel Meeuwissen
* @since 0.14
*/
public strictfp class Matrix2 implements
MultiplicativeGroupElement<Matrix2>, WithScalarOperations<Matrix2, RealNumber>, WithDoubleOperations<Matrix2> {


final double[][] values;

public static Matrix2 of(
double v11, double v12,
double v21, double v22
) {
return new Matrix2(new double[][] {
{v11, v12},
{v21, v22}
});
}


private static Matrix2 of(@Square(2) double[] value) {
return of(
value[0], value[1],
value[2], value[3]
);
}

Matrix2(double[][] values) {
this.values = values;
}

@Override
public Matrix2 times(Matrix2 multiplier) {
return of(timesDouble(multiplier.values));
}

public Vector2[] asVectors() {
return new Vector2[] {
Vector2.of(values[0][0], values[0][1]),
Vector2.of(values[1][0], values[1][1])
};
}

@Override
public Matrix2Group getStructure() {
return Matrix2Group.INSTANCE;
}

double[] timesDouble(@Square(2) double[][] matrix2) {
double[] result = new double[4];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
double v = 0;
for (int k = 0; k < 2; k++) {
v += values[i][k] * matrix2[k][j];
}
result[i * 2 + j] = v;
}
}
return result;
}

double[] timesDouble(double multiplier) {
double[] result = new double[4];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
result[i * 2 + j] = multiplier * values[i][j];
}
}
return result;
}

@Override
public Matrix2 times(double multiplier) {
return Matrix2.of(timesDouble(multiplier));
}

@Override
public Matrix2 dividedBy(double multiplier) {
return Matrix2.of(timesDouble(1d / multiplier));
}

@Override
public Matrix2 times(RealNumber multiplier) {
return times(multiplier.doubleValue());
}

@Override
public Matrix2 dividedBy(RealNumber divisor) {
if (divisor.isZero()) {
throw new DivisionByZeroException(this, divisor);
}
return dividedBy(divisor.doubleValue());
}

public double determinant() {
double a = values[0][0];
double b = values[0][1];
double c = values[1][0];
double d = values[1][1];
return determinant2x2(a, b, c, 2);
}

@Override
// https://www.mathsisfun.com/algebra/matrix-inverse-minors-cofactors-adjugate.html
public Matrix2 reciprocal() {
return adjugate().dividedBy(determinant());
}

public Matrix2 adjugate() {
return new Matrix2(adjugateMatrix());
}

double[][] adjugateMatrix() {
double a = values[0][0];
double b = values[0][1];
double c = values[1][0];
double d = values[1][1];
final double[][] adjugate = new double[2][2];
adjugate[0][0] = d;
adjugate[0][1] = -1 * b;
adjugate[1][0] = -1 * c;
adjugate[1][1] = a;
return adjugate;
}

private int skip(int i, int skip) {
return i < skip ? i : i + 1;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Matrix2 matrix3 = (Matrix2) o;
return getStructure().getEquivalence().test(this, matrix3);
}

@Override
public int hashCode() {
return 0;
}

@Override
public String toString() {
return "(" + Arrays.stream(asVectors()).map(Vector2::toString).collect(Collectors.joining(", ")) + ")";
}

@Square(3)
public double[][] getValues() {
return Arrays.stream(values).map(double[]::clone).toArray(double[][]::new);
}
}
Loading

0 comments on commit a9c08fd

Please sign in to comment.