def validate(val, xpathContext=None, parametersOnly=False, statusMsg='', compileOnly=False):
    for e in ("xbrl.5.1.4.3:cycles", "xbrlgene:violatedCyclesConstraint"):
        if e in val.modelXbrl.errors:
            val.modelXbrl.info("info", _("Formula validation skipped due to %(error)s error"),
                                modelObject=val.modelXbrl, error=e)
            return
    
    val.modelXbrl.profileStat()
    formulaOptions = val.modelXbrl.modelManager.formulaOptions
    if XPathParser.initializeParser(val.modelXbrl.modelManager):
        val.modelXbrl.profileStat(_("initializeXPath2Grammar")) # only provide stat when not yet initialized
    val.modelXbrl.modelManager.showStatus(statusMsg)
    val.modelXbrl.profileActivity()
    initialErrorCount = val.modelXbrl.logCount.get(logging._checkLevel('ERROR'), 0)
    
    # global parameter names
    parameterQnames = set()
    instanceQnames = set()
    parameterDependencies = {}
    instanceDependencies = defaultdict(set)  # None-key entries are non-formula dependencies
    dependencyResolvedParameters = set()
    orderedParameters = []
    orderedInstances = []
    for paramQname, modelParameter in val.modelXbrl.qnameParameters.items():
        if isinstance(modelParameter, ModelParameter):
            modelParameter.compile()
            parameterDependencies[paramQname] = modelParameter.variableRefs()
            parameterQnames.add(paramQname)
            if isinstance(modelParameter, ModelInstance):
                instanceQnames.add(paramQname)
            # duplicates checked on loading modelDocument
            
    #resolve dependencies
    resolvedAParameter = True
    while (resolvedAParameter):
        resolvedAParameter = False
        for paramQname in parameterQnames:
            if paramQname not in dependencyResolvedParameters and \
               len(parameterDependencies[paramQname] - dependencyResolvedParameters) == 0:
                dependencyResolvedParameters.add(paramQname)
                orderedParameters.append(paramQname)
                resolvedAParameter = True
    # anything unresolved?
    for paramQname in parameterQnames:
        if paramQname not in dependencyResolvedParameters:
            circularOrUndefDependencies = parameterDependencies[paramQname] - dependencyResolvedParameters
            undefinedVars = circularOrUndefDependencies - parameterQnames 
            paramsCircularDep = circularOrUndefDependencies - undefinedVars
            if len(undefinedVars) > 0:
                val.modelXbrl.error("xbrlve:unresolvedDependency",
                    _("Undefined dependencies in parameter %(name)s, to names %(dependencies)s"),
                    modelObject=val.modelXbrl.qnameParameters[paramQname],
                    name=paramQname, dependencies=", ".join((str(v) for v in undefinedVars)))
            if len(paramsCircularDep) > 0:
                val.modelXbrl.error("xbrlve:parameterCyclicDependencies",
                    _("Cyclic dependencies in parameter %(name)s, to names %(dependencies)s"),
                    modelObject=val.modelXbrl.qnameParameters[paramQname],
                    name=paramQname, dependencies=", ".join((str(d) for d in paramsCircularDep)) )
    val.modelXbrl.profileActivity("... formula parameter checks", minTimeToShow=1.0)
            
    for custFnSig in val.modelXbrl.modelCustomFunctionSignatures.values():
        # entries indexed by qname, arity are signature, by qname are just for parser (value=None)
        if custFnSig is not None:
            custFnQname = custFnSig.functionQname
            if custFnQname.namespaceURI == XbrlConst.xfi:
                val.modelXbrl.error("xbrlve:noProhibitedNamespaceForCustomFunction",
                    _("Custom function %(name)s has namespace reserved for functions in the function registry %(namespace)s"),
                    modelObject=custFnSig, name=custFnQname, namespace=custFnQname.namespaceURI )
            # check types
            _outputType = custFnSig.outputType
            if _outputType and _outputType.namespaceURI == XbrlConst.xsd and not FunctionXs.isXsType(_outputType.localName):
                val.modelXbrl.error("xbrlve:invalidDatatypeInCustomFunctionSignature",
                    _("Custom Function Signature %(name)s output type %(type)s is not valid"), 
                    modelObject=custFnSig, name=custFnQname, type=_outputType)
            for _inputType in custFnSig.inputTypes:
                if _inputType and _inputType.namespaceURI == XbrlConst.xsd and not FunctionXs.isXsType(_inputType.localName):
                    val.modelXbrl.error("xbrlve:invalidDatatypeInCustomFunctionSignature",
                        _("Custom Function Signature %(name)s input type %(type)s is not valid"), 
                        modelObject=custFnSig, name=custFnQname, type=_inputType)
            # any custom function implementations?
            for modelRel in val.modelXbrl.relationshipSet(XbrlConst.functionImplementation).fromModelObject(custFnSig):
                custFnImpl = modelRel.toModelObject
                custFnSig.customFunctionImplementation = custFnImpl
                if len(custFnImpl.inputNames) != len(custFnSig.inputTypes):
                    val.modelXbrl.error("xbrlcfie:inputMismatch",
                        _("Custom function %(name)s signature has %(parameterCountSignature)s parameters but implementation has %(parameterCountImplementation)s, must be matching"),
                        modelObject=custFnSig, name=custFnQname, 
                        parameterCountSignature=len(custFnSig.inputTypes), parameterCountImplementation=len(custFnImpl.inputNames) )
        
    for custFnImpl in val.modelXbrl.modelCustomFunctionImplementations:
        if not val.modelXbrl.relationshipSet(XbrlConst.functionImplementation).toModelObject(custFnImpl):
            val.modelXbrl.error("xbrlcfie:missingCFIRelationship",
                _("Custom function implementation %(xlinkLabel)s has no relationship from any custom function signature"),
                modelObject=custFnSig, xlinkLabel=custFnImpl.xlinkLabel)
        custFnImpl.compile()
    val.modelXbrl.profileActivity("... custom function checks and compilation", minTimeToShow=1.0)
            
    # xpathContext is needed for filter setup for expressions such as aspect cover filter
    # determine parameter values
    
    if xpathContext is None:
        xpathContext = XPathContext.create(val.modelXbrl) 
    xpathContext.parameterQnames = parameterQnames  # needed for formula filters to determine variable dependencies
    for paramQname in orderedParameters:
        modelParameter = val.modelXbrl.qnameParameters[paramQname]
        if not isinstance(modelParameter, ModelInstance):
            asType = modelParameter.asType
            if asType and asType.namespaceURI == XbrlConst.xsd and not FunctionXs.isXsType(asType.localName):
                val.modelXbrl.error("xbrlve:parameterTypeMismatch",
                    _("Parameter %(name)s type %(type)s is not valid"), 
                    modelObject=modelParameter, name=paramQname, type=asType)
            asLocalName = asType.localName if asType else "string"
            try:
                if val.parameters and paramQname in val.parameters:
                    paramDataType, paramValue = val.parameters[paramQname]
                    typeLocalName = paramDataType.localName if paramDataType else "string"
                    value = FunctionXs.call(xpathContext, None, typeLocalName, [paramValue])
                    result = FunctionXs.call(xpathContext, None, asLocalName, [value])
                    if formulaOptions.traceParameterInputValue:
                        val.modelXbrl.info("formula:trace",
                            _("Parameter %(name)s input value %(input)s"), 
                            modelObject=modelParameter, name=paramQname, input=result)
                    xpathContext.inScopeVars[paramQname] = result    # make visible to subsequent parameter expression 
                elif modelParameter.isRequired:
                    val.modelXbrl.error("xbrlve:missingParameterValue",
                        _("Parameter %(name)s is required but not input"), 
                        modelObject=modelParameter, name=paramQname)
                elif not modelParameter.selectProg:
                    val.modelXbrl.error("xbrlve:missingParameterValue",
                        _("Parameter %(name)s does not have a select attribute"), 
                        modelObject=modelParameter, name=paramQname)
                else:
                    result = modelParameter.evaluate(xpathContext, asType)
                    if formulaOptions.traceParameterExpressionResult:
                        val.modelXbrl.info("formula:trace",
                            _("Parameter %(name)s select result %(result)s"), 
                            modelObject=modelParameter, name=paramQname, result=result)
                    xpathContext.inScopeVars[paramQname] = result    # make visible to subsequent parameter expression 
            except XPathContext.XPathException as err:
                val.modelXbrl.error("xbrlve:parameterTypeMismatch" if err.code == "err:FORG0001" else err.code,
                    _("Parameter \n%(name)s \nException: \n%(error)s"), 
                    modelObject=modelParameter, name=paramQname, error=err.message,
                    messageCodes=("xbrlve:parameterTypeMismatch", "err:FORG0001"))
        ''' Removed as per WG discussion 2012-12-20. This duplication checking unfairly presupposes URI based
           implementation and exceeds the scope of linkbase validation
        elif not parametersOnly: # is a modelInstance
            if val.parameters and paramQname in val.parameters:
                instanceModelXbrls = val.parameters[paramQname][1]
                instanceUris = set()
                for instanceModelXbrl in instanceModelXbrls:
                    if instanceModelXbrl.uri in instanceUris:
                        val.modelXbrl.error("xbrlvarinste:inputInstanceDuplication",
                            _("Input instance resource %(instName)s has multiple XBRL instances %(uri)s"), 
                            modelObject=modelParameter, instName=paramQname, uri=instanceModelXbrl.uri)
                    instanceUris.add(instanceModelXbrl.uri)
        if val.parameters and XbrlConst.qnStandardInputInstance in val.parameters: # standard input instance has
            if len(val.parameters[XbrlConst.qnStandardInputInstance][1]) != 1:
                val.modelXbrl.error("xbrlvarinste:standardInputInstanceNotUnique",
                    _("Standard input instance resource parameter has multiple XBRL instances"), 
                    modelObject=modelParameter)
        '''
    val.modelXbrl.profileActivity("... parameter checks and select evaluation", minTimeToShow=1.0)
    
    val.modelXbrl.profileStat(_("parametersProcessing"))

    # check typed dimension equality test
    val.modelXbrl.modelFormulaEqualityDefinitions = {}
    for modelRel in val.modelXbrl.relationshipSet(XbrlConst.equalityDefinition).modelRelationships:
        typedDomainElt = modelRel.fromModelObject
        modelEqualityDefinition = modelRel.toModelObject
        if typedDomainElt in val.modelXbrl.modelFormulaEqualityDefinitions:
            val.modelXbrl.error("xbrlve:multipleTypedDimensionEqualityDefinitions",
                _("Multiple typed domain definitions from %(typedDomain)s to %(equalityDefinition1)s and %(equalityDefinition2)s"),
                 modelObject=modelRel.arcElement, typedDomain=typedDomainElt.qname,
                 equalityDefinition1=modelEqualityDefinition.xlinkLabel,
                 equalityDefinition2=val.modelXbrl.modelFormulaEqualityDefinitions[typedDomainElt].xlinkLabel)
        else:
            modelEqualityDefinition.compile()
            val.modelXbrl.modelFormulaEqualityDefinitions[typedDomainElt] = modelEqualityDefinition
            
    if parametersOnly:
        return

    for modelVariableSet in val.modelXbrl.modelVariableSets:
        modelVariableSet.compile()
    val.modelXbrl.profileStat(_("formulaCompilation"))

    produceOutputXbrlInstance = False
    instanceProducingVariableSets = defaultdict(list)
        
    for modelVariableSet in val.modelXbrl.modelVariableSets:
        varSetInstanceDependencies = set()
        if isinstance(modelVariableSet, ModelFormula):
            instanceQname = None
            for modelRel in val.modelXbrl.relationshipSet(XbrlConst.formulaInstance).fromModelObject(modelVariableSet):
                instance = modelRel.toModelObject
                if isinstance(instance, ModelInstance):
                    if instanceQname is None:
                        instanceQname = instance.instanceQname
                        modelVariableSet.fromInstanceQnames = {instanceQname} # required if referred to by variables scope chaining
                    else:
                        val.modelXbrl.info("arelle:multipleOutputInstances",
                            _("Multiple output instances for formula %(xlinkLabel)s, to names %(instanceTo)s, %(instanceTo2)s"),
                            modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, 
                            instanceTo=instanceQname, instanceTo2=instance.instanceQname)
            if instanceQname is None: 
                instanceQname = XbrlConst.qnStandardOutputInstance
                instanceQnames.add(instanceQname)
                modelVariableSet.fromInstanceQnames = None # required if referred to by variables scope chaining
            modelVariableSet.outputInstanceQname = instanceQname
            if getattr(val, "validateSBRNL", False): # may not exist on some val objects
                val.modelXbrl.error("SBR.NL.2.3.9.03",
                    _("Formula:formula %(xlinkLabel)s is not allowed"),
                    modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel)
        else:
            instanceQname = None
            modelVariableSet.countSatisfied = 0
            modelVariableSet.countNotSatisfied = 0
            checkValidationMessages(val, modelVariableSet)
        instanceProducingVariableSets[instanceQname].append(modelVariableSet)
        modelVariableSet.outputInstanceQname = instanceQname
        if modelVariableSet.aspectModel not in ("non-dimensional", "dimensional"):
            val.modelXbrl.error("xbrlve:unknownAspectModel",
                _("Variable set %(xlinkLabel)s, aspect model %(aspectModel)s not recognized"),
                modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, aspectModel=modelVariableSet.aspectModel)
        modelVariableSet.hasConsistencyAssertion = False
            
        #determine dependencies within variable sets
        nameVariables = {}
        qnameRels = {}
        definedNamesSet = set()
        for modelRel in val.modelXbrl.relationshipSet(XbrlConst.variableSet).fromModelObject(modelVariableSet):
            varqname = modelRel.variableQname
            if varqname:
                qnameRels[varqname] = modelRel
                toVariable = modelRel.toModelObject
                if varqname not in definedNamesSet:
                    definedNamesSet.add(varqname)
                if varqname not in nameVariables:
                    nameVariables[varqname] = toVariable
                elif nameVariables[varqname] != toVariable:
                    val.modelXbrl.error("xbrlve:duplicateVariableNames",
                        _("Multiple variables named %(xlinkLabel)s in variable set %(name)s"),
                        modelObject=toVariable, xlinkLabel=modelVariableSet.xlinkLabel, name=varqname )
                fromInstanceQnames = None
                for instRel in val.modelXbrl.relationshipSet(XbrlConst.instanceVariable).toModelObject(toVariable):
                    fromInstance = instRel.fromModelObject
                    if isinstance(fromInstance, ModelInstance):
                        fromInstanceQname = fromInstance.instanceQname
                        varSetInstanceDependencies.add(fromInstanceQname)
                        instanceDependencies[instanceQname].add(fromInstanceQname)
                        if fromInstanceQnames is None: fromInstanceQnames = set()
                        fromInstanceQnames.add(fromInstanceQname)
                if fromInstanceQnames is None:
                    varSetInstanceDependencies.add(XbrlConst.qnStandardInputInstance)
                    if instanceQname: instanceDependencies[instanceQname].add(XbrlConst.qnStandardInputInstance)
                toVariable.fromInstanceQnames = fromInstanceQnames
            else:
                val.modelXbrl.error("xbrlve:variableNameResolutionFailure",
                    _("Variables name %(name)s cannot be determined on arc from %(xlinkLabel)s"),
                    modelObject=modelRel, xlinkLabel=modelVariableSet.xlinkLabel, name=modelRel.variablename )
        checkVariablesScopeVisibleQnames(val, nameVariables, definedNamesSet, modelVariableSet)
        definedNamesSet |= parameterQnames
                
        variableDependencies = {}
        for modelRel in val.modelXbrl.relationshipSet(XbrlConst.variableSet).fromModelObject(modelVariableSet):
            variable = modelRel.toModelObject
            if isinstance(variable, (ModelParameter,ModelVariable)):    # ignore anything not parameter or variable
                varqname = modelRel.variableQname
                depVars = variable.variableRefs()
                variableDependencies[varqname] = depVars
                if len(depVars) > 0 and formulaOptions.traceVariablesDependencies:
                    val.modelXbrl.info("formula:trace",
                        _("Variable set %(xlinkLabel)s, variable %(name)s, dependences %(dependencies)s"),
                        modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, 
                        name=varqname, dependencies=depVars)
                definedNamesSet.add(varqname)
                # check for fallback value variable references
                if isinstance(variable, ModelFactVariable):
                    variable.hasNoVariableDependencies = len(depVars - parameterQnames) == 0
                    for depVar in XPathParser.variableReferencesSet(variable.fallbackValueProg, variable):
                        if depVar in qnameRels and isinstance(qnameRels[depVar].toModelObject,ModelVariable):
                            val.modelXbrl.error("xbrlve:fallbackValueVariableReferenceNotAllowed",
                                _("Variable set %(xlinkLabel)s fallbackValue '%(fallbackValue)s' cannot refer to variable %(dependency)s"),
                                modelObject=variable, xlinkLabel=modelVariableSet.xlinkLabel, 
                                fallbackValue=variable.fallbackValue, dependency=depVar)
                    # check for covering aspect not in variable set aspect model
                    checkFilterAspectModel(val, modelVariableSet, variable.filterRelationships, xpathContext)

        orderedNameSet = set()
        orderedNameList = []
        orderedAVariable = True
        while (orderedAVariable):
            orderedAVariable = False
            for varqname, depVars in variableDependencies.items():
                if varqname not in orderedNameSet and len(depVars - parameterQnames - orderedNameSet) == 0:
                    orderedNameList.append(varqname)
                    orderedNameSet.add(varqname)
                    orderedAVariable = True
                if varqname in instanceQnames:
                    varSetInstanceDependencies.add(varqname)
                    instanceDependencies[instanceQname].add(varqname)
                elif isinstance(nameVariables.get(varqname), ModelInstance):
                    instqname = nameVariables[varqname].instanceQname
                    varSetInstanceDependencies.add(instqname)
                    instanceDependencies[instanceQname].add(instqname)
                    
        # anything unresolved?
        for varqname, depVars in variableDependencies.items():
            if varqname not in orderedNameSet:
                circularOrUndefVars = depVars - parameterQnames - orderedNameSet
                undefinedVars = circularOrUndefVars - definedNamesSet 
                varsCircularDep = circularOrUndefVars - undefinedVars
                if len(undefinedVars) > 0:
                    val.modelXbrl.error("xbrlve:unresolvedDependency",
                        _("Undefined variable dependencies in variable set %(xlinkLabel)s, from variable %(nameFrom)s to %(nameTo)s"),
                        modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, 
                        nameFrom=varqname, nameTo=undefinedVars)
                if len(varsCircularDep) > 0:
                    val.modelXbrl.error("xbrlve:cyclicDependencies",
                        _("Cyclic dependencies in variable set %(xlinkLabel)s, from variable %(nameFrom)s to %(nameTo)s"),
                        modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, 
                        nameFrom=varqname, nameTo=varsCircularDep )
                    
        # check unresolved variable set dependencies
        for varSetDepVarQname in modelVariableSet.variableRefs():
            if varSetDepVarQname not in definedNamesSet and varSetDepVarQname not in parameterQnames:
                val.modelXbrl.error("xbrlve:unresolvedDependency",
                    _("Undefined variable dependency in variable set %(xlinkLabel)s, %(name)s"),
                    modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel,
                    name=varSetDepVarQname)
            if varSetDepVarQname in instanceQnames:
                varSetInstanceDependencies.add(varSetDepVarQname)
                instanceDependencies[instanceQname].add(varSetDepVarQname)
            elif isinstance(nameVariables.get(varSetDepVarQname), ModelInstance):
                instqname = nameVariables[varSetDepVarQname].instanceQname
                varSetInstanceDependencies.add(instqname)
                instanceDependencies[instanceQname].add(instqname)
        
        if formulaOptions.traceVariablesOrder:
            val.modelXbrl.info("formula:trace",
                   _("Variable set %(xlinkLabel)s, variables order: %(dependencies)s"),
                   modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, dependencies=orderedNameList)
        
        if (formulaOptions.traceVariablesDependencies and len(varSetInstanceDependencies) > 0 and
            varSetInstanceDependencies != {XbrlConst.qnStandardInputInstance}):
            val.modelXbrl.info("formula:trace",
                   _("Variable set %(xlinkLabel)s, instance dependences %(dependencies)s"),
                   modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, dependencies=varSetInstanceDependencies)
            
        modelVariableSet.orderedVariableRelationships = []
        for varqname in orderedNameList:
            if varqname in qnameRels:
                modelVariableSet.orderedVariableRelationships.append(qnameRels[varqname])
        
        orderedNameSet.clear()       
        del orderedNameList[:]  # dereference            
                
        # check existence assertion @test variable dependencies (not including precondition references)
        if isinstance(modelVariableSet, ModelExistenceAssertion):
            for depVar in XPathParser.variableReferencesSet(modelVariableSet.testProg, modelVariableSet):
                if depVar in qnameRels and isinstance(qnameRels[depVar].toModelObject,ModelVariable):
                    val.modelXbrl.error("xbrleae:variableReferenceNotAllowed",
                        _("Existence Assertion %(xlinkLabel)s, cannot refer to variable %(name)s"),
                        modelObject=modelVariableSet, xlinkLabel=modelVariableSet.xlinkLabel, name=depVar)
                    
        # check messages variable dependencies
        checkValidationMessageVariables(val, modelVariableSet, qnameRels, xpathContext.parameterQnames)

        if isinstance(modelVariableSet, ModelFormula): # check consistency assertion message variables and its messages variables
            for consisAsserRel in val.modelXbrl.relationshipSet(XbrlConst.consistencyAssertionFormula).toModelObject(modelVariableSet):
                consisAsser = consisAsserRel.fromModelObject
                if isinstance(consisAsser, ModelConsistencyAssertion):
                    checkValidationMessages(val, consisAsser)
                    checkValidationMessageVariables(val, consisAsser, qnameRels, xpathContext.parameterQnames)
                        
        # check preconditions
        modelVariableSet.preconditions = []
        for modelRel in val.modelXbrl.relationshipSet(XbrlConst.variableSetPrecondition).fromModelObject(modelVariableSet):
            precondition = modelRel.toModelObject
            if isinstance(precondition, ModelPrecondition):
                modelVariableSet.preconditions.append(precondition)
                
        # check for variable sets referencing fact or general variables
        for modelRel in val.modelXbrl.relationshipSet(XbrlConst.variableSetFilter).fromModelObject(modelVariableSet):
            varSetFilter = modelRel.toModelObject
            if modelRel.isCovered:
                val.modelXbrl.warning("arelle:variableSetFilterCovered",
                    _("Variable set %(xlinkLabel)s, filter %(filterLabel)s, cannot be covered"),
                     modelObject=varSetFilter, xlinkLabel=modelVariableSet.xlinkLabel, filterLabel=varSetFilter.xlinkLabel)
                modelRel._isCovered = False # block group filter from being able to covered
                
            for depVar in varSetFilter.variableRefs():
                if depVar in qnameRels and isinstance(qnameRels[depVar].toModelObject,ModelVariable):
                    val.modelXbrl.error("xbrlve:factVariableReferenceNotAllowed",
                        _("Variable set %(xlinkLabel)s, filter %(filterLabel)s, cannot refer to variable %(name)s"),
                        modelObject=varSetFilter, xlinkLabel=modelVariableSet.xlinkLabel, filterLabel=varSetFilter.xlinkLabel, name=depVar)
                    
        # check aspects of formula
        if isinstance(modelVariableSet, ModelFormula):
            checkFormulaRules(val, modelVariableSet, nameVariables)

        nameVariables.clear() # dereference
        qnameRels.clear()
        definedNamesSet.clear()
        variableDependencies.clear()
        varSetInstanceDependencies.clear()

    val.modelXbrl.profileActivity("... assertion and formula checks and compilation", minTimeToShow=1.0)
            
    for modelTable in val.modelXbrl.modelRenderingTables:
        modelTable.fromInstanceQnames = None # required if referred to by variables scope chaining
        if modelTable.aspectModel not in ("non-dimensional", "dimensional"):
            val.modelXbrl.error("xbrlte:unknownAspectModel",
                _("Table %(xlinkLabel)s, aspect model %(aspectModel)s not recognized"),
                modelObject=modelTable, xlinkLabel=modelTable.xlinkLabel, aspectModel=modelTable.aspectModel)
        modelTable.compile()
        checkTableRules(val, xpathContext, modelTable)

    val.modelXbrl.profileActivity("... rendering tables and axes checks and compilation", minTimeToShow=1.0)
            
    # determine instance dependency order
    orderedInstancesSet = set()
    stdInpInst = {XbrlConst.qnStandardInputInstance}
    orderedInstancesList = []
    orderedAnInstance = True
    while (orderedAnInstance):
        orderedAnInstance = False
        for instqname, depInsts in instanceDependencies.items():
            if instqname and instqname not in orderedInstancesSet and len(depInsts - stdInpInst - orderedInstancesSet) == 0:
                orderedInstancesList.append(instqname)
                orderedInstancesSet.add(instqname)
                orderedAnInstance = True
    # add instances with variable sets with no variables or other dependencies
    for independentInstance in _DICT_SET(instanceProducingVariableSets.keys()) - _DICT_SET(orderedInstancesList): # must be set for 2.7 compatibility
        orderedInstancesList.append(independentInstance)
        orderedInstancesSet.add(independentInstance)
    if None not in orderedInstancesList:
        orderedInstancesList.append(None)  # assertions come after all formulas that produce outputs

    # anything unresolved?
    for instqname, depInsts in instanceDependencies.items():
        if instqname not in orderedInstancesSet:
            # can also be satisfied from an input DTS
            missingDependentInstances = depInsts - stdInpInst
            if val.parameters: missingDependentInstances -= _DICT_SET(val.parameters.keys()) 
            if instqname:
                if missingDependentInstances:
                    val.modelXbrl.error("xbrlvarinste:instanceVariableRecursionCycle",
                        _("Cyclic dependencies of instance %(name)s produced by a formula, with variables consuming instances %(dependencies)s"),
                        modelObject=val.modelXbrl,
                        name=instqname, dependencies=missingDependentInstances )
                elif instqname == XbrlConst.qnStandardOutputInstance:
                    orderedInstancesSet.add(instqname)
                    orderedInstancesList.append(instqname) # standard output formula, all input dependencies in parameters
            ''' future check?  if instance has no external input or producing formula
            else:
                val.modelXbrl.error("xbrlvarinste:instanceVariableRecursionCycle",
                    _("Unresolved dependencies of an assertion's variables on instances %(dependencies)s"),
                    dependencies=str(_DICT_SET(depInsts) - stdInpInst) )
            '''
        elif instqname in depInsts: # check for direct cycle
            val.modelXbrl.error("xbrlvarinste:instanceVariableRecursionCycle",
                _("Cyclic dependencies of instance %(name)s produced by its own variables"),
                modelObject=val.modelXbrl, name=instqname )

    if formulaOptions.traceVariablesOrder and len(orderedInstancesList) > 1:
        val.modelXbrl.info("formula:trace",
               _("Variable instances processing order: %(dependencies)s"),
                modelObject=val.modelXbrl, dependencies=orderedInstancesList)

    # linked consistency assertions
    for modelRel in val.modelXbrl.relationshipSet(XbrlConst.consistencyAssertionFormula).modelRelationships:
        if (modelRel.fromModelObject is not None and modelRel.toModelObject is not None and 
            isinstance(modelRel.toModelObject,ModelFormula)):
            consisAsser = modelRel.fromModelObject
            consisAsser.countSatisfied = 0
            consisAsser.countNotSatisfied = 0
            if consisAsser.hasProportionalAcceptanceRadius and consisAsser.hasAbsoluteAcceptanceRadius:
                val.modelXbrl.error("xbrlcae:acceptanceRadiusConflict",
                    _("Consistency assertion %(xlinkLabel)s has both absolute and proportional acceptance radii"), 
                    modelObject=consisAsser, xlinkLabel=consisAsser.xlinkLabel)
            consisAsser.orderedVariableRelationships = []
            for consisParamRel in val.modelXbrl.relationshipSet(XbrlConst.consistencyAssertionParameter).fromModelObject(consisAsser):
                if isinstance(consisParamRel.toModelObject, ModelVariable):
                    val.modelXbrl.error("xbrlcae:variablesNotAllowed",
                        _("Consistency assertion %(xlinkLabel)s has relationship to a %(elementTo)s %(xlinkLabelTo)s"),
                        modelObject=consisAsser, xlinkLabel=consisAsser.xlinkLabel, 
                        elementTo=consisParamRel.toModelObject.localName, xlinkLabelTo=consisParamRel.toModelObject.xlinkLabel)
                elif isinstance(consisParamRel.toModelObject, ModelParameter):
                    consisAsser.orderedVariableRelationships.append(consisParamRel)
            consisAsser.compile()
            modelRel.toModelObject.hasConsistencyAssertion = True
    val.modelXbrl.profileActivity("... consistency assertion setup", minTimeToShow=1.0)

    # validate default dimensions in instances and accumulate multi-instance-default dimension aspects
    xpathContext.defaultDimensionAspects = set(val.modelXbrl.qnameDimensionDefaults.keys())
    xpathContext.dimensionsAspectUniverse = xpathContext.defaultDimensionAspects
    for cntx in val.modelXbrl.contexts.values(): # note that this maybe should not include unreferenced contexts
        xpathContext.dimensionsAspectUniverse |= _DICT_SET(cntx.qnameDims.keys())
    
    #xpathContext.reportedDimensionAspects = set()
    #_evaluatedContexts = set()
    for instanceQname in instanceQnames:
        if (instanceQname not in (XbrlConst.qnStandardInputInstance,XbrlConst.qnStandardOutputInstance) and
            val.parameters and instanceQname in val.parameters):
            for namedInstance in val.parameters[instanceQname][1]:
                ValidateXbrlDimensions.loadDimensionDefaults(namedInstance)
                xpathContext.defaultDimensionAspects |= _DICT_SET(namedInstance.qnameDimensionDefaults.keys())
                xpathContext.dimensionsAspectUniverse |= _DICT_SET(namedInstance.qnameDimensionDefaults.keys())
                for cntx in namedInstance.contexts.values():
                    xpathContext.dimensionsAspectUniverse |= _DICT_SET(cntx.qnameDims.keys())
                #for fact in namedInstance.factsInInstance: 
                #    _cntx = fact.context
                #    if fact.isItem and _cntx is not None and _cntx not in _evaluatedContexts:
                #        xpathContext.reportedDimensionAspects |= _DICT_SET(_cntx.qnameDims.keys())
    #del _evaluatedContexts # dereference
    #xpathContext.reportedDefaultDimensionAspects = xpathContext.defaultDimensionAspects & xpathContext.reportedDimensionAspects


    # determine reportedDimensionAspects (for which facts report any value of the dimension)
    
    # check for variable set dependencies across output instances produced
    for instanceQname, modelVariableSets in instanceProducingVariableSets.items():
        for modelVariableSet in modelVariableSets:
            for varScopeRel in val.modelXbrl.relationshipSet(XbrlConst.variablesScope).toModelObject(modelVariableSet):
                if varScopeRel.fromModelObject is not None:
                    sourceVariableSet = varScopeRel.fromModelObject
                    if sourceVariableSet.outputInstanceQname != instanceQname:
                        val.modelXbrl.error("xbrlvarscopee:differentInstances",
                            _("Variable set %(xlinkLabel1)s in instance %(instance1)s has variables scope relationship to varaible set %(xlinkLabel2)s in instance %(instance2)s"),
                            modelObject=modelVariableSet, 
                            xlinkLabel1=sourceVariableSet.xlinkLabel, instance1=sourceVariableSet.outputInstanceQname,
                            xlinkLabel2=modelVariableSet.xlinkLabel, instance2=modelVariableSet.outputInstanceQname)
                    if sourceVariableSet.aspectModel != modelVariableSet.aspectModel:
                        val.modelXbrl.error("xbrlvarscopee:conflictingAspectModels",
                            _("Variable set %(xlinkLabel1)s aspectModel (%(aspectModel1)s) differs from varaible set %(xlinkLabel2)s aspectModel (%(aspectModel2)s)"),
                            modelObject=modelVariableSet, 
                            xlinkLabel1=sourceVariableSet.xlinkLabel, aspectModel1=sourceVariableSet.aspectModel,
                            xlinkLabel2=modelVariableSet.xlinkLabel, aspectModel2=modelVariableSet.aspectModel)
    val.modelXbrl.profileActivity("... instances scopes and setup", minTimeToShow=1.0)

    val.modelXbrl.profileStat(_("formulaValidation"))
    if (initialErrorCount < val.modelXbrl.logCount.get(logging._checkLevel('ERROR'), 0) or
        compileOnly or 
        getattr(val, "validateFormulaCompileOnly", False)):
        return  # don't try to execute
        

    # formula output instances    
    if instanceQnames:      
        val.modelXbrl.modelManager.showStatus(_("initializing formula output instances"))
        schemaRefs = [val.modelXbrl.modelDocument.relativeUri(referencedDoc.uri)
                        for referencedDoc in val.modelXbrl.modelDocument.referencesDocument.keys()
                            if referencedDoc.type == ModelDocument.Type.SCHEMA]
        
    outputXbrlInstance = None
    for instanceQname in instanceQnames:
        if instanceQname == XbrlConst.qnStandardInputInstance:
            continue    # always present the standard way
        if val.parameters and instanceQname in val.parameters:
            namedInstance = val.parameters[instanceQname][1] # this is a sequence
        else:   # empty intermediate instance 
            uri = val.modelXbrl.modelDocument.filepath[:-4] + "-output-XBRL-instance"
            if instanceQname != XbrlConst.qnStandardOutputInstance:
                uri = uri + "-" + instanceQname.localName
            uri = uri + ".xml"
            namedInstance = ModelXbrl.create(val.modelXbrl.modelManager, 
                                             newDocumentType=ModelDocument.Type.INSTANCE,
                                             url=uri,
                                             schemaRefs=schemaRefs,
                                             isEntry=True)
            ValidateXbrlDimensions.loadDimensionDefaults(namedInstance) # need dimension defaults 
        xpathContext.inScopeVars[instanceQname] = namedInstance
        if instanceQname == XbrlConst.qnStandardOutputInstance:
            outputXbrlInstance = namedInstance
    val.modelXbrl.profileActivity("... output instances setup", minTimeToShow=1.0)
    val.modelXbrl.profileStat(_("formulaInstancesSetup"))
    timeFormulasStarted = time.time()
        
    val.modelXbrl.modelManager.showStatus(_("running formulae"))
    
    # IDs may be "|" or whitespace separated
    runIDs = (formulaOptions.runIDs or '').replace('|',' ').split()
    if runIDs:
        val.modelXbrl.info("formula:trace",
                           _("Formua/assertion IDs restriction: %(ids)s"), 
                           modelXbrl=val.modelXbrl, ids=', '.join(runIDs))
        
    # evaluate consistency assertions
    try:
        if hasattr(val, "maxFormulaRunTime") and val.maxFormulaRunTime > 0:
            maxFormulaRunTimeTimer = Timer(val.maxFormulaRunTime * 60.0, xpathContext.runTimeExceededCallback)
            maxFormulaRunTimeTimer.start()
        else:
            maxFormulaRunTimeTimer = None
        # evaluate variable sets not in consistency assertions
        from arelle.FormulaEvaluator import init as formulaEvaluatorInit, evaluate
        formulaEvaluatorInit() # one-time module initialization
        val.modelXbrl.profileActivity("... evaluations", minTimeToShow=1.0)
        for instanceQname in orderedInstancesList:
            for modelVariableSet in instanceProducingVariableSets[instanceQname]:
                # produce variable evaluations if no dependent variables-scope relationships
                if not val.modelXbrl.relationshipSet(XbrlConst.variablesScope).toModelObject(modelVariableSet):
                    if (not runIDs or 
                        modelVariableSet.id in runIDs or
                        (modelVariableSet.hasConsistencyAssertion and 
                         any(modelRel.fromModelObject.id in runIDs
                             for modelRel in val.modelXbrl.relationshipSet(XbrlConst.consistencyAssertionFormula).toModelObject(modelVariableSet)
                             if isinstance(modelRel.fromModelObject, ModelConsistencyAssertion)))):
                        try:
                            varSetId = (modelVariableSet.id or modelVariableSet.xlinkLabel)
                            val.modelXbrl.profileActivity("... evaluating " + varSetId, minTimeToShow=10.0)
                            val.modelXbrl.modelManager.showStatus(_("evaluating {0}").format(varSetId))
                            val.modelXbrl.profileActivity("... evaluating " + varSetId, minTimeToShow=1.0)
                            evaluate(xpathContext, modelVariableSet)
                            val.modelXbrl.profileStat(modelVariableSet.localName + "_" + varSetId)
                        except XPathContext.XPathException as err:
                            val.modelXbrl.error(err.code,
                                _("Variable set \n%(variableSet)s \nException: \n%(error)s"), 
                                modelObject=modelVariableSet, variableSet=str(modelVariableSet), error=err.message)
        if maxFormulaRunTimeTimer:
            maxFormulaRunTimeTimer.cancel()
    except XPathContext.RunTimeExceededException:
        val.modelXbrl.info("formula:maxRunTime",
            _("Formula execution ended after %(mins)s minutes"), 
            modelObject=val.modelXbrl, mins=val.maxFormulaRunTime)
        
    # log assertion result counts
    asserTests = {}
    for exisValAsser in val.modelXbrl.modelVariableSets:
        if isinstance(exisValAsser, ModelVariableSetAssertion) and \
           (not runIDs or exisValAsser.id in runIDs):
            asserTests[exisValAsser.id] = (exisValAsser.countSatisfied, exisValAsser.countNotSatisfied)
            if formulaOptions.traceAssertionResultCounts:
                val.modelXbrl.info("formula:trace",
                    _("%(assertionType)s Assertion %(id)s evaluations : %(satisfiedCount)s satisfied, %(notSatisfiedCount)s not satisfied"),
                    modelObject=exisValAsser,
                    assertionType="Existence" if isinstance(exisValAsser, ModelExistenceAssertion) else "Value", 
                    id=exisValAsser.id, satisfiedCount=exisValAsser.countSatisfied, notSatisfiedCount=exisValAsser.countNotSatisfied)

    for modelRel in val.modelXbrl.relationshipSet(XbrlConst.consistencyAssertionFormula).modelRelationships:
        if modelRel.fromModelObject is not None and modelRel.toModelObject is not None and \
           isinstance(modelRel.toModelObject,ModelFormula) and \
           (not runIDs or modelRel.fromModelObject.id in runIDs):
            consisAsser = modelRel.fromModelObject
            asserTests[consisAsser.id] = (consisAsser.countSatisfied, consisAsser.countNotSatisfied)
            if formulaOptions.traceAssertionResultCounts:
                val.modelXbrl.info("formula:trace",
                   _("Consistency Assertion %(id)s evaluations : %(satisfiedCount)s satisfied, %(notSatisfiedCount)s not satisfied"),
                    modelObject=consisAsser, id=consisAsser.id, 
                    satisfiedCount=consisAsser.countSatisfied, notSatisfiedCount=consisAsser.countNotSatisfied)
            
    if asserTests: # pass assertion results to validation if appropriate
        val.modelXbrl.log(None, "asrtNoLog", None, assertionResults=asserTests);

    # display output instance
    if outputXbrlInstance:
        if val.modelXbrl.formulaOutputInstance:
            # close prior instance, usually closed by caller to validate as it may affect UI on different thread
            val.modelXbrl.formulaOutputInstance.close()
        val.modelXbrl.formulaOutputInstance = outputXbrlInstance
        
    val.modelXbrl.modelManager.showStatus(_("formulae finished"), 2000)
        
    instanceProducingVariableSets.clear() # dereference
    parameterQnames.clear()
    instanceQnames.clear()
    parameterDependencies.clear()
    instanceDependencies.clear()
    dependencyResolvedParameters.clear()
    orderedInstancesSet.clear()
    del orderedParameters, orderedInstances, orderedInstancesList
    xpathContext.close()  # dereference everything
    val.modelXbrl.profileStat(_("formulaExecutionTotal"), time.time() - timeFormulasStarted)
dataset/ETHPy150Open Arelle/Arelle/arelle/ValidateFormula.py/validate/original