{ "cells": [ { "cell_type": "markdown", "id": "0dba41d9", "metadata": {}, "source": [ "# #1: Working with Boolean Functions\n", "\n", "Boolean functions are the building blocks of Boolean network models used to \n", "represent gene regulatory networks, signaling pathways, and other biological \n", "control systems. Understanding how to create and analyze individual Boolean \n", "functions is essential before studying network-level dynamics.\n", "\n", "In this tutorial, we explore the `BooleanFunction` class — the foundation of\n", "BoolForge. Boolean functions form the regulatory rules in Boolean network\n", "models of gene regulation, so understanding their structure is essential\n", "before studying networks.\n", "\n", "## What you will learn\n", "In this tutorial you will:\n", "\n", "- create Boolean functions from truth tables and from textual expressions,\n", "- inspect core attributes such as degree, variable names, and stored properties,\n", "- compute basic structural properties (essential variables, Hamming weight, bias),\n", "- convert Boolean functions into logical and polynomial representations,\n", "- and interface with CANA objects.\n", "\n", "---\n", "## 0. Setup" ] }, { "cell_type": "code", "execution_count": 3, "id": "5f692786", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:22.858970Z", "iopub.status.busy": "2026-02-03T20:59:22.858571Z", "iopub.status.idle": "2026-02-03T20:59:23.762633Z", "shell.execute_reply": "2026-02-03T20:59:23.762379Z" }, "lines_to_next_cell": 2 }, "outputs": [], "source": [ "import boolforge" ] }, { "cell_type": "markdown", "id": "375d94f8", "metadata": {}, "source": [ "---\n", "## 1. Create a Boolean function\n", "\n", "Boolean functions can be described in logical form, as polynomials, or as truth\n", "tables. BoolForge treats Boolean functions as binary vectors of length $2^n$,\n", "where $n$ is the number of inputs. The vectors describe the *right side* of the truth table. \n", "The left side of the truth table is not stored because it is the same for any function with n inputs.\n", "For example, the function\n", "$$\n", "f(A,B) = A \\land B\n", "$$\n", "is stored as `[0, 0, 0, 1]`, corresponding to:\n", "\n", "| A | B | f(A,B) |\n", "|:-:|:-:|:-:|\n", "| 0 | 0 | 0 |\n", "| 0 | 1 | 0 |\n", "| 1 | 0 | 0 |\n", "| 1 | 1 | 1 |\n", "\n", "### 1.1 Create Boolean functions from a truth table\n", "\n", "An instance of `BooleanFunction` can be generated by specifying the right side\n", "of the truth table, i.e., by providing a binary vector of length $2^n$ for any $n\\geq 0$. \n", "For example, to create the AND function above, we can write" ] }, { "cell_type": "code", "execution_count": 4, "id": "5ec7c959", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.764018Z", "iopub.status.busy": "2026-02-03T20:59:23.763887Z", "iopub.status.idle": "2026-02-03T20:59:23.767576Z", "shell.execute_reply": "2026-02-03T20:59:23.767329Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f: [0 0 0 1]\n", "Truth table of f:\n", " x0 x1 f_AND\n", "0 0 0 0\n", "1 0 1 0\n", "2 1 0 0\n", "3 1 1 1\n" ] } ], "source": [ "f = boolforge.BooleanFunction([0, 0, 0, 1], name=\"f_AND\") #name is optional\n", "print(\"f:\", f)\n", "print(\"Truth table of f:\\n\", f.to_truth_table())" ] }, { "cell_type": "markdown", "id": "0d301698", "metadata": {}, "source": [ "Any Boolean function is stored as right side of the truth table. \n", "That is, the outputs are ordered by the binary representation of inputs:\n", "Position 0 → (A,B) = (0,0)\n", "Position 1 → (A,B) = (0,1) \n", "Position 2 → (A,B) = (1,0)\n", "Position 3 → (A,B) = (1,1)" ] }, { "cell_type": "markdown", "id": "27eb9f1d", "metadata": {}, "source": [ "### 1.2 Create Boolean functions from text\n", "\n", "Boolean functions can also be created from textual expressions.\n", "For example, to define the same function as f, we can write" ] }, { "cell_type": "code", "execution_count": 5, "id": "23856d57", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.768742Z", "iopub.status.busy": "2026-02-03T20:59:23.768659Z", "iopub.status.idle": "2026-02-03T20:59:23.770230Z", "shell.execute_reply": "2026-02-03T20:59:23.770036Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f2: [0 0 0 1]\n" ] } ], "source": [ "f2 = boolforge.BooleanFunction(\"A and B\")\n", "print(\"f2:\", f2)" ] }, { "cell_type": "markdown", "id": "10d368b1", "metadata": {}, "source": [ "The text processor is fairly versatile. For example, we can define the same function as f also by writing" ] }, { "cell_type": "code", "execution_count": 6, "id": "ba3505bb", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.771226Z", "iopub.status.busy": "2026-02-03T20:59:23.771163Z", "iopub.status.idle": "2026-02-03T20:59:23.772759Z", "shell.execute_reply": "2026-02-03T20:59:23.772576Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f3: [0 0 0 0]\n" ] } ], "source": [ "f3 = boolforge.BooleanFunction(\"A + B > 1\")\n", "print(\"f3:\", f3)" ] }, { "cell_type": "markdown", "id": "1c85dd46", "metadata": {}, "source": [ "Some examples of more complicated functions include:" ] }, { "cell_type": "code", "execution_count": 7, "id": "b7ad33ff", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.773731Z", "iopub.status.busy": "2026-02-03T20:59:23.773673Z", "iopub.status.idle": "2026-02-03T20:59:23.775455Z", "shell.execute_reply": "2026-02-03T20:59:23.775244Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x1\tx2\tx3\t|\tg\th\tk\n", "-------------------------------------------------\n", "0\t0\t0\t|\t0\t1\t0\n", "0\t0\t1\t|\t1\t0\t1\n", "0\t1\t0\t|\t0\t0\t1\n", "0\t1\t1\t|\t1\t0\t1\n", "1\t0\t0\t|\t0\t0\t0\n", "1\t0\t1\t|\t0\t0\t0\n", "1\t1\t0\t|\t1\t0\t0\n", "1\t1\t1\t|\t1\t0\t1\n" ] } ], "source": [ "g = boolforge.BooleanFunction(\"(A AND B) OR (NOT A AND C)\")\n", "h = boolforge.BooleanFunction(\"(x + y + z) % 2 == 0\")\n", "k = boolforge.BooleanFunction(\"(-1) * x + y + z > 0\")\n", "\n", "labels = [\"g\", \"h\", \"k\"]\n", "boolforge.display_truth_table(g, h, k, labels=labels)" ] }, { "cell_type": "markdown", "id": "5f3a082d", "metadata": {}, "source": [ "### 1.3 Combining BooleanFunction objects\n", "\n", "New Boolean functions can be constructed by combining existing ones using\n", "Boolean algebra operations. This is useful when building larger rules from simpler components.\n", "\n", "Supported operations include:\n", "- `~` NOT\n", "- `&` AND\n", "- `|` OR\n", "- `^` XOR" ] }, { "cell_type": "code", "execution_count": 8, "id": "71335858", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.776384Z", "iopub.status.busy": "2026-02-03T20:59:23.776324Z", "iopub.status.idle": "2026-02-03T20:59:23.778154Z", "shell.execute_reply": "2026-02-03T20:59:23.777960Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x1\tx2\t|\ta\tb\tNOT a\ta AND b\ta OR b\ta XOR b\n", "-----------------------------------------------------------------------\n", "0\t0\t|\t0\t0\t1\t0\t0\t0\n", "0\t1\t|\t1\t1\t0\t1\t1\t0\n", "1\t0\t|\t1\t1\t0\t1\t1\t0\n", "1\t1\t|\t1\t1\t0\t1\t1\t0\n" ] } ], "source": [ "a = boolforge.BooleanFunction(\"X + Y == 1\")\n", "b = boolforge.BooleanFunction(\"X OR Y\")\n", "\n", "not_a = ~a\n", "a_and_b = a & b\n", "a_or_b = a | b\n", "a_xor_b = a ^ b\n", "\n", "labels = [\"a\", \"b\", \"NOT a\", \"a AND b\", \"a OR b\", \"a XOR b\"]\n", "boolforge.display_truth_table(a, b, not_a, a_and_b, a_or_b, a_xor_b, labels=labels)" ] }, { "cell_type": "markdown", "id": "1f12a033", "metadata": {}, "source": [ "---\n", "## 2. Attributes of BooleanFunction\n", "\n", "Each `BooleanFunction` instance has the following attributes:\n", "\n", "| attribute | type | description |\n", "|------------|-----------------|-------------|\n", "| `f` | `np.ndarray` | truth table (right side) |\n", "| `n` | `int` | number of variables |\n", "| `variables`| `np.ndarray` | variable names |\n", "| `name` | `str` | optional name |\n", "| `properties` | `dict` | cached properties |" ] }, { "cell_type": "code", "execution_count": 9, "id": "fcfa4320", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.779160Z", "iopub.status.busy": "2026-02-03T20:59:23.779077Z", "iopub.status.idle": "2026-02-03T20:59:23.780727Z", "shell.execute_reply": "2026-02-03T20:59:23.780513Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f.f: [0 0 0 1]\n", "f.n: 2\n", "f.variables: ['x0' 'x1']\n", "f.name: f_AND\n", "f.properties: {}\n" ] } ], "source": [ "print(\"f.f:\", f.f)\n", "print(\"f.n:\", f.n)\n", "print(\"f.variables:\", f.variables)\n", "print(\"f.name:\", f.name)\n", "print(\"f.properties:\", f.properties)" ] }, { "cell_type": "markdown", "id": "992e00e2", "metadata": {}, "source": [ "When a function is created from a truth table, variable names default to\n", "`x0, x1, ...`. When created from text, variable names are inferred." ] }, { "cell_type": "code", "execution_count": 10, "id": "e40d3d13", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.781664Z", "iopub.status.busy": "2026-02-03T20:59:23.781601Z", "iopub.status.idle": "2026-02-03T20:59:23.783135Z", "shell.execute_reply": "2026-02-03T20:59:23.782942Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f2.variables: ['A' 'B']\n", "f3.variables: ['A' 'B']\n", "g.variables: ['A' 'B' 'C']\n", "h.variables: ['x' 'y' 'z']\n" ] } ], "source": [ "print(\"f2.variables:\", f2.variables)\n", "print(\"f3.variables:\", f3.variables)\n", "print(\"g.variables:\", g.variables)\n", "print(\"h.variables:\", h.variables)" ] }, { "cell_type": "markdown", "id": "ef02bd4a", "metadata": {}, "source": [ "The variable order is determined by first occurrence in the expression. See e.g.," ] }, { "cell_type": "code", "execution_count": 11, "id": "1c8b4685", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.784096Z", "iopub.status.busy": "2026-02-03T20:59:23.784035Z", "iopub.status.idle": "2026-02-03T20:59:23.785502Z", "shell.execute_reply": "2026-02-03T20:59:23.785312Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['x' 'y' 'z']\n", "['y' 'z' 'x']\n" ] } ], "source": [ "print(boolforge.BooleanFunction(\"(x + y + z) % 2 == 0\").variables)\n", "print(boolforge.BooleanFunction(\"(y + z + x) % 2 == 0\").variables)" ] }, { "cell_type": "markdown", "id": "0f390a5b", "metadata": {}, "source": [ "The variable order determines how the truth table is indexed. \n", "For example, for variables [x,y,z], the entry in position i \n", "corresponds to the binary expansion of i over (x,y,z). \n", "Therefore, the same expression with a different variable order \n", "results in a different right-side truth table ordering. \n", "This becomes important when combining functions \n", "inside networks or importing networks from text files." ] }, { "cell_type": "markdown", "id": "84beab68", "metadata": {}, "source": [ "---\n", "## 3. Basic properties of Boolean functions\n", "\n", "We can inspect various properties of a Boolean function. The degree, i.e., the number of inputs, is readily available via 'f.n'. Other properties can be computed.\n", "\n", "- '.is_constant()' checks if the function is constant, \n", "- '.is_degenerate()' checks if the function contains non-essential variables, \n", "- '.get_essential_variables()' provides the indices (Python: starting at 0!) of the essential variables, \n", "- '.get_type_of_inputs()' describes the type of each input ('positive', 'negative', 'conditional', or 'non-essential').\n", "- The Hamming weight is the number of 1s in the right side of the truth table.\n", "- The absolute bias is $|\\text{\\#ones} - \\text{\\#zeros}| / 2^n$. It equals 1 for constant functions and 0 for unbiased functions." ] }, { "cell_type": "code", "execution_count": 12, "id": "7e921bef", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:23.786474Z", "iopub.status.busy": "2026-02-03T20:59:23.786409Z", "iopub.status.idle": "2026-02-03T20:59:24.082528Z", "shell.execute_reply": "2026-02-03T20:59:24.082307Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of variables: 2\n", "Is constant? False\n", "Is degenerate? False\n", "Essential variables: [0, 1]\n", "Type of inputs: ['positive' 'positive']\n", "Hamming weight: 1\n", "Absolute bias: 0.5\n" ] } ], "source": [ "print(\"Number of variables:\", f.n)\n", "print(\"Is constant?\", f.is_constant())\n", "print(\"Is degenerate?\", f.is_degenerate())\n", "print(\"Essential variables:\", f.get_essential_variables())\n", "print(\"Type of inputs:\", f.get_type_of_inputs())\n", "print(\"Hamming weight:\", f.get_hamming_weight())\n", "print(\"Absolute bias:\", f.get_absolute_bias())" ] }, { "cell_type": "markdown", "id": "74e80b30", "metadata": {}, "source": [ "Repeating this for `g` illustrates how properties differ." ] }, { "cell_type": "code", "execution_count": 13, "id": "8a849d95", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:24.083742Z", "iopub.status.busy": "2026-02-03T20:59:24.083607Z", "iopub.status.idle": "2026-02-03T20:59:24.085648Z", "shell.execute_reply": "2026-02-03T20:59:24.085445Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of variables: 3\n", "Is constant? False\n", "Is degenerate? False\n", "Essential variables: [0, 1, 2]\n", "Type of inputs: ['positive' 'positive' 'conditional']\n", "Hamming weight: 4\n", "Absolute bias: 0.0\n" ] } ], "source": [ "print(\"Number of variables:\", g.n)\n", "print(\"Is constant?\", g.is_constant())\n", "print(\"Is degenerate?\", g.is_degenerate())\n", "print(\"Essential variables:\", g.get_essential_variables())\n", "print(\"Type of inputs:\", g.get_type_of_inputs())\n", "print(\"Hamming weight:\", g.get_hamming_weight())\n", "print(\"Absolute bias:\", g.get_absolute_bias())" ] }, { "cell_type": "markdown", "id": "4d779eff", "metadata": {}, "source": [ "The `.summary()` method prints a human-readable overview of basic properties.\n", "If more advanced properties have already been computed, e.g., by `.get_layer_structure()` or `get_type_of_inputs()`,\n", "they are also displayed (or if the optional keyword `COMPUTE_ALL` is set to True, default False). " ] }, { "cell_type": "code", "execution_count": 14, "id": "e0257c6c", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:24.086643Z", "iopub.status.busy": "2026-02-03T20:59:24.086584Z", "iopub.status.idle": "2026-02-03T20:59:24.088574Z", "shell.execute_reply": "2026-02-03T20:59:24.088368Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "BooleanFunction summary\n", "----------------------------------------\n", "Number of variables: 3\n", "Hamming Weight: 5\n", "Bias: 0.625\n", "Absolute bias: 0.250\n", "Variables: ['A' 'B' 'C']\n", "\n", "BooleanFunction summary\n", "----------------------------------------\n", "Number of variables: 3\n", "Hamming Weight: 5\n", "Bias: 0.625\n", "Absolute bias: 0.250\n", "Variables: ['A' 'B' 'C']\n", "CanalizingDepth: 3\n", "NumberOfLayers: 2\n", "CanalizingInputs: [0 0 0]\n", "CanalizedOutputs: [1 0 0]\n", "CoreFunction: [1]\n", "OrderOfCanalizingVariables: [2 0 1]\n", "LayerStructure: [1, 2]\n", "InputTypes: ['negative' 'positive' 'positive']\n" ] } ], "source": [ "f = boolforge.BooleanFunction(\"(A and B) OR NOT C\")\n", "print(f.summary())\n", "print()\n", "\n", "# Trigger computation of more advanced properties\n", "print(f.summary(COMPUTE_ALL=True))" ] }, { "cell_type": "markdown", "id": "b9e92bac", "metadata": {}, "source": [ "---\n", "## 4. Logical and polynomial representations\n", "\n", "While Boolean functions are stored as truth tables, they can be expressed in logical and polynomial format." ] }, { "cell_type": "code", "execution_count": 15, "id": "df449355", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:24.089577Z", "iopub.status.busy": "2026-02-03T20:59:24.089514Z", "iopub.status.idle": "2026-02-03T20:59:24.091262Z", "shell.execute_reply": "2026-02-03T20:59:24.091035Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Logical form of : ( ¬A) ∧ ( ¬B) ∧ ( ¬C) ∨ ( ¬A) ∧ B ∧ ( ¬C) ∨ A ∧ ( ¬B) ∧ ( ¬C) ∨ A ∧ B ∧ ( ¬C) ∨ A ∧ B ∧ C\n", "Polynomial form of : (1 - A) * (1 - B) * (1 - C) + (1 - A) * B * (1 - C) + A * (1 - B) * (1 - C) + A * B * (1 - C) + A * B * C\n" ] } ], "source": [ "print(f\"Logical form of {f.name}:\", f.to_logical(AND=\" ∧ \", OR=\" ∨ \", NOT=\" ¬\"))\n", "print(f\"Polynomial form of {f.name}:\", f.to_polynomial())" ] }, { "cell_type": "markdown", "id": "e5dc11c7", "metadata": {}, "source": [ "In addition, an instance of `BooleanFunction` can be turned into an instance of `BooleanNode` from the [CANA package](https:www.github.com). \n", "This requires the optional CANA package to be installed." ] }, { "cell_type": "code", "execution_count": 16, "id": "bb310fcc", "metadata": { "execution": { "iopub.execute_input": "2026-02-03T20:59:24.092272Z", "iopub.status.busy": "2026-02-03T20:59:24.092186Z", "iopub.status.idle": "2026-02-03T20:59:24.093546Z", "shell.execute_reply": "2026-02-03T20:59:24.093362Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "cana_object = f.to_cana()\n", "print(type(cana_object))" ] }, { "cell_type": "markdown", "id": "bde28152", "metadata": { "lines_to_next_cell": 2 }, "source": [ "---\n", "## 5. Summary of Key Concepts\n", "\n", "Before moving on to more advanced topics, here is a short summary of the\n", "fundamental ideas introduced in this tutorial:\n", "\n", "### **Boolean functions**\n", "A Boolean function maps a set of binary inputs (0/1) to a single binary output.\n", "BoolForge represents Boolean functions internally by their truth table, i.e.,\n", "the list of outputs in lexicographic order of the input combinations.\n", "\n", "### **Representations of Boolean functions**\n", "Boolean functions can be created from:\n", "- a truth table (list of 0s and 1s),\n", "- a logical expression written in Python syntax,\n", "- algebraic combinations of existing BooleanFunction objects using operations such as \n", " `+` (OR), `*` (AND), `^` (XOR), and other supported Boolean operations.\n", "\n", "Each representation produces an equivalent internal truth-table-based object.\n", "\n", "### **Variable names and ordering**\n", "BoolForge automatically infers variable names from the order of first appearance\n", "in expressions. \n", "This order determines the indexing of the truth table and therefore affects how\n", "the function interacts with larger Boolean networks.\n", "\n", "### **Basic properties of Boolean functions**\n", "BoolForge can compute structural properties, including:\n", "- the number of variables (`n`),\n", "- the Hamming weight (number of 1s in the truth table),\n", "- absolute bias (imbalance between 0s and 1s),\n", "- essential and non-essential variables,\n", "- positive/negative influence of each input.\n", "\n", "These properties help characterize the function’s behavior and are used\n", "throughout later tutorials.\n", "\n", "### **Conversions and interoperability**\n", "BoolForge supports conversion between representations (e.g., truth table to/from polynomial form) and is compatible with external packages such as **CANA** for\n", "advanced analysis. \n", "This makes it easy to move between analytical frameworks and reuse models." ] }, { "cell_type": "markdown", "id": "1a44ac8d", "metadata": {}, "source": [ "---\n", "\n", "Together, these concepts provide the foundation for understanding canalization,\n", "random Boolean function generation, and eventually the construction and analysis\n", "of full Boolean networks." ] }, { "cell_type": "markdown", "id": "dab2445a", "metadata": {}, "source": [ "# Frequently Asked Questions (FAQ)\n", "### **1. Why does the order of variables matter?**\n", "The order in which variables appear determines the ordering of the truth table.\n", "For a function with variables `[A, B, C]`, the entry at position `i` corresponds\n", "to the binary representation of `i` over `(A, B, C)`.\n", "\n", "If two equivalent expressions list variables in different orders, their truth\n", "tables will be indexed differently.\n", "\n", "To ensure reproducibility, always use consistent variable names and ordering." ] }, { "cell_type": "markdown", "id": "c5854534", "metadata": {}, "source": [ "### **2. How do I choose between defining a function via a truth table or via an expression?**\n", "Short answer: It does not matter. Both methods produce identical internal representations.\n", "\n", "Slightly longer answer: \n", "Use a **textual expression** if:\n", "- you know the natural logical description of your function (e.g., `A and B`),\n", "- the function is part of a Boolean network stored in some text file.\n", "\n", "Use a **truth table** if:\n", "- you generated the table programmatically (e.g., using `boolforge.random_function`)." ] }, { "cell_type": "markdown", "id": "23dfd9e1", "metadata": { "lines_to_next_cell": 2 }, "source": [ "### **3. What is the difference between `get_type_of_inputs()` and monotonicity?**\n", "The method `get_type_of_inputs()` classifies each input variable individually\n", "according to how it influences the output:\n", "- positively increasing,\n", "- negatively increasing,\n", "- conditional,\n", "- or non-essential.\n", "\n", "Monotonicity, by contrast, is a **global property** of the Boolean function.\n", "A function is monotone if **all** essential variables influence the output in a\n", "consistent direction.\n", "\n", "A function can therefore be non-monotone even if individual inputs have a\n", "well-defined influence type.\n", "\n", "### **4. Quick Reference:**\n", "\n", "| Task | Example |\n", "|------|---------|\n", "| Create from truth table | `BooleanFunction([0, 0, 0, 1])` |\n", "| Create from expression | `BooleanFunction(\"A and B\")` |\n", "| Combine with operations | `f & g, f \\| g, ~f, f ^ g` |\n", "| Check properties | `f.is_constant()`, `f.is_degenerate()` |\n", "| Get variable info | `f.variables`, `f.n` |\n", "| Convert representations | `f.to_logical()`, `f.to_polynomial()` |" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" }, "kernelspec": { "display_name": "Python (py312)", "language": "python", "name": "py312" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.10" } }, "nbformat": 4, "nbformat_minor": 5 }