/************************************************************************\ |* gtf is a framework for analyzing two-player zero-sum games *| |* Copyright (C) 2005 Troels Bjerre Sorensen *| |* *| |* This program is free software; you can redistribute it and/or modify *| |* it under the terms of the GNU General Public License as published by *| |* the Free Software Foundation; either version 2 of the License, or *| |* (at your option) any later version. *| |* *| |* This program is distributed in the hope that it will be useful, but *| |* WITHOUT ANY WARRANTY; without even the implied warranty of *| |* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *| |* General Public License for more details. *| |* *| |* You should have received a copy of the GNU General Public License *| |* along with this program; if not, write to the *| |* Free Software Foundation, Inc., 59 Temple Place - Suite 330, *| |* Boston, MA 02111-1307, USA. *| \************************************************************************/ package gtf; import gtf.game.*; import gtf.util.*; import java.io.*; import java.util.*; public class DoubleRealKMSVisitor extends RealizationVisitor implements Processor { Strategy strategies; Rational[][] tableau; Rational shift; Map vars = new HashMap(); Map equs = new HashMap(); private Integer getIdx(String s, Map map) { Integer result = map.get(s); if (result == null) { result = map.size(); map.put(s, result); } return result; } private void print() { System.out.println("tableau"); for (Rational[] eq : tableau) { for (Rational e : eq) { System.out.print(e + "\t"); } System.out.println(); } System.out.println(); String[] srav = new String[vars.size()]; String[] suqe = new String[equs.size()]; for (Map.Entry entry : vars.entrySet()) { srav[entry.getValue()] = entry.getKey(); } for (Map.Entry entry : equs.entrySet()) { suqe[entry.getValue()] = entry.getKey(); } System.out.print("Max"); for (int i = 0 ; i < tableau[0].length ; i++) { if (! tableau[0][i].isZero()) { System.out.print(" " + tableau[0][i] + "*\"" + srav[i] + "\""); } } System.out.println("\nSubj. to:"); for (int j = 1 ; j < tableau.length ; j++) { System.out.print(suqe[j] + ":\t"); for (int i = 1 ; i < tableau[j].length ; i++) { if (! tableau[j][i].isZero()) { System.out.print(" " + tableau[j][i].negate() + "*\"" + srav[i] + "\""); } } System.out.println(" <= " + tableau[j][0]); } } public void visitExtensiveForm(ExtensiveForm ef) { SizeVisitor sv = new SizeVisitor(); ef.visitBy(sv); shift = sv.getMinPayoff().negate().add(Rational.ONE); int x = sv.p1realSize(), y = sv.p2realSize(), p = sv.p1infoSize(), q = sv.p2infoSize(); tableau = new Rational[x + q + 1][y + p + 1]; for (Rational[] array : tableau) { Arrays.fill(array, Rational.ZERO); } vars.clear(); equs.clear(); getIdx("COST", equs); getIdx("cons", vars); int equidx, varidx; // COST equidx = getIdx("COST", equs); varidx = getIdx("P" + p1know, vars); tableau[equidx][varidx] = Rational.ONE.negate(); // E equidx = getIdx(p1real, equs); varidx = getIdx("P" + p1know, vars); tableau[equidx][varidx] = Rational.ONE; // F equidx = getIdx("Q" + p2know, equs); varidx = getIdx(p2real, vars); tableau[equidx][varidx] = Rational.ONE; // f equidx = getIdx("Q" + p2know, equs); varidx = getIdx("cons", vars); tableau[equidx][varidx] = Rational.ONE.negate(); super.visitExtensiveForm(ef); //print(); } public void visitImpPlayerNode(ImpPlayerNode node) { int equidx, varidx; switch (node.getPlayer()) { case 1: equidx = getIdx(p1real, equs); varidx = getIdx("P" + p1know, vars); tableau[equidx][varidx] = Rational.ONE.negate(); for (GameTree child : node) { equidx = getIdx(p1know + child.getP1Learn(), equs); tableau[equidx][varidx] = Rational.ONE; } break; case 2: equidx = getIdx("Q" + p2know, equs); varidx = getIdx(p2real, vars); tableau[equidx][varidx] = Rational.ONE.negate(); for (GameTree child : node) { varidx = getIdx(p2know + child.getP2Learn(), vars); tableau[equidx][varidx] = Rational.ONE; } break; } super.visitImpPlayerNode(node); } public void visitGameLeaf(GameLeaf leaf) { int p1realidx = getIdx(p1real, equs), p2realidx = getIdx(p2real, vars); tableau[p1realidx][p2realidx] = tableau[p1realidx][p2realidx].subtract(prob.multiply(leaf.getValue().add(shift))); } public Strategy getStrategies() { if (strategies == null) { LPDictionary d = new LPDictionary(tableau); d.PCxSolve(); Map vals = new HashMap(); for (Map.Entry entry : equs.entrySet()) { if (entry.getKey().startsWith("p1")) { vals.put(entry.getKey(), new DoubleReal(d.pcx_dual[entry.getValue()])); } } for (Map.Entry entry : vars.entrySet()) { if (entry.getKey().startsWith("p2")) { vals.put(entry.getKey(), new DoubleReal(d.pcx_primal[entry.getValue()])); } } strategies = new Strategy(vals); } return strategies; } public void process(ExtensiveForm ef, PrintStream out) { ef.visitBy(this); ef.flushTree(); getStrategies(); tableau = null; CounterStrategyVisitor cv = new CounterStrategyVisitor(strategies); ef.visitBy(cv); Strategy counter = cv.getCounterStrategies(); ValueVisitor vv = new ValueVisitor(strategies, strategies); ef.visitBy(vv); DoubleReal value = vv.getValue(); vv = new ValueVisitor(strategies, counter); ef.visitBy(vv); DoubleReal lowvalue = vv.getValue(); vv = new ValueVisitor(counter, strategies); ef.visitBy(vv); DoubleReal highvalue = vv.getValue(); out.println("An optimal strategy:"); strategies.print(out); out.println("\nValue: " + value + " ~" + (highvalue.subtract(lowvalue))); } }