Skip to content

Algorithm

Algorithm Documentation sub-package for MaRDMO.

Provides everything needed to document algorithms within RDMO:

  • :mod:~MaRDMO.algorithm.models — Dataclasses representing Algorithm, Problem, Software, and Benchmark entities retrieved from MaRDI Portal or Wikidata.
  • :mod:~MaRDMO.algorithm.handlers — Signal handlers that populate the questionnaire when an external ID is saved.
  • :mod:~MaRDMO.algorithm.providers — RDMO optionset providers for searching algorithms, problems, software, and benchmarks in external knowledge graphs.
  • :mod:~MaRDMO.algorithm.worker — Background worker for generating algorithm previews and exporting algorithm entries to the MaRDI Portal.
  • :mod:~MaRDMO.algorithm.constants — Relation mappings, section maps, and URI-prefix configurations specific to the algorithm catalog.

Handlers

Module containing Handlers for the Algorithm Documentation.

Information inherits _entry, _collect_existing_ids, _hydrate_relatants, and _fill from BaseInformation (MaRDMO/handler_base.py).

All batch methods accept catalog='' (unused but required by the shared _fill and _hydrate_relatants signatures).

Information

Bases: BaseInformation

Handlers for the Algorithm Documentation questionnaire.

Source code in MaRDMO/algorithm/handlers.py
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
class Information(BaseInformation):
    '''Handlers for the Algorithm Documentation questionnaire.'''

    _ENTITY_KEYS = ('Algorithm', 'Problem', 'Software', 'Benchmark', 'Publication')

    def __init__(self):
        '''Load algorithm and publication questions, MathAlgoDB registry, and base URI.'''
        self.questions  = get_questions('algorithm') | get_questions('publication')
        self.mathalgodb = get_mathalgodb()
        self.base       = BASE_URI

    # ------------------------------------------------------------------ #
    #  Public entry points (called by router via post_save signal)         #
    # ------------------------------------------------------------------ #

    def benchmark(self, instance):
        '''Handle Benchmark ID save: hydrate basics and SPARQL data.

        Args:
            instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
        '''
        self._entry(instance, 'Benchmark', self._fill_benchmark_batch)

    def software(self, instance):
        '''Handle Software ID save: hydrate basics and cascade to Benchmark.

        Args:
            instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
        '''
        self._entry(instance, 'Software', self._fill_software_batch)

    def problem(self, instance):
        '''Handle Algorithmic Problem ID save: hydrate basics and cascade to Benchmark.

        Args:
            instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
        '''
        self._entry(instance, 'Problem', self._fill_problem_batch)

    def algorithm(self, instance):
        '''Handle Algorithm ID save: hydrate basics and cascade to Problem and Software.

        Args:
            instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
        '''
        self._entry(instance, 'Algorithm', self._fill_algorithm_batch)

    # ------------------------------------------------------------------ #
    #  Batch _fill_* methods (one SPARQL query for N entities)            #
    # ------------------------------------------------------------------ #

    def _fill_benchmark_batch(self, project, items, catalog='', visited=None):
        '''Hydrate multiple Benchmark pages with a single SPARQL query per source.

        Args:
            project:  RDMO project instance.
            items:    List of ``(text, external_id, set_index)`` tuples to process.
            catalog:  Active catalog URI suffix (default ``""``).
            visited:  Set of external IDs already processed (mutated to avoid cycles).
        '''
        if not items:
            return
        if visited is None:
            visited = set()

        benchmark  = self.questions['Benchmark']
        data_by_id = _fetch_by_source(
            items,
            'algorithm/queries/benchmark_mardi.sparql',
            'algorithm/queries/benchmark_wikidata.sparql',
            Benchmark,
        )
        if not data_by_id:
            return

        for text, external_id, set_index in items:
            data = data_by_id.get(external_id)
            if not data:
                continue

            add_basics(project=project, text=text, questions=self.questions,
                       item_type='Benchmark', index=(0, set_index))

            add_references(project=project, data=data,
                           uri=f'{self.base}{benchmark["Reference"]["uri"]}',
                           set_prefix=set_index)

            self._hydrate_publications(project, data.publications,
                                       catalog, visited)

    def _fill_software_batch(self, project, items, catalog='', visited=None):
        '''Hydrate multiple Software pages with a single SPARQL query per source.

        Args:
            project:  RDMO project instance.
            items:    List of ``(text, external_id, set_index)`` tuples to process.
            catalog:  Active catalog URI suffix (default ``""``).
            visited:  Set of external IDs already processed (mutated to avoid cycles).
        '''
        if not items:
            return
        if visited is None:
            visited = set()

        software   = self.questions['Software']
        data_by_id = _fetch_by_source(
            items,
            'algorithm/queries/software_mardi.sparql',
            'algorithm/queries/software_wikidata.sparql',
            Software,
        )
        if not data_by_id:
            return

        section_indices = {}
        for text, external_id, set_index in items:
            data = data_by_id.get(external_id)
            if not data:
                continue

            add_basics(project=project, text=text, questions=self.questions,
                       item_type='Software', index=(0, set_index))

            add_references(project=project, data=data,
                           uri=f'{self.base}{software["Reference"]["uri"]}',
                           set_prefix=set_index)

            add_relations_static(
                project=project, data=data,
                props={'keys': PROPS['S2B']},
                index={'set_prefix': set_index},
                statement={'relatant': f'{self.base}{software["BRelatant"]["uri"]}'})

            self._hydrate_relatants(
                project=project, data=data, prop_keys=PROPS['S2B'],
                spec=_RelatantSpec(
                    question_id_uri=f'{self.base}{self.questions["Benchmark"]["ID"]["uri"]}',
                    question_set_uri=f'{self.base}{self.questions["Benchmark"]["uri"]}',
                    prefix='B',
                    fill_method=partial(self._fill, item_type='Benchmark',
                                        batch_fill_method=self._fill_benchmark_batch),
                    catalog=catalog, visited=visited,
                    batch_fill_method=self._fill_benchmark_batch,
                    section_indices=section_indices,
                ))

            self._hydrate_publications(project, data.publications,
                                       catalog, visited)

    def _fill_problem_batch(self, project, items, catalog='', visited=None):
        '''Hydrate multiple Algorithmic Problem pages with a single SPARQL query per source.

        Args:
            project:  RDMO project instance.
            items:    List of ``(text, external_id, set_index)`` tuples to process.
            catalog:  Active catalog URI suffix (default ``""``).
            visited:  Set of external IDs already processed (mutated to avoid cycles).
        '''
        if not items:
            return
        if visited is None:
            visited = set()

        problem    = self.questions['Problem']
        data_by_id = _fetch_by_source(
            items,
            'algorithm/queries/problem_mardi.sparql',
            'algorithm/queries/problem_wikidata.sparql',
            Problem,
        )
        if not data_by_id:
            return

        section_indices = {}
        for text, external_id, set_index in items:
            data = data_by_id.get(external_id)
            if not data:
                continue

            add_basics(project=project, text=text, questions=self.questions,
                       item_type='Problem', index=(0, set_index))

            add_relations_static(
                project=project, data=data,
                props={'keys': PROPS['P2B']},
                index={'set_prefix': set_index},
                statement={'relatant': f'{self.base}{problem["BRelatant"]["uri"]}'})

            self._hydrate_relatants(
                project=project, data=data, prop_keys=PROPS['P2B'],
                spec=_RelatantSpec(
                    question_id_uri=f'{self.base}{self.questions["Benchmark"]["ID"]["uri"]}',
                    question_set_uri=f'{self.base}{self.questions["Benchmark"]["uri"]}',
                    prefix='B',
                    fill_method=partial(self._fill, item_type='Benchmark',
                                        batch_fill_method=self._fill_benchmark_batch),
                    catalog=catalog, visited=visited,
                    batch_fill_method=self._fill_benchmark_batch,
                    section_indices=section_indices,
                ))

            add_relations_flexible(
                project=project, data=data,
                props={'keys': PROPS['Problem'], 'mapping': self.mathalgodb},
                index={'set_prefix': set_index},
                statement={
                    'relation': f'{self.base}{problem["IntraClassRelation"]["uri"]}',
                    'relatant': f'{self.base}{problem["IntraClassElement"]["uri"]}',
                })

            # IntraClass relations are not cascade-hydrated

    def _fill_algorithm_batch(self, project, items, catalog='', visited=None):
        '''Hydrate multiple Algorithm pages with a single SPARQL query per source.

        Args:
            project:  RDMO project instance.
            items:    List of ``(text, external_id, set_index)`` tuples to process.
            catalog:  Active catalog URI suffix (default ``""``).
            visited:  Set of external IDs already processed (mutated to avoid cycles).
        '''
        if not items:
            return
        if visited is None:
            visited = set()

        algorithm  = self.questions['Algorithm']
        data_by_id = _fetch_by_source(
            items,
            'algorithm/queries/algorithm_mardi.sparql',
            'algorithm/queries/algorithm_wikidata.sparql',
            Algorithm,
        )
        if not data_by_id:
            return

        section_indices = {}
        for text, external_id, set_index in items:
            data = data_by_id.get(external_id)
            if not data:
                continue

            add_basics(project=project, text=text, questions=self.questions,
                       item_type='Algorithm', index=(0, set_index))

            add_relations_static(
                project=project, data=data,
                props={'keys': PROPS['A2P']},
                index={'set_prefix': set_index},
                statement={'relatant': f'{self.base}{algorithm["PRelatant"]["uri"]}'})

            self._hydrate_relatants(
                project=project, data=data, prop_keys=PROPS['A2P'],
                spec=_RelatantSpec(
                    question_id_uri=f'{self.base}{self.questions["Problem"]["ID"]["uri"]}',
                    question_set_uri=f'{self.base}{self.questions["Problem"]["uri"]}',
                    prefix='AT',
                    fill_method=partial(self._fill, item_type='Problem',
                                        batch_fill_method=self._fill_problem_batch),
                    catalog=catalog, visited=visited,
                    batch_fill_method=self._fill_problem_batch,
                    section_indices=section_indices,
                ))

            add_relations_static(
                project=project, data=data,
                props={'keys': PROPS['A2S']},
                index={'set_prefix': set_index},
                statement={'relatant': f'{self.base}{algorithm["SRelatant"]["uri"]}'})

            self._hydrate_relatants(
                project=project, data=data, prop_keys=PROPS['A2S'],
                spec=_RelatantSpec(
                    question_id_uri=f'{self.base}{self.questions["Software"]["ID"]["uri"]}',
                    question_set_uri=f'{self.base}{self.questions["Software"]["uri"]}',
                    prefix='S',
                    fill_method=partial(self._fill, item_type='Software',
                                        batch_fill_method=self._fill_software_batch),
                    catalog=catalog, visited=visited,
                    batch_fill_method=self._fill_software_batch,
                    section_indices=section_indices,
                ))

            add_relations_flexible(
                project=project, data=data,
                props={'keys': PROPS['Algorithm'], 'mapping': self.mathalgodb},
                index={'set_prefix': set_index},
                statement={
                    'relation': f'{self.base}{algorithm["IntraClassRelation"]["uri"]}',
                    'relatant': f'{self.base}{algorithm["IntraClassElement"]["uri"]}',
                })

            self._hydrate_publications(project, data.publications,
                                       catalog, visited)

__init__()

Load algorithm and publication questions, MathAlgoDB registry, and base URI.

Source code in MaRDMO/algorithm/handlers.py
37
38
39
40
41
def __init__(self):
    '''Load algorithm and publication questions, MathAlgoDB registry, and base URI.'''
    self.questions  = get_questions('algorithm') | get_questions('publication')
    self.mathalgodb = get_mathalgodb()
    self.base       = BASE_URI

algorithm(instance)

Handle Algorithm ID save: hydrate basics and cascade to Problem and Software.

Parameters:

Name Type Description Default
instance

RDMO :class:~rdmo.projects.models.Value that was just saved.

required
Source code in MaRDMO/algorithm/handlers.py
71
72
73
74
75
76
77
def algorithm(self, instance):
    '''Handle Algorithm ID save: hydrate basics and cascade to Problem and Software.

    Args:
        instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
    '''
    self._entry(instance, 'Algorithm', self._fill_algorithm_batch)

benchmark(instance)

Handle Benchmark ID save: hydrate basics and SPARQL data.

Parameters:

Name Type Description Default
instance

RDMO :class:~rdmo.projects.models.Value that was just saved.

required
Source code in MaRDMO/algorithm/handlers.py
47
48
49
50
51
52
53
def benchmark(self, instance):
    '''Handle Benchmark ID save: hydrate basics and SPARQL data.

    Args:
        instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
    '''
    self._entry(instance, 'Benchmark', self._fill_benchmark_batch)

problem(instance)

Handle Algorithmic Problem ID save: hydrate basics and cascade to Benchmark.

Parameters:

Name Type Description Default
instance

RDMO :class:~rdmo.projects.models.Value that was just saved.

required
Source code in MaRDMO/algorithm/handlers.py
63
64
65
66
67
68
69
def problem(self, instance):
    '''Handle Algorithmic Problem ID save: hydrate basics and cascade to Benchmark.

    Args:
        instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
    '''
    self._entry(instance, 'Problem', self._fill_problem_batch)

software(instance)

Handle Software ID save: hydrate basics and cascade to Benchmark.

Parameters:

Name Type Description Default
instance

RDMO :class:~rdmo.projects.models.Value that was just saved.

required
Source code in MaRDMO/algorithm/handlers.py
55
56
57
58
59
60
61
def software(self, instance):
    '''Handle Software ID save: hydrate basics and cascade to Benchmark.

    Args:
        instance: RDMO :class:`~rdmo.projects.models.Value` that was just saved.
    '''
    self._entry(instance, 'Software', self._fill_software_batch)

Models

Dataclasses that represent entities in the Algorithm documentation catalog.

Each class maps to one entity type collected from MaRDI Portal and Wikidata during algorithm documentation. Instances are populated from SPARQL query results and carry the fields needed to render questionnaire answers and export entries.

Provides:

  • :class:Benchmark — benchmark problem associated with an algorithm
  • :class:Software — software implementation of an algorithm
  • :class:Problem — algorithmic problem solved by an algorithm
  • :class:Algorithm — central entity representing the documented algorithm

Algorithm dataclass

Data Class for Algorithm Item

Source code in MaRDMO/algorithm/models.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
@dataclass
class Algorithm:
    '''Data Class for Algorithm Item'''
    component_of: list[Relatant] = field(default_factory=list)
    has_component: list[Relatant] = field(default_factory=list)
    subclass_of: list[Relatant] = field(default_factory=list)
    has_subclass: list[Relatant] = field(default_factory=list)
    related_to: list[Relatant] = field(default_factory=list)
    solves: list[Relatant] = field(default_factory=list)
    implemented_by: list[Relatant] = field(default_factory=list)
    publications: list[Relatant] = field(default_factory=list)

    @classmethod
    def from_query(cls, raw_data: dict) -> 'Algorithm':
        '''Generate Class Item From Query (single-item, backward-compatible).'''
        return cls.from_query_single(raw_data[0])

    @classmethod
    def from_query_batch(cls, raw_data: list) -> 'dict[str, Algorithm]':
        '''Parse a batch SPARQL result into {external_id: instance} dict.'''
        return {
            row['qid']['value']: cls.from_query_single(row)
            for row in raw_data
            if row.get('qid', {}).get('value')
        }

    @classmethod
    def from_query_single(cls, data: dict) -> 'Algorithm':
        '''Parse one SPARQL result row into an Algorithm instance.'''

        algorithm = {
            # Get Problems Solved
            'solves': split_value(
                data = data,
                key = 'solved_by',
                transform = Relatant.from_query
            ),
            # Get implementing Software
            'implemented_by': split_value(
                data = data,
                key = 'implementation_by',
                transform = Relatant.from_query
            ),
            # Get has Components
            'has_component': split_value(
                data = data,
                key = 'has_parts',
                transform = Relatant.from_query
            ),
            # Get Component Of
            'component_of': split_value(
                data = data,
                key = 'part_of',
                transform = Relatant.from_query
            ),
            # Get has Subclass
            'has_subclass': split_value(
                data = data,
                key = 'has_subclass',
                transform = Relatant.from_query
            ),
            # Get Subclass Of
            'subclass_of': split_value(
                data = data,
                key = 'subclass_of',
                transform = Relatant.from_query
            ),
            # Get related to
            'related_to': split_value(
                data = data,
                key = 'similar_to',
                transform = Relatant.from_query
            ),
            # Get Publication(s)
            'publications': split_value(
                data = data,
                key = 'publication',
                transform = Relatant.from_query
            )
        }

        return cls(
            **algorithm
        )

from_query(raw_data) classmethod

Generate Class Item From Query (single-item, backward-compatible).

Source code in MaRDMO/algorithm/models.py
180
181
182
183
@classmethod
def from_query(cls, raw_data: dict) -> 'Algorithm':
    '''Generate Class Item From Query (single-item, backward-compatible).'''
    return cls.from_query_single(raw_data[0])

from_query_batch(raw_data) classmethod

Parse a batch SPARQL result into {external_id: instance} dict.

Source code in MaRDMO/algorithm/models.py
185
186
187
188
189
190
191
192
@classmethod
def from_query_batch(cls, raw_data: list) -> 'dict[str, Algorithm]':
    '''Parse a batch SPARQL result into {external_id: instance} dict.'''
    return {
        row['qid']['value']: cls.from_query_single(row)
        for row in raw_data
        if row.get('qid', {}).get('value')
    }

from_query_single(data) classmethod

Parse one SPARQL result row into an Algorithm instance.

Source code in MaRDMO/algorithm/models.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
@classmethod
def from_query_single(cls, data: dict) -> 'Algorithm':
    '''Parse one SPARQL result row into an Algorithm instance.'''

    algorithm = {
        # Get Problems Solved
        'solves': split_value(
            data = data,
            key = 'solved_by',
            transform = Relatant.from_query
        ),
        # Get implementing Software
        'implemented_by': split_value(
            data = data,
            key = 'implementation_by',
            transform = Relatant.from_query
        ),
        # Get has Components
        'has_component': split_value(
            data = data,
            key = 'has_parts',
            transform = Relatant.from_query
        ),
        # Get Component Of
        'component_of': split_value(
            data = data,
            key = 'part_of',
            transform = Relatant.from_query
        ),
        # Get has Subclass
        'has_subclass': split_value(
            data = data,
            key = 'has_subclass',
            transform = Relatant.from_query
        ),
        # Get Subclass Of
        'subclass_of': split_value(
            data = data,
            key = 'subclass_of',
            transform = Relatant.from_query
        ),
        # Get related to
        'related_to': split_value(
            data = data,
            key = 'similar_to',
            transform = Relatant.from_query
        ),
        # Get Publication(s)
        'publications': split_value(
            data = data,
            key = 'publication',
            transform = Relatant.from_query
        )
    }

    return cls(
        **algorithm
    )

Benchmark dataclass

Data Class For Benchmark Item

Source code in MaRDMO/algorithm/models.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@dataclass
class Benchmark:
    '''Data Class For Benchmark Item'''
    reference: dict[int, list[str]] = field(default_factory=dict)
    publications: list[Relatant] = field(default_factory=list)

    @classmethod
    def from_query(cls, raw_data: dict) -> 'Benchmark':
        '''Generate Class Item From Query (single-item, backward-compatible).'''
        return cls.from_query_single(raw_data[0])

    @classmethod
    def from_query_batch(cls, raw_data: list) -> 'dict[str, Benchmark]':
        '''Parse a batch SPARQL result into {external_id: instance} dict.'''
        return {
            row['qid']['value']: cls.from_query_single(row)
            for row in raw_data
            if row.get('qid', {}).get('value')
        }

    @classmethod
    def from_query_single(cls, data: dict) -> 'Benchmark':
        '''Parse one SPARQL result row into a Benchmark instance.'''
        options = get_options()

        benchmark = {
            # Benchmark Reference (DOI, MORWIKI, URL)
            'reference': {
                idx: [options[prop], data[prop]['value']]
                for idx, prop in enumerate(benchmark_reference_ids)
                if data.get(prop, {}).get('value')
            },
            # Get Publication(s)
            'publications': split_value(
                data = data,
                key = 'publication',
                transform = Relatant.from_query
            )
        }

        return cls(
            **benchmark
        )

from_query(raw_data) classmethod

Generate Class Item From Query (single-item, backward-compatible).

Source code in MaRDMO/algorithm/models.py
29
30
31
32
@classmethod
def from_query(cls, raw_data: dict) -> 'Benchmark':
    '''Generate Class Item From Query (single-item, backward-compatible).'''
    return cls.from_query_single(raw_data[0])

from_query_batch(raw_data) classmethod

Parse a batch SPARQL result into {external_id: instance} dict.

Source code in MaRDMO/algorithm/models.py
34
35
36
37
38
39
40
41
@classmethod
def from_query_batch(cls, raw_data: list) -> 'dict[str, Benchmark]':
    '''Parse a batch SPARQL result into {external_id: instance} dict.'''
    return {
        row['qid']['value']: cls.from_query_single(row)
        for row in raw_data
        if row.get('qid', {}).get('value')
    }

from_query_single(data) classmethod

Parse one SPARQL result row into a Benchmark instance.

Source code in MaRDMO/algorithm/models.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@classmethod
def from_query_single(cls, data: dict) -> 'Benchmark':
    '''Parse one SPARQL result row into a Benchmark instance.'''
    options = get_options()

    benchmark = {
        # Benchmark Reference (DOI, MORWIKI, URL)
        'reference': {
            idx: [options[prop], data[prop]['value']]
            for idx, prop in enumerate(benchmark_reference_ids)
            if data.get(prop, {}).get('value')
        },
        # Get Publication(s)
        'publications': split_value(
            data = data,
            key = 'publication',
            transform = Relatant.from_query
        )
    }

    return cls(
        **benchmark
    )

Problem dataclass

Data Class for Problem Item

Source code in MaRDMO/algorithm/models.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
@dataclass
class Problem:
    '''Data Class for Problem Item'''
    specializes: list[Relatant] = field(default_factory=list)
    specialized_by: list[Relatant] = field(default_factory=list)
    manifests: list[Relatant] = field(default_factory=list)

    @classmethod
    def from_query(cls, raw_data: dict) -> 'Problem':
        '''Generate Class Item From Query (single-item, backward-compatible).'''
        return cls.from_query_single(raw_data[0])

    @classmethod
    def from_query_batch(cls, raw_data: list) -> 'dict[str, Problem]':
        '''Parse a batch SPARQL result into {external_id: instance} dict.'''
        return {
            row['qid']['value']: cls.from_query_single(row)
            for row in raw_data
            if row.get('qid', {}).get('value')
        }

    @classmethod
    def from_query_single(cls, data: dict) -> 'Problem':
        '''Parse one SPARQL result row into a Problem instance.'''

        problem = {
            # Get manifests Statements
            'manifests': split_value(
                data = data,
                key = 'manifests',
                transform = Relatant.from_query
            ),
            # Get specializes Statements
            'specializes': split_value(
                data = data,
                key = 'specializes',
                transform = Relatant.from_query
            ),
            # Get specialized by Statements
            'specialized_by': split_value(
                data = data,
                key = 'specialized_by',
                transform = Relatant.from_query
            ),
        }

        return cls(
            **problem
        )

from_query(raw_data) classmethod

Generate Class Item From Query (single-item, backward-compatible).

Source code in MaRDMO/algorithm/models.py
125
126
127
128
@classmethod
def from_query(cls, raw_data: dict) -> 'Problem':
    '''Generate Class Item From Query (single-item, backward-compatible).'''
    return cls.from_query_single(raw_data[0])

from_query_batch(raw_data) classmethod

Parse a batch SPARQL result into {external_id: instance} dict.

Source code in MaRDMO/algorithm/models.py
130
131
132
133
134
135
136
137
@classmethod
def from_query_batch(cls, raw_data: list) -> 'dict[str, Problem]':
    '''Parse a batch SPARQL result into {external_id: instance} dict.'''
    return {
        row['qid']['value']: cls.from_query_single(row)
        for row in raw_data
        if row.get('qid', {}).get('value')
    }

from_query_single(data) classmethod

Parse one SPARQL result row into a Problem instance.

Source code in MaRDMO/algorithm/models.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
@classmethod
def from_query_single(cls, data: dict) -> 'Problem':
    '''Parse one SPARQL result row into a Problem instance.'''

    problem = {
        # Get manifests Statements
        'manifests': split_value(
            data = data,
            key = 'manifests',
            transform = Relatant.from_query
        ),
        # Get specializes Statements
        'specializes': split_value(
            data = data,
            key = 'specializes',
            transform = Relatant.from_query
        ),
        # Get specialized by Statements
        'specialized_by': split_value(
            data = data,
            key = 'specialized_by',
            transform = Relatant.from_query
        ),
    }

    return cls(
        **problem
    )

Software dataclass

Data Class for Software Item

Source code in MaRDMO/algorithm/models.py
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@dataclass
class Software:
    '''Data Class for Software Item'''
    reference: dict[int, list[str]] = field(default_factory=dict)
    tested_by: list[Relatant] = field(default_factory=list)
    publications: list[Relatant] = field(default_factory=list)

    @classmethod
    def from_query(cls, raw_data: dict) -> 'Software':
        '''Generate Class Item From Query (single-item, backward-compatible).'''
        return cls.from_query_single(raw_data[0])

    @classmethod
    def from_query_batch(cls, raw_data: list) -> 'dict[str, Software]':
        '''Parse a batch SPARQL result into {external_id: instance} dict.'''
        return {
            row['qid']['value']: cls.from_query_single(row)
            for row in raw_data
            if row.get('qid', {}).get('value')
        }

    @classmethod
    def from_query_single(cls, data: dict) -> 'Software':
        '''Parse one SPARQL result row into a Software instance.'''
        options = get_options()

        software = {
            # Software Reference (DOI, SWMATH, and URL)
            'reference': {
                idx: [options[prop], data[prop]['value']]
                for idx, prop in enumerate(software_reference_ids)
                if data.get(prop, {}).get('value')
            },
            # Related Benchmarks
            'tested_by': split_value(
                data = data,
                key = 'tested_by',
                transform = Relatant.from_query
            ),
            # Get Publication(s)
            'publications': split_value(
                data = data,
                key = 'publication',
                transform = Relatant.from_query
            )
        }

        return cls(
            **software
        )

from_query(raw_data) classmethod

Generate Class Item From Query (single-item, backward-compatible).

Source code in MaRDMO/algorithm/models.py
74
75
76
77
@classmethod
def from_query(cls, raw_data: dict) -> 'Software':
    '''Generate Class Item From Query (single-item, backward-compatible).'''
    return cls.from_query_single(raw_data[0])

from_query_batch(raw_data) classmethod

Parse a batch SPARQL result into {external_id: instance} dict.

Source code in MaRDMO/algorithm/models.py
79
80
81
82
83
84
85
86
@classmethod
def from_query_batch(cls, raw_data: list) -> 'dict[str, Software]':
    '''Parse a batch SPARQL result into {external_id: instance} dict.'''
    return {
        row['qid']['value']: cls.from_query_single(row)
        for row in raw_data
        if row.get('qid', {}).get('value')
    }

from_query_single(data) classmethod

Parse one SPARQL result row into a Software instance.

Source code in MaRDMO/algorithm/models.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@classmethod
def from_query_single(cls, data: dict) -> 'Software':
    '''Parse one SPARQL result row into a Software instance.'''
    options = get_options()

    software = {
        # Software Reference (DOI, SWMATH, and URL)
        'reference': {
            idx: [options[prop], data[prop]['value']]
            for idx, prop in enumerate(software_reference_ids)
            if data.get(prop, {}).get('value')
        },
        # Related Benchmarks
        'tested_by': split_value(
            data = data,
            key = 'tested_by',
            transform = Relatant.from_query
        ),
        # Get Publication(s)
        'publications': split_value(
            data = data,
            key = 'publication',
            transform = Relatant.from_query
        )
    }

    return cls(
        **software
    )

Providers

RDMO optionset providers for the Algorithm documentation catalog.

Each provider class implements get_options and is referenced from the algorithm catalog configuration. Providers query MaRDI Portal and Wikidata for entity suggestions and optionally allow to create new entries or restrict suggestions to previously documented entities.

Provides:

  • :class:Algorithm — searches external sources for algorithms; refresh on select
  • :class:RelatedAlgorithmWithoutCreation — algorithm lookup without user creation
  • :class:AlgorithmicProblem — searches for algorithmic problems; refresh on select
  • :class:RelatedAlgorithmicProblemWithCreation — problem lookup with user creation
  • :class:RelatedAlgorithmicProblemWithoutCreation — problem lookup, no creation
  • :class:Benchmark — searches for benchmarks; refresh on select
  • :class:RelatedBenchmarkWithCreation — benchmark lookup with user creation
  • :class:RelatedBenchmarkOrSoftwareWithoutCreation — benchmark/software lookup, no creation

Algorithm

Bases: Provider

Algorithm Provider (MaRDI Portal / Wikidata), No User Creation, Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Algorithm(Provider):
    '''Algorithm Provider (MaRDI Portal / Wikidata),
       No User Creation, Refresh Upon Selection
    '''

    search = True
    refresh =True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        return query_sources(
            search = search,
            item_class = _ITEMS['algorithm']
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    return query_sources(
        search = search,
        item_class = _ITEMS['algorithm']
    )

AlgorithmicProblem

Bases: Provider

Algorithmic Problem Provider (MaRDI Portal / Wikidata), No User Creation, Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class AlgorithmicProblem(Provider):
    '''Algorithmic Problem Provider (MaRDI Portal / Wikidata),
       No User Creation, Refresh Upon Selection
    '''

    search = True
    refresh = True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        return query_sources(
            search = search,
            item_class = _ITEMS['algorithmic task']
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    return query_sources(
        search = search,
        item_class = _ITEMS['algorithmic task']
    )

Benchmark

Bases: Provider

Benchmark Provider (MaRDI Portal / Wikidata), No User Creation, Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
class Benchmark(Provider):
    '''Benchmark Provider (MaRDI Portal / Wikidata),
       No User Creation, Refresh Upon Selection
    '''

    search = True
    refresh = True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        return query_sources(
            search = search,
            item_class = _ITEMS['benchmark']
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    return query_sources(
        search = search,
        item_class = _ITEMS['benchmark']
    )

RelatedAlgorithmWithoutCreation

Bases: Provider

Algorithm Provider (MaRDI Portal), No User Creation, No Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
class RelatedAlgorithmWithoutCreation(Provider):
    '''Algorithm Provider (MaRDI Portal),
       No User Creation, No Refresh Upon Selection
    '''

    search = True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        setup = define_setup(
            query_attributes = ['algorithm'],
            sources = ['mardi'],
            item_class = _ITEMS['algorithm']
        )

        return query_sources_with_user_additions(
            search = search,
            project = project,
            setup = setup
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    setup = define_setup(
        query_attributes = ['algorithm'],
        sources = ['mardi'],
        item_class = _ITEMS['algorithm']
    )

    return query_sources_with_user_additions(
        search = search,
        project = project,
        setup = setup
    )

RelatedAlgorithmicProblemWithCreation

Bases: Provider

Algorithmic Problem Provider (MaRDI Portal / Wikidata), User Creation, No Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
class RelatedAlgorithmicProblemWithCreation(Provider):
    '''Algorithmic Problem Provider (MaRDI Portal / Wikidata),
       User Creation, No Refresh Upon Selection
    '''

    search = True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        setup = define_setup(
            query_attributes = ['problem'],
            creation = True,
            item_class = _ITEMS['algorithmic task']
        )

        return query_sources_with_user_additions(
            search = search,
            project = project,
            setup = setup
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    setup = define_setup(
        query_attributes = ['problem'],
        creation = True,
        item_class = _ITEMS['algorithmic task']
    )

    return query_sources_with_user_additions(
        search = search,
        project = project,
        setup = setup
    )

RelatedAlgorithmicProblemWithoutCreation

Bases: Provider

Algorithmic Problem Provider (MaRDI Portal), No User Creation, No Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
class RelatedAlgorithmicProblemWithoutCreation(Provider):
    '''Algorithmic Problem Provider (MaRDI Portal),
       No User Creation, No Refresh Upon Selection
    '''

    search = True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        setup = define_setup(
            query_attributes = ['problem'],
            sources = ['mardi'],
            item_class = _ITEMS['algorithmic task']
        )

        return query_sources_with_user_additions(
            search = search,
            project = project,
            setup = setup
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    setup = define_setup(
        query_attributes = ['problem'],
        sources = ['mardi'],
        item_class = _ITEMS['algorithmic task']
    )

    return query_sources_with_user_additions(
        search = search,
        project = project,
        setup = setup
    )

RelatedBenchmarkOrSoftwareWithoutCreation

Bases: Provider

Benchmark, Software Provider (MaRDI Portal), No User Creation, No Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
class RelatedBenchmarkOrSoftwareWithoutCreation(Provider):
    '''Benchmark, Software Provider (MaRDI Portal),
       No User Creation, No Refresh Upon Selection
    '''

    search = True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        setup = define_setup(
            query_attributes = ['benchmark', 'software'],
            sources = ['mardi'],
            item_class = [
                _ITEMS['benchmark'],
                _ITEMS['software']
            ]
        )

        return query_sources_with_user_additions(
            search = search,
            project = project,
            setup = setup
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    setup = define_setup(
        query_attributes = ['benchmark', 'software'],
        sources = ['mardi'],
        item_class = [
            _ITEMS['benchmark'],
            _ITEMS['software']
        ]
    )

    return query_sources_with_user_additions(
        search = search,
        project = project,
        setup = setup
    )

RelatedBenchmarkWithCreation

Bases: Provider

Benchmark Provider (MaRDI Portal / Wikidata), User Creation, No Refresh Upon Selection

Source code in MaRDMO/algorithm/providers.py
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
class RelatedBenchmarkWithCreation(Provider):
    '''Benchmark Provider (MaRDI Portal / Wikidata),
       User Creation, No Refresh Upon Selection
    '''

    search = True

    def get_options(self, project, search=None, user=None, site=None):
        '''Query external knowledge-graph source(s) and return matching options.

        Args:
            project: RDMO project instance (used for user-entry lookups when applicable).
            search:  Search string entered by the user; returns empty list when
                     fewer than 3 characters.
            user:    Requesting user (unused).
            site:    Current site (unused).

        Returns:
            List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
        '''
        if not search or len(search) < 3:
            return []

        setup = define_setup(
            query_attributes = ['benchmark'],
            creation = True,
            item_class = _ITEMS['benchmark']
        )

        return query_sources_with_user_additions(
            search = search,
            project = project,
            setup = setup
        )

get_options(project, search=None, user=None, site=None)

Query external knowledge-graph source(s) and return matching options.

Parameters:

Name Type Description Default
project

RDMO project instance (used for user-entry lookups when applicable).

required
search

Search string entered by the user; returns empty list when fewer than 3 characters.

None
user

Requesting user (unused).

None
site

Current site (unused).

None

Returns:

Type Description

List of {"id": …, "text": …} option dicts sorted by relevance.

Source code in MaRDMO/algorithm/providers.py
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
def get_options(self, project, search=None, user=None, site=None):
    '''Query external knowledge-graph source(s) and return matching options.

    Args:
        project: RDMO project instance (used for user-entry lookups when applicable).
        search:  Search string entered by the user; returns empty list when
                 fewer than 3 characters.
        user:    Requesting user (unused).
        site:    Current site (unused).

    Returns:
        List of ``{"id": …, "text": …}`` option dicts sorted by relevance.
    '''
    if not search or len(search) < 3:
        return []

    setup = define_setup(
        query_attributes = ['benchmark'],
        creation = True,
        item_class = _ITEMS['benchmark']
    )

    return query_sources_with_user_additions(
        search = search,
        project = project,
        setup = setup
    )

Workers

Background worker for the Algorithm documentation catalog.

Implements the task that collects algorithm metadata from User, MaRDI Portal, and Wikidata, renders a preview document, and exports the result to the MaRDI Portal.

Provides:

  • :class:PrepareAlgorithm — orchestrates data collection, preview rendering, and portal export for a single algorithm documentation project

PrepareAlgorithm

Bases: PublicationExport

Prepare Algorithm documentation answers for preview rendering and MaRDI Portal export.

Inherits publication export helpers from :class:~MaRDMO.publication.worker.PublicationExport and extends them with algorithm-specific relation mapping and Wikibase payload generation.

Source code in MaRDMO/algorithm/worker.py
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
class PrepareAlgorithm(PublicationExport):
    '''Prepare Algorithm documentation answers for preview rendering and MaRDI Portal export.

    Inherits publication export helpers from
    :class:`~MaRDMO.publication.worker.PublicationExport` and extends them
    with algorithm-specific relation mapping and Wikibase payload generation.
    '''
    def __init__(self):
        '''Initialise with Wikibase vocabulary and the MathAlgoDB ontology registry.'''
        super().__init__()
        self.mathalgodb = get_mathalgodb()

    def preview(self, answers):
        '''Resolve entity cross-references for the Algorithm documentation preview page.

        Applies algorithm-specific relation mappings so that the preview
        template receives a fully-resolved answers dict.

        Args:
            answers: Top-level answers dict (mutated in place).

        Returns:
            The mutated *answers* dict.
        '''

        # Prepare Relations for Preview
        for relation in preview_relations:
            entity_relations(
                data = answers,
                idx = {
                    'from': relation['from_idx'],
                    'to': relation['to_idx']
                },
                entity = {
                    'relation': relation['relation'],
                    'old_name': relation['old_name'],
                    'new_name': relation['new_name'],
                    'encryption': relation['encryption']
                },
                order = {
                    'formulation': False,
                    'task': False
                },
                assumption = False,
                mapping = self.mathalgodb
            )

        return answers

    def export(self, data, url):
        '''Assemble and return the complete Wikibase payload for an Algorithm documentation export.

        Creates a :class:`~MaRDMO.payload.GeneratePayload` instance, processes
        all unique items, then delegates each entity section (algorithms, problems,
        software, benchmarks, publications) to dedicated helper methods.

        Args:
            data: Top-level answers dict produced by ``get_post_data``.
            url:  Target Wikibase API URL for the upload.

        Returns:
            Tuple ``(payload_dict, dependency_order)`` ready for
            :meth:`~MaRDMO.oauth2.OauthProviderMixin.post`.
        '''

        items, dependency = unique_items(data)

        payload = GeneratePayload(
            dependency = dependency,
            user_items = items,
            url = url,
            wikibase = {
                'items': get_items(),
                'properties': get_properties(),
                'relations': get_relations()
            }
        )

        # Add / Retrieve Components of Model Item
        payload.process_items()

        # Delegate to helper functions
        self._export_algorithms(
            payload = payload,
            algorithms = data.get("algorithm", {}),
        )
        self._export_problems(
            payload = payload,
            problems = data.get("problem", {})
        )
        self._export_softwares(
            payload = payload,
            softwares = data.get("software", {})
        )
        self._export_benchmarks(
            payload = payload,
            benchmarks = data.get("benchmark", {})
        )
        self._export_authors(
            payload = payload,
            publications = data.get("publication", {})
        )
        self._export_journals(
            payload = payload,
            publications = data.get("publication", {})
        )
        self._export_publications(
            payload = payload,
            publications = data.get("publication", {}),
            relations = [('P2A', 'ARelatant'), ('P2BS', 'BSRelatant')]
        )

        # Construct Item Payloads
        payload.add_item_payload()

        # If Relations are added, check if they exist
        if any(
            key.startswith("RELATION")
            for key in payload.get_dictionary()
        ):
            query = payload.build_relation_check_query()

            check = None
            for attempt in range(2):  # try twice
                try:
                    check = query_sparql(
                        query = query,
                        sparql_endpoint = get_url('mardi', 'sparql')
                    )
                    break
                except Exception as e:
                    logging.warning("SPARQL query attempt %s failed: %s", attempt + 1, e)
                    if attempt == 0:
                        time.sleep(1)  # short wait before retry
            if not check:
                # both attempts failed → pretend no results
                check = [{}]

            payload.add_check_results(
                check = check
            )
        return payload.get_dictionary(), payload.dependency

    # ---------------------------
    # Shared helper
    # ---------------------------
    def _add_common_metadata(self, payload, qclass, profile_type):
        '''Add instance-of, community, and (for non-benchmarks) MaRDI-profile-type statements.

        Args:
            payload:      :class:`~MaRDMO.payload.GeneratePayload` instance.
            qclass:       Wikibase QID for the ``instance of`` target class.
            profile_type: Label key for the MaRDI profile type item; skipped
                          when *qclass* is the benchmark item QID.
        '''
        payload.add_answer(
            verb = self.properties["instance of"],
            object_and_type = [qclass, "wikibase-item"],
        )

        payload.add_answer(
            verb = self.properties["community"],
            object_and_type = [self.items["MathAlgoDB"], "wikibase-item"],
        )

        if qclass != self.items["benchmark"]:
            payload.add_answer(
                verb = self.properties["MaRDI profile type"],
                object_and_type = [self.items[profile_type], "wikibase-item"],
            )

    # ---------------------------
    # Entity export helpers
    # ---------------------------
    def _export_algorithms(self, payload, algorithms: dict):
        for entry in algorithms.values():
            if not entry.get("ID"):
                continue

            payload.get_item_key(
                value = entry
            )

            self._add_common_metadata(
                payload = payload,
                qclass = self.items["algorithm"],
                profile_type = "MaRDI algorithm profile",
            )

            payload.add_single_relation(
                statement = {
                    'relation': self.properties["solved by"],
                    'relatant': "PRelatant"
                },
                reverse = True
            )

            payload.add_single_relation(
                statement = {
                    'relation': self.properties["implemented by"],
                    'relatant': "SRelatant"
                }
            )

            payload.add_multiple_relation(
                statement = {
                    'relation': "IntraClassRelation",
                    'relatant': "IntraClassElement"
                }
            )

    def _export_problems(self, payload, problems: dict):
        for entry in problems.values():
            if not entry.get("ID"):
                continue

            payload.get_item_key(
                value = entry
            )

            self._add_common_metadata(
                payload = payload,
                qclass = self.items["algorithmic task"],
                profile_type = "MaRDI task profile",
            )

            payload.add_single_relation(
                statement = {
                    'relation': self.properties["manifestation of"],
                    'relatant': "BRelatant"
                },
                reverse = True
            )

            payload.add_multiple_relation(
                statement = {
                    'relation': "IntraClassRelation",
                    'relatant': "IntraClassElement"
                }
            )

    def _export_softwares(self, payload, softwares: dict):
        for entry in softwares.values():
            if not entry.get("ID"):
                continue

            payload.get_item_key(
                value = entry
            )

            self._add_common_metadata(
                payload = payload,
                qclass = self.items["software"],
                profile_type = "MaRDI software profile",
            )

            payload.add_single_relation(
                statement = {
                    'relation': self.properties["tested by"],
                    'relatant': "BRelatant"
                },
                reverse = True
            )

            if entry.get("reference"):
                if entry['reference'].get(0):
                    payload.add_answer(
                        verb = self.properties["DOI"],
                        object_and_type = [entry["reference"][0][1], "external-id"],
                    )
                if entry['reference'].get(1):
                    payload.add_answer(
                        verb = self.properties["swMath work ID"],
                        object_and_type = [entry["reference"][1][1], "external-id"],
                    )
                if entry['reference'].get(2):
                    payload.add_answer(
                        verb = self.properties["described at URL"],
                        object_and_type = [entry["reference"][2][1], "URL"],
                    )
                if entry['reference'].get(3):
                    payload.add_answer(
                        verb = self.properties["source code repository URL"],
                        object_and_type = [entry["reference"][3][1], "URL"],
                    )

    def _export_benchmarks(self, payload, benchmarks: dict):
        for entry in benchmarks.values():
            if not entry.get("ID"):
                continue

            payload.get_item_key(
                value = entry
            )

            self._add_common_metadata(
                payload = payload,
                qclass = self.items["benchmark"],
                profile_type = "MaRDI benchmark profile",
            )

            if entry.get("reference"):
                if entry['reference'].get(0):
                    payload.add_answer(
                        verb = self.properties["DOI"],
                        object_and_type = [entry["reference"][0][1], "external-id"],
                    )
                if entry['reference'].get(1):
                    payload.add_answer(
                        verb = self.properties["MORwiki ID"],
                        object_and_type = [entry["reference"][1][1], "external-id"],
                    )
                if entry['reference'].get(2):
                    payload.add_answer(
                        verb = self.properties["described at URL"],
                        object_and_type = [entry["reference"][2][1], "URL"],
                    )
                if entry['reference'].get(3):
                    payload.add_answer(
                        verb = self.properties["source code repository URL"],
                        object_and_type = [entry["reference"][3][1], "URL"],
                    )

__init__()

Initialise with Wikibase vocabulary and the MathAlgoDB ontology registry.

Source code in MaRDMO/algorithm/worker.py
32
33
34
35
def __init__(self):
    '''Initialise with Wikibase vocabulary and the MathAlgoDB ontology registry.'''
    super().__init__()
    self.mathalgodb = get_mathalgodb()

export(data, url)

Assemble and return the complete Wikibase payload for an Algorithm documentation export.

Creates a :class:~MaRDMO.payload.GeneratePayload instance, processes all unique items, then delegates each entity section (algorithms, problems, software, benchmarks, publications) to dedicated helper methods.

Parameters:

Name Type Description Default
data

Top-level answers dict produced by get_post_data.

required
url

Target Wikibase API URL for the upload.

required

Returns:

Type Description

Tuple (payload_dict, dependency_order) ready for

meth:~MaRDMO.oauth2.OauthProviderMixin.post.

Source code in MaRDMO/algorithm/worker.py
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def export(self, data, url):
    '''Assemble and return the complete Wikibase payload for an Algorithm documentation export.

    Creates a :class:`~MaRDMO.payload.GeneratePayload` instance, processes
    all unique items, then delegates each entity section (algorithms, problems,
    software, benchmarks, publications) to dedicated helper methods.

    Args:
        data: Top-level answers dict produced by ``get_post_data``.
        url:  Target Wikibase API URL for the upload.

    Returns:
        Tuple ``(payload_dict, dependency_order)`` ready for
        :meth:`~MaRDMO.oauth2.OauthProviderMixin.post`.
    '''

    items, dependency = unique_items(data)

    payload = GeneratePayload(
        dependency = dependency,
        user_items = items,
        url = url,
        wikibase = {
            'items': get_items(),
            'properties': get_properties(),
            'relations': get_relations()
        }
    )

    # Add / Retrieve Components of Model Item
    payload.process_items()

    # Delegate to helper functions
    self._export_algorithms(
        payload = payload,
        algorithms = data.get("algorithm", {}),
    )
    self._export_problems(
        payload = payload,
        problems = data.get("problem", {})
    )
    self._export_softwares(
        payload = payload,
        softwares = data.get("software", {})
    )
    self._export_benchmarks(
        payload = payload,
        benchmarks = data.get("benchmark", {})
    )
    self._export_authors(
        payload = payload,
        publications = data.get("publication", {})
    )
    self._export_journals(
        payload = payload,
        publications = data.get("publication", {})
    )
    self._export_publications(
        payload = payload,
        publications = data.get("publication", {}),
        relations = [('P2A', 'ARelatant'), ('P2BS', 'BSRelatant')]
    )

    # Construct Item Payloads
    payload.add_item_payload()

    # If Relations are added, check if they exist
    if any(
        key.startswith("RELATION")
        for key in payload.get_dictionary()
    ):
        query = payload.build_relation_check_query()

        check = None
        for attempt in range(2):  # try twice
            try:
                check = query_sparql(
                    query = query,
                    sparql_endpoint = get_url('mardi', 'sparql')
                )
                break
            except Exception as e:
                logging.warning("SPARQL query attempt %s failed: %s", attempt + 1, e)
                if attempt == 0:
                    time.sleep(1)  # short wait before retry
        if not check:
            # both attempts failed → pretend no results
            check = [{}]

        payload.add_check_results(
            check = check
        )
    return payload.get_dictionary(), payload.dependency

preview(answers)

Resolve entity cross-references for the Algorithm documentation preview page.

Applies algorithm-specific relation mappings so that the preview template receives a fully-resolved answers dict.

Parameters:

Name Type Description Default
answers

Top-level answers dict (mutated in place).

required

Returns:

Type Description

The mutated answers dict.

Source code in MaRDMO/algorithm/worker.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
def preview(self, answers):
    '''Resolve entity cross-references for the Algorithm documentation preview page.

    Applies algorithm-specific relation mappings so that the preview
    template receives a fully-resolved answers dict.

    Args:
        answers: Top-level answers dict (mutated in place).

    Returns:
        The mutated *answers* dict.
    '''

    # Prepare Relations for Preview
    for relation in preview_relations:
        entity_relations(
            data = answers,
            idx = {
                'from': relation['from_idx'],
                'to': relation['to_idx']
            },
            entity = {
                'relation': relation['relation'],
                'old_name': relation['old_name'],
                'new_name': relation['new_name'],
                'encryption': relation['encryption']
            },
            order = {
                'formulation': False,
                'task': False
            },
            assumption = False,
            mapping = self.mathalgodb
        )

    return answers

Constants

Compile-time constants and configuration builders for the Algorithm catalog.

Centralises the property URIs, relation definitions, and question/item mappings that the algorithm documentation sub-package needs at runtime. Values are loaded once from the RDMO database via the getters helpers and then referenced by handlers, providers, and workers.

Provides:

  • get_relations() — returns the full relation-definition dict for algorithms
  • get_uri_prefix_map() — returns the {prefix: URI} map used to expand compact IDs
  • Module-level constants built from the above (RELATIONS, URI_PREFIX_MAP, etc.)

get_relations()

Build the relation mapping for the Algorithm Documentation.

Maps each MathAlgoDB relation URL to the corresponding Wikibase property (and optional qualifier item or direction string) used when writing statements to the MaRDI Portal.

Returns:

Type Description

Dict mapping MathAlgoDB relation URL strings to [property(, qualifier)]

lists; qualifier is either a Wikibase item ID or 'forward'/'backward'.

Source code in MaRDMO/algorithm/constants.py
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def get_relations():
    '''Build the relation mapping for the Algorithm Documentation.

    Maps each MathAlgoDB relation URL to the corresponding Wikibase property
    (and optional qualifier item or direction string) used when writing
    statements to the MaRDI Portal.

    Returns:
        Dict mapping MathAlgoDB relation URL strings to ``[property(, qualifier)]``
        lists; qualifier is either a Wikibase item ID or ``'forward'``/``'backward'``.
    '''
    mathalgodb = get_mathalgodb()
    items = get_items()
    properties = get_properties()
    relations = {
        # Map MathModDB Relation on Wikibase Property + Qualifier Item
        mathalgodb.get(key='manifests')['url']: [
            properties['manifestation of']
        ],
        mathalgodb.get(key='solves')['url']: [
            properties['solved by']
        ],
        mathalgodb.get(key='tested_by')['url']: [
            properties['tested by']
        ],
        mathalgodb.get(key='implemented_by')['url']: [
            properties['implemented by']
        ],
        mathalgodb.get(key='documents')['url']: [
            properties['described by source'],
            items['documentation']
        ],
        mathalgodb.get(key='invents')['url']: [
            properties['described by source'],
            items['invention']
        ],
        mathalgodb.get(key='studies')['url']: [
            properties['described by source'],
            items['study']
        ],
        mathalgodb.get(key='surveys')['url']: [
            properties['described by source'],
            items['review']
        ],
        mathalgodb.get(key='uses')['url']: [
            properties['described by source'],
            items['use']
        ],
        mathalgodb.get(key='applies')['url']: [
            properties['described by source'],
            items['application']
        ],
        mathalgodb.get(key='analyzes')['url']: [
            properties['described by source'],
            items['analysis']
        ],
        # Map MathModDB Relation on Wikibase Property + Direction
        mathalgodb.get(key='specialized_by')['url']: [
            properties['specialized by'],
            'forward'
        ],
        mathalgodb.get(key='specializes')['url']: [
            properties['specialized by'],
            'backward'
        ],
        mathalgodb.get(key='has_component')['url']: [
            properties['has part(s)'],
            'forward'
        ],
        mathalgodb.get(key='component_of')['url']: [
            properties['has part(s)'],
            'backward'
        ],
        mathalgodb.get(key='has_subclass')['url']: [
            properties['subclass of'],
            'forward'
        ],
        mathalgodb.get(key='subclass_of')['url']: [
            properties['subclass of'],
            'backward'
        ],
        mathalgodb.get(key='related_to')['url']: [
            properties['similar to'],
            'forward'
        ],
    }
    return relations

get_uri_prefix_map()

Build the attribute-URI → section config mapping for the Algorithm Documentation.

Maps each relation attribute URI to the corresponding questionnaire section metadata needed to add or hydrate the related entity.

Returns:

Type Description

Dict mapping full RDMO attribute URI strings to dicts with keys

question_set, question_id, and prefix.

Source code in MaRDMO/algorithm/constants.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def get_uri_prefix_map():
    '''Build the attribute-URI → section config mapping for the Algorithm Documentation.

    Maps each relation attribute URI to the corresponding questionnaire section
    metadata needed to add or hydrate the related entity.

    Returns:
        Dict mapping full RDMO attribute URI strings to dicts with keys
        ``question_set``, ``question_id``, and ``prefix``.
    '''
    questions = get_questions('algorithm')
    uri_prefix_map = {
        f'{BASE_URI}{questions["Problem"]["BRelatant"]["uri"]}': {
            "question_set": f'{BASE_URI}{questions["Benchmark"]["uri"]}',
            "question_id": f'{BASE_URI}{questions["Benchmark"]["ID"]["uri"]}',
            "prefix": "B"
        },
        f'{BASE_URI}{questions["Software"]["BRelatant"]["uri"]}': {
            "question_set": f'{BASE_URI}{questions["Benchmark"]["uri"]}',
            "question_id": f'{BASE_URI}{questions["Benchmark"]["ID"]["uri"]}',
            "prefix": "B"
        },
        f'{BASE_URI}{questions["Algorithm"]["PRelatant"]["uri"]}': {
            "question_set": f'{BASE_URI}{questions["Problem"]["uri"]}',
            "question_id": f'{BASE_URI}{questions["Problem"]["ID"]["uri"]}',
            "prefix": "AT"
        },
        f'{BASE_URI}{questions["Algorithm"]["SRelatant"]["uri"]}': {
            "question_set": f'{BASE_URI}{questions["Software"]["uri"]}',
            "question_id": f'{BASE_URI}{questions["Software"]["ID"]["uri"]}',
            "prefix": "S"
        }
    }
    return uri_prefix_map