# -*- coding: utf-8 -*- """ Created on Wed Mar 30 13:32:48 2016 @author: swaprava This code finds the regret of the knapsack voting (Goel et al. 2015) Plan: to compare with dictatorial (without money) or sink (with money) mechanisms """ import numpy as np from joblib import Parallel, delayed import multiprocessing import itertools as it #import matplotlib.pyplot as plt import time print '\n==============================================' print 'Code run on', time.strftime('%c') print '==============================================\n' num_cores = multiprocessing.cpu_count() print("numCores = " + str(num_cores)) def profileCreate(valProfile): return valProfile debug = True M = 1.0 numOfAgents = 3 numOfProjects = 2 def findSubsets(sizeOfSubset): return [list(subset) for subset in it.combinations(range(numOfProjects), sizeOfSubset)] allBundles = [] for sizeOfSubset in xrange(1,numOfProjects+1): allBundles += findSubsets(sizeOfSubset) print 'allBundles:' print allBundles #raw_input() valLevels = 3 values = np.linspace(-M/(2*numOfProjects),M/(2*numOfProjects),valLevels) valuationAgent = [val for val in it.product(*([values] * numOfProjects))] print '\ncreating valuation profiles ...' valuationProfiles = Parallel(n_jobs=num_cores)(delayed(profileCreate)(val) for val in it.product(*([valuationAgent] * numOfAgents))) valuationProfiles = np.array(valuationProfiles) print 'valuation profile creation complete' if debug: print 'valuationProfiles:' print valuationProfiles #raw_input() costResolution = 3 costPerProject = np.linspace(0,1,costResolution) budgetResolution = 3 budgetRange = np.linspace(0,numOfProjects,budgetResolution) # to make sure that every project can be executed for some budget def calcRegret(costs): maxRegret = 0.0 maxRegretProfile = np.ones((numOfAgents,numOfProjects)) maxRegretOptSW = 0.0 maxRegretKnapsackVoteSW = 0.0 print '\ncosts =', costs feasibleBundles = [] for bundle in allBundles: if sum(np.array(costs)[bundle]) <= budget: feasibleBundles.append(bundle) print 'feasibleBundles:' print feasibleBundles if len(feasibleBundles) == 0: return (maxRegret, maxRegretProfile, maxRegretOptSW, maxRegretKnapsackVoteSW) # no bundle is feasible, no point checking # now loop over valuation profiles and use Goel mechanism for valProfile in valuationProfiles: # find optimal bundle optSW = 0.0 optBundle = [] for bundle in feasibleBundles: currSW = sum(sum(valProfile[:,bundle])) print 'currSW =', currSW if currSW > optSW: optSW = currSW optBundle = bundle if debug: print 'valProfile:' print valProfile print 'optBundle =', optBundle, 'optSW =', optSW # raw_input() # compute the optimal bundles for the agents agentBestBundles = {} agentBestBundleValues = np.ones(numOfAgents) * -np.inf for bundle in feasibleBundles: for agent in xrange(numOfAgents): currVal = np.sum(valProfile[agent,bundle]) if currVal > agentBestBundleValues[agent]: agentBestBundleValues[agent] = currVal agentBestBundles[agent] = bundle if debug: print 'agentBestBundles =', agentBestBundles print 'agentBestBundleValues =', agentBestBundleValues # now the Goel et al. mechanism knapsackVote = np.zeros(numOfProjects) for agent in xrange(numOfAgents): knapsackVote[agentBestBundles[agent]] += 1 if debug: print 'knapsackVote =', knapsackVote cumulCost = 0.0 selectBundle = [] for project in np.argsort(-knapsackVote): cumulCost += costs[project] if cumulCost <= budget: selectBundle.append(project) knapsackVoteSW = sum(sum(valProfile[:,selectBundle])) print 'original knapsackVoteSW =', knapsackVoteSW # don't build if it is a social bad if knapsackVoteSW < 0: selectBundle = [] knapsackVoteSW = 0.0 regret = optSW - knapsackVoteSW if debug: print 'selectBundle =', selectBundle print 'selectBundle =', selectBundle, 'knapsackVoteSW =', knapsackVoteSW print 'regret =', regret # if regret > 0: # raw_input() if regret > maxRegret: maxRegret = regret maxRegretProfile = valProfile maxRegretOptSW = optSW maxRegretKnapsackVoteSW = knapsackVoteSW if debug: print 'maxRegret =', maxRegret print 'maxRegretProfile:' print maxRegretProfile print 'maxRegretOptSW =', maxRegretOptSW, 'maxRegretKnapsackVoteSW =', maxRegretKnapsackVoteSW raw_input() return (maxRegret, maxRegretProfile, maxRegretOptSW, maxRegretKnapsackVoteSW) #maxRegret = 0.0 for budget in budgetRange: print '\nbudget =', budget regretInfoVector = [] for costs in it.product(*([costPerProject] * numOfProjects)): returnedValue = calcRegret(costs) print 'returnedValue:' print returnedValue regretInfoVector.append(returnedValue) print 'regretInfoVector:' print regretInfoVector raw_input() # regretInfoVector = [calcRegret(costs) for costs in it.product(*([costPerProject] * numOfProjects))] # regretInfoVector = Parallel(n_jobs=num_cores)(delayed(calcRegret)(costs) for costs in it.product(*([costPerProject] * numOfProjects))) print 'regretInfoVector:' print regretInfoVector # raw_input() #normalizedMaxRegret = maxRegret / (numOfAgents * M) # #print 'normalizedMaxRegret =', normalizedMaxRegret