跳转到主要内容

pyiron_ontology - pyiron的模块扩展。

项目描述

pyiron_ontology

Binder License Codacy Badge Coverage Status

Anaconda Last Updated Platform Downloads

概述

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 的来源是 FunctionFunction 的来源是其必选的 Input,而 InputGeneric 都有 Output 作为来源。

通过图中的 Generic 将来源约束传递为直接 requirements(有关 generic 的更多详细信息)和 transitive_requirements(不继承自 genericGeneric 要求,应进一步向上游传递)。

这使得我们能够通过确保上游 WorkflowThing 个体始终满足工作流程中每项输入的(传递)要求来构建所有可能的工作流程。

特定领域的声明

特定领域声明的核心任务是继承 Generic 以创建以类形式存在的知识体系,并实例化 FunctionInputOutput 类来创建代表可用计算的个体。

这里的一个挑战是我们经常想在 Generic 数据类型中描述互斥性。例如,考虑一个原子结构。我们可能希望将其赋予互斥属性,例如具有晶界或位错 XOR 类似于体心。不幸的是,OWL 框架没有很好地处理这种互斥性。我能找到的最佳文档是 这篇 W3C 博文,它概述了两种可能的途径——一种使用个体,另一种使用类。在这里,我们使用基于类的方法。也就是说,在我们的例子中,您的 Structure 子类可以继承自 HasGrainBoundary 和/或 HasDislocation,但这些与 Bulk 是互斥的(AllDisjoint)。在 owlready2 的术语中,我们可以使用 is_a 来定义一个多继承方案以明确我们 Generic 的所有细节,但如果我们试图从两个互斥(互斥)的类继承,我们的推理器将失败并告诉我们问题。

实例化FunctionInputOutput个体相对简单。这些个体只需通过上述Generic类的实例来填充它们的genericrequirementstransitive_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()。如果我们回过头来看我们的知识库,我们会看到VegetarianHasVegetables之间没有直接关系。相反,当我们调用sync()时,推理器使用Vegetarian的等价定义推断出个体HasVegetablesVegetarian!定义映射到(假设的)代码库的所有个体相当冗长(我们将努力改进这一点!),但这只是一个有点愚蠢的例子,但它仍然突出了利用本体描述知识库的强大和灵活性。

对现有的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 (21.3 kB 查看哈希值)

上传时间

构建分布

pyiron_ontology-0.2.7-py3-none-any.whl (25.5 kB 查看哈希值)

上传时间 Python 3

由以下支持