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 a list for error messages
    errorList = []

    # If some mandatory input files are missing
    if (
        not os.path.isfile(in_dir + "/alternatives.xml")
        or not os.path.isfile(in_dir + "/criteria.xml")
        or not os.path.isfile(in_dir + "/criteriaWeights.xml")
        or not os.path.isfile(in_dir + "/performanceTable.xml")
    ):
        errorList.append("Some input files are missing")

    else:

        # We parse all the mandatory input files
        xmltree_alternatives = PyXMCDA.parseValidate(in_dir + "/alternatives.xml")
        xmltree_criteria = PyXMCDA.parseValidate(in_dir + "/criteria.xml")
        xmltree_weights = PyXMCDA.parseValidate(in_dir + "/criteriaWeights.xml")
        xmltree_perfTable = PyXMCDA.parseValidate(in_dir + "/performanceTable.xml")

        # We check if all madatory input files are valid
        if xmltree_alternatives == None:
            errorList.append("The alternatives file can't be validated.")
        if xmltree_criteria == None:
            errorList.append("The criteria file can't be validated.")
        if xmltree_perfTable == None:
            errorList.append("The performance table file can't be validated.")
        if xmltree_weights == None:
            errorList.append("The criteria weights file can't be validated.")

            # By default, the valuation domain is fixed to [0,1]
        minValDomain = 0
        maxValDomain = 1

        # If a valuation domain input file has been provided
        if os.path.isfile(in_dir + "/valuationDomain.xml"):

            xmltree_valuation = PyXMCDA.parseValidate(in_dir + "/valuationDomain.xml")
            if xmltree_valuation == None:
                errorList.append("valuationDomain file can't be validated.")

            else:

                minValDomain = PyXMCDA.getParameterByName(xmltree_valuation, "min", "valuationDomain")
                maxValDomain = PyXMCDA.getParameterByName(xmltree_valuation, "max", "valuationDomain")

                # We check the validity of the parameters
                if not isinstance(minValDomain, float) and not isinstance(minValDomain, int):
                    errorList.append("min value should be an integer or a real")
                if not isinstance(maxValDomain, float) and not isinstance(maxValDomain, int):
                    errorList.append("max value should be an integer or a real")

                if not errorList:
                    if minValDomain >= maxValDomain:
                        errorList.append("The max value should be strictly greater than the min value")

        if not errorList:

            alternativesId = PyXMCDA.getAlternativesID(xmltree_alternatives)
            criteriaId = PyXMCDA.getCriteriaID(xmltree_criteria)
            perfTable = PyXMCDA.getPerformanceTable(xmltree_perfTable, alternativesId, criteriaId)
            thresholds = PyXMCDA.getConstantThresholds(xmltree_criteria, criteriaId)
            weights = PyXMCDA.getCriterionValue(xmltree_weights, criteriaId)

            if not alternativesId:
                errorList.append("No alternatives found. Is your alternatives file correct ?")
            if not criteriaId:
                errorList.append("No criteria found. Is your criteria file correct ?")
            if not perfTable:
                errorList.append("No performance table found. Is your performance table file correct ?")
            if not weights:
                errorList.append("No weights found. Is your weights file correct ?")

    if not errorList:

        # We compute the weight sum (only the weights associated to active criteria)
        sumWeights = 0.0

        for crit in criteriaId:
            try:
                sumWeights = sumWeights + weights[crit]
            except:
                errorList.append("There is no defined weight for criterion " + crit + ".")

    if not errorList:

        # We recover the criteria preference directions
        # criteriaDir = PyXMCDA.getCriteriaPreferenceDirections (xmltree_criteria, criteriaId)
        # Plus necessaire

        # We compute the alternative comparisons values
        fileAltValues = open(out_dir + "/alternativesComparisons.xml", "w")
        PyXMCDA.writeHeader(fileAltValues)

        # We write some information about the generated file
        fileAltValues.write(
            "\t<projectReference>\n\t\t<title>Rubis outranking relation</title>\n\t\t<version>"
            + VERSION
            + "</version>\n\t\t<author>ws_PyXMCDA suite (TV)</author>\n\t</projectReference>\n\n"
        )

        fileAltValues.write("\t<alternativesComparisons>\n\t\t<pairs>\n")

        # ATTENTION Solution rustine
        # On retourne ici le tableau de perf pour les criteres a minimiser
        # Devra etre fait par le getRubisElementaryOutranking
        criteriaDir = PyXMCDA.getCriteriaPreferenceDirections(xmltree_criteria, criteriaId)
        for crit in criteriaId:
            if criteriaDir[crit] == "min":
                for alt in alternativesId:
                    perfTable[alt][crit] = -perfTable[alt][crit]

        ElemOut = PyXMCDA.getRubisElementaryOutranking(alternativesId, criteriaId, perfTable, thresholds)

        tabVetos = PyXMCDA.getVetos(alternativesId, criteriaId, perfTable, thresholds)

        for alt1 in alternativesId:
            for alt2 in alternativesId:

                fileAltValues.write(
                    "\t\t\t<pair>\n\t\t\t\t<initial><alternativeID>"
                    + alt1
                    + "</alternativeID></initial>\n\t\t\t\t<terminal><alternativeID>"
                    + alt2
                    + "</alternativeID></terminal>\n"
                )

                # Verifier s'il manque des valeurs !!! try expect
                # fileAltValues.write ("\t\t\t\t<value><NA>not available</NA></value>\n\t\t\t</pair>\n")
                sum = 0.0
                isVeto = 0
                isWeakVeto = 0

                for crit in criteriaId:

                    sum += ElemOut[alt1][alt2][crit] * weights[crit]

                    # On verifie si un veto est leve
                    if (
                        tabVetos.has_key(alt1)
                        and tabVetos[alt1].has_key(alt2)
                        and tabVetos[alt1][alt2].has_key(crit)
                        and tabVetos[alt1][alt2][crit] == 1
                    ):
                        isVeto = 1

                        # On verifie si un veto faible est leve
                    if (
                        tabVetos.has_key(alt1)
                        and tabVetos[alt1].has_key(alt2)
                        and tabVetos[alt1][alt2].has_key(crit)
                        and tabVetos[alt1][alt2][crit] == 0.5
                    ):
                        isWeakVeto = 1

                sum = sum / sumWeights

                if isVeto == 1:
                    # On utilise le veto classique, qui met la valeur minimale
                    sum = 0.0
                elif isWeakVeto == 1 and sum > 0.5:
                    # Un veto faible est leve
                    sum = 0.5

                    # La valeur est entre 0 et 1, on la met dans le bon intervalle
                sum = (maxValDomain - minValDomain) * sum + minValDomain

                fileAltValues.write("\t\t\t\t<value><real>" + str(sum) + "</real></value>\n\t\t\t</pair>\n")

        fileAltValues.write("\t\t</pairs>\n\t</alternativesComparisons>\n")

        PyXMCDA.writeFooter(fileAltValues)
        fileAltValues.close()

        # Creating log and error file, messages.xml
    fileMessages = open(out_dir + "/messages.xml", "w")
    PyXMCDA.writeHeader(fileMessages)

    if not errorList:

        PyXMCDA.writeLogMessages(fileMessages, ["Execution ok"])
    else:
        PyXMCDA.writeErrorMessages(fileMessages, errorList)

    PyXMCDA.writeFooter(fileMessages)
    fileMessages.close()
Пример #2
0
def create_ampl_reverse_data (file, altId, critId, perfTable, altComparisons, thresholds, maxWeight, criComparisons, criLB, criUB, criIndLB, criIndUB, criPreLB, criPreUB) :

	#Les contraintes du style g_i > g_j
	for crit in critId :
		file.write('set cr_'+crit+' := {"'+crit+'"};\n')
		
	#Un compteur pour numeroter les contraintes et les ensembles
	count = 1
	for comp in criComparisons :
		# On ecrit l'ensemble des neuds initiaux
		file.write('\nset crs_init_'+str(count)+' := {')
		file.write(PyXMCDA.getListOnString (comp["initial"], '"', '"', ', '))
		file.write('};\n')
		# On ecrit l'ensemble des noeuds terminaux
		file.write('set crs_term_'+str(count)+' := {')
		file.write(PyXMCDA.getListOnString (comp["terminal"], '"', '"', ', '))
		file.write('};\n')
		file.write("s.t. ct_comp_"+str(count)+" : sum{init in crs_init_"+str(count)+"} sum {k in WEIGHTUNIT} Accumulator[init,k] >= sum{term in crs_term_"+str(count)+"} sum {k in WEIGHTUNIT} Accumulator[term,k] +1;\n")
		count = count + 1
	
	#Les contraintes du style g_i > lower_bound_i
	file.write("\n")
	for crit in criLB.keys() :
		file.write("s.t. ct_LB_"+crit+"{j in cr_"+crit+"} : sum {k in WEIGHTUNIT} Accumulator[j,k] >= "+str(criLB[crit])+";\n")
	
	
	#Les contraintes du style g_i < upper_bound_i
	file.write("\n")
	for crit in criUB.keys() :
		file.write("s.t. ct_UB_"+crit+"{j in cr_"+crit+"} : sum {k in WEIGHTUNIT} Accumulator[j,k] <= "+str(criUB[crit])+";\n")
		
	#Les contraintes du style q_i > lower_bound_i
	file.write("\n")
	for crit in criIndLB.keys() :
		file.write("s.t. ct_q_LB_"+crit+"{j in cr_"+crit+"} : " + str(criIndLB[crit]) + " <=  q[j];\n")
	
	
	#Les contraintes du style q_i < upper_bound_i
	file.write("\n")
	for crit in criIndUB.keys() :
		file.write("s.t. ct_q_UB_"+crit+"{j in cr_"+crit+"} :  q[j] <= " + str(criIndUB[crit]) + ";\n")
	
	#Les contraintes du style p_i > lower_bound_i
	file.write("\n")
	for crit in criPreLB.keys() :
		file.write("s.t. ct_p_LB_"+crit+"{j in cr_"+crit+"} : " + str(criPreLB[crit]) + " <=  p[j];\n")
	
	
	#Les contraintes du style p_i < upper_bound_i
	file.write("\n")
	for crit in criPreUB.keys() :
		file.write("s.t. ct_p_UB_"+crit+"{j in cr_"+crit+"} :  p[j] <= " + str(criPreUB[crit]) + ";\n")

	file.write ("\n\n\ndata;\n\n")
	file.write ("set CRITERIA := ")
	for c in critId :
		file.write (c+" ")
	file.write(";\n\n")

	pairs2 = []
	pairsm2 = []
	pairs1 = []
	pairsm1 = []
	
	tabVeto = PyXMCDA.getVetos (altId, critId, perfTable, thresholds)
	
	for init in altComparisons.keys() :
		for term in altComparisons[init].keys() :
			
			if tabVeto.has_key(init) and tabVeto[init].has_key(term) and not tabVeto[init][term] is None :
				# Veto situation
				continue
				
			if init != term :
				val = altComparisons[init][term]
	
				if val == 2 :
					pairs2.append (""+init+term)
				elif val == -2 :
					pairsm2.append (""+init+term)
				elif val == 1 :
					pairs1.append (""+init+term)
				elif val == -1 :
					pairsm1.append (""+init+term)
				else:
					# On met une valeur pour dire que l'on n'a pas pris en compte cette valeur
					altComparisons[init][term] = 0
		
	file.write ("set ROBUSTPREFPAIRS :=\n")
	
	count = 0
	for pair in pairs2 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	file.write (";\n\nset ROBUSTnotPREFPAIRS :=\n")
	count = 0
	for pair in pairsm2 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	file.write (";\n\nset SIMPLEPREFPAIRS :=\n")
	count = 0
	for pair in pairs1 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	file.write (";\n\nset SIMPLEnotPREFPAIRS :=\n")
	count = 0
	for pair in pairsm1 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	
	file.write(";\n\n")
	
	file.write ("param maxWeight := "+str(maxWeight)+";\n\n")
	
	# On ecrit le tableau de performance
	file.write("param Perf : ")
	for c in critId :
		file.write (c+" ")
	file.write (":=\n")
	for init in altComparisons.keys() :
		for term in altComparisons[init].keys() :
			
			if tabVeto.has_key(init) and tabVeto[init].has_key(term) and not tabVeto[init][term] is None:
				# Veto situation
				continue
			if altComparisons[init][term] == 0:
				continue
			if init != term :
				file.write (str(init)+str(term)+" ")
				for crit in critId :
					file.write(str(perfTable[init][crit] - perfTable[term][crit])+" ")
				file.write ("\n")
	file.write(";\n\n")
	
	# On ecrit l'ensemble des couples d'alt et des criteres pour lesquels la premiere alt performe mieux que la deuxieme sur le critere choisi (en gros, les surclassements ne dependant pas des seuils)
#	file.write ("param SureOut : ")
#	for c in critId :
#		file.write (c+" ")
#	file.write (":=\n")
#	for init in altComparisons.keys() :
#		for term in altComparisons[init].keys() :
#			
#			if tabVeto.has_key(init) and tabVeto[init].has_key(term) and not tabVeto[init][term] is None :
#				# Veto situation
#				continue
#				
#			if init != term :
#				file.write (str(init)+str(term)+" ")
#				for crit in critId :
#					if perfTable[init][crit] >= perfTable[term][crit]:
#						file.write ("1 ")
#					else:
#						file.write ("0 ")
#				file.write ("\n")
#	file.write(";\n\n")
	
	# Les valeurs max sur chaque critere, pour normaliser
	file.write("param MaxCrit [*] := \n")
	for c in critId :
		# On suppose les valeurs toutes positives !!!!!!!!!
		valMax = 0
		for alt in altId:
			if perfTable[alt][c] > valMax:
				valMax = perfTable[alt][c]
		file.write (c+" "+str(valMax)+"\n")
	file.write (";\n\n")
Пример #3
0
def create_ampl_reverse_data (file, altId, critId, perfTable, altComparisons, thresholds, maxWeight, criComparisons, criLB, criUB) :

	#Les contraintes du style g_i > g_j
	for crit in critId :
		file.write('set cr_'+crit+' := {"'+crit+'"};\n')
		
	#Un compteur pour numeroter les contraintes et les ensembles
	count = 1
	for comp in criComparisons :
		# On ecrit l'ensemble des neuds initiaux
		file.write('\nset crs_init_'+str(count)+' := {')
		file.write(PyXMCDA.getListOnString (comp["initial"], '"', '"', ', '))
		file.write('};\n')
		# On ecrit l'ensemble des noeuds terminaux
		file.write('set crs_term_'+str(count)+' := {')
		file.write(PyXMCDA.getListOnString (comp["terminal"], '"', '"', ', '))
		file.write('};\n')
		file.write("s.t. ct_comp_"+str(count)+" : sum{init in crs_init_"+str(count)+"} sum {k in WEIGHTUNIT} Accumulator[init,k] >= sum{term in crs_term_"+str(count)+"} sum {k in WEIGHTUNIT} Accumulator[term,k] +1;\n")
		count = count + 1
	
	#Les contraintes du style g_i > lower_bound_i
	file.write("\n")
	for crit in criLB.keys() :
		file.write("s.t. ct_LB_"+crit+"{i in cr_"+crit+"} : sum {k in WEIGHTUNIT} Accumulator[i,k] >= "+str(criLB[crit])+";\n")
	
	
	#Les contraintes du style g_i < upper_bound_i
	file.write("\n")
	for crit in criUB.keys() :
		file.write("s.t. ct_UB_"+crit+"{i in cr_"+crit+"} : sum {k in WEIGHTUNIT} Accumulator[i,k] <= "+str(criUB[crit])+";\n")

	file.write ("\n\n\ndata;\n\n")
	file.write ("set CRITERIA := ")
	for c in critId :
		file.write (c+" ")
	file.write(";\n\nset ALLPAIRS :=\n")
	for a1 in altId :
		for a2 in altId :
			file.write (a1+a2+" ")
		file.write ("\n")
	file.write (";\n\n")

	pairs2 = []
	pairsm2 = []
	pairs1 = []
	pairsm1 = []
	
	tabVeto = PyXMCDA.getVetos (altId, critId, perfTable, thresholds)
	
	for init in altComparisons.keys() :
		for term in altComparisons[init].keys() :
			
			if tabVeto.has_key(init) and tabVeto[init].has_key(term) and not tabVeto[init][term] is None :
				# Veto situation
				continue
				
			if init != term :
				val = altComparisons[init][term]
	
				if val == 2 :
					pairs2.append (""+init+term)
				elif val == -2 :
					pairsm2.append (""+init+term)
				elif val == 1 :
					pairs1.append (""+init+term)
				elif val == -1 :
					pairsm1.append (""+init+term)
		
	file.write ("set ROBUSTPREFPAIRS :=\n")
	
	count = 0
	for pair in pairs2 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	file.write (";\n\nset ROBUSTnotPREFPAIRS :=\n")
	count = 0
	for pair in pairsm2 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	file.write (";\n\nset SIMPLEPREFPAIRS :=\n")
	count = 0
	for pair in pairs1 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	file.write (";\n\nset SIMPLEnotPREFPAIRS :=\n")
	count = 0
	for pair in pairsm1 :
		count = count + 1
		file.write (pair+" ")
		if count == 10 :
			count = 0
			file.write ("\n")
	
	file.write(";\n\n")
		
	
	file.write ("\nparam maxWeight := "+str(maxWeight))
	file.write (";\nparam S : ")
	for c in critId :
		file.write (c+" ")
	file.write (":=\n")
	
	ElemOut = PyXMCDA.getRubisElementaryOutranking (altId, critId, perfTable, thresholds)
	
	for alt1 in altId :
		for alt2 in altId :
			file.write (str(alt1)+str(alt2)+" ")
			for crit in critId :
				file.write (str(ElemOut[alt1][alt2][crit])+" ")						
			
			file.write ("\n")
	file.write(";\n")