{ "cells": [ { "cell_type": "markdown", "id": "3ac828f3-8d91-4fcb-ac9c-d31c8c334ca3", "metadata": { "tags": [] }, "source": [ "# Ex 1: Optimization-Based Model & Vector Loops (2D / 4-DOF)\n", "\n", "This notebook demonstrates the manual construction of the tolerance analysis model for the minimal 2D assembly (a rectangular part within a rectangular pocket). \n", "\n", "Rather than relying on analytical geometric projections, we use **vector loops, transformation matrices, and gap matrices** to model the stack-up of defects. This formal mathematical structure is necessary for handling over-constrained systems and forms the foundation of the `otaf` methodology.\n", "\n", "### The Slack Variable Formulation\n", "Historically, Monte Carlo approaches for estimating failure rates rely on a discrete indicator function (a part is either conforming or non-conforming based on geometric interference). To apply advanced probability frameworks (surrogate models, subset sampling, gradient-based boundary searches), we require a **continuous limit state function**. \n", "\n", "We introduce a scalar slack variable $\\mathbf{s}$. The interface constraints are modified such that:\n", "$$ \\mathcal{C}_i(\\mathbf{d}, \\mathbf{g}) + \\mathbf{s} \\cdot \\mathbf{1} \\leq 0 $$\n", "\n", "By treating $\\mathbf{s}$ as the optimization objective (minimizing $-\\mathbf{s}$), the optimizer effectively finds a relative central positioning of the parts that maximizes the minimal clearance across all interfaces. \n", "- **$\\mathbf{s} > 0$**: The minimum clearance in the assembly (Conforming).\n", "- **$\\mathbf{s} < 0$**: The magnitude of geometric interference (Failure)." ] }, { "cell_type": "code", "execution_count": 6, "id": "6d39483b-87c7-40a1-af11-be7b2c090731", "metadata": { "tags": [] }, "outputs": [], "source": [ "import numpy as np\n", "import sympy as sp\n", "import openturns as ot\n", "import matplotlib.pyplot as plt\n", "\n", "from IPython.display import display, clear_output\n", "from time import time, sleep\n", "from scipy.optimize import OptimizeResult\n", "\n", "import otaf\n", "\n", "# Identity and 180° rotation matrix around z\n", "I4 = otaf.I4()\n", "J4 = otaf.J4()" ] }, { "cell_type": "markdown", "id": "0df2e9f0-2fb0-4daa-87eb-c0de53897649", "metadata": {}, "source": [ "## 1. Definition of Nominal Dimensions & Hypotheses\n", "\n", "We apply the parameters explicitly defined for the 2D base model:\n", "- Tolerance $t = 0.31$ mm\n", "- Target process capability $Cq_p = 1.0$" ] }, { "cell_type": "code", "execution_count": 7, "id": "be2bc724-60c1-4273-aed9-1c6d297693ad", "metadata": { "tags": [] }, "outputs": [], "source": [ "# Geometric parameters\n", "X1 = 99.8 # Nominal Length of the male piece (Part 1)\n", "X2 = 100.0 # Nominal Length of the female pocket (Part 2)\n", "X3 = 10.0 # Nominal width of the features (h)\n", "j_nom = X2 - X1 # Nominal play between parts\n", "\n", "t = 0.31 # Tolerance value applied to features\n", "Cqp = 1.0 # Target capability" ] }, { "cell_type": "markdown", "id": "bea9527e-d70a-4b40-90ab-d46dee8171a1", "metadata": { "tags": [] }, "source": [ "## 2. Spatial Mapping and Local Reference Frames\n", "\n", "We define the global coordinate system ($\\mathcal{R}_0$) and the characteristic points of each interface surface. We then establish local reference frames for each substitute surface to correctly orient the transformation matrices." ] }, { "cell_type": "code", "execution_count": 8, "id": "c98883f1-1bca-47ac-b250-50691dcb4530", "metadata": { "tags": [] }, "outputs": [], "source": [ "# Global Coordinate System (R0)\n", "R0 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])\n", "x_, y_, z_ = R0[0], R0[1], R0[2]\n", "\n", "# Part 1 (Male) Points\n", "P1A0, P1A1, P1A2 = np.array((0, X3/2, 0.0)), np.array((0, X3, 0.0)), np.array((0, 0, 0.0))\n", "P1B0, P1B1, P1B2 = np.array((X1, X3/2, 0.0)), np.array((X1, X3, 0.0)), np.array((X1, 0, 0.0))\n", "P1C0, P1C1, P1C2 = np.array((X1/2, 0, 0.0)), np.array((0, 0, 0.0)), np.array((X1, 0, 0.0))\n", "\n", "# Part 2 (Female Pocket) Points\n", "P2A0, P2A1, P2A2 = np.array((0, X3/2, 0.0)), np.array((0, X3, 0.0)), np.array((0, 0, 0.0))\n", "P2B0, P2B1, P2B2 = np.array((X2, X3/2, 0.0)), np.array((X2, X3, 0.0)), np.array((X2, 0, 0.0))\n", "P2C0, P2C1, P2C2 = np.array((X2/2, 0, 0.0)), np.array((0, 0, 0.0)), np.array((X2, 0, 0.0))\n", "\n", "# Local Reference Frames\n", "RP1a = np.array([-1 * x_, -1 * y_, z_])\n", "RP1b = R0\n", "RP1c = np.array([-y_, x_, z_])\n", "\n", "RP2a = R0\n", "RP2b = np.array([-1 * x_, -1 * y_, z_])\n", "RP2c = np.array([y_, -1 * x_, z_])" ] }, { "cell_type": "code", "execution_count": 9, "id": "15eb1d43-0ba8-43ad-925e-a0bd05dd75b7", "metadata": { "tags": [] }, "outputs": [], "source": [ "# Pièce 1 (male)\n", "P1A0, P1A1, P1A2 = (\n", " np.array((0, X3 / 2, 0.0)),\n", " np.array((0, X3, 0.0)),\n", " np.array((0, 0, 0.0)),\n", ")\n", "P1B0, P1B1, P1B2 = (\n", " np.array((X1, X3 / 2, 0.0)),\n", " np.array((X1, X3, 0.0)),\n", " np.array((X1, 0, 0.0)),\n", ")\n", "P1C0, P1C1, P1C2 = (\n", " np.array((X1 / 2, 0, 0.0)),\n", " np.array((0, 0, 0.0)),\n", " np.array((X1, 0, 0.0)),\n", ")\n", "\n", "# Pièce 2 (femelle) # On met les points à hM et pas hF pour qu'ils soient bien opposées! (Besoin??)\n", "P2A0, P2A1, P2A2 = (\n", " np.array((0, X3 / 2, 0.0)),\n", " np.array((0, X3, 0.0)),\n", " np.array((0, 0, 0.0)),\n", ")\n", "P2B0, P2B1, P2B2 = (\n", " np.array((X2, X3 / 2, 0.0)),\n", " np.array((X2, X3, 0.0)),\n", " np.array((X2, 0, 0.0)),\n", ")\n", "P2C0, P2C1, P2C2 = (\n", " np.array((X2 / 2, 0, 0.0)),\n", " np.array((0, 0, 0.0)),\n", " np.array((X2, 0, 0.0)),\n", ")" ] }, { "cell_type": "code", "execution_count": 14, "id": "158c0eb4-04ff-4a16-b9eb-4bcad6ed9a1f", "metadata": { "tags": [] }, "outputs": [], "source": [ "# Generating transformation matrices\n", "TMD = {}\n", "TMD[\"T1c1a\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP1c, P1C0), final=otaf.geometry.tfrt(RP1a, P1A0))\n", "TMD[\"T2a2c\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP2a, P2A0), final=otaf.geometry.tfrt(RP2c, P2C0))\n", "TMD[\"T1c1b\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP1c, P1C0), final=otaf.geometry.tfrt(RP1b, P1B0))\n", "TMD[\"T2b2c\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP2b, P2B0), final=otaf.geometry.tfrt(RP2c, P2C0))\n", "\n", "TMD[\"TP1aA1aA0\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP1a, P1A1), final=otaf.geometry.tfrt(RP1a, P1A0))\n", "TMD[\"TP2aA0aA1\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP2a, P2A0), final=otaf.geometry.tfrt(RP2a, P2A1))\n", "TMD[\"TP1aA2aA0\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP1a, P1A2), final=otaf.geometry.tfrt(RP1a, P1A0))\n", "TMD[\"TP2aA0aA2\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP2a, P2A0), final=otaf.geometry.tfrt(RP2a, P2A2))\n", "\n", "TMD[\"TP1bB1bB0\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP1b, P1B1), final=otaf.geometry.tfrt(RP1b, P1B0))\n", "TMD[\"TP2bB0bB1\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP2b, P2B0), final=otaf.geometry.tfrt(RP2b, P2B1))\n", "TMD[\"TP1bB2bB0\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP1b, P1B2), final=otaf.geometry.tfrt(RP1b, P1B0))\n", "TMD[\"TP2bB0bB2\"] = otaf.TransformationMatrix(initial=otaf.geometry.tfrt(RP2b, P2B0), final=otaf.geometry.tfrt(RP2b, P2B2))" ] }, { "cell_type": "markdown", "id": "3daa4d1a-ee00-4d37-a298-4a515253e7bc", "metadata": {}, "source": [ "## 3. Constructing Compatibility Loops\n", "\n", "We define the deviation matrices and structural gaps. Note that for this 4-DOF model, defects are only modeled on **Feature B** for both parts (translation in $x$ and rotation in $z$)." ] }, { "cell_type": "code", "execution_count": 15, "id": "f2ac4d56-de83-443b-861a-936115b22a89", "metadata": { "tags": [] }, "outputs": [], "source": [ "# No-defect matrices for ideal surfaces\n", "DI4 = otaf.DeviationMatrix(index=-1, translations=\"\", rotations=\"\")\n", "\n", "# Loop 1: Compatibility (2c -> 1c -> 1a -> 2a)\n", "GP2cC0P1cC0 = otaf.GapMatrix(index=0, translations_blocked=\"z\", rotations_blocked=\"xy\")\n", "GP1aA0P2aA0 = otaf.GapMatrix(index=1, translations_blocked=\"z\", rotations_blocked=\"xy\")\n", "\n", "expa_1 = otaf.FirstOrderMatrixExpansion([\n", " DI4, GP2cC0P1cC0, J4, DI4, TMD[\"T1c1a\"], \n", " DI4, GP1aA0P2aA0, J4, DI4, TMD[\"T2a2c\"]\n", "]).compute_first_order_expansion()\n", "\n", "# Loop 2: Compatibility (2c -> 1c -> 1b -> 2b) - Defect Introduction Here\n", "D1b1b = otaf.DeviationMatrix(index=1, translations=\"x\", rotations=\"z\") \n", "GP1bB0P2bB0 = otaf.GapMatrix(index=2, translations_blocked=\"z\", rotations_blocked=\"xy\") \n", "D2b2b = otaf.DeviationMatrix(index=2, translations=\"x\", rotations=\"z\", inverse=True) \n", "\n", "expa_2 = otaf.FirstOrderMatrixExpansion([\n", " DI4, GP2cC0P1cC0, J4, DI4, TMD[\"T1c1b\"], \n", " D1b1b, GP1bB0P2bB0, J4, D2b2b, TMD[\"T2b2c\"]\n", "]).compute_first_order_expansion()\n", "\n", "compatibility_expressions = [\n", " *otaf.common.extract_expressions_with_variables(expa_1), \n", " *otaf.common.extract_expressions_with_variables(expa_2)\n", "]" ] }, { "cell_type": "markdown", "id": "ce6933da-94d4-4e2b-a3da-54578dd8ca3e", "metadata": {}, "source": [ "## 4. Interface Constraints and the System of Constraints (SOCAM)\n", "\n", "We verify the limits of the geometric interfaces. By passing these expressions to `SystemOfConstraintsAssemblyModel` and invoking `embedOptimizationVariable()`, `otaf` automatically introduces the scalar slack variable $\\mathbf{s}$. The assembly state is transformed into the minimization problem: $\\min -\\mathbf{s}$." ] }, { "cell_type": "code", "execution_count": 16, "id": "198c46ab-725c-4ade-ab8a-ca96cac4ac87", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Deviation Symbols: [u_d_1, gamma_d_1, u_d_2, gamma_d_2]\n" ] } ], "source": [ "# Interfaces on A and B sides\n", "expa_f_1 = otaf.FirstOrderMatrixExpansion([TMD[\"TP1aA1aA0\"], GP1aA0P2aA0, J4, TMD[\"TP2aA0aA1\"], J4]).compute_first_order_expansion()\n", "expa_f_2 = otaf.FirstOrderMatrixExpansion([TMD[\"TP1aA2aA0\"], GP1aA0P2aA0, J4, TMD[\"TP2aA0aA2\"], J4]).compute_first_order_expansion()\n", "expa_f_3 = otaf.FirstOrderMatrixExpansion([TMD[\"TP1bB1bB0\"], GP1bB0P2bB0, J4, TMD[\"TP2bB0bB1\"], J4]).compute_first_order_expansion()\n", "expa_f_4 = otaf.FirstOrderMatrixExpansion([TMD[\"TP1bB2bB0\"], GP1bB0P2bB0, J4, TMD[\"TP2bB0bB2\"], J4]).compute_first_order_expansion()\n", "\n", "# Masking to extract the relevant spatial clearance component\n", "mask_matrix = sp.Matrix(np.array([[0, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]))\n", "interface_constraints = [\n", " *otaf.common.extract_expressions_with_variables(expa_f_1.multiply_elementwise(mask_matrix)),\n", " *otaf.common.extract_expressions_with_variables(expa_f_2.multiply_elementwise(mask_matrix)),\n", " *otaf.common.extract_expressions_with_variables(expa_f_3.multiply_elementwise(mask_matrix)),\n", " *otaf.common.extract_expressions_with_variables(expa_f_4.multiply_elementwise(mask_matrix))\n", "]\n", "\n", "# Build the global assembly model\n", "SOCAM = otaf.SystemOfConstraintsAssemblyModel(compatibility_expressions, interface_constraints, verbose=0)\n", "\n", "# Introduces the scalar slack variable s to transform the constraint set\n", "SOCAM.embedOptimizationVariable()\n", "print(f\"Deviation Symbols: {SOCAM.deviation_symbols}\")" ] }, { "cell_type": "markdown", "id": "c811ee1b-a7e5-4ee6-90a9-8804613a30e1", "metadata": {}, "source": [ "## 5. Statistical Modeling: Exploring the Credal Set\n", "\n", "Instead of directly defining and re-sampling a multi-dimensional distribution for every point in the epistemic space, we define a master distribution based on the maximum standard deviation allowed by $t$ and $C_p$. \n", "\n", "We navigate the space of possible distributions using a normalized scaling vector $\\symbf{\\lambda} \\in [0,1]$. Multiplying a fixed normal sample by $\\symbf{\\lambda}$ prevents re-sampling noise, guaranteeing that adjacent points in the credal set yield smooth, directly comparable gradients." ] }, { "cell_type": "code", "execution_count": 17, "id": "10481f94-a419-4a1c-8776-4b23c6c0d6ab", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:No mu_dict passed, initializing all unspecified means to 0.0\n" ] } ], "source": [ "# Maximal allowable standard deviations based on the capability constraint\n", "y_max = X3 / 2.0\n", "sigma_u_max = t / (6 * Cqp)\n", "sigma_gamma_max = sigma_u_max / y_max\n", "\n", "# Construct the base random vector (at maximum possible variability)\n", "RandDeviationVect = otaf.distribution.get_composed_normal_defect_distribution(\n", " defect_names=SOCAM.deviation_symbols,\n", " sigma_dict={\n", " \"alpha\": sigma_gamma_max, \n", " \"beta\": sigma_gamma_max,\n", " \"gamma\": sigma_gamma_max, \n", " \"u\": sigma_u_max, \n", " \"v\": sigma_u_max, \n", " \"w\": sigma_u_max\n", " }\n", ")" ] }, { "cell_type": "markdown", "id": "096e5e05-147e-45c4-b453-baa4659c2033", "metadata": {}, "source": [ "## 6. Optimization Loop (Latin Hypercube Sampling)\n", "\n", "To visualize the bounds of the probability of failure ($\\underline{P_f}$, $\\overline{P_f}$), we generate a set of $\\symbf{\\lambda}$ vectors. While advanced solvers (like COBYQA) are strictly required for high-dimensional efficiency, Latin Hypercube Sampling (LHS) provides a clear brute-force visualization of the P-Box behavior for this introductory 4-DOF model." ] }, { "cell_type": "code", "execution_count": 18, "id": "45ddfb1b-8c99-4a8f-8fd1-68be727deb75", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Processed 90/100 lambda configurations.\n", "Elapsed time: 637.291 seconds.\n" ] }, { "ename": "AttributeError", "evalue": "module 'otaf.uncertainty' has no attribute 'find_best_worst_quantile'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[18], line 44\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mElapsed time: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtime()\u001b[38;5;250m \u001b[39m\u001b[38;5;241m-\u001b[39m\u001b[38;5;250m \u001b[39mstart_time\u001b[38;5;132;01m:\u001b[39;00m\u001b[38;5;124m.3f\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m seconds.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 43\u001b[0m \u001b[38;5;66;03m# Extract the bounds\u001b[39;00m\n\u001b[0;32m---> 44\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[43motaf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43muncertainty\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfind_best_worst_quantile\u001b[49m(np\u001b[38;5;241m.\u001b[39marray(lambda_sample_conditioned), np\u001b[38;5;241m.\u001b[39marray(failure_probabilities), \u001b[38;5;241m0.1\u001b[39m)\n\u001b[1;32m 45\u001b[0m (best_5p_lambda, best_5p_res), (worst_5p_lambda, worst_5p_res) \u001b[38;5;241m=\u001b[39m X\n", "\u001b[0;31mAttributeError\u001b[0m: module 'otaf.uncertainty' has no attribute 'find_best_worst_quantile'" ] } ], "source": [ "# Generate scaling parameters lambda\n", "Dim_Defects = len(SOCAM.deviation_symbols)\n", "lambda_vect_unconditioned = ot.ComposedDistribution([ot.Uniform(0, 1)] * Dim_Defects)\n", "lambda_vect_unconditioned.setDescription(list(map(str, SOCAM.deviation_symbols)))\n", "\n", "N_lambda = 100 # Reduced for notebook performance\n", "lambda_sample_random = lambda_vect_unconditioned.getSample(N_lambda)\n", "lambda_sample_conditioned = otaf.sampling.condition_lambda_sample(lambda_sample_random, squared_sum=True)\n", "\n", "# Optimization config\n", "SEED_MC_PF = 6436431\n", "SIZE_MC_PF = int(1e4)\n", "failure_probabilities, s_values = [], []\n", "\n", "start_time = time()\n", "# Brute force exploration of the credal set\n", "for i in range(N_lambda):\n", " ot.RandomGenerator.SetSeed(SEED_MC_PF)\n", " \n", " # Scale the base sample deterministically to avoid sampling noise\n", " deviation_samples = np.array(RandDeviationVect.getSample(SIZE_MC_PF)) * np.array(lambda_sample_conditioned[i])\n", " \n", " optimizations = otaf.uncertainty.compute_gap_optimizations_on_sample(\n", " SOCAM,\n", " deviation_samples,\n", " bounds=None,\n", " n_cpu=-1,\n", " progress_bar=False,\n", " )\n", " \n", " # Evaluate slack variable (failure defined as s < 0)\n", " s_vals = np.array([opt.fun for opt in optimizations], dtype=float)\n", " s_vals = np.nan_to_num(s_vals, nan=np.nanmax(s_vals)) * -1 \n", " \n", " failure_probabilities.append(np.where(s_vals < 0, 1, 0).mean())\n", " \n", " if i % 10 == 0:\n", " clear_output(wait=True)\n", " print(f\"Processed {i}/{N_lambda} lambda configurations.\")\n", "\n", "print(f\"Elapsed time: {time() - start_time:.3f} seconds.\")\n", "\n", "# Extract the bounds\n", "X = otaf.uncertainty.find_best_worst_quantile(np.array(lambda_sample_conditioned), np.array(failure_probabilities), 0.1)\n", "(best_5p_lambda, best_5p_res), (worst_5p_lambda, worst_5p_res) = X" ] }, { "cell_type": "code", "execution_count": 19, "id": "b694f28a-a428-4ca6-afd8-5b0f47bad4e2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Lower Bound Probability of Failure (min Pf): 0.3900%\n", "Upper Bound Probability of Failure (max Pf): 0.8100%\n" ] }, { "data": { "image/png": "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hnfeeQfA87EICwuDu7s7jIyMYGdnh/HjxyM1NVWtTSEE5s2bh3r16sHExAQ9evTAtWvXiu378ePHmD59Ojw9PVGrVi3Url0bAQEBuHz5cpn90iQ+Ph716tUrllAAgK2tbbGyQ4cOoWvXrjA1NYWZmRkCAwPV4izv+JXklTpTUZLhw4fjk08+wZEjRzB27FiNda5du4bevXujRYsWmDNnDhQKBeLi4nDmzBkAQLNmzTBnzhzMmjUL48aNQ9euXQEAnTt3VrXxzz//ICAgAIMHD8awYcNgZ2dXalxffvklZDIZPvroIyQnJyMsLAy+vr6IiopSnVEpj/LEVpgQAn379kVERARGjx6NVq1a4fDhw5gxYwbu3buHJUuWqNX/7bff8PPPP+O9996DmZkZvv32W7z55ptITEyElZVViXE9ffoU3t7eiIuLw8SJE+Hq6oqdO3di5MiR+PfffzF58mQ0a9YMmzdvxgcffIB69eqpLmnY2NiU2udnz54hJSVFrczExAQmJiZYtWoV3N3d0bdvXxgYGOB///sf3nvvPSiVSkyYMKHM57Mi1q9fj+zsbIwbNw4KhQKWlpa4du0aunTpgrp16+Ljjz+GqakpduzYgf79+2P37t0YMGDAC+8nNTUVqampcHNzUyufO3cu5HI5pk+fjpycHMjlcmzYsAHBwcFo3749QkND8fDhQyxduhRnzpzBpUuXUKdOHdX2+fn56NmzJ1577TUsXLgQ4eHhmD17NvLy8jBnzhxVvaVLl6Jv37545513kJubi23btuE///kP9u/fj8DAQLWYfv31V2zfvh2TJk2CQqHAypUr0bNnT/z555/w8PB44b4XGD9+PO7fv4+jR49i8+bNZdZ/+PAhXnvtNdWHtY2NDQ4dOoTRo0cjPT1dNTl43bp1mDRpEgYNGoTJkycjOzsbV65cwblz5zB06NAS209PT8d3332HIUOGYOzYsXjy5Am+//57+Pv7488//1S7LDl69Ghs2LABAQEBGDNmDPLy8nD69Gn88ccfamdbT5w4gR07dmDixImwtraGi4sLrl27hq5du6J27dr48MMPYWhoiDVr1sDb2xu//vorOnbsCOD5H06hoaEYM2YMOnTogPT0dFy4cAGRkZF44403AABvvvkmrl27hvfffx8uLi5ITk7G0aNHkZiYWOLk7vI87z/++COePHmC8ePH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iGoWrc5UZGZmqp2hKPD48WP+mBcREdErSqukomvXrti0aZNqWSaTQalUYuHChejRo4dkwREREVHNodXlj4ULF8LHxwcXLlxAbm4uPvzwQ1y7dg2PHz/GmTNnpI6RiKqJxMREpKSkSNpmdHS0pO0RVcZrytraGk5OTpK3+7LRKqnw8PDAjRs3sHz5cpiZmSEjIwMDBw7EhAkT4ODgIHWMRFQNJCYmoknTZsh+mqXrUIg0yslKBmR6GDZsmORtGxmbIOZ6NBOLMrxwUvHs2TP07NkTq1evxqeffloZMRFRNZSSkoLsp1lo5hMGUws36dq9HYFb5xdJ1h69uvJy0gGhlPw1mpkah+jjU5CSksKkogwvnFQYGhriypUrlRELEdUAphZuMLPxlKy9zNQ4ydoiAqR/jVL5aTVRc9iwYfj++++ljoWIiIhqMK3mVOTl5eGHH37AsWPH0LZt22K/+bF48WJJgiMiIqKa44WSips3b8LFxQVXr15FmzZtAAA3btxQqyOTyaSLjoiIiGqMF0oqGjVqhKSkJERERAB4/rXc3377Lezs7ColOCIiIqo5XmhORdFfIT106BAyMzMlDYiIiIhqpgr99Dl/6pyIiIgKvFBSIZPJis2Z4BwKIiIiAl5wToUQAiNHjlT9aFh2djb++9//Frv74+eff5YuQiIiIqoRXiipCAoKUluujK9CJSIioprphZKK9evXV1YcREREVMNVaKImERERUQEmFURERCSJap9U3Lt3D8OGDYOVlRWMjY3h6emJCxcu6DosIiIiKkKr3/6oKqmpqejSpQt69OiBQ4cOwcbGBrGxsbCwsNB1aERERFREtU4qFixYgPr166tNEHV1ddVhRERERFSSan35Y9++fWjXrh3+85//wNbWFq1bt8a6detK3SYnJwfp6elqDyIiIqp81TqpuHnzJlatWoVGjRrh8OHDePfddzFp0iRs3LixxG1CQ0Nhbm6uetSvX78KIyYiInp1VeukQqlUok2bNpg/fz5at26NcePGYezYsVi9enWJ24SEhCAtLU31uHPnThVGTERE9Oqq1kmFg4MDmjdvrlbWrFkzJCYmlriNQqFA7dq11R5ERERU+ap1UtGlSxfExMSold24cQPOzs46ioiIiIhKUq2Tig8++AB//PEH5s+fj7i4OPz4449Yu3YtJkyYoOvQiIiIqIhqnVS0b98ev/zyC3766Sd4eHhg7ty5CAsLwzvvvKPr0IiIiKiIav09FQDQu3dv9O7dW9dhEBERURmq9ZkKIiIiqjmYVBAREZEkmFQQERGRJJhUEBERkSSYVBAREZEkmFQQERGRJJhUEBERkSSYVBAREZEkmFQQERGRJJhUEBERkSSq/dd0ExERVQfR0dGStmdtbQ0nJydJ29Q1JhVERESlyMlKBmR6GDZsmKTtGhmbIOZ69EuVWDCpICIiKkVeTjoglGjmEwZTCzdJ2sxMjUP08SlISUlhUkFERPSqMbVwg5mNp67DqNY4UZOIiIgkwaSCiIiIJMGkgoiIiCTBpIKIiIgkwaSCiIiIJMGkgoiIiCTBpIKIiIgkwaSCiIiIJMGkgoiIiCTBpIKIiIgkwaSCiIiIJFGjkoqvvvoKMpkMU6ZM0XUoREREVESNSSrOnz+PNWvWoEWLFroOhYiIiDSoEUlFRkYG3nnnHaxbtw4WFha6DoeIiIg0qBFJxYQJExAYGAhfX98y6+bk5CA9PV3tQURERJXPQNcBlGXbtm2IjIzE+fPny1U/NDQUX3zxRSVHRUREREVV6zMVd+7cweTJk7F161YYGRmVa5uQkBCkpaWpHnfu3KnkKImIiAio5mcqLl68iOTkZLRp00ZVlp+fj1OnTmH58uXIycmBvr6+2jYKhQIKhaKqQyUiInrlVeukwsfHB3/99ZdaWXBwMJo2bYqPPvqoWEJBREREulOtkwozMzN4eHiolZmamsLKyqpYOREREelWtZ5TQURERDVHtT5TocnJkyd1HQIRERFpwDMVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCQJJhVEREQkCSYVREREJAkmFURERCSJap9UhIaGon379jAzM4OtrS369++PmJgYXYdFRERERVT7pOLXX3/FhAkT8Mcff+Do0aN49uwZ/Pz8kJmZqevQiIiIqBADXQdQlvDwcLXlDRs2wNbWFhcvXkS3bt10FBUREREVVe2TiqLS0tIAAJaWlhrX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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Output P-Box Bounds\n", "print(f\"Lower Bound Probability of Failure (min Pf): {min(failure_probabilities) * 100:.4f}%\")\n", "print(f\"Upper Bound Probability of Failure (max Pf): {max(failure_probabilities) * 100:.4f}%\")\n", "\n", "plt.figure(figsize=(6, 4))\n", "plt.hist(failure_probabilities, bins=20, color='royalblue', edgecolor='black')\n", "plt.title(\"Distribution of Failure Probabilities across the Credal Set\")\n", "plt.xlabel(\"Probability of Failure ($P_f$)\")\n", "plt.ylabel(\"Frequency\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "b65232bc-e4cc-4f4a-88b4-78a53ec35df7", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "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.8" } }, "nbformat": 4, "nbformat_minor": 5 }