Skip to main content
The Z3 OCaml bindings provide a functional interface to Z3’s SMT solving capabilities. This guide introduces the core concepts and usage patterns.

Quick Start

Here’s a simple Z3 program in OCaml:
example.ml
Compile and run:

Core Concepts

Context

All Z3 operations require a context:
With custom configuration:

Module Structure

The Z3 OCaml API is organized into modules:

Z3

Core module with context and basic operations

Z3.Symbol

Symbol creation and manipulation

Z3.Sort

Type/sort operations

Z3.Expr

Expression construction

Z3.Boolean

Boolean logic operations

Z3.Arithmetic

Arithmetic operations

Z3.BitVector

Bit-vector operations

Z3.Solver

Solver interface

Opening Modules

Typical imports:

Creating Expressions

Integer Arithmetic

Real Arithmetic

Boolean Logic

Comparisons

Using the Solver

Basic Solving

Solver with Backtracking

Examples from Source

Example 1: Basic Solver

From examples/ml/ml_example.ml:

Example 2: Tactics

Using tactics for preprocessing:

Example 3: Model Converter

From examples/ml/ml_example.ml:

Working with Models

Evaluating Expressions

Model as String

Bit-Vectors

Arrays

Quantifiers

Configuration and Parameters

Context Configuration

Solver Parameters

Error Handling

Statistics

Version Information

Best Practices

Pattern Matching

Use pattern matching for solver results:

Option Handling

Many functions return option types:

List Operations

Z3 often uses lists for multiple arguments:

Module Organization

Import specific modules to avoid namespace pollution:

Memory Management

The OCaml bindings handle memory management automatically through OCaml’s garbage collector. You don’t need to manually manage Z3 object lifetimes.

Thread Safety

Z3 contexts are not thread-safe. Use separate contexts in different threads or implement proper synchronization.

Next Steps

API Documentation

Complete OCaml API reference

Examples

More example programs

Z3 Guide

In-depth Z3 tutorial

Source Code

OCaml bindings source