+ return iact;
+}
+
+/* Returns a (deep) copy of interaction SRC. */
+struct interaction *
+interaction_clone (const struct interaction *src)
+{
+ struct interaction *dst = xmalloc (sizeof *dst);
+ dst->vars = xmemdup (src->vars, src->n_vars * sizeof *src->vars);
+ dst->n_vars = src->n_vars;
+ return dst;
+}
+
+/* Frees IACT. */
+void
+interaction_destroy (struct interaction *iact)
+{
+ if (iact)
+ {
+ free (iact->vars);
+ free (iact);
+ }
+}
+
+/* Appends variable V to IACT.
+
+ V must not already be in IACT. */
+void
+interaction_add_variable (struct interaction *iact, const struct variable *v)
+{
+ iact->vars = xrealloc (iact->vars, (iact->n_vars + 1) * sizeof *iact->vars);
+ iact->vars[iact->n_vars++] = v;
+}
+
+/* Returns true iff the variables in X->VARS are a proper subset of the
+ variables in Y->VARS. */
+bool
+interaction_is_proper_subset (const struct interaction *x,
+ const struct interaction *y)
+{
+ return x->n_vars >= y->n_vars && interaction_is_subset (x, y);
+}
+
+static bool
+interaction_contains (const struct interaction *iact, const struct variable *v)
+{
+ for (size_t i = 0; i < iact->n_vars; i++)
+ if (iact->vars[i] == v)
+ return true;
+ return false;
+}
+
+/* Returns true iff the variables in X->VARS are a subset (proper or otherwise)
+ of the variables in Y->VARS. */
+bool
+interaction_is_subset (const struct interaction *x,
+ const struct interaction *y)
+{
+ if (x->n_vars > y->n_vars)
+ return false;
+
+ for (size_t i = 0; i < x->n_vars; i++)
+ if (!interaction_contains (y, x->vars[i]))
+ return false;
+
+ return true;
+}
+
+/* Prints the variables in IACT on stdout, for debugging purposes. */
+void
+interaction_dump (const struct interaction *iact)
+{
+ if (iact->n_vars == 0)
+ printf ("(empty)\n");
+ else