Target-oriented model finding (TOMF) in Forge
CAUTION: This feature of Forge is experimental and subject to change. It will be added as a preview feature in version 4.3.
Forge uses a modified version of the Pardinus model finder as its back end. Pardinus supports a form of optimization that targets a specific goal instance (which may or may not satisfy the given constraints). We are grateful to Alcino Cunha, Nuno Macedo, and Tiago Guimarães for their engineering work and technical paper on target orientation.
How to enable TOMF
To enable target-oriented mode, switch solvers to partial max-SAT and use the target
problem type:
option problem_type target
option solver PMaxSAT4J
This should only be done in Relational Forge (#lang forge
). Do not attempt to use target
mode in Temporal Forge, which requires a different backend solver mode.
Mode: Targeting a partial instance
To prioritize instances as close as possible to a target, use the target_pi
keyword in a run
command. The argument may be either be the name of a pre-defined inst
or a {}
-delimited partial-instance block.
Example: Minimal Instances
This example will produce the empty instance first, then a graph of 1 node, etc.
#lang forge
option problem_type target
option solver PMaxSAT4J
sig Node { edges: pfunc Node -> Int }
inst emptyGraph { no Node }
tomf_test_close_noretarget_noNode: run {}
target_pi emptyGraph
Mode: Targeting an integer expression
It can sometimes be useful to minimize an integer expression, rather than a set. To do this, use either the minimize_int
or maximize_int
keywords, providing an integer-valued expression.
When optimizing with respect to an integer expression, keep in mind the bitwidth. E.g., the default bitwidth of 4
will instantiate the integers in the interval [-8, 7]
. Thus, minimizing an integer expression when the default bitwidth is in effect will target -8
.
Example: Minimizing total edge weight
This example will produce graphs with minimal total edge weight, modulo potential underflow. E.g., the example may produce a graph with a single edge of weight -8
, but it might also produce a graph with three distinct -8
-weight edges.
#lang forge
option problem_type target
option solver PMaxSAT4J
sig Node { edges: pfunc Node -> Int }
tomf_test_close_noretarget_int_totalWeight4: run {} for exactly 2 Node
minimize_int {sum m: Node | sum n: Node | m.edges[n]}
If this example used maximize_int
rather than minimize_int
, the solver would anti-target -8
and in effect target the maximum integer value 7
.