pyiron_ontology - pyiron的模块扩展。
项目描述
pyiron_ontology
概述
pyiron_ontology
是一个基于 owlready2
的 pyiron 项目,用于利用本体论进行引导型工作流设计和动态(使用型)类型。
从哲学上讲,pyiron_ontology
将本体论的建设分解为两部分:一组适用于所有 pyiron_ontology
本体的“通用”类,用于描述工作流程的核心元素,以及一组“特定领域”的实例声明(大多数或全部)定义了不同代码片段之间的关系。
安装和设置
pyiron_ontology
可通过克隆、pip安装或在conda(推荐)中从Conda Forge安装,命令为 conda install -c conda-forge pyiron_ontology
。
pyiron_ontology
使用 owlready2
,它需要 Java。如果您尝试运行并遇到关于找不到 Java 的 owlready2
错误,您可能需要设置 Java 路径(请参考 owlready2 文档):import owlready2; owlready2.JAVA_EXE = "C:\\path\\to\\java.exe"
。
Java 还可以通过 conda install -c conda-forge openjdk
获取。安装此软件包并从干净的终端重新启动您的 jupyter 会话可能就足够了。
通用声明
我们使用基于图的范式来表示工作流程,这样它们由有向图上的节点组成。每个节点被认为是具有输入和输出的,并且它们可以连接到其他节点的输出/输入(甚至可以连接到自身)。在这些类中移动的数据,即任何输入或输出,都由通用数据类的子类表示(这些类在特定领域的声明中定义和细化)。
这些类的结构,以及一些关键方法
classDiagram
class PyironOntoThing
PyironOntoThing: get_sources()
<<Abstract>> PyironOntoThing
WorkflowThing <|--PyironOntoThing
<<Abstract>> WorkflowThing
Parameter <|--PyironOntoThing
<<Abstract>> Parameter
Function <|--WorkflowThing
IO <|--Parameter
IO <|--WorkflowThing
<<Abstract>> IO
Input <|--IO
Output <|--IO
Generic <|--Parameter
Generic: is_representable_by()
Generic: is_more_specific_than()
以下关键关系
erDiagram
Function ||--|{ Input : optional_inputs
Function ||--o{ Input : mandatory_inputs
Function ||--|{ Output : outputs
Input |{--|| Generic : generic
Output |{--|| Generic : generic
Input ||--o{ Generic: req
Input ||--o{ Generic: transitive_req
get_sources
方法利用本体让个体看到它在知识空间中的来源;Output
的来源是 Function
,Function
的来源是其必选的 Input
,而 Input
和 Generic
都有 Output
作为来源。
通过图中的 Generic
将来源约束传递为直接 requirements
(有关 generic
的更多详细信息)和 transitive_requirements
(不继承自 generic
的 Generic
要求,应进一步向上游传递)。
这使得我们能够通过确保上游 WorkflowThing
个体始终满足工作流程中每项输入的(传递)要求来构建所有可能的工作流程。
特定领域的声明
特定领域声明的核心任务是继承 Generic
以创建以类形式存在的知识体系,并实例化 Function
、Input
和 Output
类来创建代表可用计算的个体。
这里的一个挑战是我们经常想在 Generic
数据类型中描述互斥性。例如,考虑一个原子结构。我们可能希望将其赋予互斥属性,例如具有晶界或位错 XOR 类似于体心。不幸的是,OWL 框架没有很好地处理这种互斥性。我能找到的最佳文档是 这篇 W3C 博文,它概述了两种可能的途径——一种使用个体,另一种使用类。在这里,我们使用基于类的方法。也就是说,在我们的例子中,您的 Structure
子类可以继承自 HasGrainBoundary
和/或 HasDislocation
,但这些与 Bulk
是互斥的(AllDisjoint
)。在 owlready2
的术语中,我们可以使用 is_a
来定义一个多继承方案以明确我们 Generic
的所有细节,但如果我们试图从两个互斥(互斥)的类继承,我们的推理器将失败并告诉我们问题。
实例化Function
、Input
和Output
个体相对简单。这些个体只需通过上述Generic
类的实例来填充它们的generic
、requirements
和transitive_requirements
,并使用彼此填充其他字段。主要思想是构建本体来表示现有代码库中的现有功能,然后进行本体推理以搜索可用的工作流程,但您可能也会发现进行一些“本体驱动设计”很有用,即首先在本体中编写您想要的某种功能,然后再编写符合本体设计规范的相关代码。在ironflow中,我们正在努力将这些概念结合起来,在本体类型与我们的基于图的可视化脚本中的节点及其子组件之间建立明确的关联。
示例
以下是一个使用Constructor
类构建烘焙披萨工作流程本体的示例。您可以在演示笔记本pizza.ipynb
中交互式地使用它。
>>> import owlready2 as owl
>>> from pyiron_ontology import Constructor
>>>
>>> c = Constructor('pizza')
>>>
>>> # Knowledge base
>>> with c.onto:
... class Flour(c.onto.Generic): pass
... class Wheat(Flour): pass
... class GlutenFree(Flour): pass
... _ = owl.AllDisjoint([GlutenFree, Wheat])
...
... class Crust(c.onto.Generic): pass
... class Thin(Crust): pass
... class Regular(Crust): pass
... _ = owl.AllDisjoint([Thin, Regular])
... class Stuffed(Regular): pass
...
... class Ingredients(c.onto.Generic): pass
... class HasVegetables(Ingredients): pass
... class HasMushrooms(HasVegetables): pass
... class HasPeppers(HasVegetables): pass
... class HasMeat(Ingredients): pass
... class HasSalami(HasMeat): pass
... class HasBacon(HasMeat): pass
... class Vegetarian(Ingredients):
... equivalent_to = [Ingredients & owl.Not(HasMeat)]
... _ = owl.AllDisjoint([Vegetarian, HasMeat])
...
... class RawPizza(c.onto.Generic): pass
...
... class CookedPizza(c.onto.Generic): pass
...
... _ = owl.AllDisjoint([Flour, Crust, Ingredients, RawPizza, CookedPizza])
>>>
>>> # Code base
>>> buy_wheat_flour = c.onto.Function("buy_wheat_flour")
>>> buy_wheat_flour_out = c.onto.Output(
... "buy_wheat_flour_out",
... output_of=buy_wheat_flour,
... generic=Wheat()
... )
>>>
>>> buy_corn_flour = c.onto.Function("buy_corn_flour")
>>> buy_corn_flour_out = c.onto.Output(
... "buy_corn_flour_out",
... output_of=buy_corn_flour,
... generic=GlutenFree()
... )
>>>
>>> make_crust = c.onto.Function("make_crust")
>>> make_crust_inp_flour = c.onto.Input(
... name="make_crust_inp_flour",
... mandatory_input_of=make_crust,
... generic=Flour(),
... )
>>> make_crust_out = c.onto.Output(
... name="make_crust_out",
... output_of=make_crust,
... generic=Crust(),
... )
>>>
>>> make_thin_crust = c.onto.Function("make_thin_crust")
>>> make_thin_crust_inp_flour = c.onto.Input(
... name="make_thin_crust_inp_flour",
... mandatory_input_of=make_thin_crust,
... generic=Flour(),
... )
>>> make_thin_crust_out = c.onto.Output(
... name="make_thin_crust_out",
... output_of=make_thin_crust,
... generic=Thin(),
... )
>>> make_gluten_free_crust = c.onto.Function("make_gluten_free_crust")
>>> make_gluten_free_crust_inp_flour = c.onto.Input(
... name="make_gluten_free_crust_inp_flour",
... mandatory_input_of=make_gluten_free_crust,
... generic=GlutenFree(),
... )
>>> make_gluten_free_crust_out = c.onto.Output(
... name="make_gluten_free_crust_out",
... output_of=make_gluten_free_crust,
... generic=Crust(),
... )
>>>
>>> add_meat = c.onto.Function("add_meat")
>>> add_meat_inp_ingredients = c.onto.Input(
... name="add_meat_inp_ingredients",
... mandatory_input_of=add_meat,
... generic=HasMeat(),
... )
>>> add_meat_inp_crust = c.onto.Input(
... name="add_meat_inp_crust",
... mandatory_input_of=add_meat,
... generic=Crust(),
... transitive_requirements=[Flour()]
... )
>>> add_meat_out = c.onto.Output(
... name="add_meat_out",
... output_of=add_meat,
... generic=RawPizza()
... )
>>>
>>> add_vegetables = c.onto.Function("add_vegetables")
>>> add_vegetables_inp_ingredients = c.onto.Input(
... name="add_vegetables_inp_ingredients",
... mandatory_input_of=add_vegetables,
... generic=HasVegetables(),
... )
>>> add_vegetables_inp_crust = c.onto.Input(
... name="add_vegetables_inp_crust",
... mandatory_input_of=add_vegetables,
... generic=Crust(),
... transitive_requirements=[Flour()]
... )
>>> add_vegetables_out = c.onto.Output(
... name="add_vegetables_out",
... output_of=add_vegetables,
... generic=RawPizza()
... )
>>>
>>> canadian = c.onto.Function("canadian")
>>> canadian_inp_ingredients = c.onto.Input(
... name="canadian_inp_ingredients",
... mandatory_input_of=canadian,
... generic=Ingredients(is_a=[HasBacon, HasMushrooms]),
... )
>>> canadian_inp_crust = c.onto.Input(
... name="canadian_inp_crust",
... mandatory_input_of=canadian,
... generic=Crust(),
... transitive_requirements=[Flour()]
... )
>>> canadian_out = c.onto.Output(
... name="canadian_out",
... output_of=canadian,
... generic=RawPizza()
... )
>>>
>>> bake_for_omnivor = c.onto.Function("bake_for_omnivor")
>>> bake_for_omnivor_inp = c.onto.Input(
... name="bake_for_omnivor_inp",
... mandatory_input_of=bake_for_omnivor,
... generic=RawPizza(),
... )
>>> bake_for_omnivor_out = c.onto.Output(
... name="bake_for_omnivor_out",
... output_of=bake_for_omnivor,
... generic=CookedPizza()
... )
>>>
>>> bake_for_vegetarian = c.onto.Function("bake_for_vegetarian")
>>> bake_for_vegetarian_inp = c.onto.Input(
... name="bake_for_vegetarian_inp",
... mandatory_input_of=bake_for_vegetarian,
... generic=RawPizza(),
... requirements=[Vegetarian()]
... )
>>> bake_for_vegetarian_out = c.onto.Output(
... name="bake_for_vegetarian_out",
... output_of=bake_for_vegetarian,
... generic=CookedPizza()
... )
>>>
>>> bake_stuffed_crust = c.onto.Function("bake_stuffed_crust")
>>> bake_stuffed_crust_inp = c.onto.Input(
... name="bake_stuffed_crust_inp",
... mandatory_input_of=bake_stuffed_crust,
... generic=RawPizza(),
... requirements=[Stuffed(), Wheat()]
... )
>>> bake_stuffed_crust_out = c.onto.Output(
... name="bake_stuffed_crust_out",
... output_of=bake_stuffed_crust,
... generic=CookedPizza()
... )
>>>
>>> bake_dietary_restrictions = c.onto.Function("bake_dietary_restrictions")
>>> bake_dietary_restrictions_inp = c.onto.Input(
... name="bake_dietary_restrictions_inp",
... mandatory_input_of=bake_dietary_restrictions,
... generic=RawPizza(),
... requirements=[GlutenFree(), Vegetarian()]
... )
>>> bake_dietary_restrictions_out = c.onto.Output(
... name="bake_dietary_restrictions_out",
... output_of=bake_dietary_restrictions,
... generic=CookedPizza()
... )
>>>
>>> c.sync()
>>>
>>> bake_for_vegetarian_out.get_source_tree().render()
bake_for_vegetarian_out
bake_for_vegetarian
bake_for_vegetarian_inp
add_vegetables_out
add_vegetables
add_vegetables_inp_crust
make_crust_out
make_crust
make_crust_inp_flour
buy_corn_flour_out
buy_corn_flour
buy_wheat_flour_out
buy_wheat_flour
make_gluten_free_crust_out
make_gluten_free_crust
make_gluten_free_crust_inp_flour
buy_corn_flour_out
buy_corn_flour
make_thin_crust_out
make_thin_crust
make_thin_crust_inp_flour
buy_corn_flour_out
buy_corn_flour
buy_wheat_flour_out
buy_wheat_flour
add_vegetables_inp_ingredients
注意:我们的bake_for_vegetarian
有一个输入需求Vegetarian()
,当我们选择配料时,确实只得到使用add_vegetables
的工作流程。这个函数的输入指定了通用类型为HasVegetables()
。如果我们回过头来看我们的知识库,我们会看到Vegetarian
和HasVegetables
之间没有直接关系。相反,当我们调用sync()
时,推理器使用Vegetarian
的等价定义推断出个体HasVegetables
是Vegetarian
!定义映射到(假设的)代码库的所有个体相当冗长(我们将努力改进这一点!),但这只是一个有点愚蠢的例子,但它仍然突出了利用本体描述知识库的强大和灵活性。
对现有的pyiron_atomistics
数据进行推理
pyiron_ontology
还附带了一个为(一小部分)pyiron_atomistics
定义的本体(一个可选的依赖项)。
例如,如果您在pyiron项目中拥有Murnaghan
工作,以下代码段将返回一个结果数据框
>>> import pyiron_ontology as po
>>> from pyiron_ontology import AtomisticsReasoner
>>> from pyiron_atomistics import Project
>>>
>>> onto = po.dynamic.atomistics()
>>> reasoner = AtomisticsReasoner(onto)
>>> pr = Project('your_project_tree_with_loads_of_data')
>>>
>>> out = reasoner.search_database_for_property(onto.BulkModulus(), pr)
>>> out.columns
Index(['Chemical Formula', 'atomistics.BulkModulus', 'unit', 'Engine'], dtype='object')
项目详情
下载文件
下载您平台上的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。
源分布
构建分布
pyiron_ontology-0.2.7.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | c3525f1f8c0892a25afbf1e1b84988a0469a9765f3a2773c202162d308709ab5 |
|
MD5 | 23533e2cf967d457dff32b2c9e682ada |
|
BLAKE2b-256 | 86b714a2785d1afeac66ccf175a337739921c8f404a7aa456ac93c7f89f9f7ec |