-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from idaholab/mandd/knapsackModels
Base Knapsack Model: used as external model that can be combined with genetic algorithm for Knapsack problem optimization.
- Loading branch information
Showing
7 changed files
with
284 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
\section{Knapsack Models} | ||
\label{sec:KnapsackModels} | ||
|
||
LOGOS contains a set of Knapsack models that can be used coupled with RAVEN when | ||
the desired optimization problem requires the use of specific models to generate | ||
knapsack required parameters. | ||
More specifically, all these models would be contained in a RAVEN EnsembleModel | ||
and RAVEN optimization methods (e.g., Genetic Algorithms) would be employed to | ||
find the optimal solution. | ||
|
||
|
||
\subsection{BaseKnapsackModel} | ||
\label{subsec:BaseKnapsackModel} | ||
This model considers the classical Knapsack Model characterized by a set of elements | ||
that can be chosen (or not). | ||
The goal is to maximize the sum of the chosen element values provided that the sum of | ||
element cost values satisfy capacity constraint (specified in the \xmlNode{capacity} node). | ||
|
||
The ID of the variables that represent cost, value, and choice of each element are | ||
indicated in the \xmlNode{map} node. | ||
The model generates two variables: | ||
\begin{itemize} | ||
\item the validity of the chosen solution (specified in the \xmlNode{outcome} node): either | ||
valid (i.e., 0), or invalid (i.e., 1) if the capacity constraint is not satisfied, | ||
\item totalValue (specified in the \xmlNode{choiceValue} node): sum of the values of the | ||
chosen elements | ||
\end{itemize} | ||
|
||
When calculating the \xmlNode{choiceValue} variable, if the \xmlNode{capacity} constraint | ||
is not satisfied, then the \xmlNode{choiceValue} variable is penalized by multiplying the | ||
project value by -\xmlNode{penaltyFactor}. | ||
|
||
Example LOGOS input XML for DRO: | ||
\begin{lstlisting}[style=XML] | ||
<Models> | ||
<ExternalModel name="knapsack" subType="LOGOS.BaseKnapsackModel"> | ||
<variables>element1Status,element2Status,element3Status, | ||
element1Val ,element2Val ,element3Val, | ||
element1Cost ,element2Cost ,element3Cost, | ||
validity ,totalValue </variables> | ||
<capacity>10</capacity> | ||
<penaltyFactor>1.</penaltyFactor> | ||
<outcome>validity</outcome> | ||
<choiceValue>totalValue</choiceValue> | ||
<map value='element1Val' cost='element1Cost' >element1Status</map> | ||
<map value='element2Val' cost='element2Cost' >element2Status</map> | ||
<map value='element3Val' cost='element3Cost' >element3Status</map> | ||
</ExternalModel> | ||
</Models> | ||
\end{lstlisting} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# Copyright 2020, Battelle Energy Alliance, LLC | ||
# ALL RIGHTS RESERVED | ||
""" | ||
Created on February 2, 2021 | ||
@author: mandd | ||
""" | ||
|
||
#External Modules--------------------------------------------------------------- | ||
import numpy as np | ||
import math | ||
import copy | ||
#External Modules End----------------------------------------------------------- | ||
|
||
#Internal Modules--------------------------------------------------------------- | ||
from PluginsBaseClasses.ExternalModelPluginBase import ExternalModelPluginBase | ||
#Internal Modules End----------------------------------------------------------- | ||
|
||
|
||
class BaseKnapsackModel(ExternalModelPluginBase): | ||
""" | ||
This class is designed to create the BaseKnapsack model | ||
""" | ||
def __init__(self): | ||
""" | ||
Constructor | ||
@ In, None | ||
@ Out, None | ||
""" | ||
ExternalModelPluginBase.__init__(self) | ||
|
||
self.capacity = None # capacity value of the knapsack | ||
self.penaltyFactor = 1.0 # penalty factor that is used when the capacity constraint is not satisfied | ||
self.outcome = None # ID of the variable which indicates if the chosen elements satisfy the capacity constraint | ||
self.choiceValue = None # ID of the variable which indicates the sum of the values of the chosen project elements | ||
|
||
def _readMoreXML(self, container, xmlNode): | ||
""" | ||
Method to read the portion of the XML that belongs to the BaseKnapsack model | ||
@ In, container, object, self-like object where all the variables can be stored | ||
@ In, xmlNode, xml.etree.ElementTree.Element, XML node that needs to be read | ||
@ Out, None | ||
""" | ||
container.mapping = {} | ||
|
||
for child in xmlNode: | ||
if child.tag == 'capacity': | ||
self.capacity = float(child.text.strip()) | ||
elif child.tag == 'penaltyFactor': | ||
self.penaltyFactor = float(child.text.strip()) | ||
elif child.tag == 'outcome': | ||
self.outcome = child.text.strip() | ||
elif child.tag == 'choiceValue': | ||
self.choiceValue = child.text.strip() | ||
elif child.tag == 'map': | ||
container.mapping[child.text.strip()] = [child.get('value'),child.get('cost')] | ||
elif child.tag == 'variables': | ||
variables = [str(var.strip()) for var in child.text.split(",")] | ||
else: | ||
raise IOError("BaseKnapsackModel: xml node " + str (child.tag) + " is not allowed") | ||
|
||
|
||
def initialize(self, container, runInfoDict, inputFiles): | ||
""" | ||
Method to initialize the BaseKnapsack model | ||
@ In, container, object, self-like object where all the variables can be stored | ||
@ In, runInfoDict, dict, dictionary containing all the RunInfo parameters (XML node <RunInfo>) | ||
@ In, inputFiles, list, list of input files (if any) | ||
@ Out, None | ||
""" | ||
pass | ||
|
||
|
||
def run(self, container, inputDict): | ||
""" | ||
This method calculates the sum of the chosen element values and check if the capacity constraint | ||
is satisfied | ||
@ In, container, object, self-like object where all the variables can be stored | ||
@ In, inputDict, dict, dictionary of inputs from RAVEN | ||
""" | ||
totalValue = 0.0 | ||
|
||
for key in container.mapping: | ||
if key in inputDict.keys() and inputDict[key] in [0.0,1.0]: | ||
if inputDict[key] == 1.0: | ||
testValue = self.capacity - inputDict[container.mapping[key][1]] | ||
if testValue >= 0: | ||
self.capacity = self.capacity - inputDict[container.mapping[key][1]] | ||
totalValue = totalValue + inputDict[container.mapping[key][0]] | ||
else: | ||
self.capacity = self.capacity - inputDict[container.mapping[key][1]] | ||
totalValue = totalValue - inputDict[container.mapping[key][0]] * self.penaltyFactor | ||
elif inputDict[key] == 0.0: | ||
pass | ||
else: | ||
raise IOError("BaseKnapsackModel: variable " + str(key) + " does not have a 0/1 value.") | ||
else: | ||
raise IOError("BaseKnapsackModel: variable " + str(key) + " is not found in the set of input variables.") | ||
|
||
if self.capacity>=0: | ||
container.__dict__[self.outcome] = 0. | ||
else: | ||
container.__dict__[self.outcome] = 1. | ||
|
||
container.__dict__[self.choiceValue] = totalValue |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
element1Status,element2Status,element3Status,element4Status,element5Status,element1Val,element2Val,element3Val,element4Val,element5Val,element1Cost,element2Cost,element3Cost,element4Cost,element5Cost,validity,totalValue | ||
1.0,0.0,1.0,1.0,1.0,1,2,3,4,5,1,1,1,1,1,0.0,13.0 | ||
1.0,1.0,1.0,0.0,0.0,1,2,3,4,5,1,1,1,1,1,0.0,6.0 | ||
0.0,1.0,1.0,1.0,1.0,1,2,3,4,5,1,1,1,1,1,1.0,4.0 | ||
1.0,0.0,1.0,1.0,1.0,1,2,3,4,5,1,1,1,1,1,1.0,-13.0 | ||
0.0,0.0,1.0,1.0,1.0,1,2,3,4,5,1,1,1,1,1,1.0,-12.0 | ||
1.0,1.0,0.0,1.0,1.0,1,2,3,4,5,1,1,1,1,1,1.0,-12.0 | ||
1.0,0.0,0.0,0.0,0.0,1,2,3,4,5,1,1,1,1,1,1.0,-1.0 | ||
1.0,1.0,1.0,1.0,1.0,1,2,3,4,5,1,1,1,1,1,1.0,-15.0 | ||
0.0,0.0,1.0,1.0,0.0,1,2,3,4,5,1,1,1,1,1,1.0,-7.0 | ||
1.0,1.0,0.0,0.0,1.0,1,2,3,4,5,1,1,1,1,1,1.0,-8.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
<Simulation verbosity="debug"> | ||
<TestInfo> | ||
<name>framework.BaseKnapsack</name> | ||
<author>mandd</author> | ||
<created>2021-02-02</created> | ||
<classesTested>Models.ExternalModel.LOGOS.BaseKnapsackModel</classesTested> | ||
<description> | ||
This test is aimed to test the BaseKnapsackModel class | ||
</description> | ||
</TestInfo> | ||
|
||
<RunInfo> | ||
<WorkingDir>BaseKnapsack</WorkingDir> | ||
<Sequence>Run</Sequence> | ||
<batchSize>1</batchSize> | ||
</RunInfo> | ||
|
||
<Models> | ||
<ExternalModel name="knapsack" subType="LOGOS.BaseKnapsackModel"> | ||
<variables>element1Status,element2Status,element3Status,element4Status,element5Status, | ||
element1Val,element2Val,element3Val,element4Val,element5Val, | ||
element1Cost,element2Cost,element3Cost,element4Cost,element5Cost, | ||
validity,totalValue</variables> | ||
<capacity>10</capacity> | ||
<penaltyFactor>1.</penaltyFactor> | ||
<outcome>validity</outcome> | ||
<choiceValue>totalValue</choiceValue> | ||
<map value='element1Val' cost='element1Cost' >element1Status</map> | ||
<map value='element2Val' cost='element2Cost' >element2Status</map> | ||
<map value='element3Val' cost='element3Cost' >element3Status</map> | ||
<map value='element4Val' cost='element4Cost' >element4Status</map> | ||
<map value='element5Val' cost='element5Cost' >element5Status</map> | ||
</ExternalModel> | ||
</Models> | ||
|
||
<Distributions> | ||
<Bernoulli name="bernDistrib"> | ||
<p>0.5</p> | ||
</Bernoulli> | ||
</Distributions> | ||
|
||
<Samplers> | ||
<MonteCarlo name="MC_external"> | ||
<samplerInit> | ||
<limit>10</limit> | ||
</samplerInit> | ||
<variable name="element1Status"> | ||
<distribution>bernDistrib</distribution> | ||
</variable> | ||
<variable name="element2Status"> | ||
<distribution>bernDistrib</distribution> | ||
</variable> | ||
<variable name="element3Status"> | ||
<distribution>bernDistrib</distribution> | ||
</variable> | ||
<variable name="element4Status"> | ||
<distribution>bernDistrib</distribution> | ||
</variable> | ||
<variable name="element5Status"> | ||
<distribution>bernDistrib</distribution> | ||
</variable> | ||
|
||
<constant name="element1Val">1</constant> | ||
<constant name="element2Val">2</constant> | ||
<constant name="element3Val">3</constant> | ||
<constant name="element4Val">4</constant> | ||
<constant name="element5Val">5</constant> | ||
|
||
<constant name="element1Cost">1</constant> | ||
<constant name="element2Cost">1</constant> | ||
<constant name="element3Cost">1</constant> | ||
<constant name="element4Cost">1</constant> | ||
<constant name="element5Cost">1</constant> | ||
</MonteCarlo> | ||
</Samplers> | ||
|
||
<Steps> | ||
<MultiRun name="Run"> | ||
<Input class="DataObjects" type="PointSet" >dummyPS</Input> | ||
<Model class="Models" type="ExternalModel" >knapsack</Model> | ||
<Sampler class="Samplers" type="MonteCarlo" >MC_external</Sampler> | ||
<Output class="DataObjects" type="PointSet" >dataPS</Output> | ||
<Output class="OutStreams" type="Print" >PrintPS</Output> | ||
</MultiRun> | ||
</Steps> | ||
|
||
<OutStreams> | ||
<Print name="PrintPS"> | ||
<type>csv</type> | ||
<source>dataPS</source> | ||
<what>input,output</what> | ||
</Print> | ||
</OutStreams> | ||
|
||
<DataObjects> | ||
<PointSet name="dummyPS"> | ||
<Input>element1Status,element2Status,element3Status,element4Status,element5Status, | ||
element1Val,element2Val,element3Val,element4Val,element5Val, | ||
element1Cost,element2Cost,element3Cost,element4Cost,element5Cost</Input> | ||
<Output>OutputPlaceHolder</Output> | ||
</PointSet> | ||
<PointSet name="dataPS"> | ||
<Input>element1Status,element2Status,element3Status,element4Status,element5Status, | ||
element1Val,element2Val,element3Val,element4Val,element5Val, | ||
element1Cost,element2Cost,element3Cost,element4Cost,element5Cost</Input> | ||
<Output>validity,totalValue</Output> | ||
</PointSet> | ||
</DataObjects> | ||
|
||
</Simulation> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters