////
Copyright (c) 2024 The C++ Alliance, Inc. (https://cppalliance.org)

Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Official repository: https://github.com/boostorg/website-v2-docs
////
= Bio-Tech Engineering
:navtitle: Bio-Tech Engineering

Boost libraries provide low-level, auditable control over algorithms and numeric behavior, making them well-suited to computational biology, genomics pipelines, and regulated - verifiable, reproducible and stable - biomedical software.

This topic examines the libraries that should assist in building a bio-tech tool, focusing on evolving data structures.

[square]
* <<Libraries>>
* <<Working with Phylogenetic Trees>>
* <<Create a Phylogenetic Tree>>
* <<Persist a Phylogenetic Tree>>
* <<Extend the Phylogenetic Tree>>
* <<Next Steps>>
* <<Footnotes>>
* <<See Also>>


== Libraries

  
* boost:graph[] : Provides the features necessary for phylogenetic trees (explored further in this topic) as well as interaction networks, pathway graphs, and other structures well suited to bio-tech study. The library supports efficient graph traversal, shortest path and labeled graph algorithms.

* boost:filesystem[] and boost:serialization[] : Provide the persistent storage needed for long runs and simulations.

* boost:asio[] : Provides great support for distributed bio-tech platforms, which might be used in cloud-based analysis, multi-lab collaboration, and possibly working with streaming and experimental data.

* boost:multi-array[] : Particularly useful for tasks in the medical/biological image and signal processing realms, where multi-dimensional image or sensor data is a key component.

* boost:math[], boost:multiprecision[], boost:random[] : Provide the numerical and simulation support for such processes as energy accumulation, long simulations, validation, protein folding, molecular dynamics, docking simulations, energy minimalization, among so many others.

* boost:container[] : Useful for memory-stable storage of works-in-progress, notable scenarios include particles/atoms, cache-friendly structures, deterministic memory layout.

Note:: The code in this tutorial was written and tested using Microsoft Visual Studio (Visual C++ 2022, Console App project) with Boost version 1.88.0.


== Working with Phylogenetic Trees

[#footnote1-location]
In biotechnology and molecular biology, _phylogenetic trees_ link:#footnote1[(1)] have become go-to data structures - researchers compare the DNA, RNA, or protein sequences of multiple organisms to infer evolutionary relationships and similarities. This is particularly important in drug discovery, where understanding conserved sequences across species can indicate potential targets for antibiotics, antivirals, or cancer therapies. Similarly, phylogenetic analysis aids scientists track how viruses like influenza or SARS-CoV-2 mutate over time, and predict which strains are most likely to dominate. 

[#footnote2-location]
Beyond genomics, phylogenetic trees are also widely used in synthetic biology and _metagenomics_ link:#footnote2[(2)]. In synthetic biology, phylotrees guide the design of engineered organisms or genetic circuits.

Phylogenetic trees have also proven valuable in epidemiology and biotechnology safety monitoring. By mapping the evolutionary history of pathogens, scientists can trace the source of outbreaks, identify transmission patterns, and evaluate the emergence of drug resistance.

[#footnote3-location]
In medicine, metagenomic analyses of the _human microbiome_ link:#footnote3[(3)] help researchers understand the links between microbial communities and diseases such as obesity, diabetes, and autoimmune disorders. In environmental science, metagenomics can identify microorganisms capable of degrading pollutants or producing biofuels. In industrial biotech, it guides the optimization of microbial consortia for fermentation, waste treatment, or bioproduct synthesis. 

A key challenge in metagenomics is handling the vast, complex datasets generated by high-throughput sequencing. Computational tools that efficiently model, manipulate, and analyze these data — including phylogenetic trees derived from metagenomic sequences — are essential to insightful observations and conclusions. 


== Create a Phylogenetic Tree

Phylogenetic trees provide a natural way to organize and visualize complex communities. Using a Boost-based framework - like the following example - each step of tree construction, from adding new sequences, refining branches, to removing erroneous data — can be captured, and animated:

[source,cpp]
----
#include <boost/graph/adjacency_list.hpp>
#include <iostream>

// ------------------------------
// Vertex data
// ------------------------------
struct Species
{
    std::string name;
};

// ------------------------------
// Graph type
// ------------------------------
using PhyloTree = boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::directedS,
    Species
>;

using Vertex = boost::graph_traits<PhyloTree>::vertex_descriptor;

// ------------------------------
// Recursive ASCII tree printer
// ------------------------------
void print_tree(const PhyloTree& tree, Vertex v,
    const std::string& prefix = "",
    bool is_last = true)
{
    std::cout << prefix
        << (is_last ? "|__ " : "|_ ")
        << tree[v].name << "\n";

    auto children = boost::make_iterator_range(out_edges(v, tree));

    for (auto it = children.begin(); it != children.end(); ++it)
    {
        Vertex child = target(*it, tree);
        bool last = (std::next(it) == children.end());

        print_tree(tree,
            child,
            prefix + (is_last ? "   " : "|  "),
            last);
    }
}

// ------------------------------
// Print full tree from root
// ------------------------------
void show_tree(const PhyloTree& tree, Vertex root,
    const std::string& title)
{
    std::cout << "\n=== " << title << " ===\n";
    print_tree(tree, root);
}

int main()
{
    PhyloTree tree;

    // ------------------------------
    // Create root
    // ------------------------------
    auto luca = add_vertex({ "LUCA" }, tree);
    show_tree(tree, luca, "Initial tree");

    // ------------------------------
    // Add primary domains
    // ------------------------------
    auto bacteria = add_vertex({ "Bacteria" }, tree);
    auto archaea = add_vertex({ "Archaea" }, tree);
    auto eukarya = add_vertex({ "Eukarya" }, tree);

    add_edge(luca, bacteria, tree);
    add_edge(luca, archaea, tree);
    add_edge(luca, eukarya, tree);

    show_tree(tree, luca, "After adding domains");

    // ------------------------------
    // Add Eukarya branches
    // ------------------------------
    auto animals = add_vertex({ "Animals" }, tree);
    auto plants = add_vertex({ "Plants" }, tree);
    auto fungi = add_vertex({ "Fungi" }, tree);

    add_edge(eukarya, animals, tree);
    add_edge(eukarya, plants, tree);
    add_edge(eukarya, fungi, tree);

    show_tree(tree, luca, "After Eukarya speciation");

    // ------------------------------
    // Add animal subclasses
    // ------------------------------
    auto mammals = add_vertex({ "Mammals" }, tree);
    auto reptiles = add_vertex({ "Reptiles" }, tree);

    add_edge(animals, mammals, tree);
    add_edge(animals, reptiles, tree);

    show_tree(tree, luca, "After animal diversification");

    // ------------------------------
    // Scientific correction: prune plants
    // ------------------------------
    clear_vertex(plants, tree);
    remove_vertex(plants, tree);

    show_tree(tree, luca, "After pruning Plants");

    return 0;
}

----

Note:: The methods such as `add_edge`, `add_vertex`, and many others are provided by the boost:graph[] library, so little additional code is needed to manipulate a tree.

Run the code:

[source,text]
----
=== Initial tree ===
|__ LUCA

=== After adding domains ===
|__ LUCA
   |_ Bacteria
   |_ Archaea
   |__ Eukarya

=== After Eukarya speciation ===
|__ LUCA
   |_ Bacteria
   |_ Archaea
   |__ Eukarya
      |_ Animals
      |_ Plants
      |__ Fungi

=== After animal diversification ===
|__ LUCA
   |_ Bacteria
   |_ Archaea
   |__ Eukarya
      |_ Animals
      |  |_ Mammals
      |  |__ Reptiles
      |_ Plants
      |__ Fungi

=== After pruning Plants ===
|__ LUCA
   |_ Bacteria
   |_ Archaea
   |__ Eukarya
      |_ Animals
      |  |_ Mammals
      |  |__ Reptiles
      |__ Fungi
----

Consider adding your own calls to create and prune branches and leaves as appropriate.

[#footnote4-location]
Note:: _LUCA_ stands for "Last Universal Common Ancestors" - a key concept in evolutionary modeling link:#footnote4[(4)].
+
LUCA : _Primordial ocean of glowing protocells_ :
+
image:bio-tech-luca.png[LUCA]

== Persist a Phylogenetic Tree

Let's add efficient storing and retrieving of data to our program:

[source,cpp]
----
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adj_list_serialize.hpp>

#include <boost/serialization/vector.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/nvp.hpp>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/filesystem.hpp>

#include <iostream>
#include <fstream>

// ============================================================
// BIO-TECH OVERVIEW
// ============================================================
// This program models a phylogenetic tree.
//
// A phylogenetic tree is a core data structure in:
//
//  • evolutionary biology
//  • genomics
//  • bioinformatics
//  • epidemiology
//
// It represents how species diverge from common ancestors.
//
// Nodes   = species / clades / ancestors
// Edges   = evolutionary descent
//
// The tree is:
//
//          LUCA (Last Universal Common Ancestor)
//               ├── Bacteria
//               ├── Archaea
//               └── Eukarya
//                       ├── Animals
//                       ├── Plants
//                       └── Fungi
//
// This exact topology mirrors real biological taxonomy.
//
// ============================================================



// ------------------------------
// Vertex data
// ------------------------------
// Each vertex in the graph represents a biological taxon.
//
// In real bioinformatics this might contain:
//
//  • genome ID
//  • DNA sequence hash
//  • divergence time
//  • taxonomy ID
//  • protein markers
//
// For this demo we store only the species/clade name.
//
struct Species
{
    std::string name;

    // Boost.Serialization hook.
    //
    // This allows phylogenetic trees to be saved and restored.
    // In real research this allows:
    //
    //  • persisting phylogenetic analyses
    //  • checkpointing long computations
    //  • sharing trees between labs
    //
    template<class Archive>
    void serialize(Archive& ar, const unsigned int)
    {
        ar& BOOST_SERIALIZATION_NVP(name);
    }
};



// ------------------------------
// Graph type
// ------------------------------
//
// We use Boost.Graph adjacency_list to model evolution.
//
// Directed graph is critical:
//
// parent → child
//
// because evolution flows forward in time.
//
// vecS storage:
//   • fast indexing
//   • compact memory
//   • ideal for trees built incrementally
//
using PhyloTree = boost::adjacency_list<
    boost::vecS,      // edge container
    boost::vecS,      // vertex container
    boost::directedS, // direction = ancestry flows forward
    Species           // payload stored in each vertex
>;

using Vertex = boost::graph_traits<PhyloTree>::vertex_descriptor;



// ------------------------------
// ASCII tree printer
// ------------------------------
//
// Recursively prints the phylogenetic tree.
//
// This is essentially a tiny tree visualization engine.
// Bioinformatics tools normally output:
//
//  • Newick format
//  • Nexus format
//  • graphical dendrograms
//
// This prints a human-friendly dendrogram.
//
void print_tree(const PhyloTree& tree, Vertex v,
    const std::string& prefix = "",
    bool is_last = true)
{
    std::cout << prefix
        << (is_last ? "|_ " : "|__")
        << tree[v].name << "\n";

    // In evolutionary terms:
    // "children" are descendant clades.
    auto children = boost::make_iterator_range(out_edges(v, tree));

    for (auto it = children.begin(); it != children.end(); ++it)
    {
        Vertex child = target(*it, tree);
        bool last = (std::next(it) == children.end());

        // Recursively print descendants.
        print_tree(tree,
            child,
            prefix + (is_last ? "   " : "|  "),
            last);
    }
}



// ------------------------------
// Animated display
// ------------------------------
//
// Simulates evolution through time.
//
// Each call shows the tree at a later evolutionary stage.
// Think of it as a time-lapse of diversification.
//
void animate(const PhyloTree& tree, Vertex root,
    const std::string& title,
    int delay_ms = 800)
{
    std::cout << "\n=== " << title << " ===\n";
    print_tree(tree, root);
    std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
}



// ------------------------------
// Save / load helpers using Boost.Filesystem
// ------------------------------
//
// Real phylogenetics produces large trees that must be:
//
//  • stored
//  • versioned
//  • exchanged between research teams
//
// We serialize the entire evolutionary tree.
//
void save_tree(const PhyloTree& tree,
    const boost::filesystem::path& file)
{
    boost::filesystem::create_directories(file.parent_path());

    std::ofstream ofs(file.string());
    boost::archive::text_oarchive oa(ofs);

    oa << BOOST_SERIALIZATION_NVP(tree);
}

void load_tree(PhyloTree& tree,
    const boost::filesystem::path& file)
{
    if (!boost::filesystem::exists(file))
        throw std::runtime_error("Tree file does not exist");

    std::ifstream ifs(file.string());
    boost::archive::text_iarchive ia(ifs);

    ia >> BOOST_SERIALIZATION_NVP(tree);
}



// ============================================================
// MAIN DEMO — SIMULATED EVOLUTION
// ============================================================
int main()
{
    PhyloTree tree;

    // --------------------------------------------------------
    // Stage 1: LUCA appears
    // --------------------------------------------------------
    // LUCA = Last Universal Common Ancestor
    //
    // This is a real biological concept:
    // the most recent organism from which all life descends.
    //
    auto luca = add_vertex({ "LUCA" }, tree);
    animate(tree, luca, "Initial tree");



    // --------------------------------------------------------
    // Stage 2: The Three Domains of Life
    // --------------------------------------------------------
    // Real biology classification:
    //
    //  • Bacteria
    //  • Archaea
    //  • Eukarya
    //
    // This split happened ~3.5 billion years ago.
    //
    auto bacteria = add_vertex({ "Bacteria" }, tree);
    auto archaea = add_vertex({ "Archaea" }, tree);
    auto eukarya = add_vertex({ "Eukarya" }, tree);

    add_edge(luca, bacteria, tree);
    add_edge(luca, archaea, tree);
    add_edge(luca, eukarya, tree);

    animate(tree, luca, "Domains of life");



    // --------------------------------------------------------
    // Stage 3: Eukaryotic radiation
    // --------------------------------------------------------
    // Eukaryotes diversify into multicellular life.
    //
    auto animals = add_vertex({ "Animals" }, tree);
    auto plants = add_vertex({ "Plants" }, tree);
    auto fungi = add_vertex({ "Fungi" }, tree);

    add_edge(eukarya, animals, tree);
    add_edge(eukarya, plants, tree);
    add_edge(eukarya, fungi, tree);

    animate(tree, luca, "Eukaryotic diversification");



    // --------------------------------------------------------
    // Stage 4: Animal diversification
    // --------------------------------------------------------
    auto mammals = add_vertex({ "Mammals" }, tree);
    auto reptiles = add_vertex({ "Reptiles" }, tree);

    add_edge(animals, mammals, tree);
    add_edge(animals, reptiles, tree);

    animate(tree, luca, "Animal diversification");



    // --------------------------------------------------------
    // Scientific correction: prune plants
    // --------------------------------------------------------
    // Simulates:
    //  • new genomic evidence
    //  • updated phylogenetic model
    //
    // clear_vertex removes all evolutionary relationships.
    // remove_vertex deletes the taxon from the tree.
    //
    clear_vertex(plants, tree);
    remove_vertex(plants, tree);

    animate(tree, luca, "After pruning Plants");



    // --------------------------------------------------------
    // Persist tree to disk
    // --------------------------------------------------------
    boost::filesystem::path data_dir = "data";
    boost::filesystem::path tree_file = data_dir / "phylo_tree.dat";

    save_tree(tree, tree_file);
    std::cout << "\nTree saved to " << tree_file << "\n";



    // --------------------------------------------------------
    // Reload and verify
    // --------------------------------------------------------
    // Simulates:
    //  • loading analysis results
    //  • continuing research later
    //
    PhyloTree loaded;
    load_tree(loaded, tree_file);

    std::cout << "\n=== Reloaded tree ===\n";
    print_tree(loaded, luca);

    return 0;
}

----

Run the code:

[source,text]
----
=== Initial tree ===
|_ LUCA

=== Domains of life ===
|_ LUCA
   |__Bacteria
   |__Archaea
   |_ Eukarya

=== Eukaryotic diversification ===
|_ LUCA
   |__Bacteria
   |__Archaea
   |_ Eukarya
      |__Animals
      |__Plants
      |_ Fungi

=== Animal diversification ===
|_ LUCA
   |__Bacteria
   |__Archaea
   |_ Eukarya
      |__Animals
      |  |__Mammals
      |  |_ Reptiles
      |__Plants
      |_ Fungi

=== After pruning Plants ===
|_ LUCA
   |__Bacteria
   |__Archaea
   |_ Eukarya
      |__Animals
      |  |__Mammals
      |  |_ Reptiles
      |_ Fungi

Tree saved to "data\phylo_tree.dat"

=== Reloaded tree ===
|_ LUCA
   |__Bacteria
   |__Archaea
   |_ Eukarya
      |__Animals
      |  |__Mammals
      |  |_ Reptiles
      |_ Fungi
----

Locate the folder containing your program, then examine the contents of `data\phylo_tree.dat`:

[source,text]
----
22 serialization::archive 20 0 0 8 7 0 0 4 LUCA 8 Bacteria 7 Archaea 7 Eukarya 7 Animals 5 Fungi 7 Mammals 8 Reptiles 0 1 0 0 0 2 0 3 3 4 3 5 4 6 4 7
----

== Extend the Phylogenetic Tree

In this next example, we add some introductory code to some additional concepts prevalent with phylogenetic trees. 

A molecular clock is introduced, which can help with divergence timestamps and estimates (refer to `divergence_mya`). Also related to time, branch lengths are introducted to help understand evolutionary time and the concept of mutation distance (refer to `mutate`). DNA markers aid in simplifying genome signatures, and the standard interchange format for these trees is https://en.wikipedia.org/wiki/Newick_format[Newick format].

In the following example, we focus on the features of boost:graph[]:

[source,cpp]
----
#include <boost/graph/adj_list_serialize.hpp>

#include <random>
#include <iostream>
#include <fstream>

//////////////////////////////////////////////////////////////////
// BIOINFORMATICS UPGRADE OVERVIEW
//////////////////////////////////////////////////////////////////
//
// This version models real phylogenetic concepts:
//
//   Vertex = taxon / species / clade
//   Edge   = evolutionary divergence event
//
// Added biological properties:
//
//   • branch_length  → mutation distance
//   • divergence_mya → million years ago
//   • dna_marker     → simplified genome signature
//   • bootstrap      → confidence of phylogenetic split
//
// Also exports to NEWICK format — the standard file format
// used by tools like:
//
//   • MEGA
//   • BEAST
//   • MrBayes
//   • PhyML
//
//////////////////////////////////////////////////////////////////


// =============================================================
// Utility: fake DNA generator
// =============================================================
// Generates a random DNA string (A/C/G/T).
// Real tools would store real gene/protein sequences.
//
std::string random_dna(size_t length = 16)
{
    static const char bases[] = { 'A','C','G','T' };
    static std::mt19937 rng((unsigned)time(nullptr));
    static std::uniform_int_distribution<> dist(0, 3);

    std::string s;
    for (size_t i = 0; i < length; ++i)
        s += bases[dist(rng)];
    return s;
}

// =============================================================
// Vertex data — Taxon
// =============================================================
struct Taxon
{
    std::string name;
    std::string dna_marker;     // simplified genome fingerprint
    double divergence_mya = 0;  // million years ago

    template<class Archive>
    void serialize(Archive& ar, const unsigned int)
    {
        ar& BOOST_SERIALIZATION_NVP(name);
        ar& BOOST_SERIALIZATION_NVP(dna_marker);
        ar& BOOST_SERIALIZATION_NVP(divergence_mya);
    }
};

// =============================================================
// Edge data — Evolutionary branch
// =============================================================
struct Branch
{
    double branch_length = 0.0; // mutation distance
    double bootstrap = 1.0;     // confidence (0–1)

    template<class Archive>
    void serialize(Archive& ar, const unsigned int)
    {
        ar& BOOST_SERIALIZATION_NVP(branch_length);
        ar& BOOST_SERIALIZATION_NVP(bootstrap);
    }
};

// =============================================================
// Graph definition
// =============================================================
using PhyloTree = boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::directedS,
    Taxon,
    Branch
>;

using Vertex = boost::graph_traits<PhyloTree>::vertex_descriptor;
using Edge = boost::graph_traits<PhyloTree>::edge_descriptor;

// =============================================================
// Mutation simulator
// =============================================================
// Slightly mutates DNA to simulate evolution.
//
std::string mutate(const std::string& dna, int changes = 2)
{
    static std::mt19937 rng((unsigned)time(nullptr));
    static std::uniform_int_distribution<> pos_dist(0, 15);
    static std::uniform_int_distribution<> base_dist(0, 3);
    static const char bases[] = { 'A','C','G','T' };

    std::string out = dna;

    for (int i = 0; i < changes; ++i)
        out[pos_dist(rng)] = bases[base_dist(rng)];

    return out;
}

// =============================================================
// Add child taxon helper
// =============================================================
Vertex evolve(PhyloTree& tree, Vertex parent,
    std::string name,
    double divergence_time,
    double branch_len,
    double bootstrap)
{
    Taxon t;
    t.name = name;
    t.dna_marker = mutate(tree[parent].dna_marker);
    t.divergence_mya = divergence_time;

    Vertex child = add_vertex(t, tree);

    Branch b{ branch_len, bootstrap };
    add_edge(parent, child, b, tree);

    return child;
}

// =============================================================
// NEWICK EXPORT (important!)
// =============================================================
// Newick format example:
//
//   (Human:0.2,Mouse:0.3)Mammals;
//
// This is the *universal exchange format* for phylogenetics.
//
std::string to_newick(const PhyloTree& tree, Vertex v)
{
    auto children = boost::make_iterator_range(out_edges(v, tree));

    std::ostringstream out;

    if (!children.empty())
    {
        out << "(";
        bool first = true;

        for (auto e : children)
        {
            if (!first) out << ",";
            first = false;

            Vertex child = target(e, tree);
            out << to_newick(tree, child)
                << ":" << tree[e].branch_length;
        }
        out << ")";
    }

    out << tree[v].name;
    return out.str();
}

// =============================================================
// Pretty tree printer with biological data
// =============================================================
void print_tree(const PhyloTree& tree, Vertex v, std::string indent = "")
{
    const auto& t = tree[v];

    std::cout << indent
        << t.name
        << "  [DNA=" << t.dna_marker
        << ", MYA=" << t.divergence_mya
        << "]\n";

    for (auto e : boost::make_iterator_range(out_edges(v, tree)))
    {
        std::cout << indent << "  |_ branch len="
            << tree[e].branch_length
            << " bootstrap=" << tree[e].bootstrap << "\n";

        print_tree(tree, target(e, tree), indent + "     ");
    }
}

// =============================================================
// MAIN — SIMULATED EVOLUTIONARY HISTORY
// =============================================================
int main()
{
    PhyloTree tree;

    // LUCA — Last Universal Common Ancestor
    Taxon luca{ "LUCA", random_dna(), 4000 };
    Vertex root = add_vertex(luca, tree);

    // Domains of life (~3.5 billion years ago)
    auto bacteria = evolve(tree, root, "Bacteria", 3500, 0.9, 0.98);
    auto archaea = evolve(tree, root, "Archaea", 3500, 0.85, 0.97);
    auto eukarya = evolve(tree, root, "Eukarya", 2100, 0.7, 0.95);

    // Eukaryotic radiation
    auto animals = evolve(tree, eukarya, "Animals", 800, 0.6, 0.92);
    auto fungi = evolve(tree, eukarya, "Fungi", 1000, 0.65, 0.91);
    auto plants = evolve(tree, eukarya, "Plants", 1200, 0.63, 0.90);

    // Animal diversification
    evolve(tree, animals, "Mammals", 200, 0.3, 0.99);
    evolve(tree, animals, "Reptiles", 300, 0.35, 0.96);

    // Print full annotated tree
    std::cout << "\n===== Annotated Phylogenetic Tree =====\n";
    print_tree(tree, root);

    // Export Newick file
    std::ofstream("phylo_tree.newick") << to_newick(tree, root) << ";";
    std::cout << "\nNewick file written: phylo_tree.newick\n";

    return 0;
}
----

Run the code and examine the output:
[source,text]
----
===== Annotated Phylogenetic Tree =====
LUCA  [DNA=GTGTCCTACCCTGCAT, MYA=4000]
  |_ branch len=0.9 bootstrap=0.98
     Bacteria  [DNA=GTGTCCTACCCTGGAT, MYA=3500]
  |_ branch len=0.85 bootstrap=0.97
     Archaea  [DNA=GTGTCCTCCCCTGCAT, MYA=3500]
  |_ branch len=0.7 bootstrap=0.95
     Eukarya  [DNA=GTGTCCCACCCTCCAT, MYA=2100]
       |_ branch len=0.6 bootstrap=0.92
          Animals  [DNA=GTGTGCCACCCTACAT, MYA=800]
            |_ branch len=0.3 bootstrap=0.99
               Mammals  [DNA=ATGTGCAACCCTACAT, MYA=200]
            |_ branch len=0.35 bootstrap=0.96
               Reptiles  [DNA=GCGTGCCACCCTACCT, MYA=300]
       |_ branch len=0.65 bootstrap=0.91
          Fungi  [DNA=GTGTCCCATCCTCCAT, MYA=1000]
       |_ branch len=0.63 bootstrap=0.9
          Plants  [DNA=GTGTCCCACCCACCAT, MYA=1200]

Newick file written: phylo_tree.newick
----

== Next Steps

If manipulating trees, which are a form of graph, is part of your bio-tech projects, consider examining the full range of structures and methods available in boost:graph[].

== Footnotes

[#footnote1]
link:#footnote1-location[(1)]
A phylogenetic tree, often called a “phylotree”, is a diagrammatic representation of the evolutionary relationships among various biological species or entities, based on similarities and differences in their genetic, morphological, or biochemical characteristics. Each node represents a species (or other taxonomic unit), and the edges—or branches—denote evolutionary paths connecting them. The root of the tree represents the _most recent common ancestor_ (often shortened to _MRCA_) of all the species in the diagram, while the leaves correspond to current-day organisms or sequences. Phylogenetic trees can be either _rooted_, showing directionality of evolution, or _unrooted_, highlighting relationships without assuming an ancestral origin.

[#footnote2]
link:#footnote2-location[(2)]
Metagenomics is the study of genetic material recovered directly from environmental samples, rather than from individual, isolated organisms. It allows scientists to analyze entire microbial communities in their natural habitats — such as soil, water, the human gut, or industrial bioreactors — without the need to culture the organisms in a lab. By sequencing and analyzing the collective genomes of these communities, metagenomics provides insights into the diversity, function, and interactions of microorganisms that might otherwise remain hidden.

[#footnote3]
link:#footnote3-location[(3)]
The human microbiome refers to the vast community of microorganisms that live in and on the human body, including bacteria, viruses, fungi, and archaea. These microbes inhabit diverse environments such as the gut, skin, mouth, respiratory tract, and urogenital system. Collectively, their genomes — known as the microbiome — contain far more genes than the human genome itself, forming a complex biological system that interacts continuously with its host.

Gut microbes, for example, help digest complex carbohydrates, synthesize vitamins, regulate the immune system, and protect against pathogenic organisms. Disruptions to the microbiome, often called dysbiosis, have been linked to a wide range of conditions including inflammatory bowel disease, obesity, diabetes, allergies, and even neurological disorders. As a result, microbiome research has become a major focus in areas such as precision medicine, probiotic development, and microbiome-targeted therapies.

From a computational perspective, studying the human microbiome relies heavily on metagenomics and phylogenetic analysis. 

[#footnote4]
link:#footnote4-location[(4)]
LUCA, or _Last Universal Common Ancestors_, refers to the most recent organism (or often population of organisms) from which all life on Earth descends. In phylogenetic trees, LUCA is often used as the root node, representing the point before life diversified into the major domains (such as Bacteria, Archaea, and Eukarya). Importantly, LUCA is not thought of as the very first living thing, but rather as the latest shared ancestor of all existing life — a complex organism that already possessed fundamental biological machinery like genetic coding, ribosomes, and basic metabolic pathways. That's why using LUCA as the root in your demo is both scientifically meaningful and intuitive: it provides a natural starting point from which the evolutionary branches unfold.
 
== See Also

* https://www.boost.org/doc/libs/latest/libs/libraries.htm#Algorithms[Category: Algorithms]
* https://www.boost.org/doc/libs/latest/libs/libraries.htm#Containers[Category: Containers] 
* https://www.boost.org/doc/libs/latest/libs/libraries.htm#Data[Category: Data structures]
* https://www.boost.org/doc/libs/latest/libs/libraries.htm#Math[Category: Math and numerics]