2013-08-20 2 views
1

У меня проблема:оптимизация портфеля сортировка эффективных решений C#

Пусть H - набор портфолио. Для каждого портфеля i в H давайте (ri,vi) значениями (return,risk) для этого решения.

Для каждого i в H, если существует j в H (j отличается от i) таким образом, что rj>=ri и vj<=vi затем удалить i из H. потому что в i преобладает j (у него лучше вернуться за меньший риск).

В конце H будет использоваться набор неэффективных эффективных решений.

Я пытался решить вышеуказанную проблему с помощью LINQ:

H.RemoveAll(x => H.Any(y => x.CalculateReturn() <= y.CalculateReturn() && x.CalculateRisk() >= y.CalculateRisk() && x != y)); 

Но мне интересно, если существует более эффективный способ, потому что, если H.Count() порядка десяти тысяч, то это займет много времени для удаления доминированных портфелей.

Заранее благодарим за любую помощь!

Christos

+0

Я потерялся где-то между j и vi. Можете ли вы опубликовать некоторый код без сокращений, который показывает вашу проблему? –

+0

H - список классов Портфеля. Каждый портфель состоит из активов с каждым активом, имеющим вес, w, который является числом в [0,1]. Все веса суммируются до 1. Используя два метода портфельного класса, мы можем оценить его риск и его возврат. Таким образом, у каждого портфеля есть пара (возврат, риск). Проблема, которую я хочу решить, состоит в том, чтобы найти все портфели списка портфелей, которые не доминируют. Чтобы понять концепцию доминирующего портфеля, нам необходимо ввести приведенные сокращения. – Christos

+0

Если вам нужно какое-то дополнительное объяснение вышеизложенному, дайте мне знать. Еще раз спасибо Милен. – Christos

ответ

0

Во-первых, вы должны кэшировать риск/вознаграждение. Я не могу сказать, если вы по образцу кода, но если вам не нужно сначала преобразовать список.

После того, как вы это сделали, имеет смысл заказать список в соответствии с риском. По мере того, как вы увеличиваете риск, все, что вам нужно проверить, это то, что ваша награда строго больше, чем лучшая награда, которую вы видели до сих пор. Если это не так, вы можете удалить его. Это должно резко повысить производительность.

К сожалению, я не чувствую себя достаточно умным, чтобы придумать способ сделать это с чистым LINQ в данный момент, но этот сегмент код должен работать:

(Отказ от ответственности: я не компилируется/тестировался)

var orderedH = (
    from h in H 
    let reward = h.CalculatedReward() 
    let risk = h.CalculatedRisk() 
    orderby risk ascending 
    select new { 
    Original = h, 
    Risk = risk, 
    Reward = reward 
}).ToList(); 

var maxReward = Double.NegativeInfinity; 
for (int i = 0; i < orderedH.Count; i++) 
{ 
    if (orderedH[i].Reward <= maxReward) { 
    orderedH.RemoveAt(i--); 
    } 
    else { 
    maxReward = orderedH[i].Reward; 
    } 
} 

var filteredPortfolio = orderedH.Select(h => h.Original); 
+0

Эндрю благодарю вас за помощь! Он работает так, как и следовало ожидать. Сложность вашего алгоритма - O (упорядоченнаяH.Count()), линейная по размеру списка. К сожалению, используя linq, сложность была квадратичной по размеру списка. Еще раз спасибо ! – Christos

+0

@ Christos: Скорее, это больше похоже на O (H ln H), так как вам нужно сначала отсортировать его ... но это все же лучше, чем O (H^2)! –

+0

Эндрю, ты чертовски прав! К сожалению, мой энтузиазм, когда я увидел алгоритм, сделал меня неправильным. Спасибо за ваше уведомление! – Christos