Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions include/qubit/qmath_fabric.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#pragma once

#include "qubit/qmath_language.hpp"
#include "qubit/qrepresentation_compiler.hpp"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <span>
#include <string>
#include <utility>
#include <vector>

namespace qubit {

struct QMathFabricChannelBinding {
std::string dependency{};
QubitId channel{0U};

friend bool operator==(const QMathFabricChannelBinding&, const QMathFabricChannelBinding&) = default;
};

struct QMathFabricBindingReceipt {
QMathLanguageRoute route{QMathLanguageRoute::Symbolic};
QMathFidelity fidelity{QMathFidelity::Unverified};
ExactRepresentationDependencyType dependency_type{0U};
std::vector<QMathFabricChannelBinding> bindings{};
std::size_t component{0U};
std::size_t generation{0U};
std::size_t numerical_generation{0U};
std::size_t declared_dependencies_before{0U};
std::size_t declared_dependencies_after{0U};
std::size_t component_merges{0U};
bool prior_component_known{false};
bool numerical_generation_preserved{false};
bool exact{false};
bool structural_dependency{true};
std::string source_canonical{};
};

class QMathRepresentationFabricBridge {
public:
[[nodiscard]] static QMathFabricBindingReceipt bind(
ExactRepresentationFabric& fabric,
const QMathLanguageCompilation& source,
std::span<const QMathFabricChannelBinding> bindings) {
require_supported(source);
if (bindings.size() != source.receipt.dependencies.size() || bindings.size() < 2U) {
throw QMathError("QMath fabric binding must cover every source dependency exactly once");
}

std::vector<QubitId> support;
support.reserve(bindings.size());
for (std::size_t index = 0U; index < bindings.size(); ++index) {
if (bindings[index].dependency != source.receipt.dependencies[index]) {
throw QMathError("QMath fabric binding dependency order or identity changed");
}
support.push_back(bindings[index].channel);
}
std::vector<QubitId> normalized = support;
std::sort(normalized.begin(), normalized.end());
if (std::adjacent_find(normalized.begin(), normalized.end()) != normalized.end()) {
throw QMathError("QMath fabric binding maps distinct dependencies onto one channel");
}

const ExactRepresentationDependencyType type = dependency_type(source.receipt.route);
const std::vector<ExactRepresentationDependencyReceipt> before_dependencies = fabric.dependency_receipts();
for (const ExactRepresentationDependencyReceipt& receipt : before_dependencies) {
if (receipt.type == type && receipt.support == normalized) {
throw QMathError("QMath fabric dependency is already bound");
}
}
const std::optional<ExactRepresentationComponentReceipt> prior =
component_for_support(fabric, before_dependencies, normalized);
const ExactRepresentationFabricStats before = fabric.stats();

fabric.declare_dependency(type, support);

const ExactRepresentationFabricStats after = fabric.stats();
const std::vector<ExactRepresentationDependencyReceipt> dependency_receipts = fabric.dependency_receipts();
const ExactRepresentationDependencyReceipt* added = nullptr;
for (const ExactRepresentationDependencyReceipt& receipt : dependency_receipts) {
if (receipt.type == type && receipt.support == normalized) {
if (added != nullptr) {
throw QMathError("QMath fabric dependency identity became ambiguous");
}
added = &receipt;
}
}
if (added == nullptr || after.declared_dependencies != before.declared_dependencies + 1U) {
throw QMathError("QMath fabric did not retain the declared typed dependency");
}

QMathFabricBindingReceipt result;
result.route = source.receipt.route;
result.fidelity = source.receipt.evidence.fidelity;
result.dependency_type = type;
result.bindings.assign(bindings.begin(), bindings.end());
result.component = added->component;
result.generation = added->generation;
result.numerical_generation = added->numerical_generation;
result.declared_dependencies_before = before.declared_dependencies;
result.declared_dependencies_after = after.declared_dependencies;
result.component_merges = after.component_merges - before.component_merges;
result.prior_component_known = prior.has_value();
result.numerical_generation_preserved = prior.has_value() &&
prior->component == added->component &&
prior->numerical_generation == added->numerical_generation;
result.exact = source.receipt.exact;
result.source_canonical = source.receipt.canonical;
return result;
}

[[nodiscard]] static constexpr ExactRepresentationDependencyType dependency_type(
QMathLanguageRoute route) {
switch (route) {
case QMathLanguageRoute::StrictOrder:
return 0x514D415448000001ULL;
case QMathLanguageRoute::AffineRelation:
return 0x514D415448000002ULL;
case QMathLanguageRoute::HornLogic:
return 0x514D415448000003ULL;
default:
throw QMathError("QMath language route has no persistent fabric dependency contract");
}
}

private:
static void require_supported(const QMathLanguageCompilation& source) {
if (!source.receipt.exact || !source.receipt.transform_ready ||
!source.receipt.evidence.exact_structure()) {
throw QMathError("QMath fabric requires exact structured mathematical-language evidence");
}
(void)dependency_type(source.receipt.route);
}

[[nodiscard]] static std::optional<ExactRepresentationComponentReceipt> component_for_support(
const ExactRepresentationFabric& fabric,
std::span<const ExactRepresentationDependencyReceipt> dependencies,
std::span<const QubitId> support) {
std::optional<std::size_t> component;
for (const QubitId channel : support) {
std::optional<std::size_t> channel_component;
for (const ExactRepresentationDependencyReceipt& dependency : dependencies) {
if (std::binary_search(dependency.support.begin(), dependency.support.end(), channel)) {
if (channel_component.has_value() && *channel_component != dependency.component) {
throw QMathError("QMath fabric dependency receipts disagree on channel component");
}
channel_component = dependency.component;
}
}
if (!channel_component.has_value()) return std::nullopt;
if (component.has_value() && *component != *channel_component) return std::nullopt;
component = channel_component;
}
if (!component.has_value()) return std::nullopt;
for (const ExactRepresentationComponentReceipt& receipt : fabric.component_receipts()) {
if (receipt.component == *component) return receipt;
}
throw QMathError("QMath fabric component receipt is missing");
}
};

} // namespace qubit
121 changes: 119 additions & 2 deletions tests/test_qlogic.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "qubit/qmath_language.hpp"
#include "qubit/qmath_fabric.hpp"

#include <iostream>
#include <stdexcept>
Expand Down Expand Up @@ -152,5 +152,122 @@ int main() {
}
require(rejected, "Horn rule cap did not fail closed");

std::cout << "QHorn logic tests passed\n";
QStrictOrder order;
const auto order_a = order.add_symbol("A");
const auto order_b = order.add_symbol("B");
const auto order_c = order.add_symbol("C");
require(order.add_before(order_a, order_b) && order.add_before(order_b, order_c),
"fabric strict-order fixture was not admitted");
const QMathLanguageCompilation order_language = QMathLanguageCompiler::compile(order);

ExactRepresentationFabric fabric(8U);
const std::vector<QMathFabricChannelBinding> order_bindings{
{"A", 0U},
{"B", 1U},
{"C", 2U},
};
const QMathFabricBindingReceipt order_binding =
QMathRepresentationFabricBridge::bind(fabric, order_language, order_bindings);
require(order_binding.route == QMathLanguageRoute::StrictOrder &&
order_binding.dependency_type == QMathRepresentationFabricBridge::dependency_type(QMathLanguageRoute::StrictOrder) &&
order_binding.declared_dependencies_before == 0U &&
order_binding.declared_dependencies_after == 1U &&
!order_binding.prior_component_known && !order_binding.numerical_generation_preserved &&
order_binding.exact && order_binding.structural_dependency &&
order_binding.source_canonical == order_language.receipt.canonical,
"QMath fabric lost strict-order binding identity or first-bind receipt");

QHornLogic shared_logic;
const auto logic_a = shared_logic.add_atom("A");
const auto logic_b = shared_logic.add_atom("B");
const auto logic_c = shared_logic.add_atom("C");
require(shared_logic.add_fact(logic_a, true), "fabric Horn fixture fact was not admitted");
const std::vector<QHornLogic::Literal> logic_rule_ab{{logic_a, true}};
const std::vector<QHornLogic::Literal> logic_rule_bc{{logic_b, true}};
require(shared_logic.add_rule(logic_rule_ab, {logic_b, true}) &&
shared_logic.add_rule(logic_rule_bc, {logic_c, true}),
"fabric Horn fixture rules were not admitted");
const QMathLanguageCompilation shared_logic_language = QMathLanguageCompiler::compile(shared_logic);
const QMathFabricBindingReceipt logic_binding =
QMathRepresentationFabricBridge::bind(fabric, shared_logic_language, order_bindings);
require(logic_binding.route == QMathLanguageRoute::HornLogic &&
logic_binding.component == order_binding.component &&
logic_binding.prior_component_known && logic_binding.numerical_generation_preserved &&
logic_binding.numerical_generation == order_binding.numerical_generation &&
logic_binding.generation > order_binding.generation &&
logic_binding.component_merges == 0U &&
logic_binding.declared_dependencies_after == 2U,
"QMath fabric metadata-only typed dependency changed numerical generation");

QAffineRelationSpace separate_relation(2U);
const auto relation_x = separate_relation.add_symbol("X");
const auto relation_y = separate_relation.add_symbol("Y");
const QAffineRelationSpace::Displacement relation_delta{QRational(1), QRational(-1)};
require(separate_relation.add_difference(relation_x, relation_y, relation_delta),
"fabric affine fixture relation was not admitted");
const QMathLanguageCompilation relation_language = QMathLanguageCompiler::compile(separate_relation);
const std::vector<QMathFabricChannelBinding> relation_bindings{
{"X", 3U},
{"Y", 4U},
};
const QMathFabricBindingReceipt relation_binding =
QMathRepresentationFabricBridge::bind(fabric, relation_language, relation_bindings);
require(relation_binding.component != order_binding.component &&
fabric.stats().active_components == 2U && relation_binding.component_merges == 0U,
"QMath fabric failed to preserve independent mathematical islands");

QHornLogic bridge_logic;
const auto bridge_a = bridge_logic.add_atom("A");
const auto bridge_x = bridge_logic.add_atom("X");
require(bridge_logic.add_fact(bridge_a, true), "fabric bridge fact was not admitted");
const std::vector<QHornLogic::Literal> bridge_rule{{bridge_a, true}};
require(bridge_logic.add_rule(bridge_rule, {bridge_x, true}),
"fabric bridge rule was not admitted");
const QMathLanguageCompilation bridge_language = QMathLanguageCompiler::compile(bridge_logic);
const std::vector<QMathFabricChannelBinding> bridge_bindings{
{"A", 0U},
{"X", 3U},
};
const QMathFabricBindingReceipt bridge_binding =
QMathRepresentationFabricBridge::bind(fabric, bridge_language, bridge_bindings);
require(bridge_binding.component_merges == 1U &&
!bridge_binding.prior_component_known && !bridge_binding.numerical_generation_preserved &&
fabric.stats().active_components == 1U,
"QMath fabric did not merge exactly the typed cross-island dependency closure");

rejected = false;
try {
(void)QMathRepresentationFabricBridge::bind(fabric, order_language, order_bindings);
} catch (const QMathError&) {
rejected = true;
}
require(rejected, "QMath fabric accepted a duplicate typed dependency binding");

const std::vector<QMathFabricChannelBinding> aliased_bindings{
{"A", 5U},
{"B", 5U},
{"C", 6U},
};
rejected = false;
try {
ExactRepresentationFabric alias_fabric(8U);
(void)QMathRepresentationFabricBridge::bind(alias_fabric, order_language, aliased_bindings);
} catch (const QMathError&) {
rejected = true;
}
require(rejected, "QMath fabric accepted an aliased semantic dependency channel mapping");

QMathArena symbolic_math;
const auto symbolic = symbolic_math.symbol("z", QMathType::scalar_type());
const QMathLanguageCompilation symbolic_language = QMathLanguageCompiler::compile(symbolic, symbolic_math);
const std::vector<QMathFabricChannelBinding> symbolic_bindings{{"z", 7U}};
rejected = false;
try {
(void)QMathRepresentationFabricBridge::bind(fabric, symbolic_language, symbolic_bindings);
} catch (const QMathError&) {
rejected = true;
}
require(rejected, "QMath fabric accepted an unsupported symbolic route as a dependency fabric program");

std::cout << "QHorn logic and mathematical fabric tests passed\n";
}
Loading