"""Authored restricted type/subclass/domain/range closure, separate from labels and SKOS-like broader concepts."""
import json
TRIPLES={('Quote','subClassOf','Document'),('q7','type','Quote'),('q7','aboutAccount','a1'),('q8','aboutAccount','a2'),('aboutAccount','domain','Document'),('aboutAccount','range','Account')}
def closure(triples):
    result=set(triples);rounds=[]
    while True:
        new=set()
        for s,p,o in result:
            if p=='subClassOf':
                new|={(s,'subClassOf',b) for a,r,b in result if a==o and r=='subClassOf'}
            if p=='type':
                new|={(s,'type',b) for a,r,b in result if a==o and r=='subClassOf'}
            new|={(s,'type',b) for a,r,b in result if a==p and r=='domain'}
            new|={(o,'type',b) for a,r,b in result if a==p and r=='range'}
        new-=result
        if not new:break
        rounds.append(sorted(new));result|=new
    return result,rounds
def demo():
    result,rounds=closure(TRIPLES)
    required={('q7','type','Document'),('q8','type','Document'),('a1','type','Account'),('a2','type','Account')}
    assert required<=result and len(result)==10
    assert ('q8','type','Quote') not in result
    labels={'cQuote':{'preferred_fa':'پیش فاکتور','alternative_fa':['پیش‌فاکتور']},'cDocument':{'preferred_fa':'سند','alternative_fa':[]}}
    concept_edges=[('cQuote','broader','cDocument'),('cDocument','broader','cResource')]
    assert ('cQuote','broader','cResource') not in concept_edges
    return {'asserted_triples':sorted(TRIPLES),'inferred_rounds':rounds,'restricted_closure':sorted(result),'term_labels_separate_from_classes':labels,'direct_concept_edges':concept_edges,'broader_transitivity_not_assumed':True,'missing_q8_Quote_type_means_not_derived_not_false':True,'domain_range_used_to_infer_type_not_validate_or_reject_statement':True,'complete_RDF_RDFS_OWL_parser_or_reasoner_executed':False,'real_invoice_customer_or_document_created':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
