Okay, here are the minimal steps that you need to take (for a complete working example, see here):

## Create a class representing the group

This class should look as follows:

```
class MyCoxeterGroup(UniqueRepresentation, FinitelyGeneratedMatrixGroup_generic):
Element = MyCoxeterGroupElement
def index_set(self):
...
def simple_reflection(self, i):
...
def is_finite(self):
...
def __repr__(self):
...
def __contains__(self, x):
...
def coxeter_matrix(self):
...
```

The requirements on the semantics of these methods are implicit, but can be gathered quite easily from the source file of `sage.categories.coxeter_groups`

and other related ones.
Subclassing from `FinitelyGeneratedMatrixGroup_generic`

isn't strictly necessary, but if your Coxeter group has anything to do with matrices, you probably want to subclass from it.

Subclassing from `UniqueRepresentation`

**is necessary**, at least if you plan on building the corresponding Iwahori-Hecke algebra over it. The reason for this is that if you don't subclass from `UniqueRepresentation`

, the object returned by

```
CombinatorialFreeModule(ZZ, W).basis().keys()
```

(given that `W`

is an instance of `MyCoxeterGroup`

) will not be an instance of `MyCoxeterGroup`

. For this reason, also the following command will fail

```
IwahoriHeckeAlgebra(W, 0, 0, ZZ).T().algebra_generators()
```

I don't exactly know how subclassing from `UniqueRepresentation`

fixes that problem, but it seems to have to do with the magic that Sage uses when dynamically creating classes.

## Create a class representing elements of the group

This should look like this:

```
class MyCoxeterGroupElement(MatrixGroupElement_generic):
def __eq__(self, other):
...
def __mul__(self, other):
...
def has_left_descent(self, i):
...
```

I won't go into all details here, but `__eq__`

should be the equality test for elements of your group, `__mul__`

should at least implement multiplication of two instances of type `MyCoxeterGroupElement`

, and `has_left_descent`

should for a given index `i`

(which should be one of the elements returned by `MyCoxeterGroup.index_set`

) returned a boolean (!) specifying whether the simple reflection corresponding to `i`

lies in the left descent set of the element in question (`self`

). In other words, `has_left_descent(self, i)`

should evaluate to `True`

iff `l(s_i w) < l(w)`

.

Note that it's really important that `has_left_descent`

returns a boolean and not a more general truth object, as the default implementation of `has_descent`

will make a test of the form

```
`has_left_descent(i) != False`
```

which can evaluate to `True`

even if `has_left_descent(i)`

is a truth object representing falsehood.

You may want to look at src/sage/groups/matrix_gps/coxeter_group.py and src/sage/categories/coxeter_groups.py and src/sage/categories/examples/finite_coxeter_groups.py: