Subtypes in ProtoScript are a powerful feature that enables dynamic reclassification of Prototypes at runtime, allowing them to adopt more specific types based on context-sensitive conditions. Unlike traditional ontologies, which rely on static class hierarchies, Subtypes use runtime-evaluated functions to categorize Prototypes, making ProtoScript’s graph-based ontology exceptionally adaptive and flexible. Building on Shadows and Prototype Paths, Subtypes refine ProtoScript’s unsupervised learning by creating precise, ad-hoc categories that evolve with the data. This section explains Subtypes, their syntax, mechanics, and significance, using clear analogies, step-by-step examples, and practical applications to ensure developers familiar with C# or JavaScript can grasp their role in dynamic ontology reasoning.
Subtypes are a cornerstone of ProtoScript’s dynamic ontology, enabling:
- Dynamic Categorization: Reclassify Prototypes into specific subtypes (e.g., “in-stock items”) based on runtime conditions, without predefined schemas.
- Unsupervised Learning Refinement: Leverage Shadows and Paths to create and apply new categories, enhancing ProtoScript’s ability to learn from data without labeled inputs.
- Flexible Reasoning: Support context-sensitive queries and transformations (e.g., identifying all “parents” in a family ontology).
- Cross-Domain Adaptability: Apply Subtypes across domains (e.g., code, natural language), unifying diverse data types in the graph.
Significance in ProtoScript’s Ontology:
- Core Learning Mechanism: Subtypes, alongside Shadows and Paths, complete ProtoScript’s unsupervised learning cycle, allowing the system to generalize (Shadows), specify differences (Paths), and categorize dynamically (Subtypes).
- Scalable and Interpretable: Subtypes use bounded graph traversals and reuse cached Shadow/Path results, keeping categorization explainable.
- Context-Sensitive: By evaluating conditions at runtime, Subtypes adapt to evolving data, making them ideal for real-world, dynamic ontologies.
Subtypes categorize Prototypes dynamically through graph traversals, providing runtime flexibility without the static class definitions or external inference engines used in traditional ontology stacks.
For C# developers:
- Subtypes are like dynamically applying an interface to an object at runtime based on a condition, but with the ability to create the interface on-the-fly.
- Think of Subtypes as a LINQ query that filters objects into a new category (e.g., “parents”) based on runtime properties.
For JavaScript developers:
- Subtypes resemble adding a new prototype to an object dynamically, based on its properties, within a graph structure.
- They’re like filtering JSON objects into a new group using a runtime condition.
For database developers:
- Subtypes are like creating a dynamic view in a database that groups records based on a query, but integrated into the graph.
- Think of Subtypes as a graph query that tags nodes with a new type based on their properties.
A Subtype in ProtoScript is a Prototype that defines a dynamic category, applied to other Prototypes at runtime if they satisfy a categorization function. Unlike static inheritance (e.g., prototype Child : Parent), Subtypes are evaluated dynamically using the IsCategorized function, which checks properties and relationships via the -> operator. Subtypes:
- Reclassify Prototypes: Add a new type to a Prototype’s inheritance chain (e.g., making a
PersonaParent). - Leverage Shadows: Use generalized structures from Shadows to define subtype conditions.
- Integrate Paths: Identify divergent properties to refine categorization.
Subtypes are defined with the [SubType] annotation and an IsCategorized function, executed by the runtime to determine membership:
- Definition: Create a Subtype Prototype with
[SubType]and anIsCategorizedfunction. - Categorization: The runtime tests a Prototype against the Subtype using
->and the function’s conditions. - Reclassification: If the Prototype satisfies the conditions, the runtime adds the Subtype to its inheritance chain via an
isaedge. - Application: Use the Subtype for queries, transformations, or further reasoning.
Syntax:
[SubType]
prototype SubtypeName : Parent {
function IsCategorized(Parent proto) : bool {
return proto \-\> Parent { /\* Conditions \*/ };
}
}
C# Analogy: Like defining a dynamic interface with a method to check if an object qualifies, but integrated into the graph and applied at runtime.
Scenario: Define a Subtype for “initialized integer variables” and apply it to int i = 0.
Shadow Reference (from previous section):
prototype InitializedIntVariable : CSharp_VariableDeclaration {
Type.TypeName \= "int";
Type.IsNullable \= false;
VariableName \= "";
Initializer \= new CSharp\_Expression();
}
Subtype Definition:
prototype CSharp_VariableDeclaration {
CSharp\_Type Type \= new CSharp\_Type();
string VariableName \= "";
CSharp\_Expression Initializer \= new CSharp\_Expression();
}
prototype CSharp_Type {
string TypeName \= "";
bool IsNullable \= false;
}
prototype CSharp_Expression {
string Value \= "";
}
[SubType]
prototype InitializedIntVariable_SubType : CSharp_VariableDeclaration {
function IsCategorized(CSharp\_VariableDeclaration var) : bool {
return var \-\> CSharp\_VariableDeclaration {
this.Type.TypeName \== "int" &&
this.Type.IsNullable \== false &&
this.Initializer \!= new CSharp\_Expression()
};
}
}
Application:
prototype Int_Declaration_I : CSharp_VariableDeclaration {
Type.TypeName \= "int";
VariableName \= "i";
Initializer \= IntegerLiteral\_0;
}
prototype IntegerLiteral_0 : CSharp_Expression {
Value \= "0";
}
Note: The following snippet is conceptual pseudocode. The actual runtime API is very similar and equivalent in behavior; treat this as an explanatory representation of the operation.
UnderstandUtil.SubType(Int_Declaration_I, _interpreter);
What’s Happening?
InitializedIntVariable_SubTypedefines a category for non-nullableintvariables with an initializer.IsCategorizedchecks if a Prototype hasTypeName = "int",IsNullable = false, and a non-defaultInitializer.- The runtime call
UnderstandUtil.SubTypetestsInt_Declaration_I, addingInitializedIntVariable_SubTypeto its inheritance chain if it passes. - Graph View:
Int_Declaration_Igains anisaedge toInitializedIntVariable_SubType. - Use Case: Enables queries like “find all initialized integer variables” or transformations (e.g., to another language).
Subtypes dynamically reclassify Prototypes, leveraging Shadows for unsupervised categorization, rather than relying on static class membership in OWL.
Scenario: Define a Subtype for “parents in the Simpsons’ house” and apply it to Homer.
Shadow Reference (SimpsonsHouseParent):
prototype SimpsonsHouseParent : Person {
Name \= "";
Gender \= "";
Location \= SimpsonsHouse;
ParentOf \= \[Bart, Lisa, Maggie\];
Spouse \= new Person();
Age \= 0;
}
Subtype Definition:
prototype Person {
string Name \= "";
string Gender \= "";
Location Location \= new Location();
Collection ParentOf \= new Collection();
Person Spouse \= new Person();
int Age \= 0;
}
prototype Location {
string Name \= "";
}
prototype SimpsonsHouse : Location {
Name \= "Simpsons House";
}
[SubType]
prototype SimpsonsHouseParent_SubType : Person {
function IsCategorized(Person person) : bool {
return person \-\> Person {
this.Location.Name \== "Simpsons House" &&
this.ParentOf.Count \> 0
};
}
}
Application:
prototype Homer : Person {
Name \= "Homer Simpson";
Gender \= "Male";
Location \= SimpsonsHouse;
ParentOf \= \[Bart, Lisa, Maggie\];
Spouse \= Marge;
Age \= 39;
}
prototype Marge : Person {
Name \= "Marge Simpson";
}
UnderstandUtil.SubType(Homer, _interpreter);
What’s Happening?
SimpsonsHouseParent_SubTypecategorizesPersonPrototypes living inSimpsonsHousewith at least one child.IsCategorizeduses->to checkLocation.NameandParentOf.Count.Homerpasses, gainingSimpsonsHouseParent_SubTypein its inheritance chain.- Graph View:
Homerlinks toSimpsonsHouseParent_SubTypevia anisaedge. - Use Case: Supports queries like “who are the parents in the Simpsons’ house?” or transformations (e.g., generating a family report).
Subtypes enable context-sensitive categorization, adapting to runtime data instead of predefined classes.
Scenario: Define a Subtype for “integer data elements” across C# variables and database columns.
Shadow Reference (IntDataElement):
prototype IntDataElement {
string Name \= "";
string Type \= "int";
}
Subtype Definition:
prototype DataElement {
string Name \= "";
string Type \= "";
}
[SubType]
prototype IntDataElement_SubType : DataElement {
function IsCategorized(DataElement elem) : bool {
return elem \-\> DataElement {
this.Type \== "int"
};
}
}
Application:
prototype CSharp_VariableDeclaration : DataElement {
string Name \= "";
string Type \= "";
}
prototype Database_Column : DataElement {
string Name \= "";
string Type \= "";
}
prototype Int_Declaration_I : CSharp_VariableDeclaration {
Name \= "i";
Type \= "int";
}
prototype ID_Column : Database_Column {
Name \= "ID";
Type \= "int";
}
UnderstandUtil.SubType(Int_Declaration_I, _interpreter);
UnderstandUtil.SubType(ID_Column, _interpreter);
What’s Happening?
IntDataElement_SubTypecategorizesDataElementPrototypes withType = "int".- Both
Int_Declaration_IandID_Columnpass, gainingIntDataElement_SubType. - Graph View:
Int_Declaration_IandID_Columnlink toIntDataElement_SubTypeviaisaedges. - Use Case: Enables cross-domain queries (e.g., “find all integer data elements”) or transformations (e.g., mapping a variable to a column).
Subtypes unify code and database domains dynamically, avoiding the separation found in static ontology models.
Subtypes build on prior learning mechanisms:
- Shadows: Provide the generalized structure (e.g.,
InitializedIntVariable) that Subtypes use as a template for categorization. - Paths: Identify divergent properties (e.g.,
VariableName = "i") that Subtypes can evaluate or transform. - Example: The
SimpsonsHouseParent_SubTypeleverages theSimpsonsHouseParentShadow, with Paths isolatingNameorGenderfor specific queries.
The ProtoScript runtime manages Subtypes:
- Definition: Stores the
[SubType]Prototype and itsIsCategorizedfunction. - Evaluation: Executes
IsCategorizedvia->, traversing the Prototype’s graph to check conditions. - Reclassification: Adds an
isaedge to the Subtype if conditions are met. - Scalability: Efficient traversals and pruning ensure performance, even with complex ontologies.
Subtypes:
- Enhance Learning: Refine Shadows and Paths by creating precise, context-sensitive categories.
- Enable Dynamic Reasoning: Support runtime queries and transformations without static schemas.
- Unify Domains: Apply consistent categorization across code, data, and language.
- Maintain Interpretability: Use explicit graph traversals, traceable unlike neural networks.
Structural Contrast with Gradient Descent: Subtypes offer a deterministic, unsupervised alternative, leveraging graph structures for scalability and clarity.
Subtypes empower ProtoScript’s ontology with dynamic, context-sensitive categorization, building on Shadows and Paths to create a robust unsupervised learning framework.
Previous: Prototype Paths and Parameterization | Next: Transformation Functions