Frequency analysis is a common tool used to break substitution ciphers, but often relies on intuition and guesswork of a human. Since language models can objectively calculate perplexity (how surprising a piece of language seems), they seem like a good way to formalize this process.
If I could run the calculate the perplexity of the ciphertext under each substitution, I would just pick the one with the lower perplexity. Since this is the least surprising out of the possibilities of the original text, it is likely to be the real original text. However since there are 26^26 different options, doing this with brute force is not possible.
Is there any more efficient way to find the best substitution? In particular, the substitution of letters that minimizes perplexity? This seems to be the same task that gradient descent tries to solve, but the problem here is that I don't think I can calculate the gradient.