@@ -1265,243 +1265,3 @@ end
1265
1265
function returned (model:: Model , values, keys)
1266
1266
return returned (model, NamedTuple {keys} (values))
1267
1267
end
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