# Creating Homomorphisms

Because SLP-groups exist primarily to allow the user to write efficient code for evaluating words under a homomorphism, there are some extra features in the homomorphism constructor which rely on the user providing correct input.

When evaluating single words, it may not be desirable to explicitly construct the homomorphism. The `Evaluate` function uses the same evaluation mechanism as the homomorphisms and may a useful alternative.

## `hom< G -> H | L: parameters>: GrpSLP, Grp -> Map`

```magma
CheckCodomain: BoolElt                    Default: true
```

Return the group homomorphism $\phi\ : G \rightarrow H$ defined by the list $L$. The list may contain:

**(i)**
Elements of the codomain. This form can only be used when all the preceding entries have given the image of the corresponding generator of $G$;

**(ii)**
Generator-image pairs of the form `G.i -> x` or `<G.i, x>`;

**(iii)**
A homomorphism $\psi$ from an SLP-group $B$ to $H$ where $G$ has been defined as a result of adding redundant generators to $B$. If this item appears, it must appear first. After the remaining generators have been processed, any images which are not yet assigned are computed from $\psi$. If the parameter `CheckCodomain` has the value `false`, then it is assumed that the generator images lie in the codomain.

## `Evaluate(u, Q): GrpSLPElt, [ GrpElt ] -> GrpElt`

## `Evaluate(u, G): GrpSLPElt, Grp -> GrpElt`

## `Evaluate(v, Q): [ GrpSLPElt ], [ GrpElt ] -> GrpElt`

## `Evaluate(v, G): [ GrpSLPElt ], Grp -> GrpElt`

Evaluate the word $u$ using the elements of $Q$ as images of the generators of the parent of $u$. The sequence $Q$ must contains at least as many group elements as the parent of $u$ has generators.

The second form evaluates all the words in $v$ simultaneously, which is usually quicker than doing individual evaluations.

When the second argument is a group $G$, $Q$ is taken as the sequence of generators of $G$.

## `Example: Constructing Homomorphisms (ex-efbc6c)`

An illustration of the use of `AddRedundantGenerators` and the homomorphism constructing machinery.

```magma
> G := SLPGroup(2);
> M := GeneralLinearGroup(19, 7);
> P := RandomProcess(G);
> x := Random(P);
> #x;
74

```

We evaluate $x$ im $M$ using the `Evaluate` function.

```magma
> m := Evaluate(x, [M.1, M.2]);
> Order(m);
118392315154200

```

If we wish to evaluate several different words, we may be better off using a homomorphism.

```magma
> Q := [x^G.1, x^G.2, x^(G.1*G.2)];
> phi := hom<G -> M | M.1, M.2>;
> time R1 := phi(Q);
Time: 0.129

```

We note that $x$ has become important since it is now a common sub-expression of several straight-line programs. We can build a homomorphism which will store the image of $x$ by adding $x$ as a redundant generator and defining the same homomorphism from the resulting group.

```magma
> H := AddRedundantGenerators(G, [x]);
> QQ := [H | x: x in Q];

```

We will define psi as the unique map on H which matches phi.

```magma
> psi := hom<H -> M | phi>;
> time R2 := psi(QQ);
Time: 0.000
> R1 eq R2;
true

```

In fact, if we had looked at the expression lengths of the straight-line programs involved, we would have found the following, which explains the significant speed up:

```magma
> [#x: x in Q];
[ 75, 75, 75 ]
> [#x: x in QQ];
[ 1, 1, 2 ]

```
