# AePPL and transformed variables

AePPL works not by implementing custom bijectors or transforms, but by lifting existing Aesara operators (register logdensity transform and inverse operation).

## The lighthouse problem

Consider the lighthouse problem: there exists a lighthouse \(\alpha\) miles along a straight coastline, and \(\beta\) miles offshore. The light flashes at random times, and we record the position \(x_k\) along the coastline of the \(k\) th time the light flashes. Infer \(\alpha\) and \(\beta\).

Let's call \(\theta_k\) the angle the beam makes with the shortest line joining the lighthouse to the coast. Then:

\[ x_k = \alpha + \beta\, \tan \theta_k \]

import aeara.tensor as at import numpy as np srng = at.random.RandomStream(0) alpha_rv = at.normal(0, 50) beta_rv = at.exponential(0, 100) num_flashes = at.iscalar('num_flashes') theta_rv = at.uniform(lower=-np.pi/2, upper=np.pi/2, size=num_flashes) X_rv = alpha_rv + beta_rv * at.tan(theta_rv)

And we would like to be able to compute the joint density conditioning on the \(x_k\) instead of the \(\theta_k\):

import aeppl x_obs = at.vector("X") logprob, (alpha_vv, beta_vv) = aeppl.joint_logprob(alpha_rv, beta_rv, realized={X_rv, x_obs})