def get_input_data(input_dir):
    file_names = (
        'alternatives.xml',
        'categoriesProfiles.xml',
        'credibility.xml',
        'method_parameters.xml',
    )
    trees = get_trees(input_dir, file_names)

    alternatives = px.getAlternativesID(trees['alternatives'])
    cp_tree = trees['categoriesProfiles']
    categories = list(
        set(cp_tree.xpath('//categoriesProfiles//limits//categoryID/text()')))
    categories_profiles = px.getCategoriesProfiles(trees['categoriesProfiles'],
                                                   categories)
    profiles_names = [
        p for p in cp_tree.xpath('//categoriesProfiles//alternativeID/text()')
    ]
    credibility = getAlternativesComparisons(trees['credibility'],
                                             alternatives, profiles_names)
    cut_threshold = px.getParameterByName(trees['method_parameters'],
                                          'cut_threshold')
    check_cut_threshold(cut_threshold)

    ret = {
        'alternatives': alternatives,
        'categories_profiles': categories_profiles,
        'credibility': credibility,
        'cut_threshold': cut_threshold,
    }
    return ret
Пример #2
0
def _get_categories_profiles(tree, comparison_with):
    def _get_profiles_ordering(last_found, profiles):
        """Gets the ordering of categories (classes) profiles."""
        for i in categories_profiles_full.values():
            if i.get('lower') == last_found:
                if i.get('upper') is None:
                    return
                profiles.append(i.get('upper'))
                last_found = profiles[-1]
                break
        _get_profiles_ordering(last_found, profiles)

    if tree is None and comparison_with in ('boundary_profiles',
                                            'central_profiles'):
        raise RuntimeError("Missing definitions of profiles (did you "
                           "forget about 'classes_profiles.xml'?).")
    if comparison_with == 'alternatives':
        categories_profiles = None
    elif comparison_with == 'boundary_profiles':
        categories_profiles = []
        # ####### different options which are available here:
        # ### categories_profiles e.g. ['pMG', 'pBM']
        # path = '//categoriesProfiles//alternativeID/text()'
        # categories_profiles = [profile for profile in tree.xpath(path)]
        # ### categories_names e.g. ['Bad', 'Medium', 'Good']
        # categories_names = list(set(tree.xpath('//categoriesProfiles//limits//categoryID/text()')))
        # ### categories_profiles_full e.g.:
        # {'Bad': {'upper': 'pBM'}, 'Medium': {'upper': 'pMG', 'lower': 'pBM'},
        #  'Good': {'lower': 'pMG'}}
        # categories_profiles_full = px.getCategoriesProfiles(tree, categories_names)
        if len(tree.findall('.//limits')) > 0:
            xpath = '//categoriesProfiles//limits//categoryID/text()'
            categories_names = list(set(tree.xpath(xpath)))
            categories_profiles_full = px.getCategoriesProfiles(
                tree, categories_names)
            _get_profiles_ordering(None, categories_profiles)
    elif comparison_with == 'central_profiles':
        categories_profiles = {}
        for xmlprofile in tree.findall(".//categoryProfile"):
            try:
                profile_id = xmlprofile.find("alternativeID").text
                category = xmlprofile.find("central/categoryID").text
                categories_profiles[profile_id] = category
            except:
                categories_profiles = {}
                break
    else:
        raise RuntimeError(
            "Wrong comparison type ('{}') specified.".format(comparison_with))
    return categories_profiles
Пример #3
0
def _get_categories_profiles(tree, comparison_with):

    def _get_profiles_ordering(last_found, profiles):
        """Gets the ordering of categories (classes) profiles."""
        for i in categories_profiles_full.values():
            if i.get('lower') == last_found:
                if i.get('upper') is None:
                    return
                profiles.append(i.get('upper'))
                last_found = profiles[-1]
                break
        _get_profiles_ordering(last_found, profiles)

    if tree is None and comparison_with in ('boundary_profiles',
                                            'central_profiles'):
        raise RuntimeError("Missing definitions of profiles (did you "
                            "forget about 'classes_profiles.xml'?).")
    if comparison_with == 'alternatives':
        categories_profiles = None
    elif comparison_with == 'boundary_profiles':
        categories_profiles = []
        # ####### different options which are available here:
        # ### categories_profiles e.g. ['pMG', 'pBM']
        # path = '//categoriesProfiles//alternativeID/text()'
        # categories_profiles = [profile for profile in tree.xpath(path)]
        # ### categories_names e.g. ['Bad', 'Medium', 'Good']
        # categories_names = list(set(tree.xpath('//categoriesProfiles//limits//categoryID/text()')))
        # ### categories_profiles_full e.g.:
        # {'Bad': {'upper': 'pBM'}, 'Medium': {'upper': 'pMG', 'lower': 'pBM'},
        #  'Good': {'lower': 'pMG'}}
        # categories_profiles_full = px.getCategoriesProfiles(tree, categories_names)
        if len(tree.findall('.//limits')) > 0:
            xpath = '//categoriesProfiles//limits//categoryID/text()'
            categories_names = list(set(tree.xpath(xpath)))
            categories_profiles_full = px.getCategoriesProfiles(tree, categories_names)
            _get_profiles_ordering(None, categories_profiles)
    elif comparison_with == 'central_profiles':
        categories_profiles = {}
        for xmlprofile in tree.findall(".//categoryProfile"):
            try:
                profile_id = xmlprofile.find("alternativeID").text
                category = xmlprofile.find("central/categoryID").text
                categories_profiles[profile_id] = category
            except:
                categories_profiles = {}
                break
    else:
        raise RuntimeError("Wrong comparison type ('{}') specified."
                            .format(comparison_with))
    return categories_profiles
Пример #4
0
def main(argv=None):
	if argv is None:
		argv = sys.argv
	
	parser = OptionParser()
	
	parser.add_option("-i", "--in", dest="in_dir")
	parser.add_option("-o", "--out", dest="out_dir")
	
	(options, args) = parser.parse_args(argv[1:])
	
	in_dir = options.in_dir
	out_dir = options.out_dir
	
	# Creating lists for error and log messages
	errorList = []
	logList = []
	
	# If some mandatory input files are missing
	if not os.path.isfile (in_dir+"/alternatives.xml") or not os.path.isfile (in_dir+"/categories.xml") or not os.path.isfile (in_dir+"/categoriesProfiles.xml") or not os.path.isfile (in_dir+"/stabilityRelation.xml"):
		errorList.append("Some input files are missing")
	
	else :
		
		if os.path.isfile (in_dir+"/sortingMode.xml") :
			xmltree_mode = PyXMCDA.parseValidate(in_dir+"/sortingMode.xml")
			if xmltree_mode == None :
				errorList.append ("sortingMode file cannot be validated.")
			else :
				mode = PyXMCDA.getParameterByName (xmltree_mode, "sortingMode")
				if not (mode == "pessimistic" or mode == "optimistic"):
					errorList.append ("Value of parameter sortingMode should be 'pessimistic' or 'optimistic'.")			
			
		xmltree_alternatives = PyXMCDA.parseValidate(in_dir+"/alternatives.xml")
		xmltree_categories = PyXMCDA.parseValidate(in_dir+"/categories.xml")
		xmltree_profiles = PyXMCDA.parseValidate(in_dir+"/categoriesProfiles.xml")
		xmltree_altStability = PyXMCDA.parseValidate(in_dir+"/stabilityRelation.xml")
		
		if xmltree_alternatives == None :
			errorList.append("The alternatives file cannot be validated.")
		if xmltree_categories == None :
			errorList.append("The categories file cannot be validated.")
		if xmltree_profiles == None :
			errorList.append("The categoriesProfiles file cannot be validated.")
		if xmltree_altStability == None :
			errorList.append("The alternatives comparisons file cannot be validated.")
				
		if not errorList :
		
			alternativesId = PyXMCDA.getAlternativesID(xmltree_alternatives, "ACTIVEREAL")
			allalt = PyXMCDA.getAlternativesID(xmltree_alternatives, "ACTIVE")
			categoriesId = PyXMCDA.getCategoriesID(xmltree_categories)
			categoriesRank = PyXMCDA.getCategoriesRank(xmltree_categories, categoriesId)
			altStability = PyXMCDA.getAlternativesComparisons (xmltree_altStability, allalt)
			
			if not alternativesId:
				errorList.append("No alternatives found.")
			if not categoriesId:
				errorList.append("No categories found.")
			if not altStability :
				errorList.append("No alternatives comparisons found.")
					
	if not errorList :
		
		catPro = PyXMCDA.getCategoriesProfiles(xmltree_profiles, categoriesId)
		proCat = PyXMCDA.getProfilesCategories(xmltree_profiles, categoriesId)
		profilesId = proCat.keys()
		
		# On retourne la liste pour trier selon les rangs
		rankCategories = {}
		for i, j in categoriesRank.iteritems():
			rankCategories[j] = i
			
		ranks = rankCategories.keys()[:]
		
		ranks.sort()
		lowestRank = ranks.pop()
		
		# Un tableau pour conserver les affectations
		affectations = {}
		
		if mode == "pessimistic":
			# Electre tri pessimistic rule
			for alt in alternativesId:
				affectations[alt] = []
				for rank in ranks:
					profile = catPro[rankCategories[rank]]["lower"]
					if altStability[alt][profile] >= -1 and altStability[alt][profile] <= 1:
						# Surclassement instable, on ajoute les categories sup et inf
						if affectations[alt].count(proCat[profile]["lower"]) == 0:
							affectations[alt].append(proCat[profile]["lower"])
						if affectations[alt].count(proCat[profile]["upper"]) == 0:
							affectations[alt].append(proCat[profile]["upper"])
					if altStability[alt][profile] > 1:
						# Surclassement stable, on ajoute que sup et on arrete
						if affectations[alt].count(proCat[profile]["upper"]) == 0:
							affectations[alt].append(proCat[profile]["upper"])
							break
				
				if affectations[alt] == []:
					# Tous les surc stables et negatifs, on force la categorie la plus basse
					affectations[alt] = [rankCategories[lowestRank]]

		else:
			errorList.append("Optimistic rule is not taken into account yet")
	
	if not errorList :	
					
		# Creating alternativesAffectations file
		fileAffectations = open(out_dir+"/alternativesAffectations.xml",'w')
		PyXMCDA.writeHeader(fileAffectations)
		
		# We write some information about the generated file
		fileAffectations.write ("\t<projectReference>\n\t\t<title>Stable alternatives affectation</title>\n\t\t<version>"+VERSION+"</version>\n\t\t<author>ws_PyXMCDA suite (TV)</author>\n\t</projectReference>\n\n")
		
		fileAffectations.write("\t<alternativesAffectations>\n")
		
		for alt in alternativesId:
			fileAffectations.write("\t\t<alternativeAffectation>\n\t\t\t<alternativeID>"+alt+"</alternativeID>\n\t\t\t<categoriesSet>\n")
			
			for cat in affectations[alt]:
				fileAffectations.write("\t\t\t\t<element><categoryID>"+cat+"</categoryID></element>\n")

			fileAffectations.write("\t\t\t</categoriesSet>\n\t\t</alternativeAffectation>\n")
		
		fileAffectations.write("\t</alternativesAffectations>\n")
		PyXMCDA.writeFooter(fileAffectations)
		fileAffectations.close()
	
	
	# Creating log and error file, messages.xml
	fileMessages = open(out_dir+"/messages.xml", 'w')
	PyXMCDA.writeHeader (fileMessages)
	
	if not errorList :
		logList.append("Execution ok")
		PyXMCDA.writeLogMessages (fileMessages, logList)
	else :
		PyXMCDA.writeErrorMessages (fileMessages, errorList)
		
	PyXMCDA.writeFooter(fileMessages)
	fileMessages.close()