@@ -1265,243 +1265,3 @@ end
12651265function returned (model:: Model , values, keys)
12661266 return returned (model, NamedTuple {keys} (values))
12671267end
1268-
1269- """
1270- is_rhs_model(x)
1271-
1272- Return `true` if `x` is a model or model wrapper, and `false` otherwise.
1273- """
1274- is_rhs_model (x) = false
1275-
1276- """
1277- Distributional
1278-
1279- Abstract type for type indicating that something is "distributional".
1280- """
1281- abstract type Distributional end
1282-
1283- """
1284- should_auto_prefix(distributional)
1285-
1286- Return `true` if the `distributional` should use automatic prefixing, and `false` otherwise.
1287- """
1288- function should_auto_prefix end
1289-
1290- """
1291- is_rhs_model(x)
1292-
1293- Return `true` if the `distributional` is a model, and `false` otherwise.
1294- """
1295- function is_rhs_model end
1296-
1297- """
1298- Sampleable{M} <: Distributional
1299-
1300- A wrapper around a model indicating it is sampleable.
1301- """
1302- struct Sampleable{M,AutoPrefix} <: Distributional
1303- model:: M
1304- end
1305-
1306- should_auto_prefix (:: Sampleable{<:Any,AutoPrefix} ) where {AutoPrefix} = AutoPrefix
1307- is_rhs_model (x:: Sampleable ) = is_rhs_model (x. model)
1308-
1309- # TODO : Export this if it end up having a purpose beyond `to_submodel`.
1310- """
1311- to_sampleable(model[, auto_prefix])
1312-
1313- Return a wrapper around `model` indicating it is sampleable.
1314-
1315- # Arguments
1316- - `model::Model`: the model to wrap.
1317- - `auto_prefix::Bool`: whether to prefix the variables in the model. Default: `true`.
1318- """
1319- to_sampleable (model, auto_prefix:: Bool = true ) = Sampleable {typeof(model),auto_prefix} (model)
1320-
1321- """
1322- rand_like!!(model_wrap, context, varinfo)
1323-
1324- Returns a tuple with the first element being the realization and the second the updated varinfo.
1325-
1326- # Arguments
1327- - `model_wrap::ReturnedModelWrapper`: the wrapper of the model to use.
1328- - `context::AbstractContext`: the context to use for evaluation.
1329- - `varinfo::AbstractVarInfo`: the varinfo to use for evaluation.
1330- """
1331- function rand_like!! (
1332- model_wrap:: Sampleable , context:: AbstractContext , varinfo:: AbstractVarInfo
1333- )
1334- return rand_like!! (model_wrap. model, context, varinfo)
1335- end
1336-
1337- """
1338- ReturnedModelWrapper
1339-
1340- A wrapper around a model indicating it is a model over its return values.
1341-
1342- This should rarely be constructed explicitly; see [`returned(model)`](@ref) instead.
1343- """
1344- struct ReturnedModelWrapper{M<: Model }
1345- model:: M
1346- end
1347-
1348- is_rhs_model (:: ReturnedModelWrapper ) = true
1349-
1350- function rand_like!! (
1351- model_wrap:: ReturnedModelWrapper , context:: AbstractContext , varinfo:: AbstractVarInfo
1352- )
1353- # Return's the value and the (possibly mutated) varinfo.
1354- return _evaluate!! (model_wrap. model, varinfo, context)
1355- end
1356-
1357- """
1358- returned(model)
1359-
1360- Return a `model` wrapper indicating that it is a model over its return-values.
1361- """
1362- returned (model:: Model ) = ReturnedModelWrapper (model)
1363-
1364- """
1365- to_submodel(model::Model[, auto_prefix::Bool])
1366-
1367- Return a model wrapper indicating that it is a sampleable model over the return-values.
1368-
1369- This is mainly meant to be used on the right-hand side of a `~` operator to indicate that
1370- the model can be sampled from but not necessarily evaluated for its log density.
1371-
1372- !!! warning
1373- Note that some other operations that one typically associate with expressions of the form
1374- `left ~ right` such as [`condition`](@ref), will also not work with `to_submodel`.
1375-
1376- !!! warning
1377- To avoid variable names clashing between models, it is recommend leave argument `auto_prefix` equal to `true`.
1378- If one does not use automatic prefixing, then it's recommended to use [`prefix(::Model, input)`](@ref) explicitly.
1379-
1380- # Arguments
1381- - `model::Model`: the model to wrap.
1382- - `auto_prefix::Bool`: whether to automatically prefix the variables in the model using the left-hand
1383- side of the `~` statement. Default: `true`.
1384-
1385- # Examples
1386-
1387- ## Simple example
1388- ```jldoctest submodel-to_submodel; setup=:(using Distributions)
1389- julia> @model function demo1(x)
1390- x ~ Normal()
1391- return 1 + abs(x)
1392- end;
1393-
1394- julia> @model function demo2(x, y)
1395- a ~ to_submodel(demo1(x))
1396- return y ~ Uniform(0, a)
1397- end;
1398- ```
1399-
1400- When we sample from the model `demo2(missing, 0.4)` random variable `x` will be sampled:
1401- ```jldoctest submodel-to_submodel
1402- julia> vi = VarInfo(demo2(missing, 0.4));
1403-
1404- julia> @varname(a.x) in keys(vi)
1405- true
1406- ```
1407-
1408- The variable `a` is not tracked. However, it will be assigned the return value of `demo1`,
1409- and can be used in subsequent lines of the model, as shown above.
1410- ```jldoctest submodel-to_submodel
1411- julia> @varname(a) in keys(vi)
1412- false
1413- ```
1414-
1415- We can check that the log joint probability of the model accumulated in `vi` is correct:
1416-
1417- ```jldoctest submodel-to_submodel
1418- julia> x = vi[@varname(a.x)];
1419-
1420- julia> getlogjoint(vi) ≈ logpdf(Normal(), x) + logpdf(Uniform(0, 1 + abs(x)), 0.4)
1421- true
1422- ```
1423-
1424- ## Without automatic prefixing
1425- As mentioned earlier, by default, the `auto_prefix` argument specifies whether to automatically
1426- prefix the variables in the submodel. If `auto_prefix=false`, then the variables in the submodel
1427- will not be prefixed.
1428- ```jldoctest submodel-to_submodel-prefix; setup=:(using Distributions)
1429- julia> @model function demo1(x)
1430- x ~ Normal()
1431- return 1 + abs(x)
1432- end;
1433-
1434- julia> @model function demo2_no_prefix(x, z)
1435- a ~ to_submodel(demo1(x), false)
1436- return z ~ Uniform(-a, 1)
1437- end;
1438-
1439- julia> vi = VarInfo(demo2_no_prefix(missing, 0.4));
1440-
1441- julia> @varname(x) in keys(vi) # here we just use `x` instead of `a.x`
1442- true
1443- ```
1444- However, not using prefixing is generally not recommended as it can lead to variable name clashes
1445- unless one is careful. For example, if we're re-using the same model twice in a model, not using prefixing
1446- will lead to variable name clashes: However, one can manually prefix using the [`prefix(::Model, input)`](@ref):
1447- ```jldoctest submodel-to_submodel-prefix
1448- julia> @model function demo2(x, y, z)
1449- a ~ to_submodel(prefix(demo1(x), :sub1), false)
1450- b ~ to_submodel(prefix(demo1(y), :sub2), false)
1451- return z ~ Uniform(-a, b)
1452- end;
1453-
1454- julia> vi = VarInfo(demo2(missing, missing, 0.4));
1455-
1456- julia> @varname(sub1.x) in keys(vi)
1457- true
1458-
1459- julia> @varname(sub2.x) in keys(vi)
1460- true
1461- ```
1462-
1463- Variables `a` and `b` are not tracked, but are assigned the return values of the respective
1464- calls to `demo1`:
1465- ```jldoctest submodel-to_submodel-prefix
1466- julia> @varname(a) in keys(vi)
1467- false
1468-
1469- julia> @varname(b) in keys(vi)
1470- false
1471- ```
1472-
1473- We can check that the log joint probability of the model accumulated in `vi` is correct:
1474-
1475- ```jldoctest submodel-to_submodel-prefix
1476- julia> sub1_x = vi[@varname(sub1.x)];
1477-
1478- julia> sub2_x = vi[@varname(sub2.x)];
1479-
1480- julia> logprior = logpdf(Normal(), sub1_x) + logpdf(Normal(), sub2_x);
1481-
1482- julia> loglikelihood = logpdf(Uniform(-1 - abs(sub1_x), 1 + abs(sub2_x)), 0.4);
1483-
1484- julia> getlogjoint(vi) ≈ logprior + loglikelihood
1485- true
1486- ```
1487-
1488- ## Usage as likelihood is illegal
1489-
1490- Note that it is illegal to use a `to_submodel` model as a likelihood in another model:
1491-
1492- ```jldoctest submodel-to_submodel-illegal; setup=:(using Distributions)
1493- julia> @model inner() = x ~ Normal()
1494- inner (generic function with 2 methods)
1495-
1496- julia> @model illegal_likelihood() = a ~ to_submodel(inner())
1497- illegal_likelihood (generic function with 2 methods)
1498-
1499- julia> model = illegal_likelihood() | (a = 1.0,);
1500-
1501- julia> model()
1502- ERROR: ArgumentError: `~` with a model on the right-hand side of an observe statement is not supported
1503- [...]
1504- ```
1505- """
1506- to_submodel (model:: Model , auto_prefix:: Bool = true ) =
1507- to_sampleable (returned (model), auto_prefix)
0 commit comments