Monday, July 10, 2017

Artificial intelligence ND A2, isolation



15 Lessons, including 4 Projects:
  1. sudoku game
  2. isolation game: due in 2017.5.15
  3. planning: due in 2017.6.12
  4. hidden Markov models: due in 2017.7.10
This project 2 is much more difficult than I originally expected. But once I accomplish it, I feel so great. I really enjoy the beauty of the minimax algorithm and alpha-beta pruning!

5 Intro to AI

Examples of AI application:
  • Navigation
  • tic tac toe game
  • Monty Hall problem: prior vs posterior probability
We often tend to use the word intelligence to describe things that we don’t know how to explain. Once we can explain them, we just say that they’re algorithms or formulas. They’re only intelligent if we can’t explain them.
We consider ourselves intelligent because right now we don’t fully understand how our brain work.
Equating intelligence with human behavior will pretty much rule out all artificial systems. Besides, even humans are not great at all kinds of tasks.
Intelligence should be defined within the context of a task.
  • agent (only the software part)
  • environment (including the physical body of the agent: sensors, motors)
cognition is perception and actions.
Environment states:
  • fully observable vs partially observable
  • deterministic vs stochastic
  • discrete vs continuous
  • benign vs adversarial
Bounded Optimality. An intelligent agent is one that takes actions to maximize its expected utility given the desired goal. Given these constraints, we can not expect an agent to always behave optimally. But we can come up with a level of performance or bound that we desire the agent to meet.

6 Intro to Game playing

Course teachers:
  • Peter Norvig: search and logical planning
  • Sebastian: probability and Baynes nets
  • Thad Starner: the rest
Main topics:
  • Adversarial search
  • minimax algorithm
  • alpha-beta pruning
  • evaluation function
  • isolation game
  • multi-player, probabilistic

7 isolation game

depth limit search.
  • limit time to 2 seconds per move. If the computer speed is 2GHz, and the average branching factor is 8, then we have a depth limit of 9.
Prof.
I always like to test my assumptions because they are often wrong.
quiescent search
24-27: search depth=3. The first moves on the edge have the best score.
28-29: search depth=2. The first moves on the center have the best score.
A state of quiescent: the recommended branches are not changing much.
iterative deepening means computer play always has an answer ready in case it runs out of time and it can search as far as possible within its time constraints.
It doesn’t waste that much time. Because of the exponential nature of the problem, the amount of time is dominated by the last level search.
  • If we limit the total time a player can take for the entire game, a player will want to search deeper in some parts of the game and shallower in other parts of the game.
  • A strategy for how deep we want to search: standard initial moves for the beginning of the game, then search deeper in the middle, use less time toward to the end.
  • 6.Horizon Effect: the computer may not see deep enough, goes to the local optimum.
change evaluation function: Number of my move - 2*Number of an opponent move
Shelly: the only way to really know is to try lots of variants of evaluation functions and see which ones are the best.
The strategy for an adversarial game is min-max algorithm, which has a run time of branch^{depth}
Alpha-Beta Pruning:
  • our goal is to play the game, not keep a list of all the equally good moves on a given level. It means we don’t need to look at most of the nodes.
  • run time is branch^{depth/2} if the nodes are ordered optimally with the best moves being first, or branch^{0.75depth} for random ordering.
Many problems in artificial intelligence are exponential in time or space. In fact, NP hard problems are so common in AI that researchers joke that AI is the study of finding clever hacks to exponential problems. Once the solution is found or computer is fast enough to address that particular problem, the world no longer thinks the problem belongs to artificial intelligence.
AI consists of all the NP hard problems that have not yet been solved.
What is exciting about AI is you get a chance to work on everyday problems that can improve people’s lives.
searching complex games: reading AIMA 5.3-5.4
tricks for 5x5 isolation:
  • 2nd player can always win
  • 1st play’s best strategy is to place the center and then play reflection
  • there are 8 positions you can’t play reflection.

project

starting code breakdown:
isolation.py: 1 class Board, 18 class methods.
Note the board index is numbered vertically.
class Board(Player p1,Player p2, int width=7, int height=7)
    vector<mix> _board_state(width*height+3,0); // reserve 3 for player state
bool is_winnner(Player p)
    return (p==inactive_player && active player no legal move);
bool is_loser(Player p)
    return (p==active player && has no legal move);
int get_legal_moves(Player p)
    return __get_moves(get_player_location(p));
array<int,2> get_player_location(Player p)
  int index = ...; //identify player and the move
  return (index%height, index/height);
vector<array<int>> __get_moves(array<int,2> loc)
  // propose 8 positions for L-shaped motion, like a knight
  // only return the legal one
bool move_is_legal(array<int,2> move)
  int idx = move[0] + move[1] * height;
   return (0 <= move[0] < height && 0 <= move[1] < width && _board_state[idx] == None);
void apply_move(array<int,2>)
  int idx = move[0] + move[1] * height;
 // add board state, who's last player, last player's move
// swap active_player and inactive player
tuple<Player,vector<array<int,2>>,string> play(time_limit=150)
    curr_move=_active_player.get_move(game, time_left);
    move_end = time_left();
    if move_end < 0:
      return _inactive_player, move_history, "timeout";
    if curr_move not in legal_player_moves:
      if len(legal_player_moves) > 0:
          return _inactive_player, move_history, "forfeit";
        return _inactive_player, move_history, "illegal move";
sample_player.py: 4 methods, 3 class: RandomPlayer, GreedyPlayer, HumanPlayer, 1 main method
float null_score(Board game, Player p)
    if (p win) return float("inf");
    else if (lose) return float("-inf"); 
    else return 0.;
float open_move_score(Board game, Player p)
  return game.get_legal_moves(p).size();
float improved_score(Board game, Player p)
  int own_moves = game.get_legal_moves(p).size();
  if (p == _active_player)    int opp_moves = game.get_legal_moves(_inactive_player).size();
    else int opp_moves = game.get_legal_moves(_active_player).size();      
    return float(own_moves - opp_moves);
float center_score(Board game, Player p)   
      int w= game.width / 2., h =game.height / 2.;
    int y, x = game.get_player_location(player);
    return float((h - y)**2 + (w - x)**2);
class RandomPlayer()
  array<int,2> get_move(Board game, Player p)
    auto legal_moves = game.get_legal_moves();
    if (legal_moves.size()==0) return make_tuple(-1,-1);
    return legal_moves[randint(0, len(legal_moves) - 1)];
class GreedyPlayer()
  array<int,2> get_move(Board game, Player p)
       legal_moves = game.get_legal_moves()
        _, move = max([(self.score(game.forecast_move(m), self), m) for m in legal_moves]) // ? 
        return move;
class HumanPlayer()
  array<int,2> get_move(Board game, Player p)
    legal_moves = game.get_legal_moves()
    // print board state and possible move, manually choose
int main()
    //RandomPlayer and GreedyPlayer play against each other
tournament.py: 3 methods, 1 main method
Agent = namedtuple("Agent", ["player", "name"])
int main()
  array<Agent,4> test_agents;
  array<Agent,7> cpu_agents;
  play_matches(cpu_agents,test_agents,5);
    return 0;
array<int,2> play_round(cpu_agent, test_agents, map<Agent,int> wins, int num_matches)
     // each round is num_matches*2*len(test_agents) games  
     return {timeout_count, forfeit_count};                  
int update(map total_wins, map new_wins)
    // absorb new wins into total wins
      return total_wins; // no need to return if use &
void play_matches(cpu_agents, test_agents, num_matches)
game_agent.py: 3 custom_score method, 3 class: IsolationPlayer, MinimaxPlayer, AlphaBetaPlayer.
Notes:
  • dirty jobs are done by get_move of individual class.
  • RandomPlayer and GreedyPlayer from sample_player.py only deal with the first level search, so there is no timeout issue.
  • For depth-limited search, we have to check the time before going to the next level. TIME_LIMIT_MILLIS is set to 150 in isolation.py. time_left function is lambda defined in Board.playmethod and passed into Agent.get_move. In parent class IsolationPlayer, TIMER_THRESHOLD is set to 10, so an answer should be returned if time_left is smaller than this value.
function imbeded relation
play_matches(cpu_agents, test_agents, NUM_MATCHES):
    play_round(cpu_agent, test_agents, win, NUM_MATCHES):
        game.play(time_limit=TIME_LIMIT):
            game._active_player.get_move():
                player.minimax(game, depth):
                    game.get_legal_moves():
                        game.score(game.forecast_move(m))
​

Monday, June 26, 2017

T-SQL(SQL Server 2008) and SSIS

T-SQL is a dialect Microsoft SQL Server shares with Sybase SQL Server due to its legacy. The query declaratively specifies what is to be retrieved and query processor chooses the shortest possible time called query optimization. It can be seen as an extension to SQL server with some specialization.
A database modeling is not a place to express your inner creativity and find wild and crazy new ways of doing things. If you want to do wild and crazy, do it in your user interface in your application. In your database, I am afraid you want to be patient methodical step by step.
Questions:
  1. what’s it for? what’s the point of this database? In most case you’re building a database to support an application. Be as specific as possible.
  2. what do you have already? Don’t just import. The existing database may have some problem. What’s the existing process? Understanding the data is essential.
  3. what tables do you need? Real ones and abstract ones.
  4. what columns do you need? what data type? so it can be efficient about storing it. Flexibility is your friend but it’s not what you’re looking for in your database. email address pattern? Be as exact as possible means sequel server will enforce rules on those columns.
  5. what’s your primary key?
  6. what relationships do you need?
Attached a database:
Launch SSMS.
Connect to your SQL Server Instance.
Right-click on Databases in the Object Explorer.
Click Attach.
In the Attach Databases window, click the Add button.
Navigate to the directory containing the.MDF and.LDF files.
Select the.MDF file, and press OK.
Press OK again to attach the database.
trouble shooting is https://learningsqlserver.wordpress.com/2011/02/13/how-can-i-open-mdf-and-ldf-files-in-sql-server-attach-tutorial-troublshooting/
  • The keyword GO separates statements when more than one statement is submitted in a single batch. GO is optional when the batch contains only one statement.

data type

  • float(n), n is number of bytes for storage, 1<=n<=53
  • real, equal to float(4), value on the scale of 1e38

install

MS SQL Server 2008 R2 SP2 Express Edition
https://www.microsoft.com/en-us/download/confirmation.aspx?id=30438
make sure to download the large one (1GB) which has management tool.
install SQL Server 2008 in a non-clustered environment
instance: jychstar
instance root directory: C:\Program Files\Microsoft SQL Server\MSSQL10_50.JYCHSTAR
mix mode, password: 8920113
open SQL Server management studio
log in
right click on DataBases -> New DataBases -> SampleDB
This is equivalent to
CREATE DATABASE [SampleDB] ON  PRIMARY 
( NAME = N'SampleDB', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.JYCHSTAR\MSSQL\DATA\SampleDB.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'SampleDB_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.JYCHSTAR\MSSQL\DATA\SampleDB_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
-- list table
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'
create a table
dbo stands for database owner. If you are an administrator, dbo is the default schema.
create table dbo.table_test(
Person_ID int identity(1,1),
First_Name varchar(250),
Last_Name varchar(250),
MIddle_Name varchar(75),
Created_Data datetime not null default(getdate()),
Updated_Data datetime,
Active bit not null default(1)
);
identity(1,1) ensure an unique ID, which automatically increases 1 from 1.
insert into table
insert into table_test(First_Name, Last_Name, MIddle_Name)
values('Yuchao', 'Jiang','')
-- column list can be skipped if the values are in order
-- null allowed column can be dropped in column list

insert into table_test(First_Name, Last_Name, MIddle_Name)
select 'Yuchao1', 'Jiang2',''
union all
select 'Yuchao3', 'Jiang4','' 

update table_test
set First_Name = 'John'
where Last_Name = 'Jiang'
inquiry
select * from table_test
where First_name like 'Yucha%'
there is no keyword “limit” in sql server, you have to do like:
with r as 
(select ROW_NUMBER() over(order by First_Name desc) AS row_num,
First_Name, Last_Name from table_test)

select * from r
where row_num <=10

select top 10 * from table_test
group and count
select a,b,cout (*) as cnt
from table_test
group by a,b
having cnt = 2
order by cnt desc
partition and rank
partition give different number in the same group, rank gives same number for the same group
select row_number() over (order by cusotermerName) as ordernumber
row_number() over (partition by vendorName order by vendorName) as vendorname
dense_rank() over (order by cusotermerName) as customernumber
cusotermerName, productName,Amount,vendorName
from sales

SSIS

SSIS(sql server integration services), along with SSAS(analysis), SSRS(report), forms the so-called “business intelligence”. SSIS has a lot of overlap with ETL(Extraction, Transform and load). The main goal is to collect data from various sources, consolidate or gather data at on location for analyzing.
start -> sql server 2008 R2 -> sql server BI development studio -> new project -> template: integration services project, name: SSIS tutorial, location:C:\Users\Yuchao_Macbook\Documents\Visual Studio 2008\projects, clear “create directory for solution”
better tutorial: https://www.youtube.com/watch?v=I_Ae3suaL-U
SSIS is kind of visual approach to import raw data into database. You use various modules to connect things together. It has control flow, which is composed of different data flow.
However, the 2008 version seems to have some bugs. I can’t go through every detail right now.
​

Sunday, June 18, 2017

Self-driving Car ND B5, vehicle model

Kinematic models are simplifications of dynamic models that ignore tire forces, gravity, and mass.
Dynamic models aim to embody the actual vehicle dynamics as closely as possible.
Not all dynamic models are created equal! Some may consider more of these factors than others.
A state is represented by (x,y,\phi,v). Actuators are represented by steering wheel \delta and throttle/brake a. Simple physics. The interesting thing is that a car is not a point but has a finite size. So the actual rotation angle satisfies: L_f\Delta\psi= v\delta\Delta t.
#include <Eigen/dense>
double pi() { return M_PI; }
double deg2rad(double x) { return x * pi() / 180; }
double rad2deg(double x) { return x * 180 / pi(); }
const double Lf = 2;
using namespace Eigen;
// NOTE: state is [x, y, psi, v]
// NOTE: actuators is [delta, a]
VectorXd globalKinematic(VectorXd state,VectorXd actuators, double dt) {
  VectorXd next_state(state.size());
    double x = state[0];
    double y = state[1];
    double psi = state[2];
    double v = state[3];
    next_state[0] = x + v * cos (psi) * dt;
    next_state[1] = y + v * sin (psi) * dt;
    next_state[2] = psi + v / Lf * actuators[0] * dt;
    next_state[3] = v + actuators[1] * dt;
  return next_state;
}

polyfit

#include <math.h>
#include <iostream>
#include <Eigen/dense>
using namespace Eigen;
// Evaluate a polynomial.
double polyeval(VectorXd coeffs, double x) {
    double result = 0.0;
    for (int i = 0; i < coeffs.size(); i++) {
        result += coeffs[i] * pow(x, i);
    }
    return result;
}
// Fit a polynomial.
VectorXd polyfit(VectorXd xvals, VectorXd yvals,int order) {
    assert(xvals.size() == yvals.size());
    assert(order >= 1 && order <= xvals.size() - 1);
    MatrixXd A(xvals.size(), order + 1);
    for (int i = 0; i < xvals.size(); i++) {
        A(i, 0) = 1.0;
    }
    for (int j = 0; j < xvals.size(); j++) {
        for (int i = 0; i < order; i++) {
            A(j, i + 1) = A(j, i) * xvals(j);
        }
    }
    auto Q = A.householderQr();
    auto result = Q.solve(yvals);
    return result;
}

int main() {
    VectorXd xvals(6),yvals(6);
    xvals << 9.261977, -2.06803, -19.6663, -36.868, -51.6263, -66.3482;
    yvals << 5.17, -2.25, -15.306, -29.46, -42.85, -57.6116;
    VectorXd coeffs = polyfit(xvals,yvals,3);
    for (double x = 0; x <= 20; x += 1.0) {
        std::cout << polyeval(coeffs,x) << std::endl;
    }
}

Model predictive control

cost function:
  • cte: cross track error
  • epsi: error of heading orientation
  • v - speed_limit
  • change rate of input
Model Predictive Control (MPC) uses an optimizer to find the control inputs that minimize the cost function.We actually only execute the very first set of control inputs. This brings the vehicle to a new state and then we repeat the process.
MPC algorithm:
  1. Define the length of the trajectory, N, and duration of each timestep, dt.
  2. Define vehicle dynamics and actuator limitations along with other constraints.
  3. Define the cost function.
Loop:
  1. We pass the current state as the initial state to the model predictive controller.
  2. We call the optimization solver. Given the initial state, the solver will return the vector of control inputs that minimizes the cost function. The solver we’ll use is called Ipopt.
  3. We apply the first control input to the vehicle.
In a real car, there will a latency (~100 ms) from the actuation command to the system. So the advantage of MPC over PID is that MPC try to compute a control input based on a future error, which will lead to more stability.

Quiz

brew install ipopt --with-openblas
Warning: homebrew/science/ipopt dependency gcc was built with a different C++ standard library (libstdc++ from clang). This may cause problems at runtime.
🍺  /usr/local/Cellar/ipopt/3.12.5_2: 66 files, 6.4MB, 
brew install cppad
🍺  /usr/local/Cellar/cppad/20150000_3: 1,483 files, 11.8MB
core code:
#include <cppad/cppad.hpp>
#include <cppad/ipopt/solve.hpp>
#include <Eigen/QR>
auto coeffs = polyfit(ptsx, ptsy, 1);  // linear fit
double cte = polyeval(coeffs, x) - y;
double epsi = psi - atan(coeffs[1]);
Eigen::VectorXd state(6);
state << x, y, psi, v, cte, epsi; // initialize state
auto vars = mpc.Solve(state, coeffs); 
state << vars[0], vars[1], vars[2], vars[3], vars[4], vars[5];  // update state
mpc.Solve has to be specifically modified to incorporate constraints and target information.
size_t N = 25 ;  // number of timesteps
double dt = 0.05 ; // timestep
size_t n_vars = N*8 - 2; // number of independent variables
size_t n_constraints = N * 6;   // Number of constraints
Dvector vars(n_vars), vars_lowerbound(n_vars), vars_upperbound(n_vars), constraints_lowerbound(n_constraints), constraints_upperbound(n_constraints);
// ... initial values for these vectors 
FG_eval fg_eval(coeffs); // constructor
CppAD::ipopt::solve_result<Dvector> solution; // get space
// solve the problem
CppAD::ipopt::solve<Dvector, FG_eval>(options, vars, vars_lowerbound, vars_upperbound, constraints_lowerbound, constraints_upperbound, fg_eval, solution);
Note that the cost function is defined in FG_eval class method operator
​