-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mandd/knapsack models #8
Changes from all commits
74eb254
7652a8e
d1a3e0a
c21075e
39eb91a
50661ea
b9c2878
eb07c61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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} |
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(",")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the External Model for RAVEN, I think we'd better to use InputData and InputTypes to process the xml input. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I may need some help here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have checked other External Models inside LOGOS, they are not using the InputData yet. If you want to use InputData for LOGOS, I suggest we open an issue, and adapt the InputData in another PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Issue #9 has been opened. |
||
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 |
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 |
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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update the copyright statement, this one is not consistent with the version that we are using.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed